From patchwork Mon Jun 27 23:09:56 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Jiang X-Patchwork-Id: 9201525 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 0E67D6075F for ; Mon, 27 Jun 2016 23:10:39 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F3096285CA for ; Mon, 27 Jun 2016 23:10:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E66BC285CD; Mon, 27 Jun 2016 23:10:38 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 52A41285CA for ; Mon, 27 Jun 2016 23:10:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751888AbcF0XKh (ORCPT ); Mon, 27 Jun 2016 19:10:37 -0400 Received: from mga14.intel.com ([192.55.52.115]:3581 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752050AbcF0XKh (ORCPT ); Mon, 27 Jun 2016 19:10:37 -0400 Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga103.fm.intel.com with ESMTP; 27 Jun 2016 16:10:17 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.26,538,1459839600"; d="scan'208";a="129533573" Received: from djiang5-desk3.ch.intel.com ([143.182.137.38]) by fmsmga004.fm.intel.com with ESMTP; 27 Jun 2016 16:10:15 -0700 Subject: [PATCH 4/5] ntb: add DMA error handling for TX DMA From: Dave Jiang To: vinod.koul@intel.com, allen.hubbe@emc.mail.wl.linuxfoundation.org, jdmason@kudzu.us Cc: dmaengine@vger.kernel.org, linux-ntb@googlegroups.com Date: Mon, 27 Jun 2016 16:09:56 -0700 Message-ID: <146706899641.188649.16969346461413257840.stgit@djiang5-desk3.ch.intel.com> In-Reply-To: <146706860557.188649.10766278554335496632.stgit@djiang5-desk3.ch.intel.com> References: <146706860557.188649.10766278554335496632.stgit@djiang5-desk3.ch.intel.com> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Sender: dmaengine-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: dmaengine@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Adding support on the tx DMA path to allow recovery of errors when DMA responds with error status and abort all the subsequent ops. Signed-off-by: Dave Jiang --- drivers/ntb/ntb_transport.c | 123 +++++++++++++++++++++++++++++++------------ 1 file changed, 89 insertions(+), 34 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe dmaengine" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c index 2ef9d913..55a5ae0 100644 --- a/drivers/ntb/ntb_transport.c +++ b/drivers/ntb/ntb_transport.c @@ -102,6 +102,10 @@ struct ntb_queue_entry { void *buf; unsigned int len; unsigned int flags; + struct dma_async_tx_descriptor *txd; + int retries; + int errors; + unsigned int tx_index; struct ntb_transport_qp *qp; union { @@ -258,6 +262,9 @@ enum { static void ntb_transport_rxc_db(unsigned long data); static const struct ntb_ctx_ops ntb_transport_ops; static struct ntb_client ntb_transport_client; +static int ntb_async_tx_submit(struct ntb_transport_qp *qp, + struct ntb_queue_entry *entry); +static void ntb_memcpy_tx(struct ntb_queue_entry *entry, void __iomem *offset); static int ntb_transport_bus_match(struct device *dev, struct device_driver *drv) @@ -1444,21 +1451,46 @@ static void ntb_tx_copy_callback(void *data) struct ntb_queue_entry *entry = data; struct ntb_transport_qp *qp = entry->qp; struct ntb_payload_header __iomem *hdr = entry->tx_hdr; + struct dma_async_tx_descriptor *txd; + unsigned int len; + bool abort = false; + + txd = entry->txd; + + /* we need to check DMA results if we are using DMA */ + if (txd) { + switch (txd->result) { + case ERR_DMA_READ: + case ERR_DMA_WRITE: + entry->errors++; + case ERR_DMA_ABORT: + abort = true; + goto handle_tx; + case ERR_DMA_NONE: + default: + break; + } + } iowrite32(entry->flags | DESC_DONE_FLAG, &hdr->flags); ntb_peer_db_set(qp->ndev, BIT_ULL(qp->qp_num)); +handle_tx: + /* The entry length can only be zero if the packet is intended to be a * "link down" or similar. Since no payload is being sent in these * cases, there is nothing to add to the completion queue. */ if (entry->len > 0) { - qp->tx_bytes += entry->len; + if (!abort) { + qp->tx_bytes += entry->len; + len = entry->len; + } else + len = 0; if (qp->tx_handler) - qp->tx_handler(qp, qp->cb_data, entry->cb_data, - entry->len); + qp->tx_handler(qp, qp->cb_data, entry->cb_data, len); } ntb_list_add(&qp->ntb_tx_free_q_lock, &entry->entry, &qp->tx_free_q); @@ -1482,37 +1514,21 @@ static void ntb_memcpy_tx(struct ntb_queue_entry *entry, void __iomem *offset) ntb_tx_copy_callback(entry); } -static void ntb_async_tx(struct ntb_transport_qp *qp, - struct ntb_queue_entry *entry) +static int ntb_async_tx_submit(struct ntb_transport_qp *qp, + struct ntb_queue_entry *entry) { - struct ntb_payload_header __iomem *hdr; - struct dma_async_tx_descriptor *txd; struct dma_chan *chan = qp->tx_dma_chan; struct dma_device *device; + size_t len = entry->len; + void *buf = entry->buf; size_t dest_off, buff_off; struct dmaengine_unmap_data *unmap; dma_addr_t dest; dma_cookie_t cookie; - void __iomem *offset; - size_t len = entry->len; - void *buf = entry->buf; int retries = 0; - offset = qp->tx_mw + qp->tx_max_frame * qp->tx_index; - hdr = offset + qp->tx_max_frame - sizeof(struct ntb_payload_header); - entry->tx_hdr = hdr; - - iowrite32(entry->len, &hdr->len); - iowrite32((u32)qp->tx_pkts, &hdr->ver); - - if (!chan) - goto err; - - if (len < copy_bytes) - goto err; - device = chan->device; - dest = qp->tx_mw_phys + qp->tx_max_frame * qp->tx_index; + dest = qp->tx_mw_phys + qp->tx_max_frame * entry->tx_index; buff_off = (size_t)buf & ~PAGE_MASK; dest_off = (size_t)dest & ~PAGE_MASK; @@ -1532,39 +1548,74 @@ static void ntb_async_tx(struct ntb_transport_qp *qp, unmap->to_cnt = 1; for (retries = 0; retries < DMA_RETRIES; retries++) { - txd = device->device_prep_dma_memcpy(chan, dest, unmap->addr[0], - len, DMA_PREP_INTERRUPT); - if (txd) + entry->txd = device->device_prep_dma_memcpy(chan, dest, + unmap->addr[0], len, + DMA_PREP_INTERRUPT); + if (entry->txd) break; set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(DMA_OUT_RESOURCE_TO); } - if (!txd) { + if (!entry->txd) { qp->dma_tx_prep_err++; goto err_get_unmap; } - txd->callback = ntb_tx_copy_callback; - txd->callback_param = entry; - dma_set_unmap(txd, unmap); + entry->txd->callback = ntb_tx_copy_callback; + entry->txd->callback_param = entry; + dma_set_unmap(entry->txd, unmap); - cookie = dmaengine_submit(txd); + cookie = dmaengine_submit(entry->txd); if (dma_submit_error(cookie)) goto err_set_unmap; dmaengine_unmap_put(unmap); dma_async_issue_pending(chan); - qp->tx_async++; - return; + return 0; err_set_unmap: dmaengine_unmap_put(unmap); err_get_unmap: dmaengine_unmap_put(unmap); err: + return -ENXIO; +} + +static void ntb_async_tx(struct ntb_transport_qp *qp, + struct ntb_queue_entry *entry) +{ + struct ntb_payload_header __iomem *hdr; + struct dma_chan *chan = qp->tx_dma_chan; + void __iomem *offset; + int res; + + entry->tx_index = qp->tx_index; + offset = qp->tx_mw + qp->tx_max_frame * entry->tx_index; + hdr = offset + qp->tx_max_frame - sizeof(struct ntb_payload_header); + entry->tx_hdr = hdr; + + iowrite32(entry->len, &hdr->len); + iowrite32((u32)qp->tx_pkts, &hdr->ver); + + if (!chan) + goto err; + + if (entry->len < copy_bytes) + goto err; + + res = ntb_async_tx_submit(qp, entry); + if (res < 0) + goto err; + + if (!entry->retries) + qp->tx_async++; + + return; + +err: ntb_memcpy_tx(entry, offset); qp->tx_memcpy++; } @@ -1940,6 +1991,10 @@ int ntb_transport_tx_enqueue(struct ntb_transport_qp *qp, void *cb, void *data, entry->buf = data; entry->len = len; entry->flags = 0; + entry->errors = 0; + entry->retries = 0; + entry->tx_index = 0; + entry->txd = NULL; rc = ntb_process_tx(qp, entry); if (rc)