Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ff886dfc authored by Alexander Duyck's avatar Alexander Duyck Committed by Jeff Kirsher
Browse files

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: default avatarAlexander Duyck <alexander.h.duyck@intel.com>
Tested-by: default avatarRoss Brattain <ross.b.brattain@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent bd198058
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -601,7 +601,8 @@ extern int ixgbe_fso(struct ixgbe_ring *tx_ring, struct sk_buff *skb,
extern void ixgbe_cleanup_fcoe(struct ixgbe_adapter *adapter);
extern int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
			  union ixgbe_adv_rx_desc *rx_desc,
                          struct sk_buff *skb);
			  struct sk_buff *skb,
			  u32 staterr);
extern int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
                              struct scatterlist *sgl, unsigned int sgc);
extern int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid,
+6 −29
Original line number Diff line number Diff line
@@ -36,25 +36,6 @@
#include <scsi/libfc.h>
#include <scsi/libfcoe.h>

/**
 * ixgbe_rx_is_fcoe - check the rx desc for incoming pkt type
 * @rx_desc: advanced rx descriptor
 *
 * Returns : true if it is FCoE pkt
 */
static inline bool ixgbe_rx_is_fcoe(union ixgbe_adv_rx_desc *rx_desc)
{
	u16 p;

	p = le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.pkt_info);
	if (p & IXGBE_RXDADV_PKTTYPE_ETQF) {
		p &= IXGBE_RXDADV_PKTTYPE_ETQF_MASK;
		p >>= IXGBE_RXDADV_PKTTYPE_ETQF_SHIFT;
		return p == IXGBE_ETQF_FILTER_FCOE;
	}
	return false;
}

/**
 * ixgbe_fcoe_clear_ddp - clear the given ddp context
 * @ddp - ptr to the ixgbe_fcoe_ddp
@@ -136,7 +117,6 @@ int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid)
	return len;
}


/**
 * ixgbe_fcoe_ddp_setup - called to set up ddp context
 * @netdev: the corresponding net_device
@@ -380,23 +360,20 @@ int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid,
 */
int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
		   union ixgbe_adv_rx_desc *rx_desc,
		   struct sk_buff *skb)
		   struct sk_buff *skb,
		   u32 staterr)
{
	u16 xid;
	u32 fctl;
	u32 sterr, fceofe, fcerr, fcstat;
	u32 fceofe, fcerr, fcstat;
	int rc = -EINVAL;
	struct ixgbe_fcoe *fcoe;
	struct ixgbe_fcoe_ddp *ddp;
	struct fc_frame_header *fh;
	struct fcoe_crc_eof *crc;

	if (!ixgbe_rx_is_fcoe(rx_desc))
		goto ddp_out;

	sterr = le32_to_cpu(rx_desc->wb.upper.status_error);
	fcerr = (sterr & IXGBE_RXDADV_ERR_FCERR);
	fceofe = (sterr & IXGBE_RXDADV_ERR_FCEOFE);
	fcerr = (staterr & IXGBE_RXDADV_ERR_FCERR);
	fceofe = (staterr & IXGBE_RXDADV_ERR_FCEOFE);
	if (fcerr == IXGBE_FCERR_BADCRC)
		skb_checksum_none_assert(skb);
	else
@@ -425,7 +402,7 @@ int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
	if (fcerr | fceofe)
		goto ddp_out;

	fcstat = (sterr & IXGBE_RXDADV_STAT_FCSTAT);
	fcstat = (staterr & IXGBE_RXDADV_STAT_FCSTAT);
	if (fcstat) {
		/* update length of DDPed data */
		ddp->len = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
+28 −11
Original line number Diff line number Diff line
@@ -1038,6 +1038,24 @@ static inline void ixgbe_rx_hash(union ixgbe_adv_rx_desc *rx_desc,
	skb->rxhash = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
}

/**
 * ixgbe_rx_is_fcoe - check the rx desc for incoming pkt type
 * @adapter: address of board private structure
 * @rx_desc: advanced rx descriptor
 *
 * Returns : true if it is FCoE pkt
 */
static inline bool ixgbe_rx_is_fcoe(struct ixgbe_adapter *adapter,
				    union ixgbe_adv_rx_desc *rx_desc)
{
	__le16 pkt_info = rx_desc->wb.lower.lo_dword.hs_rss.pkt_info;

	return (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) &&
	       ((pkt_info & cpu_to_le16(IXGBE_RXDADV_PKTTYPE_ETQF_MASK)) ==
		(cpu_to_le16(IXGBE_ETQF_FILTER_FCOE <<
			     IXGBE_RXDADV_PKTTYPE_ETQF_SHIFT)));
}

/**
 * ixgbe_receive_skb - Send a completed packet up the stack
 * @adapter: board private structure
@@ -1070,14 +1088,14 @@ static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector,
 * @adapter: address of board private structure
 * @status_err: hardware indication of status of receive
 * @skb: skb currently being received and modified
 * @status_err: status error value of last descriptor in packet
 **/
static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter,
				     union ixgbe_adv_rx_desc *rx_desc,
				     struct sk_buff *skb)
				     struct sk_buff *skb,
				     u32 status_err)
{
	u32 status_err = le32_to_cpu(rx_desc->wb.upper.status_error);

	skb_checksum_none_assert(skb);
	skb->ip_summed = CHECKSUM_NONE;

	/* Rx csum disabled */
	if (!(adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED))
@@ -1421,14 +1439,12 @@ static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
		}

		/* ERR_MASK will only have valid bits if EOP set */
		if (staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK) {
			/* trim packet back to size 0 and recycle it */
			__pskb_trim(skb, 0);
			rx_buffer_info->skb = skb;
		if (unlikely(staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK)) {
			dev_kfree_skb_any(skb);
			goto next_desc;
		}

		ixgbe_rx_checksum(adapter, rx_desc, skb);
		ixgbe_rx_checksum(adapter, rx_desc, skb, staterr);
		if (adapter->netdev->features & NETIF_F_RXHASH)
			ixgbe_rx_hash(rx_desc, skb);

@@ -1439,8 +1455,9 @@ static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
		skb->protocol = eth_type_trans(skb, rx_ring->netdev);
#ifdef IXGBE_FCOE
		/* if ddp, not passing to ULD unless for FCP_RSP or error */
		if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
			ddp_bytes = ixgbe_fcoe_ddp(adapter, rx_desc, skb);
		if (ixgbe_rx_is_fcoe(adapter, rx_desc)) {
			ddp_bytes = ixgbe_fcoe_ddp(adapter, rx_desc, skb,
						   staterr);
			if (!ddp_bytes)
				goto next_desc;
		}