diff options
author | Alexander Duyck <alexander.h.duyck@intel.com> | 2011-06-10 21:45:13 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-07-22 01:56:37 -0400 |
commit | ff886dfce2bdacbe71583ec973cec117973d8859 (patch) | |
tree | ea48f94008d8ef554f709962b7f0b7fcee860c3b /drivers/net/ixgbe | |
parent | bd19805803a954415ec36a559fd3b8a0a3647d7c (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.h | 5 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_fcoe.c | 35 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_main.c | 39 |
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); |
601 | extern void ixgbe_cleanup_fcoe(struct ixgbe_adapter *adapter); | 601 | extern void ixgbe_cleanup_fcoe(struct ixgbe_adapter *adapter); |
602 | extern int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter, | 602 | extern 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); | ||
605 | extern int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid, | 606 | extern 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); |
607 | extern int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid, | 608 | extern 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 | */ | ||
45 | static 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 | */ |
381 | int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter, | 361 | int 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 | */ | ||
1048 | static 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 | **/ |
1074 | static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter, | 1093 | static 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 | } |