[PATCH] tun: fix mismatch in mutex lock-unlock in tun_get_user()

2018-02-16 Thread Alexey Khoroshilov
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

2017-12-15 Thread Alexey Khoroshilov
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

2017-08-10 Thread Alexey Khoroshilov
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

2017-08-10 Thread Alexey Khoroshilov
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

2017-08-08 Thread Alexey Khoroshilov
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

2017-08-04 Thread Alexey Khoroshilov
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

2017-07-12 Thread Alexey Khoroshilov
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()

2017-05-19 Thread Alexey Khoroshilov
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

2017-04-22 Thread Alexey Khoroshilov
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

2017-04-14 Thread Alexey Khoroshilov
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

2017-03-24 Thread Alexey Khoroshilov
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

2017-03-04 Thread Alexey Khoroshilov
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?

2017-03-04 Thread Alexey Khoroshilov
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

2017-01-27 Thread Alexey Khoroshilov
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

2017-01-20 Thread Alexey Khoroshilov
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

2016-12-02 Thread Alexey Khoroshilov
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()

2016-11-18 Thread Alexey Khoroshilov
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()

2016-10-14 Thread Alexey Khoroshilov
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()

2016-10-07 Thread Alexey Khoroshilov
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

2016-09-30 Thread Alexey Khoroshilov
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

2016-06-17 Thread Alexey Khoroshilov
On 17.06.2016 08:38, Cong Wang wrote:
> On Thu, Jun 16, 2016 at 7:14 PM, Cong Wang  wrote:
>>
>> 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

2016-06-16 Thread Alexey Khoroshilov
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()

2016-03-04 Thread Alexey Khoroshilov
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

2016-01-01 Thread Alexey Khoroshilov
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

2015-12-25 Thread Alexey Khoroshilov
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

2015-12-19 Thread Alexey Khoroshilov
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

2015-12-19 Thread Alexey Khoroshilov
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

2015-12-18 Thread Alexey Khoroshilov
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

2015-11-27 Thread Alexey Khoroshilov
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()

2015-09-11 Thread Alexey Khoroshilov
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

2015-04-24 Thread Alexey Khoroshilov
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