aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ixgbe
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2011-06-10 21:45:13 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2011-07-22 01:56:37 -0400
commitff886dfce2bdacbe71583ec973cec117973d8859 (patch)
treeea48f94008d8ef554f709962b7f0b7fcee860c3b /drivers/net/ixgbe
parentbd19805803a954415ec36a559fd3b8a0a3647d7c (diff)
ixgbe: Pass staterr instead of re-reading status and error bits from descriptor
This change is meant to address possible race conditions from the status and error bits on the RX descriptors being re-read by multiple functions in the RX cleanup path. To resolve this I have added code that will pass the staterr value to those functions. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Tested-by: Ross Brattain <ross.b.brattain@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ixgbe')
-rw-r--r--drivers/net/ixgbe/ixgbe.h5
-rw-r--r--drivers/net/ixgbe/ixgbe_fcoe.c35
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c39
3 files changed, 37 insertions, 42 deletions
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index fbae7352b036..0d610c73164d 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -600,8 +600,9 @@ extern int ixgbe_fso(struct ixgbe_ring *tx_ring, struct sk_buff *skb,
600 u32 tx_flags, u8 *hdr_len); 600 u32 tx_flags, u8 *hdr_len);
601extern void ixgbe_cleanup_fcoe(struct ixgbe_adapter *adapter); 601extern void ixgbe_cleanup_fcoe(struct ixgbe_adapter *adapter);
602extern int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter, 602extern int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
603 union ixgbe_adv_rx_desc *rx_desc, 603 union ixgbe_adv_rx_desc *rx_desc,
604 struct sk_buff *skb); 604 struct sk_buff *skb,
605 u32 staterr);
605extern int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid, 606extern int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
606 struct scatterlist *sgl, unsigned int sgc); 607 struct scatterlist *sgl, unsigned int sgc);
607extern int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid, 608extern int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid,
diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c
index f0c1018bbf31..824edae77865 100644
--- a/drivers/net/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ixgbe/ixgbe_fcoe.c
@@ -37,25 +37,6 @@
37#include <scsi/libfcoe.h> 37#include <scsi/libfcoe.h>
38 38
39/** 39/**
40 * ixgbe_rx_is_fcoe - check the rx desc for incoming pkt type
41 * @rx_desc: advanced rx descriptor
42 *
43 * Returns : true if it is FCoE pkt
44 */
45static inline bool ixgbe_rx_is_fcoe(union ixgbe_adv_rx_desc *rx_desc)
46{
47 u16 p;
48
49 p = le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.pkt_info);
50 if (p & IXGBE_RXDADV_PKTTYPE_ETQF) {
51 p &= IXGBE_RXDADV_PKTTYPE_ETQF_MASK;
52 p >>= IXGBE_RXDADV_PKTTYPE_ETQF_SHIFT;
53 return p == IXGBE_ETQF_FILTER_FCOE;
54 }
55 return false;
56}
57
58/**
59 * ixgbe_fcoe_clear_ddp - clear the given ddp context 40 * ixgbe_fcoe_clear_ddp - clear the given ddp context
60 * @ddp - ptr to the ixgbe_fcoe_ddp 41 * @ddp - ptr to the ixgbe_fcoe_ddp
61 * 42 *
@@ -136,7 +117,6 @@ out_ddp_put:
136 return len; 117 return len;
137} 118}
138 119
139
140/** 120/**
141 * ixgbe_fcoe_ddp_setup - called to set up ddp context 121 * ixgbe_fcoe_ddp_setup - called to set up ddp context
142 * @netdev: the corresponding net_device 122 * @netdev: the corresponding net_device
@@ -380,23 +360,20 @@ int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid,
380 */ 360 */
381int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter, 361int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
382 union ixgbe_adv_rx_desc *rx_desc, 362 union ixgbe_adv_rx_desc *rx_desc,
383 struct sk_buff *skb) 363 struct sk_buff *skb,
364 u32 staterr)
384{ 365{
385 u16 xid; 366 u16 xid;
386 u32 fctl; 367 u32 fctl;
387 u32 sterr, fceofe, fcerr, fcstat; 368 u32 fceofe, fcerr, fcstat;
388 int rc = -EINVAL; 369 int rc = -EINVAL;
389 struct ixgbe_fcoe *fcoe; 370 struct ixgbe_fcoe *fcoe;
390 struct ixgbe_fcoe_ddp *ddp; 371 struct ixgbe_fcoe_ddp *ddp;
391 struct fc_frame_header *fh; 372 struct fc_frame_header *fh;
392 struct fcoe_crc_eof *crc; 373 struct fcoe_crc_eof *crc;
393 374
394 if (!ixgbe_rx_is_fcoe(rx_desc)) 375 fcerr = (staterr & IXGBE_RXDADV_ERR_FCERR);
395 goto ddp_out; 376 fceofe = (staterr & IXGBE_RXDADV_ERR_FCEOFE);
396
397 sterr = le32_to_cpu(rx_desc->wb.upper.status_error);
398 fcerr = (sterr & IXGBE_RXDADV_ERR_FCERR);
399 fceofe = (sterr & IXGBE_RXDADV_ERR_FCEOFE);
400 if (fcerr == IXGBE_FCERR_BADCRC) 377 if (fcerr == IXGBE_FCERR_BADCRC)
401 skb_checksum_none_assert(skb); 378 skb_checksum_none_assert(skb);
402 else 379 else
@@ -425,7 +402,7 @@ int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
425 if (fcerr | fceofe) 402 if (fcerr | fceofe)
426 goto ddp_out; 403 goto ddp_out;
427 404
428 fcstat = (sterr & IXGBE_RXDADV_STAT_FCSTAT); 405 fcstat = (staterr & IXGBE_RXDADV_STAT_FCSTAT);
429 if (fcstat) { 406 if (fcstat) {
430 /* update length of DDPed data */ 407 /* update length of DDPed data */
431 ddp->len = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss); 408 ddp->len = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 298c95b1480f..a222af378a32 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -1039,6 +1039,24 @@ static inline void ixgbe_rx_hash(union ixgbe_adv_rx_desc *rx_desc,
1039} 1039}
1040 1040
1041/** 1041/**
1042 * ixgbe_rx_is_fcoe - check the rx desc for incoming pkt type
1043 * @adapter: address of board private structure
1044 * @rx_desc: advanced rx descriptor
1045 *
1046 * Returns : true if it is FCoE pkt
1047 */
1048static inline bool ixgbe_rx_is_fcoe(struct ixgbe_adapter *adapter,
1049 union ixgbe_adv_rx_desc *rx_desc)
1050{
1051 __le16 pkt_info = rx_desc->wb.lower.lo_dword.hs_rss.pkt_info;
1052
1053 return (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) &&
1054 ((pkt_info & cpu_to_le16(IXGBE_RXDADV_PKTTYPE_ETQF_MASK)) ==
1055 (cpu_to_le16(IXGBE_ETQF_FILTER_FCOE <<
1056 IXGBE_RXDADV_PKTTYPE_ETQF_SHIFT)));
1057}
1058
1059/**
1042 * ixgbe_receive_skb - Send a completed packet up the stack 1060 * ixgbe_receive_skb - Send a completed packet up the stack
1043 * @adapter: board private structure 1061 * @adapter: board private structure
1044 * @skb: packet to send up 1062 * @skb: packet to send up
@@ -1070,14 +1088,14 @@ static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector,
1070 * @adapter: address of board private structure 1088 * @adapter: address of board private structure
1071 * @status_err: hardware indication of status of receive 1089 * @status_err: hardware indication of status of receive
1072 * @skb: skb currently being received and modified 1090 * @skb: skb currently being received and modified
1091 * @status_err: status error value of last descriptor in packet
1073 **/ 1092 **/
1074static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter, 1093static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter,
1075 union ixgbe_adv_rx_desc *rx_desc, 1094 union ixgbe_adv_rx_desc *rx_desc,
1076 struct sk_buff *skb) 1095 struct sk_buff *skb,
1096 u32 status_err)
1077{ 1097{
1078 u32 status_err = le32_to_cpu(rx_desc->wb.upper.status_error); 1098 skb->ip_summed = CHECKSUM_NONE;
1079
1080 skb_checksum_none_assert(skb);
1081 1099
1082 /* Rx csum disabled */ 1100 /* Rx csum disabled */
1083 if (!(adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED)) 1101 if (!(adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED))
@@ -1421,14 +1439,12 @@ static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
1421 } 1439 }
1422 1440
1423 /* ERR_MASK will only have valid bits if EOP set */ 1441 /* ERR_MASK will only have valid bits if EOP set */
1424 if (staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK) { 1442 if (unlikely(staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK)) {
1425 /* trim packet back to size 0 and recycle it */ 1443 dev_kfree_skb_any(skb);
1426 __pskb_trim(skb, 0);
1427 rx_buffer_info->skb = skb;
1428 goto next_desc; 1444 goto next_desc;
1429 } 1445 }
1430 1446
1431 ixgbe_rx_checksum(adapter, rx_desc, skb); 1447 ixgbe_rx_checksum(adapter, rx_desc, skb, staterr);
1432 if (adapter->netdev->features & NETIF_F_RXHASH) 1448 if (adapter->netdev->features & NETIF_F_RXHASH)
1433 ixgbe_rx_hash(rx_desc, skb); 1449 ixgbe_rx_hash(rx_desc, skb);
1434 1450
@@ -1439,8 +1455,9 @@ static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
1439 skb->protocol = eth_type_trans(skb, rx_ring->netdev); 1455 skb->protocol = eth_type_trans(skb, rx_ring->netdev);
1440#ifdef IXGBE_FCOE 1456#ifdef IXGBE_FCOE
1441 /* if ddp, not passing to ULD unless for FCP_RSP or error */ 1457 /* if ddp, not passing to ULD unless for FCP_RSP or error */
1442 if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { 1458 if (ixgbe_rx_is_fcoe(adapter, rx_desc)) {
1443 ddp_bytes = ixgbe_fcoe_ddp(adapter, rx_desc, skb); 1459 ddp_bytes = ixgbe_fcoe_ddp(adapter, rx_desc, skb,
1460 staterr);
1444 if (!ddp_bytes) 1461 if (!ddp_bytes)
1445 goto next_desc; 1462 goto next_desc;
1446 } 1463 }