Commit e9021331 authored by Dave Jiang's avatar Dave Jiang Committed by 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: default avatarDave Jiang <dave.jiang@intel.com>
Reported-by: default avatarAlex Depoutovitch <alex@pernixdata.com>
Tested-by: default avatarAlex Depoutovitch <alex@pernixdata.com>
Signed-off-by: default avatarJon Mason <jdmason@kudzu.us>
parent 1985a881
...@@ -124,6 +124,7 @@ struct ntb_transport_qp { ...@@ -124,6 +124,7 @@ struct ntb_transport_qp {
bool client_ready; bool client_ready;
bool link_is_up; bool link_is_up;
bool active;
u8 qp_num; /* Only 64 QP's are allowed. 0-63 */ u8 qp_num; /* Only 64 QP's are allowed. 0-63 */
u64 qp_bit; u64 qp_bit;
...@@ -719,6 +720,7 @@ static int ntb_set_mw(struct ntb_transport_ctx *nt, int num_mw, ...@@ -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) static void ntb_qp_link_down_reset(struct ntb_transport_qp *qp)
{ {
qp->link_is_up = false; qp->link_is_up = false;
qp->active = false;
qp->tx_index = 0; qp->tx_index = 0;
qp->rx_index = 0; qp->rx_index = 0;
...@@ -926,10 +928,12 @@ static void ntb_qp_link_work(struct work_struct *work) ...@@ -926,10 +928,12 @@ static void ntb_qp_link_work(struct work_struct *work)
if (val & BIT(qp->qp_num)) { if (val & BIT(qp->qp_num)) {
dev_info(&pdev->dev, "qp %d: Link Up\n", qp->qp_num); dev_info(&pdev->dev, "qp %d: Link Up\n", qp->qp_num);
qp->link_is_up = true; qp->link_is_up = true;
qp->active = true;
if (qp->event_handler) if (qp->event_handler)
qp->event_handler(qp->cb_data, qp->link_is_up); qp->event_handler(qp->cb_data, qp->link_is_up);
if (qp->active)
tasklet_schedule(&qp->rxc_db_work); tasklet_schedule(&qp->rxc_db_work);
} else if (nt->link_is_up) } else if (nt->link_is_up)
schedule_delayed_work(&qp->link_work, schedule_delayed_work(&qp->link_work,
...@@ -1411,6 +1415,7 @@ static void ntb_transport_rxc_db(unsigned long data) ...@@ -1411,6 +1415,7 @@ static void ntb_transport_rxc_db(unsigned long data)
if (i == qp->rx_max_entry) { if (i == qp->rx_max_entry) {
/* there is more work to do */ /* there is more work to do */
if (qp->active)
tasklet_schedule(&qp->rxc_db_work); tasklet_schedule(&qp->rxc_db_work);
} else if (ntb_db_read(qp->ndev) & BIT_ULL(qp->qp_num)) { } else if (ntb_db_read(qp->ndev) & BIT_ULL(qp->qp_num)) {
/* the doorbell bit is set: clear it */ /* the doorbell bit is set: clear it */
...@@ -1422,6 +1427,7 @@ static void ntb_transport_rxc_db(unsigned long data) ...@@ -1422,6 +1427,7 @@ static void ntb_transport_rxc_db(unsigned long data)
* ntb_process_rxc and clearing the doorbell bit: * ntb_process_rxc and clearing the doorbell bit:
* there might be some more work to do. * there might be some more work to do.
*/ */
if (qp->active)
tasklet_schedule(&qp->rxc_db_work); tasklet_schedule(&qp->rxc_db_work);
} }
} }
...@@ -1760,6 +1766,8 @@ void ntb_transport_free_queue(struct ntb_transport_qp *qp) ...@@ -1760,6 +1766,8 @@ void ntb_transport_free_queue(struct ntb_transport_qp *qp)
pdev = qp->ndev->pdev; pdev = qp->ndev->pdev;
qp->active = false;
if (qp->tx_dma_chan) { if (qp->tx_dma_chan) {
struct dma_chan *chan = 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 /* 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) ...@@ -1793,7 +1801,7 @@ void ntb_transport_free_queue(struct ntb_transport_qp *qp)
qp_bit = BIT_ULL(qp->qp_num); qp_bit = BIT_ULL(qp->qp_num);
ntb_db_set_mask(qp->ndev, qp_bit); 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); cancel_delayed_work_sync(&qp->link_work);
...@@ -1886,6 +1894,7 @@ int ntb_transport_rx_enqueue(struct ntb_transport_qp *qp, void *cb, void *data, ...@@ -1886,6 +1894,7 @@ 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); ntb_list_add(&qp->ntb_rx_q_lock, &entry->entry, &qp->rx_pend_q);
if (qp->active)
tasklet_schedule(&qp->rxc_db_work); tasklet_schedule(&qp->rxc_db_work);
return 0; return 0;
...@@ -2069,6 +2078,7 @@ static void ntb_transport_doorbell_callback(void *data, int vector) ...@@ -2069,6 +2078,7 @@ static void ntb_transport_doorbell_callback(void *data, int vector)
qp_num = __ffs(db_bits); qp_num = __ffs(db_bits);
qp = &nt->qp_vec[qp_num]; qp = &nt->qp_vec[qp_num];
if (qp->active)
tasklet_schedule(&qp->rxc_db_work); tasklet_schedule(&qp->rxc_db_work);
db_bits &= ~BIT_ULL(qp_num); db_bits &= ~BIT_ULL(qp_num);
......
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