Search Linux Wireless

Re: [RFC] brcmsmac: check return from dma_map_single

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 10/02/2012 08:46 PM, John W. Linville wrote:
From: "John W. Linville" <linville@xxxxxxxxxxxxx>

dma_map_single can fail, so it's return value needs to be checked and
handled accordingly.  Failure to do so is akin to failing to check the
return from a kmalloc.

http://linuxdriverproject.org/mediawiki/index.php/DMA_Mapping_Error_Analysis

Signed-off-by: John W. Linville <linville@xxxxxxxxxxxxx>
Cc: Arend van Spriel <arend@xxxxxxxxxxxx>
---
I'm not too sure about the bail-out in dma_rxfill.  Perhaps the experts
can suggest something better?

  drivers/net/wireless/brcm80211/brcmsmac/dma.c | 12 +++++++++---
  1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/dma.c b/drivers/net/wireless/brcm80211/brcmsmac/dma.c
index 5e53305..fa24c58 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/dma.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/dma.c
@@ -1079,6 +1079,10 @@ bool dma_rxfill(struct dma_pub *pub)

  		pa = dma_map_single(di->dmadev, p->data, di->rxbufsize,
  				    DMA_FROM_DEVICE);
+		if (dma_mapping_error(di->dmadev, pa)) {
+			brcmu_pkt_buf_free_skb(p);
+			break;
+		}

I noticed the calling function is ignoring any error returned by dma_rxfill(). I am not sure what to do here when this mapping error happens after being halfway the for loop filling the dma with receive buffers. The function is being called on mac80211 .start() callback so we have to pass the failure back to that.

  		/* save the free packet pointer */
  		di->rxp[rxout] = p;
@@ -1293,13 +1297,15 @@ int dma_txfast(struct dma_pub *pub, struct sk_buff *p, bool commit)
  	if (len == 0)
  		return 0;

+	/* get physical address of buffer start */
+	pa = dma_map_single(di->dmadev, data, len, DMA_TO_DEVICE);
+	if (dma_mapping_error(di->dmadev, pa))
+		return -1;
+

Same for dma_txfast() and from DMA-API.txt I understand the buffer needs to be freed:

- checking the returned dma_addr_t of dma_map_single and dma_map_page
  by using dma_mapping_error():

        dma_addr_t dma_handle;

        dma_handle = dma_map_single(dev, addr, size, direction);
        if (dma_mapping_error(dev, dma_handle)) {
                /*
                 * reduce current DMA mapping usage,
                 * delay and try again later or
                 * reset driver.
                 */
        }

Networking drivers must call dev_kfree_skb to free the socket buffer
and return NETDEV_TX_OK if the DMA mapping fails on the transmit hook
(ndo_start_xmit). This means that the socket buffer is just dropped in
the failure case.

  	/* return nonzero if out of tx descriptors */
  	if (nexttxd(di, txout) == di->txin)
  		goto outoftxd;

-	/* get physical address of buffer start */
-	pa = dma_map_single(di->dmadev, data, len, DMA_TO_DEVICE);
-
  	/* With a DMA segment list, Descriptor table is filled
  	 * using the segment list instead of looping over
  	 * buffers in multi-chain DMA. Therefore, EOF for SGLIST


I will discuss how we should handle the error flows given the options mentioned in the DMA-API pseudo-code above.

Gr. AvS

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux