Skip to content

Commit

Permalink
NTB: Fix ntb_transport link down race
Browse files Browse the repository at this point in the history
A WARN_ON is being hit in ntb_qp_link_work due to the NTB transport link
being down while the ntb qp link is still active.  This is caused by the
transport link being brought down prior to the qp link worker thread
being terminated.  To correct this, shutdown the qp's prior to bringing
the transport link down.  Also, only call the qp worker thread if it is
in interrupt context, otherwise call the function directly.

Signed-off-by: Jon Mason <jon.mason@intel.com>
  • Loading branch information
Jon Mason committed Nov 20, 2013
1 parent 9739047 commit fca4d51
Showing 1 changed file with 28 additions and 15 deletions.
43 changes: 28 additions & 15 deletions drivers/ntb/ntb_transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -584,11 +584,8 @@ static int ntb_set_mw(struct ntb_transport *nt, int num_mw, unsigned int size)
return 0;
}

static void ntb_qp_link_cleanup(struct work_struct *work)
static void ntb_qp_link_cleanup(struct ntb_transport_qp *qp)
{
struct ntb_transport_qp *qp = container_of(work,
struct ntb_transport_qp,
link_cleanup);
struct ntb_transport *nt = qp->transport;
struct pci_dev *pdev = ntb_query_pdev(nt->ndev);

Expand All @@ -602,6 +599,16 @@ static void ntb_qp_link_cleanup(struct work_struct *work)

dev_info(&pdev->dev, "qp %d: Link Down\n", qp->qp_num);
qp->qp_link = NTB_LINK_DOWN;
}

static void ntb_qp_link_cleanup_work(struct work_struct *work)
{
struct ntb_transport_qp *qp = container_of(work,
struct ntb_transport_qp,
link_cleanup);
struct ntb_transport *nt = qp->transport;

ntb_qp_link_cleanup(qp);

if (nt->transport_link == NTB_LINK_UP)
schedule_delayed_work(&qp->link_work,
Expand All @@ -613,22 +620,20 @@ static void ntb_qp_link_down(struct ntb_transport_qp *qp)
schedule_work(&qp->link_cleanup);
}

static void ntb_transport_link_cleanup(struct work_struct *work)
static void ntb_transport_link_cleanup(struct ntb_transport *nt)
{
struct ntb_transport *nt = container_of(work, struct ntb_transport,
link_cleanup);
int i;

/* Pass along the info to any clients */
for (i = 0; i < nt->max_qps; i++)
if (!test_bit(i, &nt->qp_bitmap))
ntb_qp_link_cleanup(&nt->qps[i]);

if (nt->transport_link == NTB_LINK_DOWN)
cancel_delayed_work_sync(&nt->link_work);
else
nt->transport_link = NTB_LINK_DOWN;

/* Pass along the info to any clients */
for (i = 0; i < nt->max_qps; i++)
if (!test_bit(i, &nt->qp_bitmap))
ntb_qp_link_down(&nt->qps[i]);

/* The scratchpad registers keep the values if the remote side
* goes down, blast them now to give them a sane value the next
* time they are accessed
Expand All @@ -637,6 +642,14 @@ static void ntb_transport_link_cleanup(struct work_struct *work)
ntb_write_local_spad(nt->ndev, i, 0);
}

static void ntb_transport_link_cleanup_work(struct work_struct *work)
{
struct ntb_transport *nt = container_of(work, struct ntb_transport,
link_cleanup);

ntb_transport_link_cleanup(nt);
}

static void ntb_transport_event_callback(void *data, enum ntb_hw_event event)
{
struct ntb_transport *nt = data;
Expand Down Expand Up @@ -880,7 +893,7 @@ static int ntb_transport_init_queue(struct ntb_transport *nt,
}

INIT_DELAYED_WORK(&qp->link_work, ntb_qp_link_work);
INIT_WORK(&qp->link_cleanup, ntb_qp_link_cleanup);
INIT_WORK(&qp->link_cleanup, ntb_qp_link_cleanup_work);

spin_lock_init(&qp->ntb_rx_pend_q_lock);
spin_lock_init(&qp->ntb_rx_free_q_lock);
Expand Down Expand Up @@ -936,7 +949,7 @@ int ntb_transport_init(struct pci_dev *pdev)
}

INIT_DELAYED_WORK(&nt->link_work, ntb_transport_link_work);
INIT_WORK(&nt->link_cleanup, ntb_transport_link_cleanup);
INIT_WORK(&nt->link_cleanup, ntb_transport_link_cleanup_work);

rc = ntb_register_event_callback(nt->ndev,
ntb_transport_event_callback);
Expand Down Expand Up @@ -972,7 +985,7 @@ void ntb_transport_free(void *transport)
struct ntb_device *ndev = nt->ndev;
int i;

nt->transport_link = NTB_LINK_DOWN;
ntb_transport_link_cleanup(nt);

/* verify that all the qp's are freed */
for (i = 0; i < nt->max_qps; i++) {
Expand Down

0 comments on commit fca4d51

Please sign in to comment.