[PATCH] tun: fix mismatch in mutex lock-unlock in tun_get_user()
There is a single error path where tfile->napi_mutex is left unlocked. It can lead to a deadlock. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- drivers/net/tun.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 81e6cc951e7f..0072a9832532 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1879,6 +1879,10 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, default: this_cpu_inc(tun->pcpu_stats->rx_dropped); kfree_skb(skb); + if (frags) { + tfile->napi.skb = NULL; + mutex_unlock(>napi_mutex); + } return -EINVAL; } } -- 2.7.4
[PATCH] net: phy: xgene: disable clk on error paths
There are several error paths in xgene_mdio_probe(), where clk is left undisabled. The patch fixes them. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- drivers/net/phy/mdio-xgene.c | 21 +++-- 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/net/phy/mdio-xgene.c b/drivers/net/phy/mdio-xgene.c index bfd3090fb055..07c6048200c6 100644 --- a/drivers/net/phy/mdio-xgene.c +++ b/drivers/net/phy/mdio-xgene.c @@ -194,8 +194,11 @@ static int xgene_mdio_reset(struct xgene_mdio_pdata *pdata) } ret = xgene_enet_ecc_init(pdata); - if (ret) + if (ret) { + if (pdata->dev->of_node) + clk_disable_unprepare(pdata->clk); return ret; + } xgene_gmac_reset(pdata); return 0; @@ -388,8 +391,10 @@ static int xgene_mdio_probe(struct platform_device *pdev) return ret; mdio_bus = mdiobus_alloc(); - if (!mdio_bus) - return -ENOMEM; + if (!mdio_bus) { + ret = -ENOMEM; + goto out_clk; + } mdio_bus->name = "APM X-Gene MDIO bus"; @@ -418,7 +423,7 @@ static int xgene_mdio_probe(struct platform_device *pdev) mdio_bus->phy_mask = ~0; ret = mdiobus_register(mdio_bus); if (ret) - goto out; + goto out_mdiobus; acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_HANDLE(dev), 1, acpi_register_phy, NULL, mdio_bus, NULL); @@ -426,16 +431,20 @@ static int xgene_mdio_probe(struct platform_device *pdev) } if (ret) - goto out; + goto out_mdiobus; pdata->mdio_bus = mdio_bus; xgene_mdio_status = true; return 0; -out: +out_mdiobus: mdiobus_free(mdio_bus); +out_clk: + if (dev->of_node) + clk_disable_unprepare(pdata->clk); + return ret; } -- 2.7.4
[PATCH v3 net-next 2/2] wan: dscc4: convert to plain DMA API
Make use the dma_*() interfaces rather than the pci_*() interfaces. Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- drivers/net/wan/dscc4.c | 96 ++--- 1 file changed, 51 insertions(+), 45 deletions(-) diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index 8480dbf..a043fb1 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -483,20 +483,20 @@ static void dscc4_tx_print(struct net_device *dev, static void dscc4_release_ring(struct dscc4_dev_priv *dpriv) { - struct pci_dev *pdev = dpriv->pci_priv->pdev; + struct device *d = >pci_priv->pdev->dev; struct TxFD *tx_fd = dpriv->tx_fd; struct RxFD *rx_fd = dpriv->rx_fd; struct sk_buff **skbuff; int i; - pci_free_consistent(pdev, TX_TOTAL_SIZE, tx_fd, dpriv->tx_fd_dma); - pci_free_consistent(pdev, RX_TOTAL_SIZE, rx_fd, dpriv->rx_fd_dma); + dma_free_coherent(d, TX_TOTAL_SIZE, tx_fd, dpriv->tx_fd_dma); + dma_free_coherent(d, RX_TOTAL_SIZE, rx_fd, dpriv->rx_fd_dma); skbuff = dpriv->tx_skbuff; for (i = 0; i < TX_RING_SIZE; i++) { if (*skbuff) { - pci_unmap_single(pdev, le32_to_cpu(tx_fd->data), - (*skbuff)->len, PCI_DMA_TODEVICE); + dma_unmap_single(d, le32_to_cpu(tx_fd->data), +(*skbuff)->len, DMA_TO_DEVICE); dev_kfree_skb(*skbuff); } skbuff++; @@ -506,8 +506,9 @@ static void dscc4_release_ring(struct dscc4_dev_priv *dpriv) skbuff = dpriv->rx_skbuff; for (i = 0; i < RX_RING_SIZE; i++) { if (*skbuff) { - pci_unmap_single(pdev, le32_to_cpu(rx_fd->data), - RX_MAX(HDLC_MAX_MRU), PCI_DMA_FROMDEVICE); + dma_unmap_single(d, le32_to_cpu(rx_fd->data), +RX_MAX(HDLC_MAX_MRU), +DMA_FROM_DEVICE); dev_kfree_skb(*skbuff); } skbuff++; @@ -519,7 +520,7 @@ static inline int try_get_rx_skb(struct dscc4_dev_priv *dpriv, struct net_device *dev) { unsigned int dirty = dpriv->rx_dirty%RX_RING_SIZE; - struct pci_dev *pdev = dpriv->pci_priv->pdev; + struct device *d = >pci_priv->pdev->dev; struct RxFD *rx_fd = dpriv->rx_fd + dirty; const int len = RX_MAX(HDLC_MAX_MRU); struct sk_buff *skb; @@ -530,8 +531,8 @@ static inline int try_get_rx_skb(struct dscc4_dev_priv *dpriv, goto err_out; skb->protocol = hdlc_type_trans(skb, dev); - addr = pci_map_single(pdev, skb->data, len, PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(pdev, addr)) + addr = dma_map_single(d, skb->data, len, DMA_FROM_DEVICE); + if (dma_mapping_error(d, addr)) goto err_free_skb; dpriv->rx_skbuff[dirty] = skb; @@ -654,7 +655,7 @@ static inline void dscc4_rx_skb(struct dscc4_dev_priv *dpriv, struct net_device *dev) { struct RxFD *rx_fd = dpriv->rx_fd + dpriv->rx_current%RX_RING_SIZE; - struct pci_dev *pdev = dpriv->pci_priv->pdev; + struct device *d = >pci_priv->pdev->dev; struct sk_buff *skb; int pkt_len; @@ -664,8 +665,8 @@ static inline void dscc4_rx_skb(struct dscc4_dev_priv *dpriv, goto refill; } pkt_len = TO_SIZE(le32_to_cpu(rx_fd->state2)); - pci_unmap_single(pdev, le32_to_cpu(rx_fd->data), -RX_MAX(HDLC_MAX_MRU), PCI_DMA_FROMDEVICE); + dma_unmap_single(d, le32_to_cpu(rx_fd->data), +RX_MAX(HDLC_MAX_MRU), DMA_FROM_DEVICE); if ((skb->data[--pkt_len] & FrameOk) == FrameOk) { dev->stats.rx_packets++; dev->stats.rx_bytes += pkt_len; @@ -782,8 +783,8 @@ static int dscc4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rc = -ENOMEM; - priv->iqcfg = (__le32 *) pci_alloc_consistent(pdev, - IRQ_RING_SIZE*sizeof(__le32), >iqcfg_dma); + priv->iqcfg = (__le32 *)dma_alloc_coherent(>dev, + IRQ_RING_SIZE*sizeof(__le32), >iqcfg_dma, GFP_KERNEL); if (!priv->iqcfg) goto err_free_irq_5; writel(priv->iqcfg_dma, ioaddr + IQCFG); @@ -794,16 +795,18 @@ static int dscc4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) */ for (i = 0; i < dev_per_card; i++) { dpriv = priv->root + i; - dpriv->iqtx = (__le32 *) pci_alloc_consistent(pdev, -
[PATCH v3 net-next 1/2] wan: dscc4: add checks for dma mapping errors
The driver does not check if mapping dma memory succeed. The patch adds the checks and failure handling. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- v2: Fix issues noted by David Miller and Francois Romieu. v3: Improve code per Francois Romieu recommendations. Convert to plain DMA API. drivers/net/wan/dscc4.c | 53 ++--- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index 799830f..8480dbf 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -519,22 +519,30 @@ static inline int try_get_rx_skb(struct dscc4_dev_priv *dpriv, struct net_device *dev) { unsigned int dirty = dpriv->rx_dirty%RX_RING_SIZE; + struct pci_dev *pdev = dpriv->pci_priv->pdev; struct RxFD *rx_fd = dpriv->rx_fd + dirty; const int len = RX_MAX(HDLC_MAX_MRU); struct sk_buff *skb; - int ret = 0; + dma_addr_t addr; skb = dev_alloc_skb(len); + if (!skb) + goto err_out; + + skb->protocol = hdlc_type_trans(skb, dev); + addr = pci_map_single(pdev, skb->data, len, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(pdev, addr)) + goto err_free_skb; + dpriv->rx_skbuff[dirty] = skb; - if (skb) { - skb->protocol = hdlc_type_trans(skb, dev); - rx_fd->data = cpu_to_le32(pci_map_single(dpriv->pci_priv->pdev, - skb->data, len, PCI_DMA_FROMDEVICE)); - } else { - rx_fd->data = 0; - ret = -1; - } - return ret; + rx_fd->data = cpu_to_le32(addr); + return 0; + +err_free_skb: + dev_kfree_skb_any(skb); +err_out: + rx_fd->data = 0; + return -1; } /* @@ -1145,16 +1153,23 @@ static netdev_tx_t dscc4_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct dscc4_dev_priv *dpriv = dscc4_priv(dev); - struct dscc4_pci_priv *ppriv = dpriv->pci_priv; + struct pci_dev *pdev = dpriv->pci_priv->pdev; struct TxFD *tx_fd; + dma_addr_t addr; int next; + addr = pci_map_single(pdev, skb->data, skb->len, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(pdev, addr)) { + dev_kfree_skb_any(skb); + dev->stats.tx_dropped++; + return NETDEV_TX_OK; + } + next = dpriv->tx_current%TX_RING_SIZE; dpriv->tx_skbuff[next] = skb; tx_fd = dpriv->tx_fd + next; tx_fd->state = FrameEnd | TO_STATE_TX(skb->len); - tx_fd->data = cpu_to_le32(pci_map_single(ppriv->pdev, skb->data, skb->len, -PCI_DMA_TODEVICE)); + tx_fd->data = cpu_to_le32(addr); tx_fd->complete = 0x; tx_fd->jiffies = jiffies; mb(); @@ -1887,16 +1902,22 @@ static struct sk_buff *dscc4_init_dummy_skb(struct dscc4_dev_priv *dpriv) skb = dev_alloc_skb(DUMMY_SKB_SIZE); if (skb) { + struct pci_dev *pdev = dpriv->pci_priv->pdev; int last = dpriv->tx_dirty%TX_RING_SIZE; struct TxFD *tx_fd = dpriv->tx_fd + last; + dma_addr_t addr; skb->len = DUMMY_SKB_SIZE; skb_copy_to_linear_data(skb, version, strlen(version) % DUMMY_SKB_SIZE); + addr = pci_map_single(pdev, skb->data, DUMMY_SKB_SIZE, + PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(pdev, addr)) { + dev_kfree_skb_any(skb); + return NULL; + } tx_fd->state = FrameEnd | TO_STATE_TX(DUMMY_SKB_SIZE); - tx_fd->data = cpu_to_le32(pci_map_single(dpriv->pci_priv->pdev, -skb->data, DUMMY_SKB_SIZE, -PCI_DMA_TODEVICE)); + tx_fd->data = cpu_to_le32(addr); dpriv->tx_skbuff[last] = skb; } return skb; -- 2.7.4
[PATCH net-next v2] wan: dscc4: add checks for dma mapping errors
The driver does not check if mapping dma memory succeed. The patch adds the checks and failure handling. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- v2: Fix issues noted by David Miller and Francois Romieu. drivers/net/wan/dscc4.c | 52 +++-- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index 799830f..6a9ffac 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -518,23 +518,31 @@ static void dscc4_release_ring(struct dscc4_dev_priv *dpriv) static inline int try_get_rx_skb(struct dscc4_dev_priv *dpriv, struct net_device *dev) { + struct pci_dev *pdev = dpriv->pci_priv->pdev; unsigned int dirty = dpriv->rx_dirty%RX_RING_SIZE; struct RxFD *rx_fd = dpriv->rx_fd + dirty; const int len = RX_MAX(HDLC_MAX_MRU); struct sk_buff *skb; - int ret = 0; + dma_addr_t addr; skb = dev_alloc_skb(len); + if (!skb) + goto err_out; + + skb->protocol = hdlc_type_trans(skb, dev); + addr = pci_map_single(pdev, skb->data, len, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(pdev, addr)) + goto err_free_skb; + dpriv->rx_skbuff[dirty] = skb; - if (skb) { - skb->protocol = hdlc_type_trans(skb, dev); - rx_fd->data = cpu_to_le32(pci_map_single(dpriv->pci_priv->pdev, - skb->data, len, PCI_DMA_FROMDEVICE)); - } else { - rx_fd->data = 0; - ret = -1; - } - return ret; + rx_fd->data = cpu_to_le32(addr); + return 0; + +err_free_skb: + dev_kfree_skb_any(skb); +err_out: + rx_fd->data = 0; + return -1; } /* @@ -1147,14 +1155,22 @@ static netdev_tx_t dscc4_start_xmit(struct sk_buff *skb, struct dscc4_dev_priv *dpriv = dscc4_priv(dev); struct dscc4_pci_priv *ppriv = dpriv->pci_priv; struct TxFD *tx_fd; + dma_addr_t addr; int next; + addr = pci_map_single(ppriv->pdev, skb->data, skb->len, + PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(ppriv->pdev, addr)) { + dev_kfree_skb_any(skb); + dev->stats.tx_dropped++; + return NETDEV_TX_OK; + } + next = dpriv->tx_current%TX_RING_SIZE; dpriv->tx_skbuff[next] = skb; tx_fd = dpriv->tx_fd + next; tx_fd->state = FrameEnd | TO_STATE_TX(skb->len); - tx_fd->data = cpu_to_le32(pci_map_single(ppriv->pdev, skb->data, skb->len, -PCI_DMA_TODEVICE)); + tx_fd->data = cpu_to_le32(addr); tx_fd->complete = 0x; tx_fd->jiffies = jiffies; mb(); @@ -1887,16 +1903,22 @@ static struct sk_buff *dscc4_init_dummy_skb(struct dscc4_dev_priv *dpriv) skb = dev_alloc_skb(DUMMY_SKB_SIZE); if (skb) { + struct pci_dev *pdev = dpriv->pci_priv->pdev; int last = dpriv->tx_dirty%TX_RING_SIZE; struct TxFD *tx_fd = dpriv->tx_fd + last; + dma_addr_t addr; skb->len = DUMMY_SKB_SIZE; skb_copy_to_linear_data(skb, version, strlen(version) % DUMMY_SKB_SIZE); tx_fd->state = FrameEnd | TO_STATE_TX(DUMMY_SKB_SIZE); - tx_fd->data = cpu_to_le32(pci_map_single(dpriv->pci_priv->pdev, -skb->data, DUMMY_SKB_SIZE, -PCI_DMA_TODEVICE)); + addr = pci_map_single(pdev, skb->data, DUMMY_SKB_SIZE, + PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(pdev, addr)) { + dev_kfree_skb_any(skb); + return NULL; + } + tx_fd->data = cpu_to_le32(addr); dpriv->tx_skbuff[last] = skb; } return skb; -- 2.7.4
[PATCH] wan: dscc4: add checks for dma mapping errors
The driver does not check if mapping dma memory succeed. The patch adds the checks and failure handling. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- drivers/net/wan/dscc4.c | 52 +++-- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index 799830ffcae2..1a94f0a95b2c 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -522,19 +522,27 @@ static inline int try_get_rx_skb(struct dscc4_dev_priv *dpriv, struct RxFD *rx_fd = dpriv->rx_fd + dirty; const int len = RX_MAX(HDLC_MAX_MRU); struct sk_buff *skb; - int ret = 0; + dma_addr_t addr; skb = dev_alloc_skb(len); dpriv->rx_skbuff[dirty] = skb; - if (skb) { - skb->protocol = hdlc_type_trans(skb, dev); - rx_fd->data = cpu_to_le32(pci_map_single(dpriv->pci_priv->pdev, - skb->data, len, PCI_DMA_FROMDEVICE)); - } else { - rx_fd->data = 0; - ret = -1; - } - return ret; + if (!skb) + goto err_out; + + skb->protocol = hdlc_type_trans(skb, dev); + addr = pci_map_single(dpriv->pci_priv->pdev, + skb->data, len, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(dpriv->pci_priv->pdev, addr)) + goto err_free_skb; + + rx_fd->data = cpu_to_le32(addr); + return 0; + +err_free_skb: + dev_kfree_skb_any(skb); +err_out: + rx_fd->data = 0; + return -1; } /* @@ -1147,14 +1155,22 @@ static netdev_tx_t dscc4_start_xmit(struct sk_buff *skb, struct dscc4_dev_priv *dpriv = dscc4_priv(dev); struct dscc4_pci_priv *ppriv = dpriv->pci_priv; struct TxFD *tx_fd; + dma_addr_t addr; int next; + addr = pci_map_single(ppriv->pdev, skb->data, skb->len, + PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(ppriv->pdev, addr)) { + dev_kfree_skb_any(skb); + dev->stats.tx_errors++; + return NETDEV_TX_OK; + } + next = dpriv->tx_current%TX_RING_SIZE; dpriv->tx_skbuff[next] = skb; tx_fd = dpriv->tx_fd + next; tx_fd->state = FrameEnd | TO_STATE_TX(skb->len); - tx_fd->data = cpu_to_le32(pci_map_single(ppriv->pdev, skb->data, skb->len, -PCI_DMA_TODEVICE)); + tx_fd->data = cpu_to_le32(addr); tx_fd->complete = 0x; tx_fd->jiffies = jiffies; mb(); @@ -1889,14 +1905,20 @@ static struct sk_buff *dscc4_init_dummy_skb(struct dscc4_dev_priv *dpriv) if (skb) { int last = dpriv->tx_dirty%TX_RING_SIZE; struct TxFD *tx_fd = dpriv->tx_fd + last; + dma_addr_t addr; skb->len = DUMMY_SKB_SIZE; skb_copy_to_linear_data(skb, version, strlen(version) % DUMMY_SKB_SIZE); tx_fd->state = FrameEnd | TO_STATE_TX(DUMMY_SKB_SIZE); - tx_fd->data = cpu_to_le32(pci_map_single(dpriv->pci_priv->pdev, -skb->data, DUMMY_SKB_SIZE, -PCI_DMA_TODEVICE)); + addr = pci_map_single(dpriv->pci_priv->pdev, + skb->data, DUMMY_SKB_SIZE, + PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(dpriv->pci_priv->pdev, addr)) { + dev_kfree_skb_any(skb); + return NULL; + } + tx_fd->data = cpu_to_le32(addr); dpriv->tx_skbuff[last] = skb; } return skb; -- 2.7.4
[PATCH] smsc911x: Add check for ioremap_nocache() return code
There is no check for return code of smsc911x_drv_probe() in smsc911x_drv_probe(). The patch adds one. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- drivers/net/ethernet/smsc/smsc911x.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index ea1bbc355b4d..0b6a39b003a4 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -2467,6 +2467,10 @@ static int smsc911x_drv_probe(struct platform_device *pdev) pdata = netdev_priv(dev); dev->irq = irq; pdata->ioaddr = ioremap_nocache(res->start, res_size); + if (!pdata->ioaddr) { + retval = -ENOMEM; + goto out_ioremap_fail; + } pdata->dev = dev; pdata->msg_enable = ((1 << debug) - 1); @@ -2572,6 +2576,7 @@ static int smsc911x_drv_probe(struct platform_device *pdev) smsc911x_free_resources(pdev); out_request_resources_fail: iounmap(pdata->ioaddr); +out_ioremap_fail: free_netdev(dev); out_release_io_1: release_mem_region(res->start, resource_size(res)); -- 2.7.4
[PATCH] net: atheros: atl2: don't return zero on failure path in atl2_probe()
If dma mask checks fail in atl2_probe(), it breaks off initialization, deallocates all resources, but returns zero. The patch adds proper error code return value and make error code setup unified. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- drivers/net/ethernet/atheros/atlx/atl2.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c index 63f2deec2a52..77a1c03255de 100644 --- a/drivers/net/ethernet/atheros/atlx/atl2.c +++ b/drivers/net/ethernet/atheros/atlx/atl2.c @@ -1353,6 +1353,7 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) && pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { printk(KERN_ERR "atl2: No usable DMA configuration, aborting\n"); + err = -EIO; goto err_dma; } @@ -1366,10 +1367,11 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) * pcibios_set_master to do the needed arch specific settings */ pci_set_master(pdev); - err = -ENOMEM; netdev = alloc_etherdev(sizeof(struct atl2_adapter)); - if (!netdev) + if (!netdev) { + err = -ENOMEM; goto err_alloc_etherdev; + } SET_NETDEV_DEV(netdev, >dev); @@ -1408,8 +1410,6 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (err) goto err_sw_init; - err = -EIO; - netdev->hw_features = NETIF_F_HW_VLAN_CTAG_RX; netdev->features |= (NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX); -- 2.7.4
[PATCH v2] net: natsemi: ns83820: add checks for dma mapping error
The driver does not check if mapping dma memory succeed. The patch adds the checks and failure handling. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- drivers/net/ethernet/natsemi/ns83820.c | 42 +++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c index 729095db3e08..dfc64e1e31f9 100644 --- a/drivers/net/ethernet/natsemi/ns83820.c +++ b/drivers/net/ethernet/natsemi/ns83820.c @@ -534,14 +534,19 @@ static inline int ns83820_add_rx_skb(struct ns83820 *dev, struct sk_buff *skb) ); #endif + buf = pci_map_single(dev->pci_dev, skb->data, +REAL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(dev->pci_dev, buf)) { + kfree_skb(skb); + return 1; + } + sg = dev->rx_info.descs + (next_empty * DESC_SIZE); BUG_ON(NULL != dev->rx_info.skbs[next_empty]); dev->rx_info.skbs[next_empty] = skb; dev->rx_info.next_empty = (next_empty + 1) % NR_RX_DESC; cmdsts = REAL_RX_BUF_SIZE | CMDSTS_INTR; - buf = pci_map_single(dev->pci_dev, skb->data, -REAL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); build_rx_desc(dev, sg, 0, buf, cmdsts, 0); /* update link of previous rx */ if (likely(next_empty != dev->rx_info.next_rx)) @@ -1068,6 +1073,7 @@ static netdev_tx_t ns83820_hard_start_xmit(struct sk_buff *skb, int stopped = 0; int do_intr = 0; volatile __le32 *first_desc; + volatile __le32 *desc; dprintk("ns83820_hard_start_xmit\n"); @@ -1136,11 +1142,13 @@ static netdev_tx_t ns83820_hard_start_xmit(struct sk_buff *skb, if (nr_frags) len -= skb->data_len; buf = pci_map_single(dev->pci_dev, skb->data, len, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(dev->pci_dev, buf)) + goto dma_error_first; first_desc = dev->tx_descs + (free_idx * DESC_SIZE); for (;;) { - volatile __le32 *desc = dev->tx_descs + (free_idx * DESC_SIZE); + desc = dev->tx_descs + (free_idx * DESC_SIZE); dprintk("frag[%3u]: %4u @ 0x%08Lx\n", free_idx, len, (unsigned long long)buf); @@ -1160,6 +1168,8 @@ static netdev_tx_t ns83820_hard_start_xmit(struct sk_buff *skb, buf = skb_frag_dma_map(>pci_dev->dev, frag, 0, skb_frag_size(frag), DMA_TO_DEVICE); + if (dma_mapping_error(>pci_dev->dev, buf)) + goto dma_error; dprintk("frag: buf=%08Lx page=%08lx offset=%08lx\n", (long long)buf, (long) page_to_pfn(frag->page), frag->page_offset); @@ -1183,6 +1193,32 @@ static netdev_tx_t ns83820_hard_start_xmit(struct sk_buff *skb, netif_start_queue(ndev); return NETDEV_TX_OK; + +dma_error: + do { + free_idx = (free_idx + NR_TX_DESC - 1) % NR_TX_DESC; + desc = dev->tx_descs + (free_idx * DESC_SIZE); + cmdsts = le32_to_cpu(desc[DESC_CMDSTS]); + len = cmdsts & CMDSTS_LEN_MASK; + buf = desc_addr_get(desc + DESC_BUFPTR); + if (desc == first_desc) + pci_unmap_single(dev->pci_dev, + buf, + len, + PCI_DMA_TODEVICE); + else + pci_unmap_page(dev->pci_dev, + buf, + len, + PCI_DMA_TODEVICE); + desc[DESC_CMDSTS] = cpu_to_le32(0); + mb(); + } while (desc != first_desc); + +dma_error_first: + dev_kfree_skb_any(skb); + ndev->stats.tx_errors++; + return NETDEV_TX_OK; } static void ns83820_update_stats(struct ns83820 *dev) -- 2.7.4
[PATCH] net: natsemi: ns83820: add checks for dma mapping error
The driver does not check if mapping dma memory succeed. The patch adds the checks and failure handling. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- drivers/net/ethernet/natsemi/ns83820.c | 13 +++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c index 729095db3e08..7d6d692ebb92 100644 --- a/drivers/net/ethernet/natsemi/ns83820.c +++ b/drivers/net/ethernet/natsemi/ns83820.c @@ -534,14 +534,19 @@ static inline int ns83820_add_rx_skb(struct ns83820 *dev, struct sk_buff *skb) ); #endif + buf = pci_map_single(dev->pci_dev, skb->data, +REAL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(dev->pci_dev, buf)) { + kfree_skb(skb); + return 1; + } + sg = dev->rx_info.descs + (next_empty * DESC_SIZE); BUG_ON(NULL != dev->rx_info.skbs[next_empty]); dev->rx_info.skbs[next_empty] = skb; dev->rx_info.next_empty = (next_empty + 1) % NR_RX_DESC; cmdsts = REAL_RX_BUF_SIZE | CMDSTS_INTR; - buf = pci_map_single(dev->pci_dev, skb->data, -REAL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); build_rx_desc(dev, sg, 0, buf, cmdsts, 0); /* update link of previous rx */ if (likely(next_empty != dev->rx_info.next_rx)) @@ -1136,6 +1141,10 @@ static netdev_tx_t ns83820_hard_start_xmit(struct sk_buff *skb, if (nr_frags) len -= skb->data_len; buf = pci_map_single(dev->pci_dev, skb->data, len, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(dev->pci_dev, buf)) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } first_desc = dev->tx_descs + (free_idx * DESC_SIZE); -- 2.7.4
[PATCH] irda: vlsi_ir: fix check for dma mapping errors
vlsi_alloc_ring() checks for dma mapping errors by comparison returned address with zero, while pci_dma_mapping_error() should be used. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- drivers/net/irda/vlsi_ir.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c index ffedad2a360a..15b920086251 100644 --- a/drivers/net/irda/vlsi_ir.c +++ b/drivers/net/irda/vlsi_ir.c @@ -418,8 +418,9 @@ static struct vlsi_ring *vlsi_alloc_ring(struct pci_dev *pdev, struct ring_descr memset(rd, 0, sizeof(*rd)); rd->hw = hwmap + i; rd->buf = kmalloc(len, GFP_KERNEL|GFP_DMA); - if (rd->buf == NULL || - !(busaddr = pci_map_single(pdev, rd->buf, len, dir))) { + if (rd->buf) + busaddr = pci_map_single(pdev, rd->buf, len, dir); + if (rd->buf == NULL || pci_dma_mapping_error(pdev, busaddr)) { if (rd->buf) { net_err_ratelimited("%s: failed to create PCI-MAP for %p\n", __func__, rd->buf); @@ -430,8 +431,7 @@ static struct vlsi_ring *vlsi_alloc_ring(struct pci_dev *pdev, struct ring_descr rd = r->rd + j; busaddr = rd_get_addr(rd); rd_set_addr_status(rd, 0, 0); - if (busaddr) - pci_unmap_single(pdev, busaddr, len, dir); + pci_unmap_single(pdev, busaddr, len, dir); kfree(rd->buf); rd->buf = NULL; } -- 2.7.4
[PATCH] net/sched: act_skbmod: remove unneeded rcu_read_unlock in tcf_skbmod_dump
Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- net/sched/act_skbmod.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/sched/act_skbmod.c b/net/sched/act_skbmod.c index 3b7074e23024..c736627f8f4a 100644 --- a/net/sched/act_skbmod.c +++ b/net/sched/act_skbmod.c @@ -228,7 +228,6 @@ static int tcf_skbmod_dump(struct sk_buff *skb, struct tc_action *a, return skb->len; nla_put_failure: - rcu_read_unlock(); nlmsg_trim(skb, b); return -1; } -- 2.7.4
net/sched: act_skbmod: rcu_read_unlock in tcf_skbmod_dump?
Hello! rcu_read_unlock() in tcf_skbmod_dump() looks suspicious to me. What does it mean there? -- Thank you, Alexey Khoroshilov Linux Verification Center, ISPRAS web: http://linuxtesting.org
[PATCH v2] net: adaptec: starfire: add checks for dma mapping errors
init_ring(), refill_rx_ring() and start_tx() don't check if mapping dma memory succeed. The patch adds the checks and failure handling. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- drivers/net/ethernet/adaptec/starfire.c | 45 +++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c index c12d2618eebf..3872ab96b80a 100644 --- a/drivers/net/ethernet/adaptec/starfire.c +++ b/drivers/net/ethernet/adaptec/starfire.c @@ -1152,6 +1152,12 @@ static void init_ring(struct net_device *dev) if (skb == NULL) break; np->rx_info[i].mapping = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(np->pci_dev, + np->rx_info[i].mapping)) { + dev_kfree_skb(skb); + np->rx_info[i].skb = NULL; + break; + } /* Grrr, we cannot offset to correctly align the IP header. */ np->rx_ring[i].rxaddr = cpu_to_dma(np->rx_info[i].mapping | RxDescValid); } @@ -1182,8 +1188,9 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) { struct netdev_private *np = netdev_priv(dev); unsigned int entry; + unsigned int prev_tx; u32 status; - int i; + int i, j; /* * be cautious here, wrapping the queue has weird semantics @@ -1201,6 +1208,7 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) } #endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */ + prev_tx = np->cur_tx; entry = np->cur_tx % TX_RING_SIZE; for (i = 0; i < skb_num_frags(skb); i++) { int wrap_ring = 0; @@ -1234,6 +1242,11 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) skb_frag_size(this_frag), PCI_DMA_TODEVICE); } + if (pci_dma_mapping_error(np->pci_dev, + np->tx_info[entry].mapping)) { + dev->stats.tx_dropped++; + goto err_out; + } np->tx_ring[entry].addr = cpu_to_dma(np->tx_info[entry].mapping); np->tx_ring[entry].status = cpu_to_le32(status); @@ -1268,8 +1281,30 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); return NETDEV_TX_OK; -} +err_out: + entry = prev_tx % TX_RING_SIZE; + np->tx_info[entry].skb = NULL; + if (i > 0) { + pci_unmap_single(np->pci_dev, +np->tx_info[entry].mapping, +skb_first_frag_len(skb), +PCI_DMA_TODEVICE); + np->tx_info[entry].mapping = 0; + entry = (entry + np->tx_info[entry].used_slots) % TX_RING_SIZE; + for (j = 1; j < i; j++) { + pci_unmap_single(np->pci_dev, +np->tx_info[entry].mapping, +skb_frag_size( + _shinfo(skb)->frags[j-1]), +PCI_DMA_TODEVICE); + entry++; + } + } + dev_kfree_skb_any(skb); + np->cur_tx = prev_tx; + return NETDEV_TX_OK; +} /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ @@ -1569,6 +1604,12 @@ static void refill_rx_ring(struct net_device *dev) break; /* Better luck next round. */ np->rx_info[entry].mapping = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(np->pci_dev, + np->rx_info[entry].mapping)) { + dev_kfree_skb(skb); + np->rx_info[entry].skb = NULL; + break; + } np->rx_ring[entry].rxaddr = cpu_to_dma(np->rx_info[entry].mapping | RxDescValid); } -- 2.7.4
[PATCH] net: adaptec: starfire: add checks for dma mapping errors
init_ring() and refill_rx_ring() don't check if mapping dma memory succeed. The patch adds the checks and failure handling. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- drivers/net/ethernet/adaptec/starfire.c | 12 1 file changed, 12 insertions(+) diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c index c12d2618eebf..e27043d051e1 100644 --- a/drivers/net/ethernet/adaptec/starfire.c +++ b/drivers/net/ethernet/adaptec/starfire.c @@ -1152,6 +1152,12 @@ static void init_ring(struct net_device *dev) if (skb == NULL) break; np->rx_info[i].mapping = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(np->pci_dev, + np->rx_info[i].mapping)) { + dev_kfree_skb(skb); + np->rx_info[i].skb = NULL; + break; + } /* Grrr, we cannot offset to correctly align the IP header. */ np->rx_ring[i].rxaddr = cpu_to_dma(np->rx_info[i].mapping | RxDescValid); } @@ -1569,6 +1575,12 @@ static void refill_rx_ring(struct net_device *dev) break; /* Better luck next round. */ np->rx_info[entry].mapping = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(np->pci_dev, + np->rx_info[entry].mapping)) { + dev_kfree_skb(skb); + np->rx_info[entry].skb = NULL; + break; + } np->rx_ring[entry].rxaddr = cpu_to_dma(np->rx_info[entry].mapping | RxDescValid); } -- 2.7.4
[PATCH] adm80211: add checks for dma mapping errors
The driver does not check if mapping dma memory succeed. The patch adds the checks and failure handling. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- drivers/net/wireless/admtek/adm8211.c | 24 ++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/admtek/adm8211.c b/drivers/net/wireless/admtek/adm8211.c index 70ecd82d674d..2b4a3eb38dfa 100644 --- a/drivers/net/wireless/admtek/adm8211.c +++ b/drivers/net/wireless/admtek/adm8211.c @@ -413,6 +413,13 @@ static void adm8211_interrupt_rci(struct ieee80211_hw *dev) skb_tail_pointer(newskb), RX_PKT_SIZE, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(priv->pdev, + priv->rx_buffers[entry].mapping)) { + priv->rx_buffers[entry].skb = NULL; + dev_kfree_skb(newskb); + skb = NULL; + /* TODO: update rx dropped stats */ + } } else { skb = NULL; /* TODO: update rx dropped stats */ @@ -1450,6 +1457,12 @@ static int adm8211_init_rings(struct ieee80211_hw *dev) skb_tail_pointer(rx_info->skb), RX_PKT_SIZE, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(priv->pdev, rx_info->mapping)) { + dev_kfree_skb(rx_info->skb); + rx_info->skb = NULL; + break; + } + desc->buffer1 = cpu_to_le32(rx_info->mapping); desc->status = cpu_to_le32(RDES0_STATUS_OWN | RDES0_STATUS_SQL); } @@ -1613,7 +1626,7 @@ static void adm8211_calc_durations(int *dur, int *plcp, size_t payload_len, int } /* Transmit skb w/adm8211_tx_hdr (802.11 header created by hardware) */ -static void adm8211_tx_raw(struct ieee80211_hw *dev, struct sk_buff *skb, +static int adm8211_tx_raw(struct ieee80211_hw *dev, struct sk_buff *skb, u16 plcp_signal, size_t hdrlen) { @@ -1625,6 +1638,8 @@ static void adm8211_tx_raw(struct ieee80211_hw *dev, struct sk_buff *skb, mapping = pci_map_single(priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(priv->pdev, mapping)) + return -ENOMEM; spin_lock_irqsave(>lock, flags); @@ -1657,6 +1672,8 @@ static void adm8211_tx_raw(struct ieee80211_hw *dev, struct sk_buff *skb, /* Trigger transmit poll */ ADM8211_CSR_WRITE(TDR, 0); + + return 0; } /* Put adm8211_tx_hdr on skb and transmit */ @@ -1710,7 +1727,10 @@ static void adm8211_tx(struct ieee80211_hw *dev, txhdr->retry_limit = info->control.rates[0].count; - adm8211_tx_raw(dev, skb, plcp_signal, hdrlen); + if (adm8211_tx_raw(dev, skb, plcp_signal, hdrlen)) { + /* Drop packet */ + ieee80211_free_txskb(dev, skb); + } } static int adm8211_alloc_rings(struct ieee80211_hw *dev) -- 2.7.4
[PATCH] net: macb: add check for dma mapping error in start_xmit()
at91ether_start_xmit() does not check for dma mapping errors. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- drivers/net/ethernet/cadence/macb.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index b32444a3ed79..533653bd7aec 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -2673,6 +2673,12 @@ static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev) lp->skb_length = skb->len; lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE); + if (dma_mapping_error(NULL, lp->skb_physaddr)) { + dev_kfree_skb_any(skb); + dev->stats.tx_dropped++; + netdev_err(dev, "%s: DMA mapping error\n", __func__); + return NETDEV_TX_OK; + } /* Set address of the data in the Transmit Address register */ macb_writel(lp, TAR, lp->skb_physaddr); -- 2.7.4
[PATCH v2] vmxnet3: avoid assumption about invalid dma_pa in vmxnet3_set_mc()
vmxnet3_set_mc() checks new_table_pa returned by dma_map_single() with dma_mapping_error(), but even there it assumes zero is invalid pa (it assumes dma_mapping_error(...,0) returns true if new_table is NULL). The patch adds an explicit variable to track status of new_table_pa. Found by Linux Driver Verification project (linuxtesting.org). v2: use "bool" and "true"/"false" for boolean variables. Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- drivers/net/vmxnet3/vmxnet3_drv.c | 17 ++--- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index b5554f2ebee4..ef83ae3b0a44 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -2279,6 +2279,7 @@ vmxnet3_set_mc(struct net_device *netdev) >shared->devRead.rxFilterConf; u8 *new_table = NULL; dma_addr_t new_table_pa = 0; + bool new_table_pa_valid = false; u32 new_mode = VMXNET3_RXM_UCAST; if (netdev->flags & IFF_PROMISC) { @@ -2307,13 +2308,15 @@ vmxnet3_set_mc(struct net_device *netdev) new_table, sz, PCI_DMA_TODEVICE); + if (!dma_mapping_error(>pdev->dev, + new_table_pa)) { + new_mode |= VMXNET3_RXM_MCAST; + new_table_pa_valid = true; + rxConf->mfTablePA = cpu_to_le64( + new_table_pa); + } } - - if (!dma_mapping_error(>pdev->dev, - new_table_pa)) { - new_mode |= VMXNET3_RXM_MCAST; - rxConf->mfTablePA = cpu_to_le64(new_table_pa); - } else { + if (!new_table_pa_valid) { netdev_info(netdev, "failed to copy mcast list, setting ALL_MULTI\n"); new_mode |= VMXNET3_RXM_ALL_MULTI; @@ -2338,7 +2341,7 @@ vmxnet3_set_mc(struct net_device *netdev) VMXNET3_CMD_UPDATE_MAC_FILTERS); spin_unlock_irqrestore(>cmd_lock, flags); - if (new_table_pa) + if (new_table_pa_valid) dma_unmap_single(>pdev->dev, new_table_pa, rxConf->mfTableLen, PCI_DMA_TODEVICE); kfree(new_table); -- 2.7.4
[PATCH] vmxnet3: avoid assumption about invalid dma_pa in vmxnet3_set_mc()
vmxnet3_set_mc() still assumes zero is invalid pa: it assumes dma_mapping_error(...,0) returns true if vmxnet3_copy_mc() fails; it calls dma_unmap_single() iff new_table_pa is not zero. The patch adds an explicit variable to track status of new_table_pa. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- drivers/net/vmxnet3/vmxnet3_drv.c | 17 ++--- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index b5554f2ebee4..5ee059eafe9c 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -2279,6 +2279,7 @@ vmxnet3_set_mc(struct net_device *netdev) >shared->devRead.rxFilterConf; u8 *new_table = NULL; dma_addr_t new_table_pa = 0; + int new_table_pa_valid = 0; u32 new_mode = VMXNET3_RXM_UCAST; if (netdev->flags & IFF_PROMISC) { @@ -2307,13 +2308,15 @@ vmxnet3_set_mc(struct net_device *netdev) new_table, sz, PCI_DMA_TODEVICE); + if (!dma_mapping_error(>pdev->dev, + new_table_pa)) { + new_mode |= VMXNET3_RXM_MCAST; + new_table_pa_valid = 1; + rxConf->mfTablePA = cpu_to_le64( + new_table_pa); + } } - - if (!dma_mapping_error(>pdev->dev, - new_table_pa)) { - new_mode |= VMXNET3_RXM_MCAST; - rxConf->mfTablePA = cpu_to_le64(new_table_pa); - } else { + if (!new_table_pa_valid) { netdev_info(netdev, "failed to copy mcast list, setting ALL_MULTI\n"); new_mode |= VMXNET3_RXM_ALL_MULTI; @@ -2338,7 +2341,7 @@ vmxnet3_set_mc(struct net_device *netdev) VMXNET3_CMD_UPDATE_MAC_FILTERS); spin_unlock_irqrestore(>cmd_lock, flags); - if (new_table_pa) + if (new_table_pa_valid) dma_unmap_single(>pdev->dev, new_table_pa, rxConf->mfTableLen, PCI_DMA_TODEVICE); kfree(new_table); -- 2.7.4
[PATCH] net: mvmdio: do not clk_disable_unprepare() NULL clock
There is no need to clk_disable_unprepare(dev->clk) before it was initialized. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- drivers/net/ethernet/marvell/mvmdio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c index 8982c882af1b..a0d1b084ecec 100644 --- a/drivers/net/ethernet/marvell/mvmdio.c +++ b/drivers/net/ethernet/marvell/mvmdio.c @@ -211,8 +211,7 @@ static int orion_mdio_probe(struct platform_device *pdev) dev->regs = devm_ioremap(>dev, r->start, resource_size(r)); if (!dev->regs) { dev_err(>dev, "Unable to remap SMI register\n"); - ret = -ENODEV; - goto out_mdio; + return -ENODEV; } init_waitqueue_head(>smi_busy_wait); -- 2.7.4
Re: [BUG] act_ife: sleeping functions called in atomic context
On 17.06.2016 08:38, Cong Wang wrote: > On Thu, Jun 16, 2016 at 7:14 PM, Cong Wangwrote: >> >> I think we can just remove that tcf_lock, I am testing a patch now. > > Please try the attached patch, I will do more tests tomorrow. > > Thanks! > Looks good with two notes: 1. add_metainfo() still contains ret = ops->alloc(mi, metaval); that allocates memory with GFP_KERNEL. So, I would add gfpflag argument to alloc() operation. 2. It makes sense to mention ife_mod_lock in the comment before add_metainfo(), because ife_mod_lock is the reason to use GFP_ATOMIC there. -- Alexey
[BUG] act_ife: sleeping functions called in atomic context
tcf_ife_init() contains a big chunk of code executed with ife->tcf_lock spinlock held. But that code contains several calls to sleeping functions: populate_metalist() and use_all_metadata() -> add_metainfo() -> find_ife_oplist(metaid) -> read_lock() -> try_module_get(o->owner) -> kzalloc(sizeof(*mi), GFP_KERNEL); -> ops->alloc(mi, metaval); -> module_put(ops->owner); _tcf_ife_cleanup() -> module_put() The same problem is actual for tcf_ife_cleanup() as well. Found by Linux Driver Verification project (linuxtesting.org). -- Alexey Khoroshilov Linux Verification Center, ISPRAS web: http://linuxtesting.org
Suspicious code in tun_flow_update()
Hello, If tun_flow_find() successfully finds tun_flow_entry, tun_flow_update() updates the entry in place. Is such usage of RCU safe here? Found by Linux Driver Verification project (linuxtesting.org). -- Alexey Khoroshilov Linux Verification Center, ISPRAS
[PATCH] ipw2x00: add checks for dma mapping errors
ipw2100_alloc_skb() and ipw2100_tx_send_data() do not check if mapping dma memory succeed. The patch adds the checks and failure handling. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- drivers/net/wireless/ipw2x00/ipw2100.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 36818c7f30b9..f93a7f71c047 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -2311,8 +2311,10 @@ static int ipw2100_alloc_skb(struct ipw2100_priv *priv, packet->dma_addr = pci_map_single(priv->pci_dev, packet->skb->data, sizeof(struct ipw2100_rx), PCI_DMA_FROMDEVICE); - /* NOTE: pci_map_single does not return an error code, and 0 is a valid -* dma_addr */ + if (pci_dma_mapping_error(priv->pci_dev, packet->dma_addr)) { + dev_kfree_skb(packet->skb); + return -ENOMEM; + } return 0; } @@ -3183,6 +3185,11 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv) LIBIPW_3ADDR_LEN, tbd->buf_length, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(priv->pci_dev, + tbd->host_addr)) { + IPW_DEBUG_TX("dma mapping error\n"); + break; + } IPW_DEBUG_TX("data frag tbd TX%d P=%08x L=%d\n", txq->next, tbd->host_addr, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] prism54: fix checks for dma mapping errors
prism54 checks for dma mapping errors by comparison returned address with zero, while pci_dma_mapping_error() should be used. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- drivers/net/wireless/prism54/islpci_dev.c | 4 +++- drivers/net/wireless/prism54/islpci_eth.c | 5 +++-- drivers/net/wireless/prism54/islpci_mgt.c | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index 931cf440ff18..84a42012aeae 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c @@ -707,7 +707,9 @@ islpci_alloc_memory(islpci_private *priv) pci_map_single(priv->pdev, (void *) skb->data, MAX_FRAGMENT_SIZE_RX + 2, PCI_DMA_FROMDEVICE); - if (!priv->pci_map_rx_address[counter]) { + if (pci_dma_mapping_error(priv->pdev, + priv->pci_map_rx_address[counter])) { + priv->pci_map_rx_address[counter] = 0; /* error mapping the buffer to device accessible memory address */ printk(KERN_ERR "failed to map skb DMA'able\n"); diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index 674658f2e6ef..d83f6332019e 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c @@ -190,7 +190,7 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev) pci_map_address = pci_map_single(priv->pdev, (void *) skb->data, skb->len, PCI_DMA_TODEVICE); - if (unlikely(pci_map_address == 0)) { + if (pci_dma_mapping_error(priv->pdev, pci_map_address)) { printk(KERN_WARNING "%s: cannot map buffer to PCI\n", ndev->name); goto drop_free; @@ -448,7 +448,8 @@ islpci_eth_receive(islpci_private *priv) pci_map_single(priv->pdev, (void *) skb->data, MAX_FRAGMENT_SIZE_RX + 2, PCI_DMA_FROMDEVICE); - if (unlikely(!priv->pci_map_rx_address[index])) { + if (pci_dma_mapping_error(priv->pdev, + priv->pci_map_rx_address[index])) { /* error mapping the buffer to device accessible memory address */ DEBUG(SHOW_ERROR_MESSAGES, "Error mapping DMA address\n"); diff --git a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c index 0de14dfa68cc..53d7a1705e8e 100644 --- a/drivers/net/wireless/prism54/islpci_mgt.c +++ b/drivers/net/wireless/prism54/islpci_mgt.c @@ -130,7 +130,7 @@ islpci_mgmt_rx_fill(struct net_device *ndev) buf->pci_addr = pci_map_single(priv->pdev, buf->mem, MGMT_FRAME_SIZE, PCI_DMA_FROMDEVICE); - if (!buf->pci_addr) { + if (pci_dma_mapping_error(priv->pdev, buf->pci_addr)) { printk(KERN_WARNING "Failed to make memory DMA'able.\n"); return -ENOMEM; @@ -217,7 +217,7 @@ islpci_mgt_transmit(struct net_device *ndev, int operation, unsigned long oid, err = -ENOMEM; buf.pci_addr = pci_map_single(priv->pdev, buf.mem, frag_len, PCI_DMA_TODEVICE); - if (!buf.pci_addr) { + if (pci_dma_mapping_error(priv->pdev, buf.pci_addr)) { printk(KERN_WARNING "%s: cannot map PCI memory for mgmt\n", ndev->name); goto error_free; -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] natsemi: add checks for dma mapping errors
On 19.12.2015 05:36, David Miller wrote: > From: Alexey Khoroshilov <khoroshi...@ispras.ru> > Date: Sat, 19 Dec 2015 00:55:37 +0300 > >> @@ -2093,6 +2099,10 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) >> np->tx_skbuff[entry] = skb; >> np->tx_dma[entry] = pci_map_single(np->pci_dev, >> skb->data,skb->len, PCI_DMA_TODEVICE); >> +if (pci_dma_mapping_error(np->pci_dev, np->tx_dma[entry])) { >> +np->tx_skbuff[entry] = NULL; >> +return NETDEV_TX_BUSY; >> +} >> >> np->tx_ring[entry].addr = cpu_to_le32(np->tx_dma[entry]); >> > > Returning NETDEV_TX_BUSY and freeing the SKB will crash the system. I do not quite understand what do you mean by 'freeing the SKB'. At least the patch left skb untouched. But I saw such pattern, for example, in drivers/net/ethernet/freescale/fec_main.c: addr = dma_map_single(>pdev->dev, data, size, DMA_TO_DEVICE); if (dma_mapping_error(>pdev->dev, addr)) { dev_kfree_skb_any(skb); if (net_ratelimit()) netdev_err(ndev, "Tx DMA memory map failed\n"); return NETDEV_TX_BUSY; } > > NETDEV_TX_BUSY is only for buggy drivers that do not manage their > TX ring busy condition correctly, and thus need retries. Ok, I will replace NETDEV_TX_BUSY by dropping the packet. -- Alexey -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2] natsemi: add checks for dma mapping errors
refill_rx() and start_tx() do not check if mapping dma memory succeed. The patch adds the checks and failure handling. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- drivers/net/ethernet/natsemi/natsemi.c | 12 1 file changed, 12 insertions(+) diff --git a/drivers/net/ethernet/natsemi/natsemi.c b/drivers/net/ethernet/natsemi/natsemi.c index b83f7c0fcf99..122c2ee3dfe2 100644 --- a/drivers/net/ethernet/natsemi/natsemi.c +++ b/drivers/net/ethernet/natsemi/natsemi.c @@ -1937,6 +1937,12 @@ static void refill_rx(struct net_device *dev) break; /* Better luck next round. */ np->rx_dma[entry] = pci_map_single(np->pci_dev, skb->data, buflen, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(np->pci_dev, + np->rx_dma[entry])) { + dev_kfree_skb_any(skb); + np->rx_skbuff[entry] = NULL; + break; /* Better luck next round. */ + } np->rx_ring[entry].addr = cpu_to_le32(np->rx_dma[entry]); } np->rx_ring[entry].cmd_status = cpu_to_le32(np->rx_buf_sz); @@ -2093,6 +2099,12 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) np->tx_skbuff[entry] = skb; np->tx_dma[entry] = pci_map_single(np->pci_dev, skb->data,skb->len, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(np->pci_dev, np->tx_dma[entry])) { + np->tx_skbuff[entry] = NULL; + dev_kfree_skb_irq(skb); + dev->stats.tx_dropped++; + return NETDEV_TX_OK; + } np->tx_ring[entry].addr = cpu_to_le32(np->tx_dma[entry]); -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] natsemi: add checks for dma mapping errors
refill_rx() and start_tx() do not check if mapping dma memory succeed. The patch adds the checks and failure handling. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- drivers/net/ethernet/natsemi/natsemi.c | 10 ++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/ethernet/natsemi/natsemi.c b/drivers/net/ethernet/natsemi/natsemi.c index b83f7c0fcf99..282e59d66a52 100644 --- a/drivers/net/ethernet/natsemi/natsemi.c +++ b/drivers/net/ethernet/natsemi/natsemi.c @@ -1937,6 +1937,12 @@ static void refill_rx(struct net_device *dev) break; /* Better luck next round. */ np->rx_dma[entry] = pci_map_single(np->pci_dev, skb->data, buflen, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(np->pci_dev, + np->rx_dma[entry])) { + dev_kfree_skb_any(skb); + np->rx_skbuff[entry] = NULL; + break; /* Better luck next round. */ + } np->rx_ring[entry].addr = cpu_to_le32(np->rx_dma[entry]); } np->rx_ring[entry].cmd_status = cpu_to_le32(np->rx_buf_sz); @@ -2093,6 +2099,10 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) np->tx_skbuff[entry] = skb; np->tx_dma[entry] = pci_map_single(np->pci_dev, skb->data,skb->len, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(np->pci_dev, np->tx_dma[entry])) { + np->tx_skbuff[entry] = NULL; + return NETDEV_TX_BUSY; + } np->tx_ring[entry].addr = cpu_to_le32(np->tx_dma[entry]); -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] vmxnet3: fix checks for dma mapping errors
vmxnet3_drv does check dma_addr with dma_mapping_error() after mapping dma memory. The patch adds the checks and tries to handle failures. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- drivers/net/vmxnet3/vmxnet3_drv.c | 71 +-- 1 file changed, 60 insertions(+), 11 deletions(-) diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 899ea4288197..417903715437 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -587,6 +587,12 @@ vmxnet3_rq_alloc_rx_buf(struct vmxnet3_rx_queue *rq, u32 ring_idx, >pdev->dev, rbi->skb->data, rbi->len, PCI_DMA_FROMDEVICE); + if (dma_mapping_error(>pdev->dev, + rbi->dma_addr)) { + dev_kfree_skb_any(rbi->skb); + rq->stats.rx_buf_alloc_failure++; + break; + } } else { /* rx buffer skipped by the device */ } @@ -605,13 +611,18 @@ vmxnet3_rq_alloc_rx_buf(struct vmxnet3_rx_queue *rq, u32 ring_idx, >pdev->dev, rbi->page, 0, PAGE_SIZE, PCI_DMA_FROMDEVICE); + if (dma_mapping_error(>pdev->dev, + rbi->dma_addr)) { + put_page(rbi->page); + rq->stats.rx_buf_alloc_failure++; + break; + } } else { /* rx buffers skipped by the device */ } val = VMXNET3_RXD_BTYPE_BODY << VMXNET3_RXD_BTYPE_SHIFT; } - BUG_ON(rbi->dma_addr == 0); gd->rxd.addr = cpu_to_le64(rbi->dma_addr); gd->dword[2] = cpu_to_le32((!ring->gen << VMXNET3_RXD_GEN_SHIFT) | val | rbi->len); @@ -655,7 +666,7 @@ vmxnet3_append_frag(struct sk_buff *skb, struct Vmxnet3_RxCompDesc *rcd, } -static void +static int vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx, struct vmxnet3_tx_queue *tq, struct pci_dev *pdev, struct vmxnet3_adapter *adapter) @@ -715,6 +726,8 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx, tbi->dma_addr = dma_map_single(>pdev->dev, skb->data + buf_offset, buf_size, PCI_DMA_TODEVICE); + if (dma_mapping_error(>pdev->dev, tbi->dma_addr)) + return -EFAULT; tbi->len = buf_size; @@ -755,6 +768,8 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx, tbi->dma_addr = skb_frag_dma_map(>pdev->dev, frag, buf_offset, buf_size, DMA_TO_DEVICE); + if (dma_mapping_error(>pdev->dev, tbi->dma_addr)) + return -EFAULT; tbi->len = buf_size; @@ -782,6 +797,8 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx, /* set the last buf_info for the pkt */ tbi->skb = skb; tbi->sop_idx = ctx->sop_txd - tq->tx_ring.base; + + return 0; } @@ -1020,7 +1037,8 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq, } /* fill tx descs related to addr & len */ - vmxnet3_map_pkt(skb, , tq, adapter->pdev, adapter); + if (vmxnet3_map_pkt(skb, , tq, adapter->pdev, adapter)) + goto unlock_drop_pkt; /* setup the EOP desc */ ctx.eop_txd->dword[3] = cpu_to_le32(VMXNET3_TXD_CQ | VMXNET3_TXD_EOP); @@ -1231,6 +1249,7 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq, struct vmxnet3_rx_buf_info *rbi; struct sk_buff *skb, *new_skb = NULL; struct page *new_page = NULL; + dma_addr_t new_dma_addr; int num_to_alloc; struct Vmxnet3_RxDesc *rxd; u32 idx, ring_idx; @@ -1287,6 +1306,21 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
[PATCH] irda: ali-ircc: Fix deadlock in ali_ircc_sir_change_speed()
ali_ircc_sir_change_speed() is always called with self->lock held, so acquiring the lock inside it leads to unavoidable deadlock. Call graph: ali_ircc_sir_change_speed() is called from ali_ircc_change_speed() ali_ircc_fir_hard_xmit() under spin_lock_irqsave(>lock, flags); ali_ircc_sir_hard_xmit() under spin_lock_irqsave(>lock, flags); ali_ircc_net_ioctl() under spin_lock_irqsave(>lock, flags); ali_ircc_dma_xmit_complete() ali_ircc_fir_interrupt() ali_ircc_interrupt() under spin_lock(>lock); ali_ircc_sir_write_wakeup() ali_ircc_sir_interrupt() ali_ircc_interrupt() under spin_lock(>lock); The patch removes spin_lock/unlock from ali_ircc_sir_change_speed(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshi...@ispras.ru> --- drivers/net/irda/ali-ircc.c | 6 -- 1 file changed, 6 deletions(-) diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c index 58ae11a14bb6..64bb44d5d867 100644 --- a/drivers/net/irda/ali-ircc.c +++ b/drivers/net/irda/ali-ircc.c @@ -1031,7 +1031,6 @@ static void ali_ircc_fir_change_speed(struct ali_ircc_cb *priv, __u32 baud) static void ali_ircc_sir_change_speed(struct ali_ircc_cb *priv, __u32 speed) { struct ali_ircc_cb *self = priv; - unsigned long flags; int iobase; int fcr;/* FIFO control reg */ int lcr;/* Line control reg */ @@ -1061,8 +1060,6 @@ static void ali_ircc_sir_change_speed(struct ali_ircc_cb *priv, __u32 speed) /* Update accounting for new speed */ self->io.speed = speed; - spin_lock_irqsave(>lock, flags); - divisor = 115200/speed; fcr = UART_FCR_ENABLE_FIFO; @@ -1089,9 +1086,6 @@ static void ali_ircc_sir_change_speed(struct ali_ircc_cb *priv, __u32 speed) /* without this, the connection will be broken after come back from FIR speed, but with this, the SIR connection is harder to established */ outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase+UART_MCR); - - spin_unlock_irqrestore(>lock, flags); - } static void ali_ircc_change_dongle_speed(struct ali_ircc_cb *priv, int speed) -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] pxa168: fix double deallocation of managed resources
Commit 43d3ddf87a57 (net: pxa168_eth: add device tree support) starts to use managed resources by adding devm_clk_get() and devm_ioremap_resource(), but it leaves explicit iounmap() and clock_put() in pxa168_eth_remove() and in failure handling code of pxa168_eth_probe(). As a result double free can happen. The patch removes explicit resource deallocation. Also it converts clk_disable() to clk_disable_unprepare() to make it symmetrical with clk_prepare_enable(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov khoroshi...@ispras.ru --- drivers/net/ethernet/marvell/pxa168_eth.c | 16 +--- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c index af829c578400..7ace07dad6a3 100644 --- a/drivers/net/ethernet/marvell/pxa168_eth.c +++ b/drivers/net/ethernet/marvell/pxa168_eth.c @@ -1508,7 +1508,8 @@ static int pxa168_eth_probe(struct platform_device *pdev) np = of_parse_phandle(pdev-dev.of_node, phy-handle, 0); if (!np) { dev_err(pdev-dev, missing phy-handle\n); - return -EINVAL; + err = -EINVAL; + goto err_netdev; } of_property_read_u32(np, reg, pep-phy_addr); pep-phy_intf = of_get_phy_mode(pdev-dev.of_node); @@ -1526,7 +1527,7 @@ static int pxa168_eth_probe(struct platform_device *pdev) pep-smi_bus = mdiobus_alloc(); if (pep-smi_bus == NULL) { err = -ENOMEM; - goto err_base; + goto err_netdev; } pep-smi_bus-priv = pep; pep-smi_bus-name = pxa168_eth smi; @@ -1551,13 +1552,10 @@ err_mdiobus: mdiobus_unregister(pep-smi_bus); err_free_mdio: mdiobus_free(pep-smi_bus); -err_base: - iounmap(pep-base); err_netdev: free_netdev(dev); err_clk: - clk_disable(clk); - clk_put(clk); + clk_disable_unprepare(clk); return err; } @@ -1574,13 +1572,9 @@ static int pxa168_eth_remove(struct platform_device *pdev) if (pep-phy) phy_disconnect(pep-phy); if (pep-clk) { - clk_disable(pep-clk); - clk_put(pep-clk); - pep-clk = NULL; + clk_disable_unprepare(pep-clk); } - iounmap(pep-base); - pep-base = NULL; mdiobus_unregister(pep-smi_bus); mdiobus_free(pep-smi_bus); unregister_netdev(dev); -- 1.9.1 -- To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html