Skip to content

Commit defe4b8

Browse files
author
Paolo Abeni
committed
Merge branch 'net-mana-fix-some-tx-processing-bugs'
Haiyang Zhang says: ==================== net: mana: Fix some TX processing bugs Fix TX processing bugs on error handling, tso_bytes calculation, and sge0 size. ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
2 parents d0f9589 + a43e8e9 commit defe4b8

File tree

2 files changed

+149
-67
lines changed

2 files changed

+149
-67
lines changed

drivers/net/ethernet/microsoft/mana/mana_en.c

Lines changed: 146 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -91,63 +91,137 @@ static unsigned int mana_checksum_info(struct sk_buff *skb)
9191
return 0;
9292
}
9393

94+
static void mana_add_sge(struct mana_tx_package *tp, struct mana_skb_head *ash,
95+
int sg_i, dma_addr_t da, int sge_len, u32 gpa_mkey)
96+
{
97+
ash->dma_handle[sg_i] = da;
98+
ash->size[sg_i] = sge_len;
99+
100+
tp->wqe_req.sgl[sg_i].address = da;
101+
tp->wqe_req.sgl[sg_i].mem_key = gpa_mkey;
102+
tp->wqe_req.sgl[sg_i].size = sge_len;
103+
}
104+
94105
static int mana_map_skb(struct sk_buff *skb, struct mana_port_context *apc,
95-
struct mana_tx_package *tp)
106+
struct mana_tx_package *tp, int gso_hs)
96107
{
97108
struct mana_skb_head *ash = (struct mana_skb_head *)skb->head;
109+
int hsg = 1; /* num of SGEs of linear part */
98110
struct gdma_dev *gd = apc->ac->gdma_dev;
111+
int skb_hlen = skb_headlen(skb);
112+
int sge0_len, sge1_len = 0;
99113
struct gdma_context *gc;
100114
struct device *dev;
101115
skb_frag_t *frag;
102116
dma_addr_t da;
117+
int sg_i;
103118
int i;
104119

105120
gc = gd->gdma_context;
106121
dev = gc->dev;
107-
da = dma_map_single(dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
108122

123+
if (gso_hs && gso_hs < skb_hlen) {
124+
sge0_len = gso_hs;
125+
sge1_len = skb_hlen - gso_hs;
126+
} else {
127+
sge0_len = skb_hlen;
128+
}
129+
130+
da = dma_map_single(dev, skb->data, sge0_len, DMA_TO_DEVICE);
109131
if (dma_mapping_error(dev, da))
110132
return -ENOMEM;
111133

112-
ash->dma_handle[0] = da;
113-
ash->size[0] = skb_headlen(skb);
134+
mana_add_sge(tp, ash, 0, da, sge0_len, gd->gpa_mkey);
114135

115-
tp->wqe_req.sgl[0].address = ash->dma_handle[0];
116-
tp->wqe_req.sgl[0].mem_key = gd->gpa_mkey;
117-
tp->wqe_req.sgl[0].size = ash->size[0];
136+
if (sge1_len) {
137+
sg_i = 1;
138+
da = dma_map_single(dev, skb->data + sge0_len, sge1_len,
139+
DMA_TO_DEVICE);
140+
if (dma_mapping_error(dev, da))
141+
goto frag_err;
142+
143+
mana_add_sge(tp, ash, sg_i, da, sge1_len, gd->gpa_mkey);
144+
hsg = 2;
145+
}
118146

119147
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
148+
sg_i = hsg + i;
149+
120150
frag = &skb_shinfo(skb)->frags[i];
121151
da = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag),
122152
DMA_TO_DEVICE);
123-
124153
if (dma_mapping_error(dev, da))
125154
goto frag_err;
126155

127-
ash->dma_handle[i + 1] = da;
128-
ash->size[i + 1] = skb_frag_size(frag);
129-
130-
tp->wqe_req.sgl[i + 1].address = ash->dma_handle[i + 1];
131-
tp->wqe_req.sgl[i + 1].mem_key = gd->gpa_mkey;
132-
tp->wqe_req.sgl[i + 1].size = ash->size[i + 1];
156+
mana_add_sge(tp, ash, sg_i, da, skb_frag_size(frag),
157+
gd->gpa_mkey);
133158
}
134159

135160
return 0;
136161

137162
frag_err:
138-
for (i = i - 1; i >= 0; i--)
139-
dma_unmap_page(dev, ash->dma_handle[i + 1], ash->size[i + 1],
163+
for (i = sg_i - 1; i >= hsg; i--)
164+
dma_unmap_page(dev, ash->dma_handle[i], ash->size[i],
140165
DMA_TO_DEVICE);
141166

142-
dma_unmap_single(dev, ash->dma_handle[0], ash->size[0], DMA_TO_DEVICE);
167+
for (i = hsg - 1; i >= 0; i--)
168+
dma_unmap_single(dev, ash->dma_handle[i], ash->size[i],
169+
DMA_TO_DEVICE);
143170

144171
return -ENOMEM;
145172
}
146173

174+
/* Handle the case when GSO SKB linear length is too large.
175+
* MANA NIC requires GSO packets to put only the packet header to SGE0.
176+
* So, we need 2 SGEs for the skb linear part which contains more than the
177+
* header.
178+
* Return a positive value for the number of SGEs, or a negative value
179+
* for an error.
180+
*/
181+
static int mana_fix_skb_head(struct net_device *ndev, struct sk_buff *skb,
182+
int gso_hs)
183+
{
184+
int num_sge = 1 + skb_shinfo(skb)->nr_frags;
185+
int skb_hlen = skb_headlen(skb);
186+
187+
if (gso_hs < skb_hlen) {
188+
num_sge++;
189+
} else if (gso_hs > skb_hlen) {
190+
if (net_ratelimit())
191+
netdev_err(ndev,
192+
"TX nonlinear head: hs:%d, skb_hlen:%d\n",
193+
gso_hs, skb_hlen);
194+
195+
return -EINVAL;
196+
}
197+
198+
return num_sge;
199+
}
200+
201+
/* Get the GSO packet's header size */
202+
static int mana_get_gso_hs(struct sk_buff *skb)
203+
{
204+
int gso_hs;
205+
206+
if (skb->encapsulation) {
207+
gso_hs = skb_inner_tcp_all_headers(skb);
208+
} else {
209+
if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) {
210+
gso_hs = skb_transport_offset(skb) +
211+
sizeof(struct udphdr);
212+
} else {
213+
gso_hs = skb_tcp_all_headers(skb);
214+
}
215+
}
216+
217+
return gso_hs;
218+
}
219+
147220
netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev)
148221
{
149222
enum mana_tx_pkt_format pkt_fmt = MANA_SHORT_PKT_FMT;
150223
struct mana_port_context *apc = netdev_priv(ndev);
224+
int gso_hs = 0; /* zero for non-GSO pkts */
151225
u16 txq_idx = skb_get_queue_mapping(skb);
152226
struct gdma_dev *gd = apc->ac->gdma_dev;
153227
bool ipv4 = false, ipv6 = false;
@@ -159,7 +233,6 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev)
159233
struct mana_txq *txq;
160234
struct mana_cq *cq;
161235
int err, len;
162-
u16 ihs;
163236

164237
if (unlikely(!apc->port_is_up))
165238
goto tx_drop;
@@ -209,26 +282,33 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev)
209282
pkg.wqe_req.client_data_unit = 0;
210283

211284
pkg.wqe_req.num_sge = 1 + skb_shinfo(skb)->nr_frags;
212-
WARN_ON_ONCE(pkg.wqe_req.num_sge > MAX_TX_WQE_SGL_ENTRIES);
213-
214-
if (pkg.wqe_req.num_sge <= ARRAY_SIZE(pkg.sgl_array)) {
215-
pkg.wqe_req.sgl = pkg.sgl_array;
216-
} else {
217-
pkg.sgl_ptr = kmalloc_array(pkg.wqe_req.num_sge,
218-
sizeof(struct gdma_sge),
219-
GFP_ATOMIC);
220-
if (!pkg.sgl_ptr)
221-
goto tx_drop_count;
222-
223-
pkg.wqe_req.sgl = pkg.sgl_ptr;
224-
}
225285

226286
if (skb->protocol == htons(ETH_P_IP))
227287
ipv4 = true;
228288
else if (skb->protocol == htons(ETH_P_IPV6))
229289
ipv6 = true;
230290

231291
if (skb_is_gso(skb)) {
292+
int num_sge;
293+
294+
gso_hs = mana_get_gso_hs(skb);
295+
296+
num_sge = mana_fix_skb_head(ndev, skb, gso_hs);
297+
if (num_sge > 0)
298+
pkg.wqe_req.num_sge = num_sge;
299+
else
300+
goto tx_drop_count;
301+
302+
u64_stats_update_begin(&tx_stats->syncp);
303+
if (skb->encapsulation) {
304+
tx_stats->tso_inner_packets++;
305+
tx_stats->tso_inner_bytes += skb->len - gso_hs;
306+
} else {
307+
tx_stats->tso_packets++;
308+
tx_stats->tso_bytes += skb->len - gso_hs;
309+
}
310+
u64_stats_update_end(&tx_stats->syncp);
311+
232312
pkg.tx_oob.s_oob.is_outer_ipv4 = ipv4;
233313
pkg.tx_oob.s_oob.is_outer_ipv6 = ipv6;
234314

@@ -252,28 +332,6 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev)
252332
&ipv6_hdr(skb)->daddr, 0,
253333
IPPROTO_TCP, 0);
254334
}
255-
256-
if (skb->encapsulation) {
257-
ihs = skb_inner_tcp_all_headers(skb);
258-
u64_stats_update_begin(&tx_stats->syncp);
259-
tx_stats->tso_inner_packets++;
260-
tx_stats->tso_inner_bytes += skb->len - ihs;
261-
u64_stats_update_end(&tx_stats->syncp);
262-
} else {
263-
if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) {
264-
ihs = skb_transport_offset(skb) + sizeof(struct udphdr);
265-
} else {
266-
ihs = skb_tcp_all_headers(skb);
267-
if (ipv6_has_hopopt_jumbo(skb))
268-
ihs -= sizeof(struct hop_jumbo_hdr);
269-
}
270-
271-
u64_stats_update_begin(&tx_stats->syncp);
272-
tx_stats->tso_packets++;
273-
tx_stats->tso_bytes += skb->len - ihs;
274-
u64_stats_update_end(&tx_stats->syncp);
275-
}
276-
277335
} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
278336
csum_type = mana_checksum_info(skb);
279337

@@ -296,11 +354,25 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev)
296354
} else {
297355
/* Can't do offload of this type of checksum */
298356
if (skb_checksum_help(skb))
299-
goto free_sgl_ptr;
357+
goto tx_drop_count;
300358
}
301359
}
302360

303-
if (mana_map_skb(skb, apc, &pkg)) {
361+
WARN_ON_ONCE(pkg.wqe_req.num_sge > MAX_TX_WQE_SGL_ENTRIES);
362+
363+
if (pkg.wqe_req.num_sge <= ARRAY_SIZE(pkg.sgl_array)) {
364+
pkg.wqe_req.sgl = pkg.sgl_array;
365+
} else {
366+
pkg.sgl_ptr = kmalloc_array(pkg.wqe_req.num_sge,
367+
sizeof(struct gdma_sge),
368+
GFP_ATOMIC);
369+
if (!pkg.sgl_ptr)
370+
goto tx_drop_count;
371+
372+
pkg.wqe_req.sgl = pkg.sgl_ptr;
373+
}
374+
375+
if (mana_map_skb(skb, apc, &pkg, gso_hs)) {
304376
u64_stats_update_begin(&tx_stats->syncp);
305377
tx_stats->mana_map_err++;
306378
u64_stats_update_end(&tx_stats->syncp);
@@ -1258,11 +1330,16 @@ static void mana_unmap_skb(struct sk_buff *skb, struct mana_port_context *apc)
12581330
struct mana_skb_head *ash = (struct mana_skb_head *)skb->head;
12591331
struct gdma_context *gc = apc->ac->gdma_dev->gdma_context;
12601332
struct device *dev = gc->dev;
1261-
int i;
1333+
int hsg, i;
12621334

1263-
dma_unmap_single(dev, ash->dma_handle[0], ash->size[0], DMA_TO_DEVICE);
1335+
/* Number of SGEs of linear part */
1336+
hsg = (skb_is_gso(skb) && skb_headlen(skb) > ash->size[0]) ? 2 : 1;
12641337

1265-
for (i = 1; i < skb_shinfo(skb)->nr_frags + 1; i++)
1338+
for (i = 0; i < hsg; i++)
1339+
dma_unmap_single(dev, ash->dma_handle[i], ash->size[i],
1340+
DMA_TO_DEVICE);
1341+
1342+
for (i = hsg; i < skb_shinfo(skb)->nr_frags + hsg; i++)
12661343
dma_unmap_page(dev, ash->dma_handle[i], ash->size[i],
12671344
DMA_TO_DEVICE);
12681345
}
@@ -1317,19 +1394,23 @@ static void mana_poll_tx_cq(struct mana_cq *cq)
13171394
case CQE_TX_VPORT_IDX_OUT_OF_RANGE:
13181395
case CQE_TX_VPORT_DISABLED:
13191396
case CQE_TX_VLAN_TAGGING_VIOLATION:
1320-
WARN_ONCE(1, "TX: CQE error %d: ignored.\n",
1321-
cqe_oob->cqe_hdr.cqe_type);
1397+
if (net_ratelimit())
1398+
netdev_err(ndev, "TX: CQE error %d\n",
1399+
cqe_oob->cqe_hdr.cqe_type);
1400+
13221401
apc->eth_stats.tx_cqe_err++;
13231402
break;
13241403

13251404
default:
1326-
/* If the CQE type is unexpected, log an error, assert,
1327-
* and go through the error path.
1405+
/* If the CQE type is unknown, log an error,
1406+
* and still free the SKB, update tail, etc.
13281407
*/
1329-
WARN_ONCE(1, "TX: Unexpected CQE type %d: HW BUG?\n",
1330-
cqe_oob->cqe_hdr.cqe_type);
1408+
if (net_ratelimit())
1409+
netdev_err(ndev, "TX: unknown CQE type %d\n",
1410+
cqe_oob->cqe_hdr.cqe_type);
1411+
13311412
apc->eth_stats.tx_cqe_unknown_type++;
1332-
return;
1413+
break;
13331414
}
13341415

13351416
if (WARN_ON_ONCE(txq->gdma_txq_id != completions[i].wq_num))

include/net/mana/mana.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,10 @@ struct mana_txq {
103103

104104
/* skb data and frags dma mappings */
105105
struct mana_skb_head {
106-
dma_addr_t dma_handle[MAX_SKB_FRAGS + 1];
106+
/* GSO pkts may have 2 SGEs for the linear part*/
107+
dma_addr_t dma_handle[MAX_SKB_FRAGS + 2];
107108

108-
u32 size[MAX_SKB_FRAGS + 1];
109+
u32 size[MAX_SKB_FRAGS + 2];
109110
};
110111

111112
#define MANA_HEADROOM sizeof(struct mana_skb_head)

0 commit comments

Comments
 (0)