]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-4.4/qlcnic-fix-tx-descriptor-corruption-on-82xx-devices.patch
239ca7d2c1d51cc0cbc7f398b4bb99a298d3b969
[thirdparty/kernel/stable-queue.git] / queue-4.4 / qlcnic-fix-tx-descriptor-corruption-on-82xx-devices.patch
1 From foo@baz Tue Oct 16 16:47:53 CEST 2018
2 From: Shahed Shaikh <shahed.shaikh@cavium.com>
3 Date: Wed, 26 Sep 2018 12:41:10 -0700
4 Subject: qlcnic: fix Tx descriptor corruption on 82xx devices
5
6 From: Shahed Shaikh <shahed.shaikh@cavium.com>
7
8 [ Upstream commit c333fa0c4f220f8f7ea5acd6b0ebf3bf13fd684d ]
9
10 In regular NIC transmission flow, driver always configures MAC using
11 Tx queue zero descriptor as a part of MAC learning flow.
12 But with multi Tx queue supported NIC, regular transmission can occur on
13 any non-zero Tx queue and from that context it uses
14 Tx queue zero descriptor to configure MAC, at the same time TX queue
15 zero could be used by another CPU for regular transmission
16 which could lead to Tx queue zero descriptor corruption and cause FW
17 abort.
18
19 This patch fixes this in such a way that driver always configures
20 learned MAC address from the same Tx queue which is used for
21 regular transmission.
22
23 Fixes: 7e2cf4feba05 ("qlcnic: change driver hardware interface mechanism")
24 Signed-off-by: Shahed Shaikh <shahed.shaikh@cavium.com>
25 Signed-off-by: David S. Miller <davem@davemloft.net>
26 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
27 ---
28 drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 8 +++++---
29 drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 3 ++-
30 drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | 3 ++-
31 drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h | 3 ++-
32 drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | 12 ++++++------
33 5 files changed, 17 insertions(+), 12 deletions(-)
34
35 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
36 +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
37 @@ -1802,7 +1802,8 @@ struct qlcnic_hardware_ops {
38 int (*config_loopback) (struct qlcnic_adapter *, u8);
39 int (*clear_loopback) (struct qlcnic_adapter *, u8);
40 int (*config_promisc_mode) (struct qlcnic_adapter *, u32);
41 - void (*change_l2_filter) (struct qlcnic_adapter *, u64 *, u16);
42 + void (*change_l2_filter)(struct qlcnic_adapter *adapter, u64 *addr,
43 + u16 vlan, struct qlcnic_host_tx_ring *tx_ring);
44 int (*get_board_info) (struct qlcnic_adapter *);
45 void (*set_mac_filter_count) (struct qlcnic_adapter *);
46 void (*free_mac_list) (struct qlcnic_adapter *);
47 @@ -2044,9 +2045,10 @@ static inline int qlcnic_nic_set_promisc
48 }
49
50 static inline void qlcnic_change_filter(struct qlcnic_adapter *adapter,
51 - u64 *addr, u16 id)
52 + u64 *addr, u16 vlan,
53 + struct qlcnic_host_tx_ring *tx_ring)
54 {
55 - adapter->ahw->hw_ops->change_l2_filter(adapter, addr, id);
56 + adapter->ahw->hw_ops->change_l2_filter(adapter, addr, vlan, tx_ring);
57 }
58
59 static inline int qlcnic_get_board_info(struct qlcnic_adapter *adapter)
60 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
61 +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
62 @@ -2132,7 +2132,8 @@ out:
63 }
64
65 void qlcnic_83xx_change_l2_filter(struct qlcnic_adapter *adapter, u64 *addr,
66 - u16 vlan_id)
67 + u16 vlan_id,
68 + struct qlcnic_host_tx_ring *tx_ring)
69 {
70 u8 mac[ETH_ALEN];
71 memcpy(&mac, addr, ETH_ALEN);
72 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
73 +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
74 @@ -550,7 +550,8 @@ int qlcnic_83xx_wrt_reg_indirect(struct
75 int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *, u32);
76 int qlcnic_83xx_config_hw_lro(struct qlcnic_adapter *, int);
77 int qlcnic_83xx_config_rss(struct qlcnic_adapter *, int);
78 -void qlcnic_83xx_change_l2_filter(struct qlcnic_adapter *, u64 *, u16);
79 +void qlcnic_83xx_change_l2_filter(struct qlcnic_adapter *adapter, u64 *addr,
80 + u16 vlan, struct qlcnic_host_tx_ring *ring);
81 int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *, struct qlcnic_pci_info *);
82 int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *);
83 void qlcnic_83xx_initialize_nic(struct qlcnic_adapter *, int);
84 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
85 +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
86 @@ -173,7 +173,8 @@ int qlcnic_82xx_napi_add(struct qlcnic_a
87 struct net_device *netdev);
88 void qlcnic_82xx_get_beacon_state(struct qlcnic_adapter *);
89 void qlcnic_82xx_change_filter(struct qlcnic_adapter *adapter,
90 - u64 *uaddr, u16 vlan_id);
91 + u64 *uaddr, u16 vlan_id,
92 + struct qlcnic_host_tx_ring *tx_ring);
93 int qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *,
94 struct ethtool_coalesce *);
95 int qlcnic_82xx_set_rx_coalesce(struct qlcnic_adapter *);
96 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
97 +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
98 @@ -269,13 +269,12 @@ static void qlcnic_add_lb_filter(struct
99 }
100
101 void qlcnic_82xx_change_filter(struct qlcnic_adapter *adapter, u64 *uaddr,
102 - u16 vlan_id)
103 + u16 vlan_id, struct qlcnic_host_tx_ring *tx_ring)
104 {
105 struct cmd_desc_type0 *hwdesc;
106 struct qlcnic_nic_req *req;
107 struct qlcnic_mac_req *mac_req;
108 struct qlcnic_vlan_req *vlan_req;
109 - struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
110 u32 producer;
111 u64 word;
112
113 @@ -302,7 +301,8 @@ void qlcnic_82xx_change_filter(struct ql
114
115 static void qlcnic_send_filter(struct qlcnic_adapter *adapter,
116 struct cmd_desc_type0 *first_desc,
117 - struct sk_buff *skb)
118 + struct sk_buff *skb,
119 + struct qlcnic_host_tx_ring *tx_ring)
120 {
121 struct vlan_ethhdr *vh = (struct vlan_ethhdr *)(skb->data);
122 struct ethhdr *phdr = (struct ethhdr *)(skb->data);
123 @@ -336,7 +336,7 @@ static void qlcnic_send_filter(struct ql
124 tmp_fil->vlan_id == vlan_id) {
125 if (jiffies > (QLCNIC_READD_AGE * HZ + tmp_fil->ftime))
126 qlcnic_change_filter(adapter, &src_addr,
127 - vlan_id);
128 + vlan_id, tx_ring);
129 tmp_fil->ftime = jiffies;
130 return;
131 }
132 @@ -351,7 +351,7 @@ static void qlcnic_send_filter(struct ql
133 if (!fil)
134 return;
135
136 - qlcnic_change_filter(adapter, &src_addr, vlan_id);
137 + qlcnic_change_filter(adapter, &src_addr, vlan_id, tx_ring);
138 fil->ftime = jiffies;
139 fil->vlan_id = vlan_id;
140 memcpy(fil->faddr, &src_addr, ETH_ALEN);
141 @@ -767,7 +767,7 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_
142 }
143
144 if (adapter->drv_mac_learn)
145 - qlcnic_send_filter(adapter, first_desc, skb);
146 + qlcnic_send_filter(adapter, first_desc, skb, tx_ring);
147
148 tx_ring->tx_stats.tx_bytes += skb->len;
149 tx_ring->tx_stats.xmit_called++;