Skip to content

Commit eb6c503

Browse files
Casey Leedomdavem330
authored andcommitted
cxgb4vf: fix some errors in Gather List to skb conversion
There were some errors in the way that internal Gather Lists were being translated into skb's. This also makes the VF Driver look more like the PF Driver to facilitate easier comarison. Signed-off-by: Casey Leedom <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent b94e72e commit eb6c503

File tree

1 file changed

+74
-47
lines changed

1 file changed

+74
-47
lines changed

drivers/net/cxgb4vf/sge.c

Lines changed: 74 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -154,13 +154,14 @@ enum {
154154
*/
155155
RX_COPY_THRES = 256,
156156
RX_PULL_LEN = 128,
157-
};
158157

159-
/*
160-
* Can't define this in the above enum because PKTSHIFT isn't a constant in
161-
* the VF Driver ...
162-
*/
163-
#define RX_PKT_PULL_LEN (RX_PULL_LEN + PKTSHIFT)
158+
/*
159+
* Main body length for sk_buffs used for RX Ethernet packets with
160+
* fragments. Should be >= RX_PULL_LEN but possibly bigger to give
161+
* pskb_may_pull() some room.
162+
*/
163+
RX_SKB_LEN = 512,
164+
};
164165

165166
/*
166167
* Software state per TX descriptor.
@@ -1354,6 +1355,67 @@ int t4vf_eth_xmit(struct sk_buff *skb, struct net_device *dev)
13541355
return NETDEV_TX_OK;
13551356
}
13561357

1358+
/**
1359+
* t4vf_pktgl_to_skb - build an sk_buff from a packet gather list
1360+
* @gl: the gather list
1361+
* @skb_len: size of sk_buff main body if it carries fragments
1362+
* @pull_len: amount of data to move to the sk_buff's main body
1363+
*
1364+
* Builds an sk_buff from the given packet gather list. Returns the
1365+
* sk_buff or %NULL if sk_buff allocation failed.
1366+
*/
1367+
struct sk_buff *t4vf_pktgl_to_skb(const struct pkt_gl *gl,
1368+
unsigned int skb_len, unsigned int pull_len)
1369+
{
1370+
struct sk_buff *skb;
1371+
struct skb_shared_info *ssi;
1372+
1373+
/*
1374+
* If the ingress packet is small enough, allocate an skb large enough
1375+
* for all of the data and copy it inline. Otherwise, allocate an skb
1376+
* with enough room to pull in the header and reference the rest of
1377+
* the data via the skb fragment list.
1378+
*
1379+
* Below we rely on RX_COPY_THRES being less than the smallest Rx
1380+
* buff! size, which is expected since buffers are at least
1381+
* PAGE_SIZEd. In this case packets up to RX_COPY_THRES have only one
1382+
* fragment.
1383+
*/
1384+
if (gl->tot_len <= RX_COPY_THRES) {
1385+
/* small packets have only one fragment */
1386+
skb = alloc_skb(gl->tot_len, GFP_ATOMIC);
1387+
if (unlikely(!skb))
1388+
goto out;
1389+
__skb_put(skb, gl->tot_len);
1390+
skb_copy_to_linear_data(skb, gl->va, gl->tot_len);
1391+
} else {
1392+
skb = alloc_skb(skb_len, GFP_ATOMIC);
1393+
if (unlikely(!skb))
1394+
goto out;
1395+
__skb_put(skb, pull_len);
1396+
skb_copy_to_linear_data(skb, gl->va, pull_len);
1397+
1398+
ssi = skb_shinfo(skb);
1399+
ssi->frags[0].page = gl->frags[0].page;
1400+
ssi->frags[0].page_offset = gl->frags[0].page_offset + pull_len;
1401+
ssi->frags[0].size = gl->frags[0].size - pull_len;
1402+
if (gl->nfrags > 1)
1403+
memcpy(&ssi->frags[1], &gl->frags[1],
1404+
(gl->nfrags-1) * sizeof(skb_frag_t));
1405+
ssi->nr_frags = gl->nfrags;
1406+
1407+
skb->len = gl->tot_len;
1408+
skb->data_len = skb->len - pull_len;
1409+
skb->truesize += skb->data_len;
1410+
1411+
/* Get a reference for the last page, we don't own it */
1412+
get_page(gl->frags[gl->nfrags - 1].page);
1413+
}
1414+
1415+
out:
1416+
return skb;
1417+
}
1418+
13571419
/**
13581420
* t4vf_pktgl_free - free a packet gather list
13591421
* @gl: the gather list
@@ -1463,10 +1525,8 @@ int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp,
14631525
{
14641526
struct sk_buff *skb;
14651527
struct port_info *pi;
1466-
struct skb_shared_info *ssi;
14671528
const struct cpl_rx_pkt *pkt = (void *)&rsp[1];
14681529
bool csum_ok = pkt->csum_calc && !pkt->err_vec;
1469-
unsigned int len = be16_to_cpu(pkt->len);
14701530
struct sge_eth_rxq *rxq = container_of(rspq, struct sge_eth_rxq, rspq);
14711531

14721532
/*
@@ -1481,42 +1541,14 @@ int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp,
14811541
}
14821542

14831543
/*
1484-
* If the ingress packet is small enough, allocate an skb large enough
1485-
* for all of the data and copy it inline. Otherwise, allocate an skb
1486-
* with enough room to pull in the header and reference the rest of
1487-
* the data via the skb fragment list.
1544+
* Convert the Packet Gather List into an skb.
14881545
*/
1489-
if (len <= RX_COPY_THRES) {
1490-
/* small packets have only one fragment */
1491-
skb = alloc_skb(gl->frags[0].size, GFP_ATOMIC);
1492-
if (!skb)
1493-
goto nomem;
1494-
__skb_put(skb, gl->frags[0].size);
1495-
skb_copy_to_linear_data(skb, gl->va, gl->frags[0].size);
1496-
} else {
1497-
skb = alloc_skb(RX_PKT_PULL_LEN, GFP_ATOMIC);
1498-
if (!skb)
1499-
goto nomem;
1500-
__skb_put(skb, RX_PKT_PULL_LEN);
1501-
skb_copy_to_linear_data(skb, gl->va, RX_PKT_PULL_LEN);
1502-
1503-
ssi = skb_shinfo(skb);
1504-
ssi->frags[0].page = gl->frags[0].page;
1505-
ssi->frags[0].page_offset = (gl->frags[0].page_offset +
1506-
RX_PKT_PULL_LEN);
1507-
ssi->frags[0].size = gl->frags[0].size - RX_PKT_PULL_LEN;
1508-
if (gl->nfrags > 1)
1509-
memcpy(&ssi->frags[1], &gl->frags[1],
1510-
(gl->nfrags-1) * sizeof(skb_frag_t));
1511-
ssi->nr_frags = gl->nfrags;
1512-
skb->len = len + PKTSHIFT;
1513-
skb->data_len = skb->len - RX_PKT_PULL_LEN;
1514-
skb->truesize += skb->data_len;
1515-
1516-
/* Get a reference for the last page, we don't own it */
1517-
get_page(gl->frags[gl->nfrags - 1].page);
1546+
skb = t4vf_pktgl_to_skb(gl, RX_SKB_LEN, RX_PULL_LEN);
1547+
if (unlikely(!skb)) {
1548+
t4vf_pktgl_free(gl);
1549+
rxq->stats.rx_drops++;
1550+
return 0;
15181551
}
1519-
15201552
__skb_pull(skb, PKTSHIFT);
15211553
skb->protocol = eth_type_trans(skb, rspq->netdev);
15221554
skb_record_rx_queue(skb, rspq->idx);
@@ -1549,11 +1581,6 @@ int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp,
15491581
netif_receive_skb(skb);
15501582

15511583
return 0;
1552-
1553-
nomem:
1554-
t4vf_pktgl_free(gl);
1555-
rxq->stats.rx_drops++;
1556-
return 0;
15571584
}
15581585

15591586
/**

0 commit comments

Comments
 (0)