Skip to content

Commit

Permalink
qed: Fix LL2 race during connection terminate
Browse files Browse the repository at this point in the history
Stress on qedi/qedr load unload lead to list_del corruption.
This is due to ll2 connection terminate freeing resources without
verifying that no more ll2 processing will occur.

This patch unregisters the ll2 status block before terminating
the connection to assure this race does not occur.

Fixes: 1d6cff4 ("qed: Add iSCSI out of order packet handling")
Signed-off-by: Ariel Elior <Ariel.Elior@cavium.com>
Signed-off-by: Michal Kalderon <Michal.Kalderon@cavium.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Michal Kalderon authored and David S. Miller committed May 16, 2018
1 parent 6291c60 commit fc16f56
Showing 1 changed file with 14 additions and 10 deletions.
24 changes: 14 additions & 10 deletions drivers/net/ethernet/qlogic/qed/qed_ll2.c
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,9 @@ static int qed_ll2_lb_rxq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)
struct qed_ll2_info *p_ll2_conn = (struct qed_ll2_info *)p_cookie;
int rc;

if (!QED_LL2_RX_REGISTERED(p_ll2_conn))
return 0;

rc = qed_ll2_lb_rxq_handler(p_hwfn, p_ll2_conn);
if (rc)
return rc;
Expand All @@ -849,6 +852,9 @@ static int qed_ll2_lb_txq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)
u16 new_idx = 0, num_bds = 0;
int rc;

if (!QED_LL2_TX_REGISTERED(p_ll2_conn))
return 0;

new_idx = le16_to_cpu(*p_tx->p_fw_cons);
num_bds = ((s16)new_idx - (s16)p_tx->bds_idx);

Expand Down Expand Up @@ -1915,17 +1921,25 @@ int qed_ll2_terminate_connection(void *cxt, u8 connection_handle)

/* Stop Tx & Rx of connection, if needed */
if (QED_LL2_TX_REGISTERED(p_ll2_conn)) {
p_ll2_conn->tx_queue.b_cb_registred = false;
smp_wmb(); /* Make sure this is seen by ll2_lb_rxq_completion */
rc = qed_sp_ll2_tx_queue_stop(p_hwfn, p_ll2_conn);
if (rc)
goto out;

qed_ll2_txq_flush(p_hwfn, connection_handle);
qed_int_unregister_cb(p_hwfn, p_ll2_conn->tx_queue.tx_sb_index);
}

if (QED_LL2_RX_REGISTERED(p_ll2_conn)) {
p_ll2_conn->rx_queue.b_cb_registred = false;
smp_wmb(); /* Make sure this is seen by ll2_lb_rxq_completion */
rc = qed_sp_ll2_rx_queue_stop(p_hwfn, p_ll2_conn);
if (rc)
goto out;

qed_ll2_rxq_flush(p_hwfn, connection_handle);
qed_int_unregister_cb(p_hwfn, p_ll2_conn->rx_queue.rx_sb_index);
}

if (p_ll2_conn->input.conn_type == QED_LL2_TYPE_OOO)
Expand Down Expand Up @@ -1974,16 +1988,6 @@ void qed_ll2_release_connection(void *cxt, u8 connection_handle)
if (!p_ll2_conn)
return;

if (QED_LL2_RX_REGISTERED(p_ll2_conn)) {
p_ll2_conn->rx_queue.b_cb_registred = false;
qed_int_unregister_cb(p_hwfn, p_ll2_conn->rx_queue.rx_sb_index);
}

if (QED_LL2_TX_REGISTERED(p_ll2_conn)) {
p_ll2_conn->tx_queue.b_cb_registred = false;
qed_int_unregister_cb(p_hwfn, p_ll2_conn->tx_queue.tx_sb_index);
}

kfree(p_ll2_conn->tx_queue.descq_mem);
qed_chain_free(p_hwfn->cdev, &p_ll2_conn->tx_queue.txq_chain);

Expand Down

0 comments on commit fc16f56

Please sign in to comment.