Skip to content

Commit 362b37b

Browse files
cavagiudavem330
authored andcommitted
stmmac: fix dma api misuse
Enabling DMA_API_DEBUG, warnings are reported at runtime because the device driver frees DMA memory with wrong functions and it does not call dma_mapping_error after mapping dma memory. The first problem is fixed by of introducing a flag that helps us keeping track which mapping technique was used, so that we can use the right API for unmap. This approach was inspired by the e1000 driver, which uses a similar technique. Signed-off-by: Andre Draszik <andre.draszik@st.com> Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com> Reviewed-by: Denis Kirjanov <kda@linux-powerpc.org> Cc: Hans de Goede <hdegoede@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 5566401 commit 362b37b

File tree

5 files changed

+79
-27
lines changed

5 files changed

+79
-27
lines changed

drivers/net/ethernet/stmicro/stmmac/chain_mode.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
#include "stmmac.h"
3030

31-
static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
31+
static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
3232
{
3333
struct stmmac_priv *priv = (struct stmmac_priv *)p;
3434
unsigned int txsize = priv->dma_tx_size;
@@ -47,7 +47,9 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
4747

4848
desc->des2 = dma_map_single(priv->device, skb->data,
4949
bmax, DMA_TO_DEVICE);
50-
priv->tx_skbuff_dma[entry] = desc->des2;
50+
if (dma_mapping_error(priv->device, desc->des2))
51+
return -1;
52+
priv->tx_skbuff_dma[entry].buf = desc->des2;
5153
priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum, STMMAC_CHAIN_MODE);
5254

5355
while (len != 0) {
@@ -59,7 +61,9 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
5961
desc->des2 = dma_map_single(priv->device,
6062
(skb->data + bmax * i),
6163
bmax, DMA_TO_DEVICE);
62-
priv->tx_skbuff_dma[entry] = desc->des2;
64+
if (dma_mapping_error(priv->device, desc->des2))
65+
return -1;
66+
priv->tx_skbuff_dma[entry].buf = desc->des2;
6367
priv->hw->desc->prepare_tx_desc(desc, 0, bmax, csum,
6468
STMMAC_CHAIN_MODE);
6569
priv->hw->desc->set_tx_owner(desc);
@@ -69,7 +73,9 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
6973
desc->des2 = dma_map_single(priv->device,
7074
(skb->data + bmax * i), len,
7175
DMA_TO_DEVICE);
72-
priv->tx_skbuff_dma[entry] = desc->des2;
76+
if (dma_mapping_error(priv->device, desc->des2))
77+
return -1;
78+
priv->tx_skbuff_dma[entry].buf = desc->des2;
7379
priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
7480
STMMAC_CHAIN_MODE);
7581
priv->hw->desc->set_tx_owner(desc);

drivers/net/ethernet/stmicro/stmmac/common.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ struct stmmac_mode_ops {
425425
void (*init) (void *des, dma_addr_t phy_addr, unsigned int size,
426426
unsigned int extend_desc);
427427
unsigned int (*is_jumbo_frm) (int len, int ehn_desc);
428-
unsigned int (*jumbo_frm) (void *priv, struct sk_buff *skb, int csum);
428+
int (*jumbo_frm)(void *priv, struct sk_buff *skb, int csum);
429429
int (*set_16kib_bfsize)(int mtu);
430430
void (*init_desc3)(struct dma_desc *p);
431431
void (*refill_desc3) (void *priv, struct dma_desc *p);

drivers/net/ethernet/stmicro/stmmac/ring_mode.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
#include "stmmac.h"
3030

31-
static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
31+
static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
3232
{
3333
struct stmmac_priv *priv = (struct stmmac_priv *)p;
3434
unsigned int txsize = priv->dma_tx_size;
@@ -53,7 +53,10 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
5353

5454
desc->des2 = dma_map_single(priv->device, skb->data,
5555
bmax, DMA_TO_DEVICE);
56-
priv->tx_skbuff_dma[entry] = desc->des2;
56+
if (dma_mapping_error(priv->device, desc->des2))
57+
return -1;
58+
59+
priv->tx_skbuff_dma[entry].buf = desc->des2;
5760
desc->des3 = desc->des2 + BUF_SIZE_4KiB;
5861
priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum,
5962
STMMAC_RING_MODE);
@@ -68,7 +71,9 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
6871

6972
desc->des2 = dma_map_single(priv->device, skb->data + bmax,
7073
len, DMA_TO_DEVICE);
71-
priv->tx_skbuff_dma[entry] = desc->des2;
74+
if (dma_mapping_error(priv->device, desc->des2))
75+
return -1;
76+
priv->tx_skbuff_dma[entry].buf = desc->des2;
7277
desc->des3 = desc->des2 + BUF_SIZE_4KiB;
7378
priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
7479
STMMAC_RING_MODE);
@@ -77,7 +82,9 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
7782
} else {
7883
desc->des2 = dma_map_single(priv->device, skb->data,
7984
nopaged_len, DMA_TO_DEVICE);
80-
priv->tx_skbuff_dma[entry] = desc->des2;
85+
if (dma_mapping_error(priv->device, desc->des2))
86+
return -1;
87+
priv->tx_skbuff_dma[entry].buf = desc->des2;
8188
desc->des3 = desc->des2 + BUF_SIZE_4KiB;
8289
priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len, csum,
8390
STMMAC_RING_MODE);

drivers/net/ethernet/stmicro/stmmac/stmmac.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@
3434
#include <linux/ptp_clock_kernel.h>
3535
#include <linux/reset.h>
3636

37+
struct stmmac_tx_info {
38+
dma_addr_t buf;
39+
bool map_as_page;
40+
};
41+
3742
struct stmmac_priv {
3843
/* Frequently used values are kept adjacent for cache effect */
3944
struct dma_extended_desc *dma_etx ____cacheline_aligned_in_smp;
@@ -45,7 +50,7 @@ struct stmmac_priv {
4550
u32 tx_count_frames;
4651
u32 tx_coal_frames;
4752
u32 tx_coal_timer;
48-
dma_addr_t *tx_skbuff_dma;
53+
struct stmmac_tx_info *tx_skbuff_dma;
4954
dma_addr_t dma_tx_phy;
5055
int tx_coalesce;
5156
int hwts_tx_en;

drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,7 +1073,8 @@ static int init_dma_desc_rings(struct net_device *dev)
10731073
else
10741074
p = priv->dma_tx + i;
10751075
p->des2 = 0;
1076-
priv->tx_skbuff_dma[i] = 0;
1076+
priv->tx_skbuff_dma[i].buf = 0;
1077+
priv->tx_skbuff_dma[i].map_as_page = false;
10771078
priv->tx_skbuff[i] = NULL;
10781079
}
10791080

@@ -1112,17 +1113,24 @@ static void dma_free_tx_skbufs(struct stmmac_priv *priv)
11121113
else
11131114
p = priv->dma_tx + i;
11141115

1115-
if (priv->tx_skbuff_dma[i]) {
1116-
dma_unmap_single(priv->device,
1117-
priv->tx_skbuff_dma[i],
1118-
priv->hw->desc->get_tx_len(p),
1119-
DMA_TO_DEVICE);
1120-
priv->tx_skbuff_dma[i] = 0;
1116+
if (priv->tx_skbuff_dma[i].buf) {
1117+
if (priv->tx_skbuff_dma[i].map_as_page)
1118+
dma_unmap_page(priv->device,
1119+
priv->tx_skbuff_dma[i].buf,
1120+
priv->hw->desc->get_tx_len(p),
1121+
DMA_TO_DEVICE);
1122+
else
1123+
dma_unmap_single(priv->device,
1124+
priv->tx_skbuff_dma[i].buf,
1125+
priv->hw->desc->get_tx_len(p),
1126+
DMA_TO_DEVICE);
11211127
}
11221128

11231129
if (priv->tx_skbuff[i] != NULL) {
11241130
dev_kfree_skb_any(priv->tx_skbuff[i]);
11251131
priv->tx_skbuff[i] = NULL;
1132+
priv->tx_skbuff_dma[i].buf = 0;
1133+
priv->tx_skbuff_dma[i].map_as_page = false;
11261134
}
11271135
}
11281136
}
@@ -1143,7 +1151,8 @@ static int alloc_dma_desc_resources(struct stmmac_priv *priv)
11431151
if (!priv->rx_skbuff)
11441152
goto err_rx_skbuff;
11451153

1146-
priv->tx_skbuff_dma = kmalloc_array(txsize, sizeof(dma_addr_t),
1154+
priv->tx_skbuff_dma = kmalloc_array(txsize,
1155+
sizeof(*priv->tx_skbuff_dma),
11471156
GFP_KERNEL);
11481157
if (!priv->tx_skbuff_dma)
11491158
goto err_tx_skbuff_dma;
@@ -1305,12 +1314,19 @@ static void stmmac_tx_clean(struct stmmac_priv *priv)
13051314
pr_debug("%s: curr %d, dirty %d\n", __func__,
13061315
priv->cur_tx, priv->dirty_tx);
13071316

1308-
if (likely(priv->tx_skbuff_dma[entry])) {
1309-
dma_unmap_single(priv->device,
1310-
priv->tx_skbuff_dma[entry],
1311-
priv->hw->desc->get_tx_len(p),
1312-
DMA_TO_DEVICE);
1313-
priv->tx_skbuff_dma[entry] = 0;
1317+
if (likely(priv->tx_skbuff_dma[entry].buf)) {
1318+
if (priv->tx_skbuff_dma[entry].map_as_page)
1319+
dma_unmap_page(priv->device,
1320+
priv->tx_skbuff_dma[entry].buf,
1321+
priv->hw->desc->get_tx_len(p),
1322+
DMA_TO_DEVICE);
1323+
else
1324+
dma_unmap_single(priv->device,
1325+
priv->tx_skbuff_dma[entry].buf,
1326+
priv->hw->desc->get_tx_len(p),
1327+
DMA_TO_DEVICE);
1328+
priv->tx_skbuff_dma[entry].buf = 0;
1329+
priv->tx_skbuff_dma[entry].map_as_page = false;
13141330
}
13151331
priv->hw->mode->clean_desc3(priv, p);
13161332

@@ -1905,12 +1921,16 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
19051921
if (likely(!is_jumbo)) {
19061922
desc->des2 = dma_map_single(priv->device, skb->data,
19071923
nopaged_len, DMA_TO_DEVICE);
1908-
priv->tx_skbuff_dma[entry] = desc->des2;
1924+
if (dma_mapping_error(priv->device, desc->des2))
1925+
goto dma_map_err;
1926+
priv->tx_skbuff_dma[entry].buf = desc->des2;
19091927
priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len,
19101928
csum_insertion, priv->mode);
19111929
} else {
19121930
desc = first;
19131931
entry = priv->hw->mode->jumbo_frm(priv, skb, csum_insertion);
1932+
if (unlikely(entry < 0))
1933+
goto dma_map_err;
19141934
}
19151935

19161936
for (i = 0; i < nfrags; i++) {
@@ -1926,7 +1946,11 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
19261946

19271947
desc->des2 = skb_frag_dma_map(priv->device, frag, 0, len,
19281948
DMA_TO_DEVICE);
1929-
priv->tx_skbuff_dma[entry] = desc->des2;
1949+
if (dma_mapping_error(priv->device, desc->des2))
1950+
goto dma_map_err; /* should reuse desc w/o issues */
1951+
1952+
priv->tx_skbuff_dma[entry].buf = desc->des2;
1953+
priv->tx_skbuff_dma[entry].map_as_page = true;
19301954
priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion,
19311955
priv->mode);
19321956
wmb();
@@ -1993,7 +2017,12 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
19932017
priv->hw->dma->enable_dma_transmission(priv->ioaddr);
19942018

19952019
spin_unlock(&priv->tx_lock);
2020+
return NETDEV_TX_OK;
19962021

2022+
dma_map_err:
2023+
dev_err(priv->device, "Tx dma map failed\n");
2024+
dev_kfree_skb(skb);
2025+
priv->dev->stats.tx_dropped++;
19972026
return NETDEV_TX_OK;
19982027
}
19992028

@@ -2046,7 +2075,12 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv)
20462075
priv->rx_skbuff_dma[entry] =
20472076
dma_map_single(priv->device, skb->data, bfsize,
20482077
DMA_FROM_DEVICE);
2049-
2078+
if (dma_mapping_error(priv->device,
2079+
priv->rx_skbuff_dma[entry])) {
2080+
dev_err(priv->device, "Rx dma map failed\n");
2081+
dev_kfree_skb(skb);
2082+
break;
2083+
}
20502084
p->des2 = priv->rx_skbuff_dma[entry];
20512085

20522086
priv->hw->mode->refill_desc3(priv, p);

0 commit comments

Comments
 (0)