[PATCH] vmxnet3: fix LRO feature check

Subsystems: networking drivers, the rest, vmware vmxnet3 ethernet driver

STALE3131d

9 messages, 4 authors, 2018-03-20 · open the first message on its own page

[PATCH] vmxnet3: fix LRO feature check

From: Igor Pylypiv <hidden>
Date: 2018-03-17 07:59:48

rxcsum and lro fields were deleted in commit a0d2730c9571 ("net: vmxnet3:
convert to hw_features"). With upgrading to newer version those fields were
resurrected and new code started using uninitialized lro field.
Removing rxcsum and lro fields.

Fixes: 45dac1d6ea04 ("vmxnet3: Changes for vmxnet3 adapter version 2 (fwd)")
Signed-off-by: Igor Pylypiv <redacted>
---
 drivers/net/vmxnet3/vmxnet3_drv.c | 4 +++-
 drivers/net/vmxnet3/vmxnet3_int.h | 3 ---
 2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 8b39c160743d..60776c86aaaf 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -1470,8 +1470,10 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
 			vmxnet3_rx_csum(adapter, skb,
 					(union Vmxnet3_GenericDesc *)rcd);
 			skb->protocol = eth_type_trans(skb, adapter->netdev);
-			if (!rcd->tcp || !adapter->lro)
+			if (!rcd->tcp ||
+			    !adapter->netdev->features & NETIF_F_LRO) {
 				goto not_lro;
+			}
 
 			if (segCnt != 0 && mss != 0) {
 				skb_shinfo(skb)->gso_type = rcd->v4 ?
diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
index 5ba222920e80..3de4cecda35a 100644
--- a/drivers/net/vmxnet3/vmxnet3_int.h
+++ b/drivers/net/vmxnet3/vmxnet3_int.h
@@ -342,9 +342,6 @@ struct vmxnet3_adapter {
 	u8			__iomem *hw_addr1; /* for BAR 1 */
 	u8                              version;
 
-	bool				rxcsum;
-	bool				lro;
-
 #ifdef VMXNET3_RSS
 	struct UPT1_RSSConf		*rss_conf;
 	bool				rss;
-- 
2.16.2

Re: [PATCH] vmxnet3: fix LRO feature check

From: David Miller <davem@davemloft.net>
Date: 2018-03-18 00:20:33

From: Igor Pylypiv <redacted>
Date: Sat, 17 Mar 2018 00:58:52 -0700
rxcsum and lro fields were deleted in commit a0d2730c9571 ("net: vmxnet3:
convert to hw_features"). With upgrading to newer version those fields were
resurrected and new code started using uninitialized lro field.
Removing rxcsum and lro fields.

Fixes: 45dac1d6ea04 ("vmxnet3: Changes for vmxnet3 adapter version 2 (fwd)")
Signed-off-by: Igor Pylypiv <redacted>
Why are you posting this again?

I applied the copy of this patch which was part of a two part series
posted earlier.

Re: [PATCH] vmxnet3: fix LRO feature check

From: Igor Pylypiv <hidden>
Date: 2018-03-18 01:08:59

The 03/17/2018 20:20, David Miller wrote:
From: Igor Pylypiv <redacted>
Date: Sat, 17 Mar 2018 00:58:52 -0700
quoted
rxcsum and lro fields were deleted in commit a0d2730c9571 ("net: vmxnet3:
convert to hw_features"). With upgrading to newer version those fields were
resurrected and new code started using uninitialized lro field.
Removing rxcsum and lro fields.

Fixes: 45dac1d6ea04 ("vmxnet3: Changes for vmxnet3 adapter version 2 (fwd)")
Signed-off-by: Igor Pylypiv <redacted>
Why are you posting this again?

I applied the copy of this patch which was part of a two part series
posted earlier.
No way!!! 
I know it is hard to believe but I found this bug myself.
That's really odd. I took linux-next-20180316 and patch wasn't there.
Now I see the patch in your tree.

Anyway, let me send another one to delete rxcsum at least...

Re: [PATCH] vmxnet3: fix LRO feature check

From: kbuild test robot <hidden>
Date: 2018-03-18 06:38:02

Hi Igor,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on v4.16-rc4]
[also build test WARNING on next-20180316]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Igor-Pylypiv/vmxnet3-fix-LRO-feature-check/20180318-140725
config: i386-randconfig-x003-201811 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All warnings (new ones prefixed by >>):

   drivers/net/vmxnet3/vmxnet3_drv.c: In function 'vmxnet3_rq_rx_complete':
quoted
drivers/net/vmxnet3/vmxnet3_drv.c:1474:8: warning: suggest parentheses around operand of '!' or change '&' to '&&' or '!' to '~' [-Wparentheses]
           !adapter->netdev->features & NETIF_F_LRO) {
           ^~~~~~~~~~~~~~~~~~~~~~~~~~

vim +1474 drivers/net/vmxnet3/vmxnet3_drv.c

  1255	
  1256	static int
  1257	vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
  1258			       struct vmxnet3_adapter *adapter, int quota)
  1259	{
  1260		static const u32 rxprod_reg[2] = {
  1261			VMXNET3_REG_RXPROD, VMXNET3_REG_RXPROD2
  1262		};
  1263		u32 num_pkts = 0;
  1264		bool skip_page_frags = false;
  1265		struct Vmxnet3_RxCompDesc *rcd;
  1266		struct vmxnet3_rx_ctx *ctx = &rq->rx_ctx;
  1267		u16 segCnt = 0, mss = 0;
  1268	#ifdef __BIG_ENDIAN_BITFIELD
  1269		struct Vmxnet3_RxDesc rxCmdDesc;
  1270		struct Vmxnet3_RxCompDesc rxComp;
  1271	#endif
  1272		vmxnet3_getRxComp(rcd, &rq->comp_ring.base[rq->comp_ring.next2proc].rcd,
  1273				  &rxComp);
  1274		while (rcd->gen == rq->comp_ring.gen) {
  1275			struct vmxnet3_rx_buf_info *rbi;
  1276			struct sk_buff *skb, *new_skb = NULL;
  1277			struct page *new_page = NULL;
  1278			dma_addr_t new_dma_addr;
  1279			int num_to_alloc;
  1280			struct Vmxnet3_RxDesc *rxd;
  1281			u32 idx, ring_idx;
  1282			struct vmxnet3_cmd_ring	*ring = NULL;
  1283			if (num_pkts >= quota) {
  1284				/* we may stop even before we see the EOP desc of
  1285				 * the current pkt
  1286				 */
  1287				break;
  1288			}
  1289			BUG_ON(rcd->rqID != rq->qid && rcd->rqID != rq->qid2 &&
  1290			       rcd->rqID != rq->dataRingQid);
  1291			idx = rcd->rxdIdx;
  1292			ring_idx = VMXNET3_GET_RING_IDX(adapter, rcd->rqID);
  1293			ring = rq->rx_ring + ring_idx;
  1294			vmxnet3_getRxDesc(rxd, &rq->rx_ring[ring_idx].base[idx].rxd,
  1295					  &rxCmdDesc);
  1296			rbi = rq->buf_info[ring_idx] + idx;
  1297	
  1298			BUG_ON(rxd->addr != rbi->dma_addr ||
  1299			       rxd->len != rbi->len);
  1300	
  1301			if (unlikely(rcd->eop && rcd->err)) {
  1302				vmxnet3_rx_error(rq, rcd, ctx, adapter);
  1303				goto rcd_done;
  1304			}
  1305	
  1306			if (rcd->sop) { /* first buf of the pkt */
  1307				bool rxDataRingUsed;
  1308				u16 len;
  1309	
  1310				BUG_ON(rxd->btype != VMXNET3_RXD_BTYPE_HEAD ||
  1311				       (rcd->rqID != rq->qid &&
  1312					rcd->rqID != rq->dataRingQid));
  1313	
  1314				BUG_ON(rbi->buf_type != VMXNET3_RX_BUF_SKB);
  1315				BUG_ON(ctx->skb != NULL || rbi->skb == NULL);
  1316	
  1317				if (unlikely(rcd->len == 0)) {
  1318					/* Pretend the rx buffer is skipped. */
  1319					BUG_ON(!(rcd->sop && rcd->eop));
  1320					netdev_dbg(adapter->netdev,
  1321						"rxRing[%u][%u] 0 length\n",
  1322						ring_idx, idx);
  1323					goto rcd_done;
  1324				}
  1325	
  1326				skip_page_frags = false;
  1327				ctx->skb = rbi->skb;
  1328	
  1329				rxDataRingUsed =
  1330					VMXNET3_RX_DATA_RING(adapter, rcd->rqID);
  1331				len = rxDataRingUsed ? rcd->len : rbi->len;
  1332				new_skb = netdev_alloc_skb_ip_align(adapter->netdev,
  1333								    len);
  1334				if (new_skb == NULL) {
  1335					/* Skb allocation failed, do not handover this
  1336					 * skb to stack. Reuse it. Drop the existing pkt
  1337					 */
  1338					rq->stats.rx_buf_alloc_failure++;
  1339					ctx->skb = NULL;
  1340					rq->stats.drop_total++;
  1341					skip_page_frags = true;
  1342					goto rcd_done;
  1343				}
  1344	
  1345				if (rxDataRingUsed) {
  1346					size_t sz;
  1347	
  1348					BUG_ON(rcd->len > rq->data_ring.desc_size);
  1349	
  1350					ctx->skb = new_skb;
  1351					sz = rcd->rxdIdx * rq->data_ring.desc_size;
  1352					memcpy(new_skb->data,
  1353					       &rq->data_ring.base[sz], rcd->len);
  1354				} else {
  1355					ctx->skb = rbi->skb;
  1356	
  1357					new_dma_addr =
  1358						dma_map_single(&adapter->pdev->dev,
  1359							       new_skb->data, rbi->len,
  1360							       PCI_DMA_FROMDEVICE);
  1361					if (dma_mapping_error(&adapter->pdev->dev,
  1362							      new_dma_addr)) {
  1363						dev_kfree_skb(new_skb);
  1364						/* Skb allocation failed, do not
  1365						 * handover this skb to stack. Reuse
  1366						 * it. Drop the existing pkt.
  1367						 */
  1368						rq->stats.rx_buf_alloc_failure++;
  1369						ctx->skb = NULL;
  1370						rq->stats.drop_total++;
  1371						skip_page_frags = true;
  1372						goto rcd_done;
  1373					}
  1374	
  1375					dma_unmap_single(&adapter->pdev->dev,
  1376							 rbi->dma_addr,
  1377							 rbi->len,
  1378							 PCI_DMA_FROMDEVICE);
  1379	
  1380					/* Immediate refill */
  1381					rbi->skb = new_skb;
  1382					rbi->dma_addr = new_dma_addr;
  1383					rxd->addr = cpu_to_le64(rbi->dma_addr);
  1384					rxd->len = rbi->len;
  1385				}
  1386	
  1387	#ifdef VMXNET3_RSS
  1388				if (rcd->rssType != VMXNET3_RCD_RSS_TYPE_NONE &&
  1389				    (adapter->netdev->features & NETIF_F_RXHASH))
  1390					skb_set_hash(ctx->skb,
  1391						     le32_to_cpu(rcd->rssHash),
  1392						     PKT_HASH_TYPE_L3);
  1393	#endif
  1394				skb_put(ctx->skb, rcd->len);
  1395	
  1396				if (VMXNET3_VERSION_GE_2(adapter) &&
  1397				    rcd->type == VMXNET3_CDTYPE_RXCOMP_LRO) {
  1398					struct Vmxnet3_RxCompDescExt *rcdlro;
  1399					rcdlro = (struct Vmxnet3_RxCompDescExt *)rcd;
  1400	
  1401					segCnt = rcdlro->segCnt;
  1402					WARN_ON_ONCE(segCnt == 0);
  1403					mss = rcdlro->mss;
  1404					if (unlikely(segCnt <= 1))
  1405						segCnt = 0;
  1406				} else {
  1407					segCnt = 0;
  1408				}
  1409			} else {
  1410				BUG_ON(ctx->skb == NULL && !skip_page_frags);
  1411	
  1412				/* non SOP buffer must be type 1 in most cases */
  1413				BUG_ON(rbi->buf_type != VMXNET3_RX_BUF_PAGE);
  1414				BUG_ON(rxd->btype != VMXNET3_RXD_BTYPE_BODY);
  1415	
  1416				/* If an sop buffer was dropped, skip all
  1417				 * following non-sop fragments. They will be reused.
  1418				 */
  1419				if (skip_page_frags)
  1420					goto rcd_done;
  1421	
  1422				if (rcd->len) {
  1423					new_page = alloc_page(GFP_ATOMIC);
  1424					/* Replacement page frag could not be allocated.
  1425					 * Reuse this page. Drop the pkt and free the
  1426					 * skb which contained this page as a frag. Skip
  1427					 * processing all the following non-sop frags.
  1428					 */
  1429					if (unlikely(!new_page)) {
  1430						rq->stats.rx_buf_alloc_failure++;
  1431						dev_kfree_skb(ctx->skb);
  1432						ctx->skb = NULL;
  1433						skip_page_frags = true;
  1434						goto rcd_done;
  1435					}
  1436					new_dma_addr = dma_map_page(&adapter->pdev->dev,
  1437								    new_page,
  1438								    0, PAGE_SIZE,
  1439								    PCI_DMA_FROMDEVICE);
  1440					if (dma_mapping_error(&adapter->pdev->dev,
  1441							      new_dma_addr)) {
  1442						put_page(new_page);
  1443						rq->stats.rx_buf_alloc_failure++;
  1444						dev_kfree_skb(ctx->skb);
  1445						ctx->skb = NULL;
  1446						skip_page_frags = true;
  1447						goto rcd_done;
  1448					}
  1449	
  1450					dma_unmap_page(&adapter->pdev->dev,
  1451						       rbi->dma_addr, rbi->len,
  1452						       PCI_DMA_FROMDEVICE);
  1453	
  1454					vmxnet3_append_frag(ctx->skb, rcd, rbi);
  1455	
  1456					/* Immediate refill */
  1457					rbi->page = new_page;
  1458					rbi->dma_addr = new_dma_addr;
  1459					rxd->addr = cpu_to_le64(rbi->dma_addr);
  1460					rxd->len = rbi->len;
  1461				}
  1462			}
  1463	
  1464	
  1465			skb = ctx->skb;
  1466			if (rcd->eop) {
  1467				u32 mtu = adapter->netdev->mtu;
  1468				skb->len += skb->data_len;
  1469	
  1470				vmxnet3_rx_csum(adapter, skb,
  1471						(union Vmxnet3_GenericDesc *)rcd);
  1472				skb->protocol = eth_type_trans(skb, adapter->netdev);
  1473				if (!rcd->tcp ||
1474				    !adapter->netdev->features & NETIF_F_LRO) {
  1475					goto not_lro;
  1476				}
  1477	
  1478				if (segCnt != 0 && mss != 0) {
  1479					skb_shinfo(skb)->gso_type = rcd->v4 ?
  1480						SKB_GSO_TCPV4 : SKB_GSO_TCPV6;
  1481					skb_shinfo(skb)->gso_size = mss;
  1482					skb_shinfo(skb)->gso_segs = segCnt;
  1483				} else if (segCnt != 0 || skb->len > mtu) {
  1484					u32 hlen;
  1485	
  1486					hlen = vmxnet3_get_hdr_len(adapter, skb,
  1487						(union Vmxnet3_GenericDesc *)rcd);
  1488					if (hlen == 0)
  1489						goto not_lro;
  1490	
  1491					skb_shinfo(skb)->gso_type =
  1492						rcd->v4 ? SKB_GSO_TCPV4 : SKB_GSO_TCPV6;
  1493					if (segCnt != 0) {
  1494						skb_shinfo(skb)->gso_segs = segCnt;
  1495						skb_shinfo(skb)->gso_size =
  1496							DIV_ROUND_UP(skb->len -
  1497								hlen, segCnt);
  1498					} else {
  1499						skb_shinfo(skb)->gso_size = mtu - hlen;
  1500					}
  1501				}
  1502	not_lro:
  1503				if (unlikely(rcd->ts))
  1504					__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), rcd->tci);
  1505	
  1506				if (adapter->netdev->features & NETIF_F_LRO)
  1507					netif_receive_skb(skb);
  1508				else
  1509					napi_gro_receive(&rq->napi, skb);
  1510	
  1511				ctx->skb = NULL;
  1512				num_pkts++;
  1513			}
  1514	
  1515	rcd_done:
  1516			/* device may have skipped some rx descs */
  1517			ring->next2comp = idx;
  1518			num_to_alloc = vmxnet3_cmd_ring_desc_avail(ring);
  1519			ring = rq->rx_ring + ring_idx;
  1520			while (num_to_alloc) {
  1521				vmxnet3_getRxDesc(rxd, &ring->base[ring->next2fill].rxd,
  1522						  &rxCmdDesc);
  1523				BUG_ON(!rxd->addr);
  1524	
  1525				/* Recv desc is ready to be used by the device */
  1526				rxd->gen = ring->gen;
  1527				vmxnet3_cmd_ring_adv_next2fill(ring);
  1528				num_to_alloc--;
  1529			}
  1530	
  1531			/* if needed, update the register */
  1532			if (unlikely(rq->shared->updateRxProd)) {
  1533				VMXNET3_WRITE_BAR0_REG(adapter,
  1534						       rxprod_reg[ring_idx] + rq->qid * 8,
  1535						       ring->next2fill);
  1536			}
  1537	
  1538			vmxnet3_comp_ring_adv_next2proc(&rq->comp_ring);
  1539			vmxnet3_getRxComp(rcd,
  1540					  &rq->comp_ring.base[rq->comp_ring.next2proc].rcd, &rxComp);
  1541		}
  1542	
  1543		return num_pkts;
  1544	}
  1545	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

Re: [PATCH] vmxnet3: fix LRO feature check

From: kbuild test robot <hidden>
Date: 2018-03-18 11:24:14

Hi Igor,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on v4.16-rc4]
[also build test WARNING on next-20180316]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Igor-Pylypiv/vmxnet3-fix-LRO-feature-check/20180318-140725
config: x86_64-randconfig-s3-03181820 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All warnings (new ones prefixed by >>):

   In file included from include/linux/kernel.h:10:0,
                    from include/linux/list.h:9,
                    from include/linux/module.h:9,
                    from drivers/net//vmxnet3/vmxnet3_drv.c:27:
   drivers/net//vmxnet3/vmxnet3_drv.c: In function 'vmxnet3_rq_rx_complete':
   drivers/net//vmxnet3/vmxnet3_drv.c:1474:8: warning: suggest parentheses around operand of '!' or change '&' to '&&' or '!' to '~' [-Wparentheses]
           !adapter->netdev->features & NETIF_F_LRO) {
           ^~~~~~~~~~~~~~~~~~~
   include/linux/compiler.h:58:30: note: in definition of macro '__trace_if'
     if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
                                 ^~~~
quoted
drivers/net//vmxnet3/vmxnet3_drv.c:1473:4: note: in expansion of macro 'if'
       if (!rcd->tcp ||
       ^~
   drivers/net//vmxnet3/vmxnet3_drv.c:1474:8: warning: suggest parentheses around operand of '!' or change '&' to '&&' or '!' to '~' [-Wparentheses]
           !adapter->netdev->features & NETIF_F_LRO) {
           ^~~~~~~~~~~~~~~~~~~
   include/linux/compiler.h:58:42: note: in definition of macro '__trace_if'
     if (__builtin_constant_p(!!(cond)) ? !!(cond) :   \
                                             ^~~~
quoted
drivers/net//vmxnet3/vmxnet3_drv.c:1473:4: note: in expansion of macro 'if'
       if (!rcd->tcp ||
       ^~
   drivers/net//vmxnet3/vmxnet3_drv.c:1474:8: warning: suggest parentheses around operand of '!' or change '&' to '&&' or '!' to '~' [-Wparentheses]
           !adapter->netdev->features & NETIF_F_LRO) {
           ^~~~~~~~~~~~~~~~~~~
   include/linux/compiler.h:69:16: note: in definition of macro '__trace_if'
      ______r = !!(cond);     \
                   ^~~~
quoted
drivers/net//vmxnet3/vmxnet3_drv.c:1473:4: note: in expansion of macro 'if'
       if (!rcd->tcp ||
       ^~

vim +/if +1473 drivers/net//vmxnet3/vmxnet3_drv.c

  1255	
  1256	static int
  1257	vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
  1258			       struct vmxnet3_adapter *adapter, int quota)
  1259	{
  1260		static const u32 rxprod_reg[2] = {
  1261			VMXNET3_REG_RXPROD, VMXNET3_REG_RXPROD2
  1262		};
  1263		u32 num_pkts = 0;
  1264		bool skip_page_frags = false;
  1265		struct Vmxnet3_RxCompDesc *rcd;
  1266		struct vmxnet3_rx_ctx *ctx = &rq->rx_ctx;
  1267		u16 segCnt = 0, mss = 0;
  1268	#ifdef __BIG_ENDIAN_BITFIELD
  1269		struct Vmxnet3_RxDesc rxCmdDesc;
  1270		struct Vmxnet3_RxCompDesc rxComp;
  1271	#endif
  1272		vmxnet3_getRxComp(rcd, &rq->comp_ring.base[rq->comp_ring.next2proc].rcd,
  1273				  &rxComp);
  1274		while (rcd->gen == rq->comp_ring.gen) {
  1275			struct vmxnet3_rx_buf_info *rbi;
  1276			struct sk_buff *skb, *new_skb = NULL;
  1277			struct page *new_page = NULL;
  1278			dma_addr_t new_dma_addr;
  1279			int num_to_alloc;
  1280			struct Vmxnet3_RxDesc *rxd;
  1281			u32 idx, ring_idx;
  1282			struct vmxnet3_cmd_ring	*ring = NULL;
  1283			if (num_pkts >= quota) {
  1284				/* we may stop even before we see the EOP desc of
  1285				 * the current pkt
  1286				 */
  1287				break;
  1288			}
  1289			BUG_ON(rcd->rqID != rq->qid && rcd->rqID != rq->qid2 &&
  1290			       rcd->rqID != rq->dataRingQid);
  1291			idx = rcd->rxdIdx;
  1292			ring_idx = VMXNET3_GET_RING_IDX(adapter, rcd->rqID);
  1293			ring = rq->rx_ring + ring_idx;
  1294			vmxnet3_getRxDesc(rxd, &rq->rx_ring[ring_idx].base[idx].rxd,
  1295					  &rxCmdDesc);
  1296			rbi = rq->buf_info[ring_idx] + idx;
  1297	
  1298			BUG_ON(rxd->addr != rbi->dma_addr ||
  1299			       rxd->len != rbi->len);
  1300	
  1301			if (unlikely(rcd->eop && rcd->err)) {
  1302				vmxnet3_rx_error(rq, rcd, ctx, adapter);
  1303				goto rcd_done;
  1304			}
  1305	
  1306			if (rcd->sop) { /* first buf of the pkt */
  1307				bool rxDataRingUsed;
  1308				u16 len;
  1309	
  1310				BUG_ON(rxd->btype != VMXNET3_RXD_BTYPE_HEAD ||
  1311				       (rcd->rqID != rq->qid &&
  1312					rcd->rqID != rq->dataRingQid));
  1313	
  1314				BUG_ON(rbi->buf_type != VMXNET3_RX_BUF_SKB);
  1315				BUG_ON(ctx->skb != NULL || rbi->skb == NULL);
  1316	
  1317				if (unlikely(rcd->len == 0)) {
  1318					/* Pretend the rx buffer is skipped. */
  1319					BUG_ON(!(rcd->sop && rcd->eop));
  1320					netdev_dbg(adapter->netdev,
  1321						"rxRing[%u][%u] 0 length\n",
  1322						ring_idx, idx);
  1323					goto rcd_done;
  1324				}
  1325	
  1326				skip_page_frags = false;
  1327				ctx->skb = rbi->skb;
  1328	
  1329				rxDataRingUsed =
  1330					VMXNET3_RX_DATA_RING(adapter, rcd->rqID);
  1331				len = rxDataRingUsed ? rcd->len : rbi->len;
  1332				new_skb = netdev_alloc_skb_ip_align(adapter->netdev,
  1333								    len);
  1334				if (new_skb == NULL) {
  1335					/* Skb allocation failed, do not handover this
  1336					 * skb to stack. Reuse it. Drop the existing pkt
  1337					 */
  1338					rq->stats.rx_buf_alloc_failure++;
  1339					ctx->skb = NULL;
  1340					rq->stats.drop_total++;
  1341					skip_page_frags = true;
  1342					goto rcd_done;
  1343				}
  1344	
  1345				if (rxDataRingUsed) {
  1346					size_t sz;
  1347	
  1348					BUG_ON(rcd->len > rq->data_ring.desc_size);
  1349	
  1350					ctx->skb = new_skb;
  1351					sz = rcd->rxdIdx * rq->data_ring.desc_size;
  1352					memcpy(new_skb->data,
  1353					       &rq->data_ring.base[sz], rcd->len);
  1354				} else {
  1355					ctx->skb = rbi->skb;
  1356	
  1357					new_dma_addr =
  1358						dma_map_single(&adapter->pdev->dev,
  1359							       new_skb->data, rbi->len,
  1360							       PCI_DMA_FROMDEVICE);
  1361					if (dma_mapping_error(&adapter->pdev->dev,
  1362							      new_dma_addr)) {
  1363						dev_kfree_skb(new_skb);
  1364						/* Skb allocation failed, do not
  1365						 * handover this skb to stack. Reuse
  1366						 * it. Drop the existing pkt.
  1367						 */
  1368						rq->stats.rx_buf_alloc_failure++;
  1369						ctx->skb = NULL;
  1370						rq->stats.drop_total++;
  1371						skip_page_frags = true;
  1372						goto rcd_done;
  1373					}
  1374	
  1375					dma_unmap_single(&adapter->pdev->dev,
  1376							 rbi->dma_addr,
  1377							 rbi->len,
  1378							 PCI_DMA_FROMDEVICE);
  1379	
  1380					/* Immediate refill */
  1381					rbi->skb = new_skb;
  1382					rbi->dma_addr = new_dma_addr;
  1383					rxd->addr = cpu_to_le64(rbi->dma_addr);
  1384					rxd->len = rbi->len;
  1385				}
  1386	
  1387	#ifdef VMXNET3_RSS
  1388				if (rcd->rssType != VMXNET3_RCD_RSS_TYPE_NONE &&
  1389				    (adapter->netdev->features & NETIF_F_RXHASH))
  1390					skb_set_hash(ctx->skb,
  1391						     le32_to_cpu(rcd->rssHash),
  1392						     PKT_HASH_TYPE_L3);
  1393	#endif
  1394				skb_put(ctx->skb, rcd->len);
  1395	
  1396				if (VMXNET3_VERSION_GE_2(adapter) &&
  1397				    rcd->type == VMXNET3_CDTYPE_RXCOMP_LRO) {
  1398					struct Vmxnet3_RxCompDescExt *rcdlro;
  1399					rcdlro = (struct Vmxnet3_RxCompDescExt *)rcd;
  1400	
  1401					segCnt = rcdlro->segCnt;
  1402					WARN_ON_ONCE(segCnt == 0);
  1403					mss = rcdlro->mss;
  1404					if (unlikely(segCnt <= 1))
  1405						segCnt = 0;
  1406				} else {
  1407					segCnt = 0;
  1408				}
  1409			} else {
  1410				BUG_ON(ctx->skb == NULL && !skip_page_frags);
  1411	
  1412				/* non SOP buffer must be type 1 in most cases */
  1413				BUG_ON(rbi->buf_type != VMXNET3_RX_BUF_PAGE);
  1414				BUG_ON(rxd->btype != VMXNET3_RXD_BTYPE_BODY);
  1415	
  1416				/* If an sop buffer was dropped, skip all
  1417				 * following non-sop fragments. They will be reused.
  1418				 */
  1419				if (skip_page_frags)
  1420					goto rcd_done;
  1421	
  1422				if (rcd->len) {
  1423					new_page = alloc_page(GFP_ATOMIC);
  1424					/* Replacement page frag could not be allocated.
  1425					 * Reuse this page. Drop the pkt and free the
  1426					 * skb which contained this page as a frag. Skip
  1427					 * processing all the following non-sop frags.
  1428					 */
  1429					if (unlikely(!new_page)) {
  1430						rq->stats.rx_buf_alloc_failure++;
  1431						dev_kfree_skb(ctx->skb);
  1432						ctx->skb = NULL;
  1433						skip_page_frags = true;
  1434						goto rcd_done;
  1435					}
  1436					new_dma_addr = dma_map_page(&adapter->pdev->dev,
  1437								    new_page,
  1438								    0, PAGE_SIZE,
  1439								    PCI_DMA_FROMDEVICE);
  1440					if (dma_mapping_error(&adapter->pdev->dev,
  1441							      new_dma_addr)) {
  1442						put_page(new_page);
  1443						rq->stats.rx_buf_alloc_failure++;
  1444						dev_kfree_skb(ctx->skb);
  1445						ctx->skb = NULL;
  1446						skip_page_frags = true;
  1447						goto rcd_done;
  1448					}
  1449	
  1450					dma_unmap_page(&adapter->pdev->dev,
  1451						       rbi->dma_addr, rbi->len,
  1452						       PCI_DMA_FROMDEVICE);
  1453	
  1454					vmxnet3_append_frag(ctx->skb, rcd, rbi);
  1455	
  1456					/* Immediate refill */
  1457					rbi->page = new_page;
  1458					rbi->dma_addr = new_dma_addr;
  1459					rxd->addr = cpu_to_le64(rbi->dma_addr);
  1460					rxd->len = rbi->len;
  1461				}
  1462			}
  1463	
  1464	
  1465			skb = ctx->skb;
  1466			if (rcd->eop) {
  1467				u32 mtu = adapter->netdev->mtu;
  1468				skb->len += skb->data_len;
  1469	
  1470				vmxnet3_rx_csum(adapter, skb,
  1471						(union Vmxnet3_GenericDesc *)rcd);
  1472				skb->protocol = eth_type_trans(skb, adapter->netdev);
1473				if (!rcd->tcp ||
  1474				    !adapter->netdev->features & NETIF_F_LRO) {
  1475					goto not_lro;
  1476				}
  1477	
  1478				if (segCnt != 0 && mss != 0) {
  1479					skb_shinfo(skb)->gso_type = rcd->v4 ?
  1480						SKB_GSO_TCPV4 : SKB_GSO_TCPV6;
  1481					skb_shinfo(skb)->gso_size = mss;
  1482					skb_shinfo(skb)->gso_segs = segCnt;
  1483				} else if (segCnt != 0 || skb->len > mtu) {
  1484					u32 hlen;
  1485	
  1486					hlen = vmxnet3_get_hdr_len(adapter, skb,
  1487						(union Vmxnet3_GenericDesc *)rcd);
  1488					if (hlen == 0)
  1489						goto not_lro;
  1490	
  1491					skb_shinfo(skb)->gso_type =
  1492						rcd->v4 ? SKB_GSO_TCPV4 : SKB_GSO_TCPV6;
  1493					if (segCnt != 0) {
  1494						skb_shinfo(skb)->gso_segs = segCnt;
  1495						skb_shinfo(skb)->gso_size =
  1496							DIV_ROUND_UP(skb->len -
  1497								hlen, segCnt);
  1498					} else {
  1499						skb_shinfo(skb)->gso_size = mtu - hlen;
  1500					}
  1501				}
  1502	not_lro:
  1503				if (unlikely(rcd->ts))
  1504					__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), rcd->tci);
  1505	
  1506				if (adapter->netdev->features & NETIF_F_LRO)
  1507					netif_receive_skb(skb);
  1508				else
  1509					napi_gro_receive(&rq->napi, skb);
  1510	
  1511				ctx->skb = NULL;
  1512				num_pkts++;
  1513			}
  1514	
  1515	rcd_done:
  1516			/* device may have skipped some rx descs */
  1517			ring->next2comp = idx;
  1518			num_to_alloc = vmxnet3_cmd_ring_desc_avail(ring);
  1519			ring = rq->rx_ring + ring_idx;
  1520			while (num_to_alloc) {
  1521				vmxnet3_getRxDesc(rxd, &ring->base[ring->next2fill].rxd,
  1522						  &rxCmdDesc);
  1523				BUG_ON(!rxd->addr);
  1524	
  1525				/* Recv desc is ready to be used by the device */
  1526				rxd->gen = ring->gen;
  1527				vmxnet3_cmd_ring_adv_next2fill(ring);
  1528				num_to_alloc--;
  1529			}
  1530	
  1531			/* if needed, update the register */
  1532			if (unlikely(rq->shared->updateRxProd)) {
  1533				VMXNET3_WRITE_BAR0_REG(adapter,
  1534						       rxprod_reg[ring_idx] + rq->qid * 8,
  1535						       ring->next2fill);
  1536			}
  1537	
  1538			vmxnet3_comp_ring_adv_next2proc(&rq->comp_ring);
  1539			vmxnet3_getRxComp(rcd,
  1540					  &rq->comp_ring.base[rq->comp_ring.next2proc].rcd, &rxComp);
  1541		}
  1542	
  1543		return num_pkts;
  1544	}
  1545	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

Re: [PATCH] vmxnet3: fix LRO feature check

From: David Miller <davem@davemloft.net>
Date: 2018-03-20 14:57:24

From: kbuild test robot <redacted>
Date: Sun, 18 Mar 2018 14:37:35 +0800
All warnings (new ones prefixed by >>):

   drivers/net/vmxnet3/vmxnet3_drv.c: In function 'vmxnet3_rq_rx_complete':
quoted
quoted
drivers/net/vmxnet3/vmxnet3_drv.c:1474:8: warning: suggest parentheses around operand of '!' or change '&' to '&&' or '!' to '~' [-Wparentheses]
           !adapter->netdev->features & NETIF_F_LRO) {
           ^~~~~~~~~~~~~~~~~~~~~~~~~~
Igor, I will fix this up for you.  But it is clear that this patch wasn't tested
very well.

Because !adapter->netdev->features evaluates wholly before the "& NETIF_F_LRO",
the flags aren't being tested properly at all.

Re: [PATCH] vmxnet3: fix LRO feature check

From: Igor Pylypiv <hidden>
Date: 2018-03-20 18:24:52

The 03/20/2018 10:57, David Miller wrote:
From: kbuild test robot <redacted>
Date: Sun, 18 Mar 2018 14:37:35 +0800
quoted
All warnings (new ones prefixed by >>):

   drivers/net/vmxnet3/vmxnet3_drv.c: In function 'vmxnet3_rq_rx_complete':
quoted
quoted
drivers/net/vmxnet3/vmxnet3_drv.c:1474:8: warning: suggest parentheses around operand of '!' or change '&' to '&&' or '!' to '~' [-Wparentheses]
           !adapter->netdev->features & NETIF_F_LRO) {
           ^~~~~~~~~~~~~~~~~~~~~~~~~~
Igor, I will fix this up for you.  But it is clear that this patch wasn't tested
very well.

Because !adapter->netdev->features evaluates wholly before the "& NETIF_F_LRO",
the flags aren't being tested properly at all.
My bad.

I have even been looking at C operator precedence table:

----------------------------
| Operator | Associativity |
|--------------------------|
| ++ --    | right-to-left |
| + -      |               |
| ! ~      |               |
| (type)   |               |
| *        |               |
| &        |               |
| sizeof   |               |
----------------------------

According to this table '&' will be evaluated first, because it is on the right side.

But yeah, that was "Address of", not "Bitwise AND".

Re: [PATCH] vmxnet3: fix LRO feature check

From: Shrikrishna Khare <hidden>
Date: 2018-03-20 18:57:50


On Tue, 20 Mar 2018, David Miller wrote:
From: kbuild test robot <redacted>
Date: Sun, 18 Mar 2018 14:37:35 +0800
quoted
All warnings (new ones prefixed by >>):

   drivers/net/vmxnet3/vmxnet3_drv.c: In function 'vmxnet3_rq_rx_complete':
quoted
quoted
drivers/net/vmxnet3/vmxnet3_drv.c:1474:8: warning: suggest parentheses around operand of '!' or change '&' to '&&' or '!' to '~' [-Wparentheses]
           !adapter->netdev->features & NETIF_F_LRO) {
           ^~~~~~~~~~~~~~~~~~~~~~~~~~
Igor, I will fix this up for you.  But it is clear that this patch wasn't tested
very well.

Because !adapter->netdev->features evaluates wholly before the "& NETIF_F_LRO",
the flags aren't being tested properly at all.
Ronak's patch that fixes this issue has the right code, and is already 
accepted in net tree (Commit: 034f405793897a3c8f642935f5494b86c340cde7). 
We no longer need Igor's patch.

Thanks,
Shri

 

Re: [PATCH] vmxnet3: fix LRO feature check

From: David Miller <davem@davemloft.net>
Date: 2018-03-20 18:59:05

From: Shrikrishna Khare <redacted>
Date: Tue, 20 Mar 2018 11:42:47 -0700
Ronak's patch that fixes this issue has the right code, and is already 
accepted in net tree (Commit: 034f405793897a3c8f642935f5494b86c340cde7). 
We no longer need Igor's patch.
That explains why things in my actual tree are fine.

Thanks.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help