net/smc: do not call dma sync for unmapped memory

The dma related ...sync_sg... functions check the link state before the
dma function is actually called. But the check in smc_link_usable()
allows links in ACTIVATING state which are not yet mapped to dma memory.
Under high load it may happen that the sync_sg functions are called for
such a link which results in an debug output like
   DMA-API: mlx5_core 0002:00:00.0: device driver tries to sync
   DMA memory it has not allocated [device address=0x0000000103370000]
   [size=65536 bytes]
To fix that introduce a helper to check for the link state ACTIVE and
use it where appropriate. And move the link state update to ACTIVATING
to the end of smcr_link_init() when most initial setup is done.

Reviewed-by: Ursula Braun <ubraun@linux.ibm.com>
Fixes: d854fcbfae ("net/smc: add new link state and related helpers")
Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Karsten Graul 2020-07-18 15:06:16 +02:00 committed by David S. Miller
parent b9979c2e83
commit 741a49a4dc
4 changed files with 18 additions and 14 deletions

View File

@ -352,7 +352,7 @@ static int smcr_lgr_reg_rmbs(struct smc_link *link,
*/ */
mutex_lock(&lgr->llc_conf_mutex); mutex_lock(&lgr->llc_conf_mutex);
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_ACTIVE) if (!smc_link_active(&lgr->lnk[i]))
continue; continue;
rc = smcr_link_reg_rmb(&lgr->lnk[i], rmb_desc); rc = smcr_link_reg_rmb(&lgr->lnk[i], rmb_desc);
if (rc) if (rc)

View File

@ -318,7 +318,6 @@ int smcr_link_init(struct smc_link_group *lgr, struct smc_link *lnk,
get_device(&ini->ib_dev->ibdev->dev); get_device(&ini->ib_dev->ibdev->dev);
atomic_inc(&ini->ib_dev->lnk_cnt); atomic_inc(&ini->ib_dev->lnk_cnt);
lnk->state = SMC_LNK_ACTIVATING;
lnk->link_id = smcr_next_link_id(lgr); lnk->link_id = smcr_next_link_id(lgr);
lnk->lgr = lgr; lnk->lgr = lgr;
lnk->link_idx = link_idx; lnk->link_idx = link_idx;
@ -354,6 +353,7 @@ int smcr_link_init(struct smc_link_group *lgr, struct smc_link *lnk,
rc = smc_wr_create_link(lnk); rc = smc_wr_create_link(lnk);
if (rc) if (rc)
goto destroy_qp; goto destroy_qp;
lnk->state = SMC_LNK_ACTIVATING;
return 0; return 0;
destroy_qp: destroy_qp:
@ -542,8 +542,7 @@ struct smc_link *smc_switch_conns(struct smc_link_group *lgr,
smc_wr_wakeup_tx_wait(from_lnk); smc_wr_wakeup_tx_wait(from_lnk);
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_ACTIVE || if (!smc_link_active(&lgr->lnk[i]) || i == from_lnk->link_idx)
i == from_lnk->link_idx)
continue; continue;
if (is_dev_err && from_lnk->smcibdev == lgr->lnk[i].smcibdev && if (is_dev_err && from_lnk->smcibdev == lgr->lnk[i].smcibdev &&
from_lnk->ibport == lgr->lnk[i].ibport) { from_lnk->ibport == lgr->lnk[i].ibport) {
@ -1269,7 +1268,7 @@ static bool smcr_lgr_match(struct smc_link_group *lgr,
return false; return false;
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_ACTIVE) if (!smc_link_active(&lgr->lnk[i]))
continue; continue;
if ((lgr->role == SMC_SERV || lgr->lnk[i].peer_qpn == clcqpn) && if ((lgr->role == SMC_SERV || lgr->lnk[i].peer_qpn == clcqpn) &&
!memcmp(lgr->lnk[i].peer_gid, &lcl->gid, SMC_GID_SIZE) && !memcmp(lgr->lnk[i].peer_gid, &lcl->gid, SMC_GID_SIZE) &&
@ -1717,14 +1716,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 || !smc_link_usable(conn->lnk)) if (!conn->lgr || conn->lgr->is_smcd || !smc_link_active(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 || !smc_link_usable(conn->lnk)) if (!conn->lgr || conn->lgr->is_smcd || !smc_link_active(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);
} }
@ -1736,7 +1735,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 (!smc_link_usable(&conn->lgr->lnk[i])) if (!smc_link_active(&conn->lgr->lnk[i]))
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);
@ -1750,7 +1749,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 (!smc_link_usable(&conn->lgr->lnk[i])) if (!smc_link_active(&conn->lgr->lnk[i]))
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);

View File

@ -349,6 +349,11 @@ static inline bool smc_link_usable(struct smc_link *lnk)
return true; return true;
} }
static inline bool smc_link_active(struct smc_link *lnk)
{
return lnk->state == SMC_LNK_ACTIVE;
}
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;

View File

@ -428,7 +428,7 @@ static int smc_llc_send_confirm_rkey(struct smc_link *send_link,
rtok_ix = 1; rtok_ix = 1;
for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
link = &send_link->lgr->lnk[i]; link = &send_link->lgr->lnk[i];
if (link->state == SMC_LNK_ACTIVE && link != send_link) { if (smc_link_active(link) && link != send_link) {
rkeyllc->rtoken[rtok_ix].link_id = link->link_id; rkeyllc->rtoken[rtok_ix].link_id = link->link_id;
rkeyllc->rtoken[rtok_ix].rmb_key = rkeyllc->rtoken[rtok_ix].rmb_key =
htonl(rmb_desc->mr_rx[link->link_idx]->rkey); htonl(rmb_desc->mr_rx[link->link_idx]->rkey);
@ -944,7 +944,7 @@ static int smc_llc_active_link_count(struct smc_link_group *lgr)
int i, link_count = 0; int i, link_count = 0;
for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
if (!smc_link_usable(&lgr->lnk[i])) if (!smc_link_active(&lgr->lnk[i]))
continue; continue;
link_count++; link_count++;
} }
@ -1622,7 +1622,7 @@ static void smc_llc_rx_response(struct smc_link *link,
switch (llc_type) { switch (llc_type) {
case SMC_LLC_TEST_LINK: case SMC_LLC_TEST_LINK:
if (link->state == SMC_LNK_ACTIVE) if (smc_link_active(link))
complete(&link->llc_testlink_resp); complete(&link->llc_testlink_resp);
break; break;
case SMC_LLC_ADD_LINK: case SMC_LLC_ADD_LINK:
@ -1706,7 +1706,7 @@ static void smc_llc_testlink_work(struct work_struct *work)
u8 user_data[16] = { 0 }; u8 user_data[16] = { 0 };
int rc; int rc;
if (link->state != SMC_LNK_ACTIVE) if (!smc_link_active(link))
return; /* don't reschedule worker */ return; /* don't reschedule worker */
expire_time = link->wr_rx_tstamp + link->llc_testlink_time; expire_time = link->wr_rx_tstamp + link->llc_testlink_time;
if (time_is_after_jiffies(expire_time)) { if (time_is_after_jiffies(expire_time)) {
@ -1718,7 +1718,7 @@ static void smc_llc_testlink_work(struct work_struct *work)
/* receive TEST LINK response over RoCE fabric */ /* receive TEST LINK response over RoCE fabric */
rc = wait_for_completion_interruptible_timeout(&link->llc_testlink_resp, rc = wait_for_completion_interruptible_timeout(&link->llc_testlink_resp,
SMC_LLC_WAIT_TIME); SMC_LLC_WAIT_TIME);
if (link->state != SMC_LNK_ACTIVE) if (!smc_link_active(link))
return; /* link state changed */ return; /* link state changed */
if (rc <= 0) { if (rc <= 0) {
smcr_link_down_cond_sched(link); smcr_link_down_cond_sched(link);