Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ded0e250 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'ntb-4.3' of git://github.com/jonmason/ntb

Pull NTB fixes from Jon Mason:
 "NTB bug and documentation fixes, new device IDs, performance
  improvements, and adding a mailing list to MAINTAINERS for NTB"

* tag 'ntb-4.3' of git://github.com/jonmason/ntb:
  NTB: Fix range check on memory window index
  NTB: Improve index handling in B2B MW workaround
  NTB: Fix documentation for ntb_peer_db_clear.
  NTB: Fix documentation for ntb_link_is_up
  NTB: Use unique DMA channels for TX and RX
  NTB: Remove dma_sync_wait from ntb_async_rx
  NTB: Clean up QP stats info
  NTB: Make the transport list in order of discovery
  NTB: Add PCI Device IDs for Broadwell Xeon
  NTB: Add flow control to the ntb_netdev
  NTB: Add list to MAINTAINERS
parents f0c032d8 9a07826f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -7396,6 +7396,7 @@ NTB DRIVER CORE
M:	Jon Mason <jdmason@kudzu.us>
M:	Dave Jiang <dave.jiang@intel.com>
M:	Allen Hubbe <Allen.Hubbe@emc.com>
L:	linux-ntb@googlegroups.com
S:	Supported
W:	https://github.com/jonmason/ntb/wiki
T:	git git://github.com/jonmason/ntb.git
@@ -7407,6 +7408,7 @@ F: include/linux/ntb_transport.h
NTB INTEL DRIVER
M:	Jon Mason <jdmason@kudzu.us>
M:	Dave Jiang <dave.jiang@intel.com>
L:	linux-ntb@googlegroups.com
S:	Supported
W:	https://github.com/jonmason/ntb/wiki
T:	git git://github.com/jonmason/ntb.git
+77 −0
Original line number Diff line number Diff line
@@ -61,11 +61,21 @@ MODULE_VERSION(NTB_NETDEV_VER);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Intel Corporation");

/* Time in usecs for tx resource reaper */
static unsigned int tx_time = 1;

/* Number of descriptors to free before resuming tx */
static unsigned int tx_start = 10;

/* Number of descriptors still available before stop upper layer tx */
static unsigned int tx_stop = 5;

struct ntb_netdev {
	struct list_head list;
	struct pci_dev *pdev;
	struct net_device *ndev;
	struct ntb_transport_qp *qp;
	struct timer_list tx_timer;
};

#define	NTB_TX_TIMEOUT_MS	1000
@@ -136,11 +146,42 @@ static void ntb_netdev_rx_handler(struct ntb_transport_qp *qp, void *qp_data,
	}
}

static int __ntb_netdev_maybe_stop_tx(struct net_device *netdev,
				      struct ntb_transport_qp *qp, int size)
{
	struct ntb_netdev *dev = netdev_priv(netdev);

	netif_stop_queue(netdev);
	/* Make sure to see the latest value of ntb_transport_tx_free_entry()
	 * since the queue was last started.
	 */
	smp_mb();

	if (likely(ntb_transport_tx_free_entry(qp) < size)) {
		mod_timer(&dev->tx_timer, jiffies + usecs_to_jiffies(tx_time));
		return -EBUSY;
	}

	netif_start_queue(netdev);
	return 0;
}

static int ntb_netdev_maybe_stop_tx(struct net_device *ndev,
				    struct ntb_transport_qp *qp, int size)
{
	if (netif_queue_stopped(ndev) ||
	    (ntb_transport_tx_free_entry(qp) >= size))
		return 0;

	return __ntb_netdev_maybe_stop_tx(ndev, qp, size);
}

static void ntb_netdev_tx_handler(struct ntb_transport_qp *qp, void *qp_data,
				  void *data, int len)
{
	struct net_device *ndev = qp_data;
	struct sk_buff *skb;
	struct ntb_netdev *dev = netdev_priv(ndev);

	skb = data;
	if (!skb || !ndev)
@@ -155,6 +196,15 @@ static void ntb_netdev_tx_handler(struct ntb_transport_qp *qp, void *qp_data,
	}

	dev_kfree_skb(skb);

	if (ntb_transport_tx_free_entry(dev->qp) >= tx_start) {
		/* Make sure anybody stopping the queue after this sees the new
		 * value of ntb_transport_tx_free_entry()
		 */
		smp_mb();
		if (netif_queue_stopped(ndev))
			netif_wake_queue(ndev);
	}
}

static netdev_tx_t ntb_netdev_start_xmit(struct sk_buff *skb,
@@ -163,10 +213,15 @@ static netdev_tx_t ntb_netdev_start_xmit(struct sk_buff *skb,
	struct ntb_netdev *dev = netdev_priv(ndev);
	int rc;

	ntb_netdev_maybe_stop_tx(ndev, dev->qp, tx_stop);

	rc = ntb_transport_tx_enqueue(dev->qp, skb, skb->data, skb->len);
	if (rc)
		goto err;

	/* check for next submit */
	ntb_netdev_maybe_stop_tx(ndev, dev->qp, tx_stop);

	return NETDEV_TX_OK;

err:
@@ -175,6 +230,23 @@ static netdev_tx_t ntb_netdev_start_xmit(struct sk_buff *skb,
	return NETDEV_TX_BUSY;
}

static void ntb_netdev_tx_timer(unsigned long data)
{
	struct net_device *ndev = (struct net_device *)data;
	struct ntb_netdev *dev = netdev_priv(ndev);

	if (ntb_transport_tx_free_entry(dev->qp) < tx_stop) {
		mod_timer(&dev->tx_timer, jiffies + msecs_to_jiffies(tx_time));
	} else {
		/* Make sure anybody stopping the queue after this sees the new
		 * value of ntb_transport_tx_free_entry()
		 */
		smp_mb();
		if (netif_queue_stopped(ndev))
			netif_wake_queue(ndev);
	}
}

static int ntb_netdev_open(struct net_device *ndev)
{
	struct ntb_netdev *dev = netdev_priv(ndev);
@@ -197,8 +269,11 @@ static int ntb_netdev_open(struct net_device *ndev)
		}
	}

	setup_timer(&dev->tx_timer, ntb_netdev_tx_timer, (unsigned long)ndev);

	netif_carrier_off(ndev);
	ntb_transport_link_up(dev->qp);
	netif_start_queue(ndev);

	return 0;

@@ -219,6 +294,8 @@ static int ntb_netdev_close(struct net_device *ndev)
	while ((skb = ntb_transport_rx_remove(dev->qp, &len)))
		dev_kfree_skb(skb);

	del_timer_sync(&dev->tx_timer);

	return 0;
}

+32 −7
Original line number Diff line number Diff line
@@ -190,14 +190,17 @@ static inline int pdev_is_xeon(struct pci_dev *pdev)
	case PCI_DEVICE_ID_INTEL_NTB_SS_SNB:
	case PCI_DEVICE_ID_INTEL_NTB_SS_IVT:
	case PCI_DEVICE_ID_INTEL_NTB_SS_HSX:
	case PCI_DEVICE_ID_INTEL_NTB_SS_BDX:
	case PCI_DEVICE_ID_INTEL_NTB_PS_JSF:
	case PCI_DEVICE_ID_INTEL_NTB_PS_SNB:
	case PCI_DEVICE_ID_INTEL_NTB_PS_IVT:
	case PCI_DEVICE_ID_INTEL_NTB_PS_HSX:
	case PCI_DEVICE_ID_INTEL_NTB_PS_BDX:
	case PCI_DEVICE_ID_INTEL_NTB_B2B_JSF:
	case PCI_DEVICE_ID_INTEL_NTB_B2B_SNB:
	case PCI_DEVICE_ID_INTEL_NTB_B2B_IVT:
	case PCI_DEVICE_ID_INTEL_NTB_B2B_HSX:
	case PCI_DEVICE_ID_INTEL_NTB_B2B_BDX:
		return 1;
	}
	return 0;
@@ -237,7 +240,7 @@ static inline int ndev_ignore_unsafe(struct intel_ntb_dev *ndev,

static int ndev_mw_to_bar(struct intel_ntb_dev *ndev, int idx)
{
	if (idx < 0 || idx > ndev->mw_count)
	if (idx < 0 || idx >= ndev->mw_count)
		return -EINVAL;
	return ndev->reg->mw_bar[idx];
}
@@ -572,10 +575,13 @@ static ssize_t ndev_debugfs_read(struct file *filp, char __user *ubuf,
			 "Connection Topology -\t%s\n",
			 ntb_topo_string(ndev->ntb.topo));

	if (ndev->b2b_idx != UINT_MAX) {
		off += scnprintf(buf + off, buf_size - off,
			 "B2B Offset -\t\t%#lx\n", ndev->b2b_off);
				 "B2B MW Idx -\t\t%u\n", ndev->b2b_idx);
		off += scnprintf(buf + off, buf_size - off,
			 "B2B MW Idx -\t\t%d\n", ndev->b2b_idx);
				 "B2B Offset -\t\t%#lx\n", ndev->b2b_off);
	}

	off += scnprintf(buf + off, buf_size - off,
			 "BAR4 Split -\t\t%s\n",
			 ndev->bar4_split ? "yes" : "no");
@@ -1484,7 +1490,7 @@ static int xeon_setup_b2b_mw(struct intel_ntb_dev *ndev,
	pdev = ndev_pdev(ndev);
	mmio = ndev->self_mmio;

	if (ndev->b2b_idx >= ndev->mw_count) {
	if (ndev->b2b_idx == UINT_MAX) {
		dev_dbg(ndev_dev(ndev), "not using b2b mw\n");
		b2b_bar = 0;
		ndev->b2b_off = 0;
@@ -1776,6 +1782,13 @@ static int xeon_init_ntb(struct intel_ntb_dev *ndev)
			else
				ndev->b2b_idx = b2b_mw_idx;

			if (ndev->b2b_idx >= ndev->mw_count) {
				dev_dbg(ndev_dev(ndev),
					"b2b_mw_idx %d invalid for mw_count %u\n",
					b2b_mw_idx, ndev->mw_count);
				return -EINVAL;
			}

			dev_dbg(ndev_dev(ndev),
				"setting up b2b mw idx %d means %d\n",
				b2b_mw_idx, ndev->b2b_idx);
@@ -1843,6 +1856,9 @@ static int xeon_init_dev(struct intel_ntb_dev *ndev)
	case PCI_DEVICE_ID_INTEL_NTB_SS_HSX:
	case PCI_DEVICE_ID_INTEL_NTB_PS_HSX:
	case PCI_DEVICE_ID_INTEL_NTB_B2B_HSX:
	case PCI_DEVICE_ID_INTEL_NTB_SS_BDX:
	case PCI_DEVICE_ID_INTEL_NTB_PS_BDX:
	case PCI_DEVICE_ID_INTEL_NTB_B2B_BDX:
		ndev->hwerr_flags |= NTB_HWERR_SDOORBELL_LOCKUP;
		break;
	}
@@ -1857,6 +1873,9 @@ static int xeon_init_dev(struct intel_ntb_dev *ndev)
	case PCI_DEVICE_ID_INTEL_NTB_SS_HSX:
	case PCI_DEVICE_ID_INTEL_NTB_PS_HSX:
	case PCI_DEVICE_ID_INTEL_NTB_B2B_HSX:
	case PCI_DEVICE_ID_INTEL_NTB_SS_BDX:
	case PCI_DEVICE_ID_INTEL_NTB_PS_BDX:
	case PCI_DEVICE_ID_INTEL_NTB_B2B_BDX:
		ndev->hwerr_flags |= NTB_HWERR_SB01BASE_LOCKUP;
		break;
	}
@@ -1878,6 +1897,9 @@ static int xeon_init_dev(struct intel_ntb_dev *ndev)
	case PCI_DEVICE_ID_INTEL_NTB_SS_HSX:
	case PCI_DEVICE_ID_INTEL_NTB_PS_HSX:
	case PCI_DEVICE_ID_INTEL_NTB_B2B_HSX:
	case PCI_DEVICE_ID_INTEL_NTB_SS_BDX:
	case PCI_DEVICE_ID_INTEL_NTB_PS_BDX:
	case PCI_DEVICE_ID_INTEL_NTB_B2B_BDX:
		ndev->hwerr_flags |= NTB_HWERR_B2BDOORBELL_BIT14;
		break;
	}
@@ -1996,7 +2018,7 @@ static inline void ndev_init_struct(struct intel_ntb_dev *ndev,
	ndev->ntb.ops = &intel_ntb_ops;

	ndev->b2b_off = 0;
	ndev->b2b_idx = INT_MAX;
	ndev->b2b_idx = UINT_MAX;

	ndev->bar4_split = 0;

@@ -2234,14 +2256,17 @@ static const struct pci_device_id intel_ntb_pci_tbl[] = {
	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_B2B_SNB)},
	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_B2B_IVT)},
	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_B2B_HSX)},
	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_B2B_BDX)},
	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_PS_JSF)},
	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_PS_SNB)},
	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_PS_IVT)},
	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_PS_HSX)},
	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_PS_BDX)},
	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_SS_JSF)},
	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_SS_SNB)},
	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_SS_IVT)},
	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_SS_HSX)},
	{PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_NTB_SS_BDX)},
	{0}
};
MODULE_DEVICE_TABLE(pci, intel_ntb_pci_tbl);
+3 −0
Original line number Diff line number Diff line
@@ -67,6 +67,9 @@
#define PCI_DEVICE_ID_INTEL_NTB_PS_HSX	0x2F0E
#define PCI_DEVICE_ID_INTEL_NTB_SS_HSX	0x2F0F
#define PCI_DEVICE_ID_INTEL_NTB_B2B_BWD	0x0C4E
#define PCI_DEVICE_ID_INTEL_NTB_B2B_BDX	0x6F0D
#define PCI_DEVICE_ID_INTEL_NTB_PS_BDX	0x6F0E
#define PCI_DEVICE_ID_INTEL_NTB_SS_BDX	0x6F0F

/* Intel Xeon hardware */

+91 −35
Original line number Diff line number Diff line
@@ -119,7 +119,8 @@ struct ntb_transport_qp {
	struct ntb_transport_ctx *transport;
	struct ntb_dev *ndev;
	void *cb_data;
	struct dma_chan *dma_chan;
	struct dma_chan *tx_dma_chan;
	struct dma_chan *rx_dma_chan;

	bool client_ready;
	bool link_is_up;
@@ -297,7 +298,7 @@ static LIST_HEAD(ntb_transport_list);

static int ntb_bus_init(struct ntb_transport_ctx *nt)
{
	list_add(&nt->entry, &ntb_transport_list);
	list_add_tail(&nt->entry, &ntb_transport_list);
	return 0;
}

@@ -452,7 +453,7 @@ static ssize_t debugfs_read(struct file *filp, char __user *ubuf, size_t count,

	out_offset = 0;
	out_offset += snprintf(buf + out_offset, out_count - out_offset,
			       "NTB QP stats\n");
			       "\nNTB QP stats:\n\n");
	out_offset += snprintf(buf + out_offset, out_count - out_offset,
			       "rx_bytes - \t%llu\n", qp->rx_bytes);
	out_offset += snprintf(buf + out_offset, out_count - out_offset,
@@ -470,11 +471,11 @@ static ssize_t debugfs_read(struct file *filp, char __user *ubuf, size_t count,
	out_offset += snprintf(buf + out_offset, out_count - out_offset,
			       "rx_err_ver - \t%llu\n", qp->rx_err_ver);
	out_offset += snprintf(buf + out_offset, out_count - out_offset,
			       "rx_buff - \t%p\n", qp->rx_buff);
			       "rx_buff - \t0x%p\n", qp->rx_buff);
	out_offset += snprintf(buf + out_offset, out_count - out_offset,
			       "rx_index - \t%u\n", qp->rx_index);
	out_offset += snprintf(buf + out_offset, out_count - out_offset,
			       "rx_max_entry - \t%u\n", qp->rx_max_entry);
			       "rx_max_entry - \t%u\n\n", qp->rx_max_entry);

	out_offset += snprintf(buf + out_offset, out_count - out_offset,
			       "tx_bytes - \t%llu\n", qp->tx_bytes);
@@ -489,15 +490,32 @@ static ssize_t debugfs_read(struct file *filp, char __user *ubuf, size_t count,
	out_offset += snprintf(buf + out_offset, out_count - out_offset,
			       "tx_err_no_buf - %llu\n", qp->tx_err_no_buf);
	out_offset += snprintf(buf + out_offset, out_count - out_offset,
			       "tx_mw - \t%p\n", qp->tx_mw);
			       "tx_mw - \t0x%p\n", qp->tx_mw);
	out_offset += snprintf(buf + out_offset, out_count - out_offset,
			       "tx_index - \t%u\n", qp->tx_index);
			       "tx_index (H) - \t%u\n", qp->tx_index);
	out_offset += snprintf(buf + out_offset, out_count - out_offset,
			       "RRI (T) - \t%u\n",
			       qp->remote_rx_info->entry);
	out_offset += snprintf(buf + out_offset, out_count - out_offset,
			       "tx_max_entry - \t%u\n", qp->tx_max_entry);
	out_offset += snprintf(buf + out_offset, out_count - out_offset,
			       "free tx - \t%u\n",
			       ntb_transport_tx_free_entry(qp));

	out_offset += snprintf(buf + out_offset, out_count - out_offset,
			       "\nQP Link %s\n",
			       "\n");
	out_offset += snprintf(buf + out_offset, out_count - out_offset,
			       "Using TX DMA - \t%s\n",
			       qp->tx_dma_chan ? "Yes" : "No");
	out_offset += snprintf(buf + out_offset, out_count - out_offset,
			       "Using RX DMA - \t%s\n",
			       qp->rx_dma_chan ? "Yes" : "No");
	out_offset += snprintf(buf + out_offset, out_count - out_offset,
			       "QP Link - \t%s\n",
			       qp->link_is_up ? "Up" : "Down");
	out_offset += snprintf(buf + out_offset, out_count - out_offset,
			       "\n");

	if (out_offset > out_count)
		out_offset = out_count;

@@ -535,6 +553,7 @@ static struct ntb_queue_entry *ntb_list_rm(spinlock_t *lock,
	}
	entry = list_first_entry(list, struct ntb_queue_entry, entry);
	list_del(&entry->entry);

out:
	spin_unlock_irqrestore(lock, flags);

@@ -1206,7 +1225,7 @@ static void ntb_async_rx(struct ntb_queue_entry *entry, void *offset)
{
	struct dma_async_tx_descriptor *txd;
	struct ntb_transport_qp *qp = entry->qp;
	struct dma_chan *chan = qp->dma_chan;
	struct dma_chan *chan = qp->rx_dma_chan;
	struct dma_device *device;
	size_t pay_off, buff_off, len;
	struct dmaengine_unmap_data *unmap;
@@ -1219,18 +1238,18 @@ static void ntb_async_rx(struct ntb_queue_entry *entry, void *offset)
		goto err;

	if (len < copy_bytes)
		goto err_wait;
		goto err;

	device = chan->device;
	pay_off = (size_t)offset & ~PAGE_MASK;
	buff_off = (size_t)buf & ~PAGE_MASK;

	if (!is_dma_copy_aligned(device, pay_off, buff_off, len))
		goto err_wait;
		goto err;

	unmap = dmaengine_get_unmap_data(device->dev, 2, GFP_NOWAIT);
	if (!unmap)
		goto err_wait;
		goto err;

	unmap->len = len;
	unmap->addr[0] = dma_map_page(device->dev, virt_to_page(offset),
@@ -1273,12 +1292,6 @@ static void ntb_async_rx(struct ntb_queue_entry *entry, void *offset)
	dmaengine_unmap_put(unmap);
err_get_unmap:
	dmaengine_unmap_put(unmap);
err_wait:
	/* If the callbacks come out of order, the writing of the index to the
	 * last completed will be out of order.  This may result in the
	 * receive stalling forever.
	 */
	dma_sync_wait(chan, qp->last_cookie);
err:
	ntb_memcpy_rx(entry, offset);
	qp->rx_memcpy++;
@@ -1373,8 +1386,8 @@ static void ntb_transport_rxc_db(unsigned long data)
			break;
	}

	if (i && qp->dma_chan)
		dma_async_issue_pending(qp->dma_chan);
	if (i && qp->rx_dma_chan)
		dma_async_issue_pending(qp->rx_dma_chan);

	if (i == qp->rx_max_entry) {
		/* there is more work to do */
@@ -1441,7 +1454,7 @@ static void ntb_async_tx(struct ntb_transport_qp *qp,
{
	struct ntb_payload_header __iomem *hdr;
	struct dma_async_tx_descriptor *txd;
	struct dma_chan *chan = qp->dma_chan;
	struct dma_chan *chan = qp->tx_dma_chan;
	struct dma_device *device;
	size_t dest_off, buff_off;
	struct dmaengine_unmap_data *unmap;
@@ -1634,14 +1647,27 @@ ntb_transport_create_queue(void *data, struct device *client_dev,
	dma_cap_set(DMA_MEMCPY, dma_mask);

	if (use_dma) {
		qp->dma_chan = dma_request_channel(dma_mask, ntb_dma_filter_fn,
		qp->tx_dma_chan =
			dma_request_channel(dma_mask, ntb_dma_filter_fn,
					    (void *)(unsigned long)node);
		if (!qp->dma_chan)
			dev_info(&pdev->dev, "Unable to allocate DMA channel\n");
		if (!qp->tx_dma_chan)
			dev_info(&pdev->dev, "Unable to allocate TX DMA channel\n");

		qp->rx_dma_chan =
			dma_request_channel(dma_mask, ntb_dma_filter_fn,
					    (void *)(unsigned long)node);
		if (!qp->rx_dma_chan)
			dev_info(&pdev->dev, "Unable to allocate RX DMA channel\n");
	} else {
		qp->dma_chan = NULL;
		qp->tx_dma_chan = NULL;
		qp->rx_dma_chan = NULL;
	}
	dev_dbg(&pdev->dev, "Using %s memcpy\n", qp->dma_chan ? "DMA" : "CPU");

	dev_dbg(&pdev->dev, "Using %s memcpy for TX\n",
		qp->tx_dma_chan ? "DMA" : "CPU");

	dev_dbg(&pdev->dev, "Using %s memcpy for RX\n",
		qp->rx_dma_chan ? "DMA" : "CPU");

	for (i = 0; i < NTB_QP_DEF_NUM_ENTRIES; i++) {
		entry = kzalloc_node(sizeof(*entry), GFP_ATOMIC, node);
@@ -1676,8 +1702,10 @@ ntb_transport_create_queue(void *data, struct device *client_dev,
err1:
	while ((entry = ntb_list_rm(&qp->ntb_rx_q_lock, &qp->rx_free_q)))
		kfree(entry);
	if (qp->dma_chan)
		dma_release_channel(qp->dma_chan);
	if (qp->tx_dma_chan)
		dma_release_channel(qp->tx_dma_chan);
	if (qp->rx_dma_chan)
		dma_release_channel(qp->rx_dma_chan);
	nt->qp_bitmap_free |= qp_bit;
err:
	return NULL;
@@ -1701,12 +1729,27 @@ void ntb_transport_free_queue(struct ntb_transport_qp *qp)

	pdev = qp->ndev->pdev;

	if (qp->dma_chan) {
		struct dma_chan *chan = qp->dma_chan;
	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
		 * processed by the CPU instead of the DAM engine
		 */
		qp->dma_chan = NULL;
		qp->tx_dma_chan = NULL;

		/* Try to be nice and wait for any queued DMA engine
		 * transactions to process before smashing it with a rock
		 */
		dma_sync_wait(chan, qp->last_cookie);
		dmaengine_terminate_all(chan);
		dma_release_channel(chan);
	}

	if (qp->rx_dma_chan) {
		struct dma_chan *chan = qp->rx_dma_chan;
		/* Putting the dma_chan to NULL will force any new traffic to be
		 * processed by the CPU instead of the DAM engine
		 */
		qp->rx_dma_chan = NULL;

		/* Try to be nice and wait for any queued DMA engine
		 * transactions to process before smashing it with a rock
@@ -1843,7 +1886,7 @@ int ntb_transport_tx_enqueue(struct ntb_transport_qp *qp, void *cb, void *data,
	entry = ntb_list_rm(&qp->ntb_tx_free_q_lock, &qp->tx_free_q);
	if (!entry) {
		qp->tx_err_no_buf++;
		return -ENOMEM;
		return -EBUSY;
	}

	entry->cb_data = cb;
@@ -1954,21 +1997,34 @@ EXPORT_SYMBOL_GPL(ntb_transport_qp_num);
unsigned int ntb_transport_max_size(struct ntb_transport_qp *qp)
{
	unsigned int max;
	unsigned int copy_align;

	if (!qp)
		return 0;

	if (!qp->dma_chan)
	if (!qp->tx_dma_chan && !qp->rx_dma_chan)
		return qp->tx_max_frame - sizeof(struct ntb_payload_header);

	copy_align = max(qp->tx_dma_chan->device->copy_align,
			 qp->rx_dma_chan->device->copy_align);

	/* If DMA engine usage is possible, try to find the max size for that */
	max = qp->tx_max_frame - sizeof(struct ntb_payload_header);
	max -= max % (1 << qp->dma_chan->device->copy_align);
	max -= max % (1 << copy_align);

	return max;
}
EXPORT_SYMBOL_GPL(ntb_transport_max_size);

unsigned int ntb_transport_tx_free_entry(struct ntb_transport_qp *qp)
{
	unsigned int head = qp->tx_index;
	unsigned int tail = qp->remote_rx_info->entry;

	return tail > head ? tail - head : qp->tx_max_entry + tail - head;
}
EXPORT_SYMBOL_GPL(ntb_transport_tx_free_entry);

static void ntb_transport_doorbell_callback(void *data, int vector)
{
	struct ntb_transport_ctx *nt = data;
Loading