提交 e9021331 编写于 作者: D Dave Jiang 提交者: Jon Mason

ntb: stop tasklet from spinning forever during shutdown.

We can leave tasklet spinning forever if we disable the tasklet during
qp shutdown and the tasklets are still being kicked off. This hopefully
should avoid that race condition.
Signed-off-by: NDave Jiang <dave.jiang@intel.com>
Reported-by: NAlex Depoutovitch <alex@pernixdata.com>
Tested-by: NAlex Depoutovitch <alex@pernixdata.com>
Signed-off-by: NJon Mason <jdmason@kudzu.us>
上级 1985a881
......@@ -124,6 +124,7 @@ struct ntb_transport_qp {
bool client_ready;
bool link_is_up;
bool active;
u8 qp_num; /* Only 64 QP's are allowed. 0-63 */
u64 qp_bit;
......@@ -719,6 +720,7 @@ static int ntb_set_mw(struct ntb_transport_ctx *nt, int num_mw,
static void ntb_qp_link_down_reset(struct ntb_transport_qp *qp)
{
qp->link_is_up = false;
qp->active = false;
qp->tx_index = 0;
qp->rx_index = 0;
......@@ -926,11 +928,13 @@ static void ntb_qp_link_work(struct work_struct *work)
if (val & BIT(qp->qp_num)) {
dev_info(&pdev->dev, "qp %d: Link Up\n", qp->qp_num);
qp->link_is_up = true;
qp->active = true;
if (qp->event_handler)
qp->event_handler(qp->cb_data, qp->link_is_up);
tasklet_schedule(&qp->rxc_db_work);
if (qp->active)
tasklet_schedule(&qp->rxc_db_work);
} else if (nt->link_is_up)
schedule_delayed_work(&qp->link_work,
msecs_to_jiffies(NTB_LINK_DOWN_TIMEOUT));
......@@ -1411,7 +1415,8 @@ static void ntb_transport_rxc_db(unsigned long data)
if (i == qp->rx_max_entry) {
/* there is more work to do */
tasklet_schedule(&qp->rxc_db_work);
if (qp->active)
tasklet_schedule(&qp->rxc_db_work);
} else if (ntb_db_read(qp->ndev) & BIT_ULL(qp->qp_num)) {
/* the doorbell bit is set: clear it */
ntb_db_clear(qp->ndev, BIT_ULL(qp->qp_num));
......@@ -1422,7 +1427,8 @@ static void ntb_transport_rxc_db(unsigned long data)
* ntb_process_rxc and clearing the doorbell bit:
* there might be some more work to do.
*/
tasklet_schedule(&qp->rxc_db_work);
if (qp->active)
tasklet_schedule(&qp->rxc_db_work);
}
}
......@@ -1760,6 +1766,8 @@ void ntb_transport_free_queue(struct ntb_transport_qp *qp)
pdev = qp->ndev->pdev;
qp->active = false;
if (qp->tx_dma_chan) {
struct dma_chan *chan = qp->tx_dma_chan;
/* Putting the dma_chan to NULL will force any new traffic to be
......@@ -1793,7 +1801,7 @@ void ntb_transport_free_queue(struct ntb_transport_qp *qp)
qp_bit = BIT_ULL(qp->qp_num);
ntb_db_set_mask(qp->ndev, qp_bit);
tasklet_disable(&qp->rxc_db_work);
tasklet_kill(&qp->rxc_db_work);
cancel_delayed_work_sync(&qp->link_work);
......@@ -1886,7 +1894,8 @@ int ntb_transport_rx_enqueue(struct ntb_transport_qp *qp, void *cb, void *data,
ntb_list_add(&qp->ntb_rx_q_lock, &entry->entry, &qp->rx_pend_q);
tasklet_schedule(&qp->rxc_db_work);
if (qp->active)
tasklet_schedule(&qp->rxc_db_work);
return 0;
}
......@@ -2069,7 +2078,8 @@ static void ntb_transport_doorbell_callback(void *data, int vector)
qp_num = __ffs(db_bits);
qp = &nt->qp_vec[qp_num];
tasklet_schedule(&qp->rxc_db_work);
if (qp->active)
tasklet_schedule(&qp->rxc_db_work);
db_bits &= ~BIT_ULL(qp_num);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册