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

Commit 73c38e67 authored by Thomas Fourier's avatar Thomas Fourier Committed by Greg Kroah-Hartman
Browse files

nui: Fix dma_mapping_error() check



[ Upstream commit 561aa0e22b70a5e7246b73d62a824b3aef3fc375 ]

dma_map_XXX() functions return values DMA_MAPPING_ERROR as error values
which is often ~0.  The error value should be tested with
dma_mapping_error().

This patch creates a new function in niu_ops to test if the mapping
failed.  The test is fixed in niu_rbr_add_page(), added in
niu_start_xmit() and the successfully mapped pages are unmaped upon error.

Fixes: ec2deec1 ("niu: Fix to check for dma mapping errors.")
Signed-off-by: default avatarThomas Fourier <fourier.thomas@gmail.com>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 32bc854b
Loading
Loading
Loading
Loading
+30 −1
Original line number Diff line number Diff line
@@ -3317,7 +3317,7 @@ static int niu_rbr_add_page(struct niu *np, struct rx_ring_info *rp,

	addr = np->ops->map_page(np->device, page, 0,
				 PAGE_SIZE, DMA_FROM_DEVICE);
	if (!addr) {
	if (np->ops->mapping_error(np->device, addr)) {
		__free_page(page);
		return -ENOMEM;
	}
@@ -6654,6 +6654,8 @@ static netdev_tx_t niu_start_xmit(struct sk_buff *skb,
	len = skb_headlen(skb);
	mapping = np->ops->map_single(np->device, skb->data,
				      len, DMA_TO_DEVICE);
	if (np->ops->mapping_error(np->device, mapping))
		goto out_drop;

	prod = rp->prod;

@@ -6695,6 +6697,8 @@ static netdev_tx_t niu_start_xmit(struct sk_buff *skb,
		mapping = np->ops->map_page(np->device, skb_frag_page(frag),
					    skb_frag_off(frag), len,
					    DMA_TO_DEVICE);
		if (np->ops->mapping_error(np->device, mapping))
			goto out_unmap;

		rp->tx_buffs[prod].skb = NULL;
		rp->tx_buffs[prod].mapping = mapping;
@@ -6719,6 +6723,19 @@ static netdev_tx_t niu_start_xmit(struct sk_buff *skb,
out:
	return NETDEV_TX_OK;

out_unmap:
	while (i--) {
		const skb_frag_t *frag;

		prod = PREVIOUS_TX(rp, prod);
		frag = &skb_shinfo(skb)->frags[i];
		np->ops->unmap_page(np->device, rp->tx_buffs[prod].mapping,
				    skb_frag_size(frag), DMA_TO_DEVICE);
	}

	np->ops->unmap_single(np->device, rp->tx_buffs[rp->prod].mapping,
			      skb_headlen(skb), DMA_TO_DEVICE);

out_drop:
	rp->tx_errors++;
	kfree_skb(skb);
@@ -9612,6 +9629,11 @@ static void niu_pci_unmap_single(struct device *dev, u64 dma_address,
	dma_unmap_single(dev, dma_address, size, direction);
}

static int niu_pci_mapping_error(struct device *dev, u64 addr)
{
	return dma_mapping_error(dev, addr);
}

static const struct niu_ops niu_pci_ops = {
	.alloc_coherent	= niu_pci_alloc_coherent,
	.free_coherent	= niu_pci_free_coherent,
@@ -9619,6 +9641,7 @@ static const struct niu_ops niu_pci_ops = {
	.unmap_page	= niu_pci_unmap_page,
	.map_single	= niu_pci_map_single,
	.unmap_single	= niu_pci_unmap_single,
	.mapping_error	= niu_pci_mapping_error,
};

static void niu_driver_version(void)
@@ -9996,6 +10019,11 @@ static void niu_phys_unmap_single(struct device *dev, u64 dma_address,
	/* Nothing to do.  */
}

static int niu_phys_mapping_error(struct device *dev, u64 dma_address)
{
	return false;
}

static const struct niu_ops niu_phys_ops = {
	.alloc_coherent	= niu_phys_alloc_coherent,
	.free_coherent	= niu_phys_free_coherent,
@@ -10003,6 +10031,7 @@ static const struct niu_ops niu_phys_ops = {
	.unmap_page	= niu_phys_unmap_page,
	.map_single	= niu_phys_map_single,
	.unmap_single	= niu_phys_unmap_single,
	.mapping_error	= niu_phys_mapping_error,
};

static int niu_of_probe(struct platform_device *op)
+4 −0
Original line number Diff line number Diff line
@@ -2879,6 +2879,9 @@ struct tx_ring_info {
#define NEXT_TX(tp, index) \
	(((index) + 1) < (tp)->pending ? ((index) + 1) : 0)

#define PREVIOUS_TX(tp, index) \
	(((index) - 1) >= 0 ? ((index) - 1) : (((tp)->pending) - 1))

static inline u32 niu_tx_avail(struct tx_ring_info *tp)
{
	return (tp->pending -
@@ -3140,6 +3143,7 @@ struct niu_ops {
			  enum dma_data_direction direction);
	void (*unmap_single)(struct device *dev, u64 dma_address,
			     size_t size, enum dma_data_direction direction);
	int (*mapping_error)(struct device *dev, u64 dma_address);
};

struct niu_link_config {