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