ACK: [SRU B] [PATCH 1/1] qlcnic: fix Tx descriptor corruption on 82xx devices

Stefan Bader stefan.bader at canonical.com
Thu Feb 7 13:18:06 UTC 2019


On 07.02.19 13:44, Guilherme G. Piccoli wrote:
> From: Shahed Shaikh <shahed.shaikh at cavium.com>
> 
> BugLink: http://bugs.launchpad.net/bugs/1815033
> 
> In regular NIC transmission flow, driver always configures MAC using
> Tx queue zero descriptor as a part of MAC learning flow.
> But with multi Tx queue supported NIC, regular transmission can occur on
> any non-zero Tx queue and from that context it uses
> Tx queue zero descriptor to configure MAC, at the same time TX queue
> zero could be used by another CPU for regular transmission
> which could lead to Tx queue zero descriptor corruption and cause FW
> abort.
> 
> This patch fixes this in such a way that driver always configures
> learned MAC address from the same Tx queue which is used for
> regular transmission.
> 
> Fixes: 7e2cf4feba05 ("qlcnic: change driver hardware interface mechanism")
> Signed-off-by: Shahed Shaikh <shahed.shaikh at cavium.com>
> Signed-off-by: David S. Miller <davem at davemloft.net>
> (cherry picked from commit c333fa0c4f220f8f7ea5acd6b0ebf3bf13fd684d)
> Signed-off-by: Guilherme G. Piccoli <gpiccoli at canonical.com>
Acked-by: Stefan Bader <stefan.bader at canonical.com>
> ---

In Xenial and Cosmic already.

>  drivers/net/ethernet/qlogic/qlcnic/qlcnic.h         |  8 +++++---
>  drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c |  3 ++-
>  drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h |  3 ++-
>  drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h      |  3 ++-
>  drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c      | 12 ++++++------
>  5 files changed, 17 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
> index 81312924df14..0c443ea98479 100644
> --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
> +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
> @@ -1800,7 +1800,8 @@ struct qlcnic_hardware_ops {
>  	int (*config_loopback) (struct qlcnic_adapter *, u8);
>  	int (*clear_loopback) (struct qlcnic_adapter *, u8);
>  	int (*config_promisc_mode) (struct qlcnic_adapter *, u32);
> -	void (*change_l2_filter) (struct qlcnic_adapter *, u64 *, u16);
> +	void (*change_l2_filter)(struct qlcnic_adapter *adapter, u64 *addr,
> +				 u16 vlan, struct qlcnic_host_tx_ring *tx_ring);
>  	int (*get_board_info) (struct qlcnic_adapter *);
>  	void (*set_mac_filter_count) (struct qlcnic_adapter *);
>  	void (*free_mac_list) (struct qlcnic_adapter *);
> @@ -2064,9 +2065,10 @@ static inline int qlcnic_nic_set_promisc(struct qlcnic_adapter *adapter,
>  }
>  
>  static inline void qlcnic_change_filter(struct qlcnic_adapter *adapter,
> -					u64 *addr, u16 id)
> +					u64 *addr, u16 vlan,
> +					struct qlcnic_host_tx_ring *tx_ring)
>  {
> -	adapter->ahw->hw_ops->change_l2_filter(adapter, addr, id);
> +	adapter->ahw->hw_ops->change_l2_filter(adapter, addr, vlan, tx_ring);
>  }
>  
>  static inline int qlcnic_get_board_info(struct qlcnic_adapter *adapter)
> diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
> index 46b0372dd032..1fc84d8f891b 100644
> --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
> +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
> @@ -2134,7 +2134,8 @@ int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
>  }
>  
>  void qlcnic_83xx_change_l2_filter(struct qlcnic_adapter *adapter, u64 *addr,
> -				  u16 vlan_id)
> +				  u16 vlan_id,
> +				  struct qlcnic_host_tx_ring *tx_ring)
>  {
>  	u8 mac[ETH_ALEN];
>  	memcpy(&mac, addr, ETH_ALEN);
> diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
> index b75a81246856..73fe2f64491d 100644
> --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
> +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
> @@ -550,7 +550,8 @@ int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *, ulong, u32);
>  int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *, u32);
>  int qlcnic_83xx_config_hw_lro(struct qlcnic_adapter *, int);
>  int qlcnic_83xx_config_rss(struct qlcnic_adapter *, int);
> -void qlcnic_83xx_change_l2_filter(struct qlcnic_adapter *, u64 *, u16);
> +void qlcnic_83xx_change_l2_filter(struct qlcnic_adapter *adapter, u64 *addr,
> +				  u16 vlan, struct qlcnic_host_tx_ring *ring);
>  int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *, struct qlcnic_pci_info *);
>  int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *);
>  void qlcnic_83xx_initialize_nic(struct qlcnic_adapter *, int);
> diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
> index 4bb33af8e2b3..56a3bd9e37dc 100644
> --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
> +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
> @@ -173,7 +173,8 @@ int qlcnic_82xx_napi_add(struct qlcnic_adapter *adapter,
>  			 struct net_device *netdev);
>  void qlcnic_82xx_get_beacon_state(struct qlcnic_adapter *);
>  void qlcnic_82xx_change_filter(struct qlcnic_adapter *adapter,
> -			       u64 *uaddr, u16 vlan_id);
> +			       u64 *uaddr, u16 vlan_id,
> +			       struct qlcnic_host_tx_ring *tx_ring);
>  int qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *,
>  				     struct ethtool_coalesce *);
>  int qlcnic_82xx_set_rx_coalesce(struct qlcnic_adapter *);
> diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
> index 84dd83031a1b..9647578cbe6a 100644
> --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
> +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
> @@ -268,13 +268,12 @@ static void qlcnic_add_lb_filter(struct qlcnic_adapter *adapter,
>  }
>  
>  void qlcnic_82xx_change_filter(struct qlcnic_adapter *adapter, u64 *uaddr,
> -			       u16 vlan_id)
> +			       u16 vlan_id, struct qlcnic_host_tx_ring *tx_ring)
>  {
>  	struct cmd_desc_type0 *hwdesc;
>  	struct qlcnic_nic_req *req;
>  	struct qlcnic_mac_req *mac_req;
>  	struct qlcnic_vlan_req *vlan_req;
> -	struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
>  	u32 producer;
>  	u64 word;
>  
> @@ -301,7 +300,8 @@ void qlcnic_82xx_change_filter(struct qlcnic_adapter *adapter, u64 *uaddr,
>  
>  static void qlcnic_send_filter(struct qlcnic_adapter *adapter,
>  			       struct cmd_desc_type0 *first_desc,
> -			       struct sk_buff *skb)
> +			       struct sk_buff *skb,
> +			       struct qlcnic_host_tx_ring *tx_ring)
>  {
>  	struct vlan_ethhdr *vh = (struct vlan_ethhdr *)(skb->data);
>  	struct ethhdr *phdr = (struct ethhdr *)(skb->data);
> @@ -335,7 +335,7 @@ static void qlcnic_send_filter(struct qlcnic_adapter *adapter,
>  		    tmp_fil->vlan_id == vlan_id) {
>  			if (jiffies > (QLCNIC_READD_AGE * HZ + tmp_fil->ftime))
>  				qlcnic_change_filter(adapter, &src_addr,
> -						     vlan_id);
> +						     vlan_id, tx_ring);
>  			tmp_fil->ftime = jiffies;
>  			return;
>  		}
> @@ -350,7 +350,7 @@ static void qlcnic_send_filter(struct qlcnic_adapter *adapter,
>  	if (!fil)
>  		return;
>  
> -	qlcnic_change_filter(adapter, &src_addr, vlan_id);
> +	qlcnic_change_filter(adapter, &src_addr, vlan_id, tx_ring);
>  	fil->ftime = jiffies;
>  	fil->vlan_id = vlan_id;
>  	memcpy(fil->faddr, &src_addr, ETH_ALEN);
> @@ -766,7 +766,7 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
>  	}
>  
>  	if (adapter->drv_mac_learn)
> -		qlcnic_send_filter(adapter, first_desc, skb);
> +		qlcnic_send_filter(adapter, first_desc, skb, tx_ring);
>  
>  	tx_ring->tx_stats.tx_bytes += skb->len;
>  	tx_ring->tx_stats.xmit_called++;
> 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <https://lists.ubuntu.com/archives/kernel-team/attachments/20190207/c83eff81/attachment-0001.sig>


More information about the kernel-team mailing list