From d635711daa98be86d4c7fd01499c34f566b54ccb Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Fri, 10 Jun 2016 05:30:17 -0300 Subject: Linux-libre 4.6.2-gnu --- drivers/ntb/ntb_transport.c | 31 ++++++++++++++++++------ drivers/ntb/test/ntb_perf.c | 57 ++++++++++++++++++++++++++++----------------- 2 files changed, 60 insertions(+), 28 deletions(-) (limited to 'drivers/ntb') diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c index ec4775f0e..2ef9d9130 100644 --- a/drivers/ntb/ntb_transport.c +++ b/drivers/ntb/ntb_transport.c @@ -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; @@ -827,7 +829,7 @@ static void ntb_transport_link_work(struct work_struct *work) struct pci_dev *pdev = ndev->pdev; resource_size_t size; u32 val; - int rc, i, spad; + int rc = 0, i, spad; /* send the local info, in the opposite order of the way we read it */ for (i = 0; i < nt->mw_count; i++) { @@ -897,6 +899,13 @@ static void ntb_transport_link_work(struct work_struct *work) out1: for (i = 0; i < nt->mw_count; i++) ntb_free_mw(nt, i); + + /* if there's an actual failure, we should just bail */ + if (rc < 0) { + ntb_link_disable(ndev); + return; + } + out: if (ntb_link_is_up(ndev, NULL, NULL) == 1) schedule_delayed_work(&nt->link_work, @@ -926,11 +935,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 +1422,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 +1434,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 +1773,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 +1808,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 +1901,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 +2085,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); } diff --git a/drivers/ntb/test/ntb_perf.c b/drivers/ntb/test/ntb_perf.c index 6bdc1e7b7..8dfce9c9a 100644 --- a/drivers/ntb/test/ntb_perf.c +++ b/drivers/ntb/test/ntb_perf.c @@ -425,6 +425,7 @@ static int perf_set_mw(struct perf_ctx *perf, resource_size_t size) { struct perf_mw *mw = &perf->mw; size_t xlat_size, buf_size; + int rc; if (!size) return -EINVAL; @@ -448,6 +449,13 @@ static int perf_set_mw(struct perf_ctx *perf, resource_size_t size) mw->buf_size = 0; } + rc = ntb_mw_set_trans(perf->ntb, 0, mw->dma_addr, mw->xlat_size); + if (rc) { + dev_err(&perf->ntb->dev, "Unable to set mw0 translation\n"); + perf_free_mw(perf); + return -EIO; + } + return 0; } @@ -542,6 +550,8 @@ static ssize_t debugfs_run_read(struct file *filp, char __user *ubuf, return 0; buf = kmalloc(64, GFP_KERNEL); + if (!buf) + return -ENOMEM; out_offset = snprintf(buf, 64, "%d\n", perf->run); ret = simple_read_from_buffer(ubuf, count, offp, buf, out_offset); kfree(buf); @@ -549,6 +559,21 @@ static ssize_t debugfs_run_read(struct file *filp, char __user *ubuf, return ret; } +static void threads_cleanup(struct perf_ctx *perf) +{ + struct pthr_ctx *pctx; + int i; + + perf->run = false; + for (i = 0; i < MAX_THREADS; i++) { + pctx = &perf->pthr_ctx[i]; + if (pctx->thread) { + kthread_stop(pctx->thread); + pctx->thread = NULL; + } + } +} + static ssize_t debugfs_run_write(struct file *filp, const char __user *ubuf, size_t count, loff_t *offp) { @@ -564,17 +589,9 @@ static ssize_t debugfs_run_write(struct file *filp, const char __user *ubuf, if (atomic_read(&perf->tsync) == 0) perf->run = false; - if (perf->run) { - /* lets stop the threads */ - perf->run = false; - for (i = 0; i < MAX_THREADS; i++) { - if (perf->pthr_ctx[i].thread) { - kthread_stop(perf->pthr_ctx[i].thread); - perf->pthr_ctx[i].thread = NULL; - } else - break; - } - } else { + if (perf->run) + threads_cleanup(perf); + else { perf->run = true; if (perf->perf_threads > MAX_THREADS) { @@ -605,17 +622,11 @@ static ssize_t debugfs_run_write(struct file *filp, const char __user *ubuf, kthread_create_on_node(ntb_perf_thread, (void *)pctx, node, "ntb_perf %d", i); - if (pctx->thread) + if (IS_ERR(pctx->thread)) { + pctx->thread = NULL; + goto err; + } else wake_up_process(pctx->thread); - else { - perf->run = false; - for (i = 0; i < MAX_THREADS; i++) { - if (pctx->thread) { - kthread_stop(pctx->thread); - pctx->thread = NULL; - } - } - } if (perf->run == false) return -ENXIO; @@ -624,6 +635,10 @@ static ssize_t debugfs_run_write(struct file *filp, const char __user *ubuf, } return count; + +err: + threads_cleanup(perf); + return -ENXIO; } static const struct file_operations ntb_perf_debugfs_run = { -- cgit v1.2.3-54-g00ecf