Commit d854fcbf authored by Karsten Graul's avatar Karsten Graul Committed by David S. Miller

net/smc: add new link state and related helpers

Before a link can be reused it must have been cleared. Lowest current
link state is INACTIVE, which does not mean that the link is already
cleared.
Add a new state UNUSED that is set when the link is cleared and can be
reused.
Add helper smc_llc_usable_link() to find an active link in a link group,
and smc_link_usable() to determine if a link is usable.
Signed-off-by: default avatarKarsten Graul <kgraul@linux.ibm.com>
Reviewed-by: default avatarUrsula Braun <ubraun@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e07d31dc
...@@ -260,7 +260,7 @@ static void smc_lgr_free_work(struct work_struct *work) ...@@ -260,7 +260,7 @@ static void smc_lgr_free_work(struct work_struct *work)
for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
struct smc_link *lnk = &lgr->lnk[i]; struct smc_link *lnk = &lgr->lnk[i];
if (lnk->state != SMC_LNK_INACTIVE) if (smc_link_usable(lnk))
smc_llc_link_inactive(lnk); smc_llc_link_inactive(lnk);
} }
} }
...@@ -286,7 +286,7 @@ static u8 smcr_next_link_id(struct smc_link_group *lgr) ...@@ -286,7 +286,7 @@ static u8 smcr_next_link_id(struct smc_link_group *lgr)
if (!link_id) /* skip zero as link_id */ if (!link_id) /* skip zero as link_id */
link_id = ++lgr->next_link_id; link_id = ++lgr->next_link_id;
for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
if (lgr->lnk[i].state != SMC_LNK_INACTIVE && if (smc_link_usable(&lgr->lnk[i]) &&
lgr->lnk[i].link_id == link_id) lgr->lnk[i].link_id == link_id)
continue; continue;
} }
...@@ -350,6 +350,7 @@ static int smcr_link_init(struct smc_link_group *lgr, struct smc_link *lnk, ...@@ -350,6 +350,7 @@ static int smcr_link_init(struct smc_link_group *lgr, struct smc_link *lnk,
out: out:
put_device(&ini->ib_dev->ibdev->dev); put_device(&ini->ib_dev->ibdev->dev);
memset(lnk, 0, sizeof(struct smc_link)); memset(lnk, 0, sizeof(struct smc_link));
lnk->state = SMC_LNK_UNUSED;
if (!atomic_dec_return(&ini->ib_dev->lnk_cnt)) if (!atomic_dec_return(&ini->ib_dev->lnk_cnt))
wake_up(&ini->ib_dev->lnks_deleted); wake_up(&ini->ib_dev->lnks_deleted);
return rc; return rc;
...@@ -500,6 +501,8 @@ void smc_conn_free(struct smc_connection *conn) ...@@ -500,6 +501,8 @@ void smc_conn_free(struct smc_connection *conn)
static void smcr_link_clear(struct smc_link *lnk) static void smcr_link_clear(struct smc_link *lnk)
{ {
struct smc_ib_device *smcibdev;
if (lnk->peer_qpn == 0) if (lnk->peer_qpn == 0)
return; return;
lnk->peer_qpn = 0; lnk->peer_qpn = 0;
...@@ -510,8 +513,11 @@ static void smcr_link_clear(struct smc_link *lnk) ...@@ -510,8 +513,11 @@ static void smcr_link_clear(struct smc_link *lnk)
smc_ib_dealloc_protection_domain(lnk); smc_ib_dealloc_protection_domain(lnk);
smc_wr_free_link_mem(lnk); smc_wr_free_link_mem(lnk);
put_device(&lnk->smcibdev->ibdev->dev); put_device(&lnk->smcibdev->ibdev->dev);
if (!atomic_dec_return(&lnk->smcibdev->lnk_cnt)) smcibdev = lnk->smcibdev;
wake_up(&lnk->smcibdev->lnks_deleted); memset(lnk, 0, sizeof(struct smc_link));
lnk->state = SMC_LNK_UNUSED;
if (!atomic_dec_return(&smcibdev->lnk_cnt))
wake_up(&smcibdev->lnks_deleted);
} }
static void smcr_buf_free(struct smc_link_group *lgr, bool is_rmb, static void smcr_buf_free(struct smc_link_group *lgr, bool is_rmb,
...@@ -604,9 +610,8 @@ static void smc_lgr_free(struct smc_link_group *lgr) ...@@ -604,9 +610,8 @@ static void smc_lgr_free(struct smc_link_group *lgr)
wake_up(&lgr->smcd->lgrs_deleted); wake_up(&lgr->smcd->lgrs_deleted);
} else { } else {
for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
if (lgr->lnk[i].state == SMC_LNK_INACTIVE) if (lgr->lnk[i].state != SMC_LNK_UNUSED)
continue; smcr_link_clear(&lgr->lnk[i]);
smcr_link_clear(&lgr->lnk[i]);
} }
if (!atomic_dec_return(&lgr_cnt)) if (!atomic_dec_return(&lgr_cnt))
wake_up(&lgrs_deleted); wake_up(&lgrs_deleted);
...@@ -686,7 +691,7 @@ static void smc_lgr_cleanup(struct smc_link_group *lgr) ...@@ -686,7 +691,7 @@ static void smc_lgr_cleanup(struct smc_link_group *lgr)
for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
struct smc_link *lnk = &lgr->lnk[i]; struct smc_link *lnk = &lgr->lnk[i];
if (lnk->state != SMC_LNK_INACTIVE) if (smc_link_usable(lnk))
smc_llc_link_inactive(lnk); smc_llc_link_inactive(lnk);
} }
} }
...@@ -764,7 +769,7 @@ void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport) ...@@ -764,7 +769,7 @@ void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport)
continue; continue;
/* tbd - terminate only when no more links are active */ /* tbd - terminate only when no more links are active */
for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
if (lgr->lnk[i].state == SMC_LNK_INACTIVE || if (!smc_link_usable(&lgr->lnk[i]) ||
lgr->lnk[i].state == SMC_LNK_DELETING) lgr->lnk[i].state == SMC_LNK_DELETING)
continue; continue;
if (lgr->lnk[i].smcibdev == smcibdev && if (lgr->lnk[i].smcibdev == smcibdev &&
...@@ -1161,8 +1166,7 @@ static int smcr_buf_map_usable_links(struct smc_link_group *lgr, ...@@ -1161,8 +1166,7 @@ static int smcr_buf_map_usable_links(struct smc_link_group *lgr,
for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
struct smc_link *lnk = &lgr->lnk[i]; struct smc_link *lnk = &lgr->lnk[i];
if (lnk->state != SMC_LNK_ACTIVE && if (!smc_link_usable(lnk))
lnk->state != SMC_LNK_ACTIVATING)
continue; continue;
if (smcr_buf_map_link(buf_desc, is_rmb, lnk)) { if (smcr_buf_map_link(buf_desc, is_rmb, lnk)) {
smcr_buf_unuse(buf_desc, lnk); smcr_buf_unuse(buf_desc, lnk);
...@@ -1294,14 +1298,14 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb) ...@@ -1294,14 +1298,14 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb)
void smc_sndbuf_sync_sg_for_cpu(struct smc_connection *conn) void smc_sndbuf_sync_sg_for_cpu(struct smc_connection *conn)
{ {
if (!conn->lgr || conn->lgr->is_smcd) if (!conn->lgr || conn->lgr->is_smcd || !smc_link_usable(conn->lnk))
return; return;
smc_ib_sync_sg_for_cpu(conn->lnk, conn->sndbuf_desc, DMA_TO_DEVICE); smc_ib_sync_sg_for_cpu(conn->lnk, conn->sndbuf_desc, DMA_TO_DEVICE);
} }
void smc_sndbuf_sync_sg_for_device(struct smc_connection *conn) void smc_sndbuf_sync_sg_for_device(struct smc_connection *conn)
{ {
if (!conn->lgr || conn->lgr->is_smcd) if (!conn->lgr || conn->lgr->is_smcd || !smc_link_usable(conn->lnk))
return; return;
smc_ib_sync_sg_for_device(conn->lnk, conn->sndbuf_desc, DMA_TO_DEVICE); smc_ib_sync_sg_for_device(conn->lnk, conn->sndbuf_desc, DMA_TO_DEVICE);
} }
...@@ -1313,8 +1317,7 @@ void smc_rmb_sync_sg_for_cpu(struct smc_connection *conn) ...@@ -1313,8 +1317,7 @@ void smc_rmb_sync_sg_for_cpu(struct smc_connection *conn)
if (!conn->lgr || conn->lgr->is_smcd) if (!conn->lgr || conn->lgr->is_smcd)
return; return;
for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
if (conn->lgr->lnk[i].state != SMC_LNK_ACTIVE && if (!smc_link_usable(&conn->lgr->lnk[i]))
conn->lgr->lnk[i].state != SMC_LNK_ACTIVATING)
continue; continue;
smc_ib_sync_sg_for_cpu(&conn->lgr->lnk[i], conn->rmb_desc, smc_ib_sync_sg_for_cpu(&conn->lgr->lnk[i], conn->rmb_desc,
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
...@@ -1328,8 +1331,7 @@ void smc_rmb_sync_sg_for_device(struct smc_connection *conn) ...@@ -1328,8 +1331,7 @@ void smc_rmb_sync_sg_for_device(struct smc_connection *conn)
if (!conn->lgr || conn->lgr->is_smcd) if (!conn->lgr || conn->lgr->is_smcd)
return; return;
for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
if (conn->lgr->lnk[i].state != SMC_LNK_ACTIVE && if (!smc_link_usable(&conn->lgr->lnk[i]))
conn->lgr->lnk[i].state != SMC_LNK_ACTIVATING)
continue; continue;
smc_ib_sync_sg_for_device(&conn->lgr->lnk[i], conn->rmb_desc, smc_ib_sync_sg_for_device(&conn->lgr->lnk[i], conn->rmb_desc,
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
......
...@@ -32,6 +32,7 @@ enum smc_lgr_role { /* possible roles of a link group */ ...@@ -32,6 +32,7 @@ enum smc_lgr_role { /* possible roles of a link group */
}; };
enum smc_link_state { /* possible states of a link */ enum smc_link_state { /* possible states of a link */
SMC_LNK_UNUSED, /* link is unused */
SMC_LNK_INACTIVE, /* link is inactive */ SMC_LNK_INACTIVE, /* link is inactive */
SMC_LNK_ACTIVATING, /* link is being activated */ SMC_LNK_ACTIVATING, /* link is being activated */
SMC_LNK_ACTIVE, /* link is active */ SMC_LNK_ACTIVE, /* link is active */
...@@ -295,6 +296,14 @@ static inline struct smc_connection *smc_lgr_find_conn( ...@@ -295,6 +296,14 @@ static inline struct smc_connection *smc_lgr_find_conn(
return res; return res;
} }
/* returns true if the specified link is usable */
static inline bool smc_link_usable(struct smc_link *lnk)
{
if (lnk->state == SMC_LNK_UNUSED || lnk->state == SMC_LNK_INACTIVE)
return false;
return true;
}
struct smc_sock; struct smc_sock;
struct smc_clc_msg_accept_confirm; struct smc_clc_msg_accept_confirm;
struct smc_clc_msg_local; struct smc_clc_msg_local;
......
...@@ -372,7 +372,7 @@ static void smc_llc_send_message_work(struct work_struct *work) ...@@ -372,7 +372,7 @@ static void smc_llc_send_message_work(struct work_struct *work)
struct smc_wr_buf *wr_buf; struct smc_wr_buf *wr_buf;
int rc; int rc;
if (llcwrk->link->state == SMC_LNK_INACTIVE) if (!smc_link_usable(llcwrk->link))
goto out; goto out;
rc = smc_llc_add_pending_send(llcwrk->link, &wr_buf, &pend); rc = smc_llc_add_pending_send(llcwrk->link, &wr_buf, &pend);
if (rc) if (rc)
...@@ -562,7 +562,7 @@ static void smc_llc_rx_handler(struct ib_wc *wc, void *buf) ...@@ -562,7 +562,7 @@ static void smc_llc_rx_handler(struct ib_wc *wc, void *buf)
return; /* short message */ return; /* short message */
if (llc->raw.hdr.length != sizeof(*llc)) if (llc->raw.hdr.length != sizeof(*llc))
return; /* invalid message */ return; /* invalid message */
if (link->state == SMC_LNK_INACTIVE) if (!smc_link_usable(link))
return; /* link not active, drop msg */ return; /* link not active, drop msg */
switch (llc->raw.hdr.common.type) { switch (llc->raw.hdr.common.type) {
......
...@@ -35,6 +35,17 @@ enum smc_llc_msg_type { ...@@ -35,6 +35,17 @@ enum smc_llc_msg_type {
SMC_LLC_DELETE_RKEY = 0x09, SMC_LLC_DELETE_RKEY = 0x09,
}; };
/* returns a usable link of the link group, or NULL */
static inline struct smc_link *smc_llc_usable_link(struct smc_link_group *lgr)
{
int i;
for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++)
if (smc_link_usable(&lgr->lnk[i]))
return &lgr->lnk[i];
return NULL;
}
/* transmit */ /* transmit */
int smc_llc_send_confirm_link(struct smc_link *lnk, int smc_llc_send_confirm_link(struct smc_link *lnk,
enum smc_llc_reqresp reqresp); enum smc_llc_reqresp reqresp);
......
...@@ -207,7 +207,7 @@ int smc_wr_tx_get_free_slot(struct smc_link *link, ...@@ -207,7 +207,7 @@ int smc_wr_tx_get_free_slot(struct smc_link *link,
} else { } else {
rc = wait_event_interruptible_timeout( rc = wait_event_interruptible_timeout(
link->wr_tx_wait, link->wr_tx_wait,
link->state == SMC_LNK_INACTIVE || !smc_link_usable(link) ||
lgr->terminating || lgr->terminating ||
(smc_wr_tx_get_free_slot_index(link, &idx) != -EBUSY), (smc_wr_tx_get_free_slot_index(link, &idx) != -EBUSY),
SMC_WR_TX_WAIT_FREE_SLOT_TIME); SMC_WR_TX_WAIT_FREE_SLOT_TIME);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment