.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Huawei HiNIC PCI Express Linux driver |
---|
3 | 4 | * Copyright(c) 2017 Huawei Technologies Co., Ltd |
---|
4 | | - * |
---|
5 | | - * This program is free software; you can redistribute it and/or modify it |
---|
6 | | - * under the terms and conditions of the GNU General Public License, |
---|
7 | | - * version 2, as published by the Free Software Foundation. |
---|
8 | | - * |
---|
9 | | - * This program is distributed in the hope it will be useful, but WITHOUT |
---|
10 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
11 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
---|
12 | | - * for more details. |
---|
13 | | - * |
---|
14 | 5 | */ |
---|
15 | 6 | |
---|
16 | 7 | #include <linux/kernel.h> |
---|
.. | .. |
---|
27 | 18 | #include <linux/semaphore.h> |
---|
28 | 19 | #include <linux/workqueue.h> |
---|
29 | 20 | #include <net/ip.h> |
---|
| 21 | +#include <net/devlink.h> |
---|
30 | 22 | #include <linux/bitops.h> |
---|
31 | 23 | #include <linux/bitmap.h> |
---|
32 | 24 | #include <linux/delay.h> |
---|
33 | 25 | #include <linux/err.h> |
---|
34 | 26 | |
---|
| 27 | +#include "hinic_debugfs.h" |
---|
35 | 28 | #include "hinic_hw_qp.h" |
---|
36 | 29 | #include "hinic_hw_dev.h" |
---|
| 30 | +#include "hinic_devlink.h" |
---|
37 | 31 | #include "hinic_port.h" |
---|
38 | 32 | #include "hinic_tx.h" |
---|
39 | 33 | #include "hinic_rx.h" |
---|
40 | 34 | #include "hinic_dev.h" |
---|
| 35 | +#include "hinic_sriov.h" |
---|
41 | 36 | |
---|
42 | 37 | MODULE_AUTHOR("Huawei Technologies CO., Ltd"); |
---|
43 | 38 | MODULE_DESCRIPTION("Huawei Intelligent NIC driver"); |
---|
.. | .. |
---|
51 | 46 | module_param(rx_weight, uint, 0644); |
---|
52 | 47 | MODULE_PARM_DESC(rx_weight, "Number Rx packets for NAPI budget (default=64)"); |
---|
53 | 48 | |
---|
54 | | -#define HINIC_DEV_ID_QUAD_PORT_25GE 0x1822 |
---|
55 | | -#define HINIC_DEV_ID_DUAL_PORT_25GE 0x0200 |
---|
56 | | -#define HINIC_DEV_ID_DUAL_PORT_100GE 0x0201 |
---|
| 49 | +#define HINIC_DEV_ID_QUAD_PORT_25GE 0x1822 |
---|
| 50 | +#define HINIC_DEV_ID_DUAL_PORT_100GE 0x0200 |
---|
| 51 | +#define HINIC_DEV_ID_DUAL_PORT_100GE_MEZZ 0x0205 |
---|
| 52 | +#define HINIC_DEV_ID_QUAD_PORT_25GE_MEZZ 0x0210 |
---|
| 53 | +#define HINIC_DEV_ID_VF 0x375e |
---|
57 | 54 | |
---|
58 | 55 | #define HINIC_WQ_NAME "hinic_dev" |
---|
59 | 56 | |
---|
.. | .. |
---|
61 | 58 | NETIF_MSG_IFUP | \ |
---|
62 | 59 | NETIF_MSG_TX_ERR | NETIF_MSG_RX_ERR) |
---|
63 | 60 | |
---|
64 | | -#define VLAN_BITMAP_SIZE(nic_dev) (ALIGN(VLAN_N_VID, 8) / 8) |
---|
| 61 | +#define HINIC_LRO_MAX_WQE_NUM_DEFAULT 8 |
---|
| 62 | + |
---|
| 63 | +#define HINIC_LRO_RX_TIMER_DEFAULT 16 |
---|
65 | 64 | |
---|
66 | 65 | #define work_to_rx_mode_work(work) \ |
---|
67 | 66 | container_of(work, struct hinic_rx_mode_work, work) |
---|
.. | .. |
---|
69 | 68 | #define rx_mode_work_to_nic_dev(rx_mode_work) \ |
---|
70 | 69 | container_of(rx_mode_work, struct hinic_dev, rx_mode_work) |
---|
71 | 70 | |
---|
| 71 | +#define HINIC_WAIT_SRIOV_CFG_TIMEOUT 15000 |
---|
| 72 | + |
---|
| 73 | +#define HINIC_DEAULT_TXRX_MSIX_PENDING_LIMIT 2 |
---|
| 74 | +#define HINIC_DEAULT_TXRX_MSIX_COALESC_TIMER_CFG 32 |
---|
| 75 | +#define HINIC_DEAULT_TXRX_MSIX_RESEND_TIMER_CFG 7 |
---|
| 76 | + |
---|
72 | 77 | static int change_mac_addr(struct net_device *netdev, const u8 *addr); |
---|
73 | 78 | |
---|
74 | | -static void set_link_speed(struct ethtool_link_ksettings *link_ksettings, |
---|
75 | | - enum hinic_speed speed) |
---|
| 79 | +static int set_features(struct hinic_dev *nic_dev, |
---|
| 80 | + netdev_features_t pre_features, |
---|
| 81 | + netdev_features_t features, bool force_change); |
---|
| 82 | + |
---|
| 83 | +static void gather_rx_stats(struct hinic_rxq_stats *nic_rx_stats, struct hinic_rxq *rxq) |
---|
76 | 84 | { |
---|
77 | | - switch (speed) { |
---|
78 | | - case HINIC_SPEED_10MB_LINK: |
---|
79 | | - link_ksettings->base.speed = SPEED_10; |
---|
80 | | - break; |
---|
81 | | - |
---|
82 | | - case HINIC_SPEED_100MB_LINK: |
---|
83 | | - link_ksettings->base.speed = SPEED_100; |
---|
84 | | - break; |
---|
85 | | - |
---|
86 | | - case HINIC_SPEED_1000MB_LINK: |
---|
87 | | - link_ksettings->base.speed = SPEED_1000; |
---|
88 | | - break; |
---|
89 | | - |
---|
90 | | - case HINIC_SPEED_10GB_LINK: |
---|
91 | | - link_ksettings->base.speed = SPEED_10000; |
---|
92 | | - break; |
---|
93 | | - |
---|
94 | | - case HINIC_SPEED_25GB_LINK: |
---|
95 | | - link_ksettings->base.speed = SPEED_25000; |
---|
96 | | - break; |
---|
97 | | - |
---|
98 | | - case HINIC_SPEED_40GB_LINK: |
---|
99 | | - link_ksettings->base.speed = SPEED_40000; |
---|
100 | | - break; |
---|
101 | | - |
---|
102 | | - case HINIC_SPEED_100GB_LINK: |
---|
103 | | - link_ksettings->base.speed = SPEED_100000; |
---|
104 | | - break; |
---|
105 | | - |
---|
106 | | - default: |
---|
107 | | - link_ksettings->base.speed = SPEED_UNKNOWN; |
---|
108 | | - break; |
---|
109 | | - } |
---|
110 | | -} |
---|
111 | | - |
---|
112 | | -static int hinic_get_link_ksettings(struct net_device *netdev, |
---|
113 | | - struct ethtool_link_ksettings |
---|
114 | | - *link_ksettings) |
---|
115 | | -{ |
---|
116 | | - struct hinic_dev *nic_dev = netdev_priv(netdev); |
---|
117 | | - enum hinic_port_link_state link_state; |
---|
118 | | - struct hinic_port_cap port_cap; |
---|
119 | | - int err; |
---|
120 | | - |
---|
121 | | - ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising); |
---|
122 | | - ethtool_link_ksettings_add_link_mode(link_ksettings, supported, |
---|
123 | | - Autoneg); |
---|
124 | | - |
---|
125 | | - link_ksettings->base.speed = SPEED_UNKNOWN; |
---|
126 | | - link_ksettings->base.autoneg = AUTONEG_DISABLE; |
---|
127 | | - link_ksettings->base.duplex = DUPLEX_UNKNOWN; |
---|
128 | | - |
---|
129 | | - err = hinic_port_get_cap(nic_dev, &port_cap); |
---|
130 | | - if (err) { |
---|
131 | | - netif_err(nic_dev, drv, netdev, |
---|
132 | | - "Failed to get port capabilities\n"); |
---|
133 | | - return err; |
---|
134 | | - } |
---|
135 | | - |
---|
136 | | - err = hinic_port_link_state(nic_dev, &link_state); |
---|
137 | | - if (err) { |
---|
138 | | - netif_err(nic_dev, drv, netdev, |
---|
139 | | - "Failed to get port link state\n"); |
---|
140 | | - return err; |
---|
141 | | - } |
---|
142 | | - |
---|
143 | | - if (link_state != HINIC_LINK_STATE_UP) { |
---|
144 | | - netif_info(nic_dev, drv, netdev, "No link\n"); |
---|
145 | | - return err; |
---|
146 | | - } |
---|
147 | | - |
---|
148 | | - set_link_speed(link_ksettings, port_cap.speed); |
---|
149 | | - |
---|
150 | | - if (!!(port_cap.autoneg_cap & HINIC_AUTONEG_SUPPORTED)) |
---|
151 | | - ethtool_link_ksettings_add_link_mode(link_ksettings, |
---|
152 | | - advertising, Autoneg); |
---|
153 | | - |
---|
154 | | - if (port_cap.autoneg_state == HINIC_AUTONEG_ACTIVE) |
---|
155 | | - link_ksettings->base.autoneg = AUTONEG_ENABLE; |
---|
156 | | - |
---|
157 | | - link_ksettings->base.duplex = (port_cap.duplex == HINIC_DUPLEX_FULL) ? |
---|
158 | | - DUPLEX_FULL : DUPLEX_HALF; |
---|
159 | | - return 0; |
---|
160 | | -} |
---|
161 | | - |
---|
162 | | -static void hinic_get_drvinfo(struct net_device *netdev, |
---|
163 | | - struct ethtool_drvinfo *info) |
---|
164 | | -{ |
---|
165 | | - struct hinic_dev *nic_dev = netdev_priv(netdev); |
---|
166 | | - struct hinic_hwdev *hwdev = nic_dev->hwdev; |
---|
167 | | - struct hinic_hwif *hwif = hwdev->hwif; |
---|
168 | | - |
---|
169 | | - strlcpy(info->driver, HINIC_DRV_NAME, sizeof(info->driver)); |
---|
170 | | - strlcpy(info->bus_info, pci_name(hwif->pdev), sizeof(info->bus_info)); |
---|
171 | | -} |
---|
172 | | - |
---|
173 | | -static void hinic_get_ringparam(struct net_device *netdev, |
---|
174 | | - struct ethtool_ringparam *ring) |
---|
175 | | -{ |
---|
176 | | - ring->rx_max_pending = HINIC_RQ_DEPTH; |
---|
177 | | - ring->tx_max_pending = HINIC_SQ_DEPTH; |
---|
178 | | - ring->rx_pending = HINIC_RQ_DEPTH; |
---|
179 | | - ring->tx_pending = HINIC_SQ_DEPTH; |
---|
180 | | -} |
---|
181 | | - |
---|
182 | | -static void hinic_get_channels(struct net_device *netdev, |
---|
183 | | - struct ethtool_channels *channels) |
---|
184 | | -{ |
---|
185 | | - struct hinic_dev *nic_dev = netdev_priv(netdev); |
---|
186 | | - struct hinic_hwdev *hwdev = nic_dev->hwdev; |
---|
187 | | - |
---|
188 | | - channels->max_rx = hwdev->nic_cap.max_qps; |
---|
189 | | - channels->max_tx = hwdev->nic_cap.max_qps; |
---|
190 | | - channels->max_other = 0; |
---|
191 | | - channels->max_combined = 0; |
---|
192 | | - channels->rx_count = hinic_hwdev_num_qps(hwdev); |
---|
193 | | - channels->tx_count = hinic_hwdev_num_qps(hwdev); |
---|
194 | | - channels->other_count = 0; |
---|
195 | | - channels->combined_count = 0; |
---|
196 | | -} |
---|
197 | | - |
---|
198 | | -static const struct ethtool_ops hinic_ethtool_ops = { |
---|
199 | | - .get_link_ksettings = hinic_get_link_ksettings, |
---|
200 | | - .get_drvinfo = hinic_get_drvinfo, |
---|
201 | | - .get_link = ethtool_op_get_link, |
---|
202 | | - .get_ringparam = hinic_get_ringparam, |
---|
203 | | - .get_channels = hinic_get_channels, |
---|
204 | | -}; |
---|
205 | | - |
---|
206 | | -static void update_rx_stats(struct hinic_dev *nic_dev, struct hinic_rxq *rxq) |
---|
207 | | -{ |
---|
208 | | - struct hinic_rxq_stats *nic_rx_stats = &nic_dev->rx_stats; |
---|
209 | 85 | struct hinic_rxq_stats rx_stats; |
---|
210 | | - |
---|
211 | | - u64_stats_init(&rx_stats.syncp); |
---|
212 | 86 | |
---|
213 | 87 | hinic_rxq_get_stats(rxq, &rx_stats); |
---|
214 | 88 | |
---|
215 | | - u64_stats_update_begin(&nic_rx_stats->syncp); |
---|
216 | 89 | nic_rx_stats->bytes += rx_stats.bytes; |
---|
217 | 90 | nic_rx_stats->pkts += rx_stats.pkts; |
---|
218 | | - u64_stats_update_end(&nic_rx_stats->syncp); |
---|
219 | | - |
---|
220 | | - hinic_rxq_clean_stats(rxq); |
---|
| 91 | + nic_rx_stats->errors += rx_stats.errors; |
---|
| 92 | + nic_rx_stats->csum_errors += rx_stats.csum_errors; |
---|
| 93 | + nic_rx_stats->other_errors += rx_stats.other_errors; |
---|
221 | 94 | } |
---|
222 | 95 | |
---|
223 | | -static void update_tx_stats(struct hinic_dev *nic_dev, struct hinic_txq *txq) |
---|
| 96 | +static void gather_tx_stats(struct hinic_txq_stats *nic_tx_stats, struct hinic_txq *txq) |
---|
224 | 97 | { |
---|
225 | | - struct hinic_txq_stats *nic_tx_stats = &nic_dev->tx_stats; |
---|
226 | 98 | struct hinic_txq_stats tx_stats; |
---|
227 | | - |
---|
228 | | - u64_stats_init(&tx_stats.syncp); |
---|
229 | 99 | |
---|
230 | 100 | hinic_txq_get_stats(txq, &tx_stats); |
---|
231 | 101 | |
---|
232 | | - u64_stats_update_begin(&nic_tx_stats->syncp); |
---|
233 | 102 | nic_tx_stats->bytes += tx_stats.bytes; |
---|
234 | 103 | nic_tx_stats->pkts += tx_stats.pkts; |
---|
235 | 104 | nic_tx_stats->tx_busy += tx_stats.tx_busy; |
---|
236 | 105 | nic_tx_stats->tx_wake += tx_stats.tx_wake; |
---|
237 | 106 | nic_tx_stats->tx_dropped += tx_stats.tx_dropped; |
---|
238 | | - u64_stats_update_end(&nic_tx_stats->syncp); |
---|
239 | | - |
---|
240 | | - hinic_txq_clean_stats(txq); |
---|
| 107 | + nic_tx_stats->big_frags_pkts += tx_stats.big_frags_pkts; |
---|
241 | 108 | } |
---|
242 | 109 | |
---|
243 | | -static void update_nic_stats(struct hinic_dev *nic_dev) |
---|
| 110 | +static void gather_nic_stats(struct hinic_dev *nic_dev, |
---|
| 111 | + struct hinic_rxq_stats *nic_rx_stats, |
---|
| 112 | + struct hinic_txq_stats *nic_tx_stats) |
---|
244 | 113 | { |
---|
245 | 114 | int i, num_qps = hinic_hwdev_num_qps(nic_dev->hwdev); |
---|
246 | 115 | |
---|
247 | 116 | for (i = 0; i < num_qps; i++) |
---|
248 | | - update_rx_stats(nic_dev, &nic_dev->rxqs[i]); |
---|
| 117 | + gather_rx_stats(nic_rx_stats, &nic_dev->rxqs[i]); |
---|
249 | 118 | |
---|
250 | 119 | for (i = 0; i < num_qps; i++) |
---|
251 | | - update_tx_stats(nic_dev, &nic_dev->txqs[i]); |
---|
| 120 | + gather_tx_stats(nic_tx_stats, &nic_dev->txqs[i]); |
---|
252 | 121 | } |
---|
253 | 122 | |
---|
254 | 123 | /** |
---|
.. | .. |
---|
261 | 130 | { |
---|
262 | 131 | int err, i, j, num_txqs = hinic_hwdev_num_qps(nic_dev->hwdev); |
---|
263 | 132 | struct net_device *netdev = nic_dev->netdev; |
---|
264 | | - size_t txq_size; |
---|
265 | 133 | |
---|
266 | 134 | if (nic_dev->txqs) |
---|
267 | 135 | return -EINVAL; |
---|
268 | 136 | |
---|
269 | | - txq_size = num_txqs * sizeof(*nic_dev->txqs); |
---|
270 | | - nic_dev->txqs = devm_kzalloc(&netdev->dev, txq_size, GFP_KERNEL); |
---|
| 137 | + nic_dev->txqs = devm_kcalloc(&netdev->dev, num_txqs, |
---|
| 138 | + sizeof(*nic_dev->txqs), GFP_KERNEL); |
---|
271 | 139 | if (!nic_dev->txqs) |
---|
272 | 140 | return -ENOMEM; |
---|
| 141 | + |
---|
| 142 | + hinic_sq_dbgfs_init(nic_dev); |
---|
273 | 143 | |
---|
274 | 144 | for (i = 0; i < num_txqs; i++) { |
---|
275 | 145 | struct hinic_sq *sq = hinic_hwdev_get_sq(nic_dev->hwdev, i); |
---|
.. | .. |
---|
280 | 150 | "Failed to init Txq\n"); |
---|
281 | 151 | goto err_init_txq; |
---|
282 | 152 | } |
---|
| 153 | + |
---|
| 154 | + err = hinic_sq_debug_add(nic_dev, i); |
---|
| 155 | + if (err) { |
---|
| 156 | + netif_err(nic_dev, drv, netdev, |
---|
| 157 | + "Failed to add SQ%d debug\n", i); |
---|
| 158 | + goto err_add_sq_dbg; |
---|
| 159 | + } |
---|
| 160 | + |
---|
283 | 161 | } |
---|
284 | 162 | |
---|
285 | 163 | return 0; |
---|
286 | 164 | |
---|
| 165 | +err_add_sq_dbg: |
---|
| 166 | + hinic_clean_txq(&nic_dev->txqs[i]); |
---|
287 | 167 | err_init_txq: |
---|
288 | | - for (j = 0; j < i; j++) |
---|
| 168 | + for (j = 0; j < i; j++) { |
---|
| 169 | + hinic_sq_debug_rem(nic_dev->txqs[j].sq); |
---|
289 | 170 | hinic_clean_txq(&nic_dev->txqs[j]); |
---|
| 171 | + } |
---|
| 172 | + |
---|
| 173 | + hinic_sq_dbgfs_uninit(nic_dev); |
---|
290 | 174 | |
---|
291 | 175 | devm_kfree(&netdev->dev, nic_dev->txqs); |
---|
292 | 176 | return err; |
---|
| 177 | +} |
---|
| 178 | + |
---|
| 179 | +static void enable_txqs_napi(struct hinic_dev *nic_dev) |
---|
| 180 | +{ |
---|
| 181 | + int num_txqs = hinic_hwdev_num_qps(nic_dev->hwdev); |
---|
| 182 | + int i; |
---|
| 183 | + |
---|
| 184 | + for (i = 0; i < num_txqs; i++) |
---|
| 185 | + napi_enable(&nic_dev->txqs[i].napi); |
---|
| 186 | +} |
---|
| 187 | + |
---|
| 188 | +static void disable_txqs_napi(struct hinic_dev *nic_dev) |
---|
| 189 | +{ |
---|
| 190 | + int num_txqs = hinic_hwdev_num_qps(nic_dev->hwdev); |
---|
| 191 | + int i; |
---|
| 192 | + |
---|
| 193 | + for (i = 0; i < num_txqs; i++) |
---|
| 194 | + napi_disable(&nic_dev->txqs[i].napi); |
---|
293 | 195 | } |
---|
294 | 196 | |
---|
295 | 197 | /** |
---|
.. | .. |
---|
304 | 206 | if (!nic_dev->txqs) |
---|
305 | 207 | return; |
---|
306 | 208 | |
---|
307 | | - for (i = 0; i < num_txqs; i++) |
---|
| 209 | + for (i = 0; i < num_txqs; i++) { |
---|
| 210 | + hinic_sq_debug_rem(nic_dev->txqs[i].sq); |
---|
308 | 211 | hinic_clean_txq(&nic_dev->txqs[i]); |
---|
| 212 | + } |
---|
| 213 | + |
---|
| 214 | + hinic_sq_dbgfs_uninit(nic_dev); |
---|
309 | 215 | |
---|
310 | 216 | devm_kfree(&netdev->dev, nic_dev->txqs); |
---|
311 | 217 | nic_dev->txqs = NULL; |
---|
.. | .. |
---|
321 | 227 | { |
---|
322 | 228 | int err, i, j, num_rxqs = hinic_hwdev_num_qps(nic_dev->hwdev); |
---|
323 | 229 | struct net_device *netdev = nic_dev->netdev; |
---|
324 | | - size_t rxq_size; |
---|
325 | 230 | |
---|
326 | 231 | if (nic_dev->rxqs) |
---|
327 | 232 | return -EINVAL; |
---|
328 | 233 | |
---|
329 | | - rxq_size = num_rxqs * sizeof(*nic_dev->rxqs); |
---|
330 | | - nic_dev->rxqs = devm_kzalloc(&netdev->dev, rxq_size, GFP_KERNEL); |
---|
| 234 | + nic_dev->rxqs = devm_kcalloc(&netdev->dev, num_rxqs, |
---|
| 235 | + sizeof(*nic_dev->rxqs), GFP_KERNEL); |
---|
331 | 236 | if (!nic_dev->rxqs) |
---|
332 | 237 | return -ENOMEM; |
---|
| 238 | + |
---|
| 239 | + hinic_rq_dbgfs_init(nic_dev); |
---|
333 | 240 | |
---|
334 | 241 | for (i = 0; i < num_rxqs; i++) { |
---|
335 | 242 | struct hinic_rq *rq = hinic_hwdev_get_rq(nic_dev->hwdev, i); |
---|
.. | .. |
---|
340 | 247 | "Failed to init rxq\n"); |
---|
341 | 248 | goto err_init_rxq; |
---|
342 | 249 | } |
---|
| 250 | + |
---|
| 251 | + err = hinic_rq_debug_add(nic_dev, i); |
---|
| 252 | + if (err) { |
---|
| 253 | + netif_err(nic_dev, drv, netdev, |
---|
| 254 | + "Failed to add RQ%d debug\n", i); |
---|
| 255 | + goto err_add_rq_dbg; |
---|
| 256 | + } |
---|
343 | 257 | } |
---|
344 | 258 | |
---|
345 | 259 | return 0; |
---|
346 | 260 | |
---|
| 261 | +err_add_rq_dbg: |
---|
| 262 | + hinic_clean_rxq(&nic_dev->rxqs[i]); |
---|
347 | 263 | err_init_rxq: |
---|
348 | | - for (j = 0; j < i; j++) |
---|
| 264 | + for (j = 0; j < i; j++) { |
---|
| 265 | + hinic_rq_debug_rem(nic_dev->rxqs[j].rq); |
---|
349 | 266 | hinic_clean_rxq(&nic_dev->rxqs[j]); |
---|
| 267 | + } |
---|
| 268 | + |
---|
| 269 | + hinic_rq_dbgfs_uninit(nic_dev); |
---|
350 | 270 | |
---|
351 | 271 | devm_kfree(&netdev->dev, nic_dev->rxqs); |
---|
352 | 272 | return err; |
---|
.. | .. |
---|
364 | 284 | if (!nic_dev->rxqs) |
---|
365 | 285 | return; |
---|
366 | 286 | |
---|
367 | | - for (i = 0; i < num_rxqs; i++) |
---|
| 287 | + for (i = 0; i < num_rxqs; i++) { |
---|
| 288 | + hinic_rq_debug_rem(nic_dev->rxqs[i].rq); |
---|
368 | 289 | hinic_clean_rxq(&nic_dev->rxqs[i]); |
---|
| 290 | + } |
---|
| 291 | + |
---|
| 292 | + hinic_rq_dbgfs_uninit(nic_dev); |
---|
369 | 293 | |
---|
370 | 294 | devm_kfree(&netdev->dev, nic_dev->rxqs); |
---|
371 | 295 | nic_dev->rxqs = NULL; |
---|
372 | 296 | } |
---|
373 | 297 | |
---|
374 | | -static int hinic_open(struct net_device *netdev) |
---|
| 298 | +static int hinic_configure_max_qnum(struct hinic_dev *nic_dev) |
---|
| 299 | +{ |
---|
| 300 | + int err; |
---|
| 301 | + |
---|
| 302 | + err = hinic_set_max_qnum(nic_dev, nic_dev->hwdev->nic_cap.max_qps); |
---|
| 303 | + if (err) |
---|
| 304 | + return err; |
---|
| 305 | + |
---|
| 306 | + return 0; |
---|
| 307 | +} |
---|
| 308 | + |
---|
| 309 | +static int hinic_rss_init(struct hinic_dev *nic_dev) |
---|
| 310 | +{ |
---|
| 311 | + u8 default_rss_key[HINIC_RSS_KEY_SIZE]; |
---|
| 312 | + u8 tmpl_idx = nic_dev->rss_tmpl_idx; |
---|
| 313 | + u32 *indir_tbl; |
---|
| 314 | + int err, i; |
---|
| 315 | + |
---|
| 316 | + indir_tbl = kcalloc(HINIC_RSS_INDIR_SIZE, sizeof(u32), GFP_KERNEL); |
---|
| 317 | + if (!indir_tbl) |
---|
| 318 | + return -ENOMEM; |
---|
| 319 | + |
---|
| 320 | + netdev_rss_key_fill(default_rss_key, sizeof(default_rss_key)); |
---|
| 321 | + for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++) |
---|
| 322 | + indir_tbl[i] = ethtool_rxfh_indir_default(i, nic_dev->num_rss); |
---|
| 323 | + |
---|
| 324 | + err = hinic_rss_set_template_tbl(nic_dev, tmpl_idx, default_rss_key); |
---|
| 325 | + if (err) |
---|
| 326 | + goto out; |
---|
| 327 | + |
---|
| 328 | + err = hinic_rss_set_indir_tbl(nic_dev, tmpl_idx, indir_tbl); |
---|
| 329 | + if (err) |
---|
| 330 | + goto out; |
---|
| 331 | + |
---|
| 332 | + err = hinic_set_rss_type(nic_dev, tmpl_idx, nic_dev->rss_type); |
---|
| 333 | + if (err) |
---|
| 334 | + goto out; |
---|
| 335 | + |
---|
| 336 | + err = hinic_rss_set_hash_engine(nic_dev, tmpl_idx, |
---|
| 337 | + nic_dev->rss_hash_engine); |
---|
| 338 | + if (err) |
---|
| 339 | + goto out; |
---|
| 340 | + |
---|
| 341 | + err = hinic_rss_cfg(nic_dev, 1, tmpl_idx); |
---|
| 342 | + if (err) |
---|
| 343 | + goto out; |
---|
| 344 | + |
---|
| 345 | +out: |
---|
| 346 | + kfree(indir_tbl); |
---|
| 347 | + return err; |
---|
| 348 | +} |
---|
| 349 | + |
---|
| 350 | +static void hinic_rss_deinit(struct hinic_dev *nic_dev) |
---|
| 351 | +{ |
---|
| 352 | + hinic_rss_cfg(nic_dev, 0, nic_dev->rss_tmpl_idx); |
---|
| 353 | +} |
---|
| 354 | + |
---|
| 355 | +static void hinic_init_rss_parameters(struct hinic_dev *nic_dev) |
---|
| 356 | +{ |
---|
| 357 | + nic_dev->rss_hash_engine = HINIC_RSS_HASH_ENGINE_TYPE_XOR; |
---|
| 358 | + nic_dev->rss_type.tcp_ipv6_ext = 1; |
---|
| 359 | + nic_dev->rss_type.ipv6_ext = 1; |
---|
| 360 | + nic_dev->rss_type.tcp_ipv6 = 1; |
---|
| 361 | + nic_dev->rss_type.ipv6 = 1; |
---|
| 362 | + nic_dev->rss_type.tcp_ipv4 = 1; |
---|
| 363 | + nic_dev->rss_type.ipv4 = 1; |
---|
| 364 | + nic_dev->rss_type.udp_ipv6 = 1; |
---|
| 365 | + nic_dev->rss_type.udp_ipv4 = 1; |
---|
| 366 | +} |
---|
| 367 | + |
---|
| 368 | +static void hinic_enable_rss(struct hinic_dev *nic_dev) |
---|
| 369 | +{ |
---|
| 370 | + struct net_device *netdev = nic_dev->netdev; |
---|
| 371 | + struct hinic_hwdev *hwdev = nic_dev->hwdev; |
---|
| 372 | + struct hinic_hwif *hwif = hwdev->hwif; |
---|
| 373 | + struct pci_dev *pdev = hwif->pdev; |
---|
| 374 | + int i, node, err = 0; |
---|
| 375 | + u16 num_cpus = 0; |
---|
| 376 | + |
---|
| 377 | + if (nic_dev->max_qps <= 1) { |
---|
| 378 | + nic_dev->flags &= ~HINIC_RSS_ENABLE; |
---|
| 379 | + nic_dev->rss_limit = nic_dev->max_qps; |
---|
| 380 | + nic_dev->num_qps = nic_dev->max_qps; |
---|
| 381 | + nic_dev->num_rss = nic_dev->max_qps; |
---|
| 382 | + |
---|
| 383 | + return; |
---|
| 384 | + } |
---|
| 385 | + |
---|
| 386 | + err = hinic_rss_template_alloc(nic_dev, &nic_dev->rss_tmpl_idx); |
---|
| 387 | + if (err) { |
---|
| 388 | + netif_err(nic_dev, drv, netdev, |
---|
| 389 | + "Failed to alloc tmpl_idx for rss, can't enable rss for this function\n"); |
---|
| 390 | + nic_dev->flags &= ~HINIC_RSS_ENABLE; |
---|
| 391 | + nic_dev->max_qps = 1; |
---|
| 392 | + nic_dev->rss_limit = nic_dev->max_qps; |
---|
| 393 | + nic_dev->num_qps = nic_dev->max_qps; |
---|
| 394 | + nic_dev->num_rss = nic_dev->max_qps; |
---|
| 395 | + |
---|
| 396 | + return; |
---|
| 397 | + } |
---|
| 398 | + |
---|
| 399 | + nic_dev->flags |= HINIC_RSS_ENABLE; |
---|
| 400 | + |
---|
| 401 | + for (i = 0; i < num_online_cpus(); i++) { |
---|
| 402 | + node = cpu_to_node(i); |
---|
| 403 | + if (node == dev_to_node(&pdev->dev)) |
---|
| 404 | + num_cpus++; |
---|
| 405 | + } |
---|
| 406 | + |
---|
| 407 | + if (!num_cpus) |
---|
| 408 | + num_cpus = num_online_cpus(); |
---|
| 409 | + |
---|
| 410 | + nic_dev->num_qps = hinic_hwdev_num_qps(hwdev); |
---|
| 411 | + nic_dev->num_qps = min_t(u16, nic_dev->num_qps, num_cpus); |
---|
| 412 | + |
---|
| 413 | + nic_dev->rss_limit = nic_dev->num_qps; |
---|
| 414 | + nic_dev->num_rss = nic_dev->num_qps; |
---|
| 415 | + |
---|
| 416 | + hinic_init_rss_parameters(nic_dev); |
---|
| 417 | + err = hinic_rss_init(nic_dev); |
---|
| 418 | + if (err) |
---|
| 419 | + netif_err(nic_dev, drv, netdev, "Failed to init rss\n"); |
---|
| 420 | +} |
---|
| 421 | + |
---|
| 422 | +int hinic_open(struct net_device *netdev) |
---|
375 | 423 | { |
---|
376 | 424 | struct hinic_dev *nic_dev = netdev_priv(netdev); |
---|
377 | 425 | enum hinic_port_link_state link_state; |
---|
378 | | - int err, ret, num_qps; |
---|
| 426 | + int err, ret; |
---|
379 | 427 | |
---|
380 | 428 | if (!(nic_dev->flags & HINIC_INTF_UP)) { |
---|
381 | | - err = hinic_hwdev_ifup(nic_dev->hwdev); |
---|
| 429 | + err = hinic_hwdev_ifup(nic_dev->hwdev, nic_dev->sq_depth, |
---|
| 430 | + nic_dev->rq_depth); |
---|
382 | 431 | if (err) { |
---|
383 | 432 | netif_err(nic_dev, drv, netdev, |
---|
384 | 433 | "Failed - HW interface up\n"); |
---|
.. | .. |
---|
393 | 442 | goto err_create_txqs; |
---|
394 | 443 | } |
---|
395 | 444 | |
---|
| 445 | + enable_txqs_napi(nic_dev); |
---|
| 446 | + |
---|
396 | 447 | err = create_rxqs(nic_dev); |
---|
397 | 448 | if (err) { |
---|
398 | 449 | netif_err(nic_dev, drv, netdev, |
---|
.. | .. |
---|
400 | 451 | goto err_create_rxqs; |
---|
401 | 452 | } |
---|
402 | 453 | |
---|
403 | | - num_qps = hinic_hwdev_num_qps(nic_dev->hwdev); |
---|
404 | | - netif_set_real_num_tx_queues(netdev, num_qps); |
---|
405 | | - netif_set_real_num_rx_queues(netdev, num_qps); |
---|
| 454 | + hinic_enable_rss(nic_dev); |
---|
| 455 | + |
---|
| 456 | + err = hinic_configure_max_qnum(nic_dev); |
---|
| 457 | + if (err) { |
---|
| 458 | + netif_err(nic_dev, drv, nic_dev->netdev, |
---|
| 459 | + "Failed to configure the maximum number of queues\n"); |
---|
| 460 | + goto err_port_state; |
---|
| 461 | + } |
---|
| 462 | + |
---|
| 463 | + netif_set_real_num_tx_queues(netdev, nic_dev->num_qps); |
---|
| 464 | + netif_set_real_num_rx_queues(netdev, nic_dev->num_qps); |
---|
406 | 465 | |
---|
407 | 466 | err = hinic_port_set_state(nic_dev, HINIC_PORT_ENABLE); |
---|
408 | 467 | if (err) { |
---|
.. | .. |
---|
418 | 477 | goto err_func_port_state; |
---|
419 | 478 | } |
---|
420 | 479 | |
---|
421 | | - /* Wait up to 3 sec between port enable to link state */ |
---|
422 | | - msleep(3000); |
---|
423 | | - |
---|
424 | 480 | down(&nic_dev->mgmt_lock); |
---|
425 | 481 | |
---|
426 | 482 | err = hinic_port_link_state(nic_dev, &link_state); |
---|
.. | .. |
---|
429 | 485 | goto err_port_link; |
---|
430 | 486 | } |
---|
431 | 487 | |
---|
432 | | - if (link_state == HINIC_LINK_STATE_UP) |
---|
| 488 | + if (!HINIC_IS_VF(nic_dev->hwdev->hwif)) |
---|
| 489 | + hinic_notify_all_vfs_link_changed(nic_dev->hwdev, link_state); |
---|
| 490 | + |
---|
| 491 | + if (link_state == HINIC_LINK_STATE_UP) { |
---|
433 | 492 | nic_dev->flags |= HINIC_LINK_UP; |
---|
| 493 | + nic_dev->cable_unplugged = false; |
---|
| 494 | + nic_dev->module_unrecognized = false; |
---|
| 495 | + } |
---|
434 | 496 | |
---|
435 | 497 | nic_dev->flags |= HINIC_INTF_UP; |
---|
436 | 498 | |
---|
.. | .. |
---|
458 | 520 | if (ret) |
---|
459 | 521 | netif_warn(nic_dev, drv, netdev, |
---|
460 | 522 | "Failed to revert port state\n"); |
---|
461 | | - |
---|
462 | 523 | err_port_state: |
---|
463 | 524 | free_rxqs(nic_dev); |
---|
| 525 | + if (nic_dev->flags & HINIC_RSS_ENABLE) { |
---|
| 526 | + hinic_rss_deinit(nic_dev); |
---|
| 527 | + hinic_rss_template_free(nic_dev, nic_dev->rss_tmpl_idx); |
---|
| 528 | + } |
---|
464 | 529 | |
---|
465 | 530 | err_create_rxqs: |
---|
| 531 | + disable_txqs_napi(nic_dev); |
---|
466 | 532 | free_txqs(nic_dev); |
---|
467 | 533 | |
---|
468 | 534 | err_create_txqs: |
---|
.. | .. |
---|
471 | 537 | return err; |
---|
472 | 538 | } |
---|
473 | 539 | |
---|
474 | | -static int hinic_close(struct net_device *netdev) |
---|
| 540 | +int hinic_close(struct net_device *netdev) |
---|
475 | 541 | { |
---|
476 | 542 | struct hinic_dev *nic_dev = netdev_priv(netdev); |
---|
477 | 543 | unsigned int flags; |
---|
| 544 | + |
---|
| 545 | + /* Disable txq napi firstly to aviod rewaking txq in free_tx_poll */ |
---|
| 546 | + disable_txqs_napi(nic_dev); |
---|
478 | 547 | |
---|
479 | 548 | down(&nic_dev->mgmt_lock); |
---|
480 | 549 | |
---|
.. | .. |
---|
484 | 553 | netif_carrier_off(netdev); |
---|
485 | 554 | netif_tx_disable(netdev); |
---|
486 | 555 | |
---|
487 | | - update_nic_stats(nic_dev); |
---|
488 | | - |
---|
489 | 556 | up(&nic_dev->mgmt_lock); |
---|
| 557 | + |
---|
| 558 | + if (!HINIC_IS_VF(nic_dev->hwdev->hwif)) |
---|
| 559 | + hinic_notify_all_vfs_link_changed(nic_dev->hwdev, 0); |
---|
490 | 560 | |
---|
491 | 561 | hinic_port_set_state(nic_dev, HINIC_PORT_DISABLE); |
---|
492 | 562 | |
---|
493 | 563 | hinic_port_set_func_state(nic_dev, HINIC_FUNC_PORT_DISABLE); |
---|
| 564 | + |
---|
| 565 | + if (nic_dev->flags & HINIC_RSS_ENABLE) { |
---|
| 566 | + hinic_rss_deinit(nic_dev); |
---|
| 567 | + hinic_rss_template_free(nic_dev, nic_dev->rss_tmpl_idx); |
---|
| 568 | + } |
---|
494 | 569 | |
---|
495 | 570 | free_rxqs(nic_dev); |
---|
496 | 571 | free_txqs(nic_dev); |
---|
.. | .. |
---|
660 | 735 | } |
---|
661 | 736 | |
---|
662 | 737 | err = hinic_port_add_mac(nic_dev, netdev->dev_addr, vid); |
---|
663 | | - if (err) { |
---|
| 738 | + if (err && err != HINIC_PF_SET_VF_ALREADY) { |
---|
664 | 739 | netif_err(nic_dev, drv, netdev, "Failed to set mac\n"); |
---|
665 | 740 | goto err_add_mac; |
---|
666 | 741 | } |
---|
.. | .. |
---|
711 | 786 | { |
---|
712 | 787 | struct hinic_rx_mode_work *rx_mode_work = work_to_rx_mode_work(work); |
---|
713 | 788 | struct hinic_dev *nic_dev = rx_mode_work_to_nic_dev(rx_mode_work); |
---|
714 | | - struct netdev_hw_addr *ha; |
---|
715 | | - |
---|
716 | | - netif_info(nic_dev, drv, nic_dev->netdev, "set rx mode work\n"); |
---|
717 | 789 | |
---|
718 | 790 | hinic_port_set_rx_mode(nic_dev, rx_mode_work->rx_mode); |
---|
719 | 791 | |
---|
720 | 792 | __dev_uc_sync(nic_dev->netdev, add_mac_addr, remove_mac_addr); |
---|
721 | 793 | __dev_mc_sync(nic_dev->netdev, add_mac_addr, remove_mac_addr); |
---|
722 | | - |
---|
723 | | - netdev_for_each_mc_addr(ha, nic_dev->netdev) |
---|
724 | | - add_mac_addr(nic_dev->netdev, ha->addr); |
---|
725 | 794 | } |
---|
726 | 795 | |
---|
727 | 796 | static void hinic_set_rx_mode(struct net_device *netdev) |
---|
.. | .. |
---|
736 | 805 | HINIC_RX_MODE_MC | |
---|
737 | 806 | HINIC_RX_MODE_BC; |
---|
738 | 807 | |
---|
739 | | - if (netdev->flags & IFF_PROMISC) |
---|
740 | | - rx_mode |= HINIC_RX_MODE_PROMISC; |
---|
741 | | - else if (netdev->flags & IFF_ALLMULTI) |
---|
| 808 | + if (netdev->flags & IFF_PROMISC) { |
---|
| 809 | + if (!HINIC_IS_VF(nic_dev->hwdev->hwif)) |
---|
| 810 | + rx_mode |= HINIC_RX_MODE_PROMISC; |
---|
| 811 | + } else if (netdev->flags & IFF_ALLMULTI) { |
---|
742 | 812 | rx_mode |= HINIC_RX_MODE_MC_ALL; |
---|
| 813 | + } |
---|
743 | 814 | |
---|
744 | 815 | rx_mode_work->rx_mode = rx_mode; |
---|
745 | 816 | |
---|
746 | 817 | queue_work(nic_dev->workq, &rx_mode_work->work); |
---|
747 | 818 | } |
---|
748 | 819 | |
---|
749 | | -static void hinic_tx_timeout(struct net_device *netdev) |
---|
| 820 | +static void hinic_tx_timeout(struct net_device *netdev, unsigned int txqueue) |
---|
750 | 821 | { |
---|
751 | 822 | struct hinic_dev *nic_dev = netdev_priv(netdev); |
---|
| 823 | + u16 sw_pi, hw_ci, sw_ci; |
---|
| 824 | + struct hinic_sq *sq; |
---|
| 825 | + u16 num_sqs, q_id; |
---|
| 826 | + |
---|
| 827 | + num_sqs = hinic_hwdev_num_qps(nic_dev->hwdev); |
---|
752 | 828 | |
---|
753 | 829 | netif_err(nic_dev, drv, netdev, "Tx timeout\n"); |
---|
| 830 | + |
---|
| 831 | + for (q_id = 0; q_id < num_sqs; q_id++) { |
---|
| 832 | + if (!netif_xmit_stopped(netdev_get_tx_queue(netdev, q_id))) |
---|
| 833 | + continue; |
---|
| 834 | + |
---|
| 835 | + sq = hinic_hwdev_get_sq(nic_dev->hwdev, q_id); |
---|
| 836 | + sw_pi = atomic_read(&sq->wq->prod_idx) & sq->wq->mask; |
---|
| 837 | + hw_ci = be16_to_cpu(*(u16 *)(sq->hw_ci_addr)) & sq->wq->mask; |
---|
| 838 | + sw_ci = atomic_read(&sq->wq->cons_idx) & sq->wq->mask; |
---|
| 839 | + netif_err(nic_dev, drv, netdev, "Txq%d: sw_pi: %d, hw_ci: %d, sw_ci: %d, napi->state: 0x%lx\n", |
---|
| 840 | + q_id, sw_pi, hw_ci, sw_ci, |
---|
| 841 | + nic_dev->txqs[q_id].napi.state); |
---|
| 842 | + } |
---|
754 | 843 | } |
---|
755 | 844 | |
---|
756 | 845 | static void hinic_get_stats64(struct net_device *netdev, |
---|
757 | 846 | struct rtnl_link_stats64 *stats) |
---|
758 | 847 | { |
---|
759 | 848 | struct hinic_dev *nic_dev = netdev_priv(netdev); |
---|
760 | | - struct hinic_rxq_stats *nic_rx_stats; |
---|
761 | | - struct hinic_txq_stats *nic_tx_stats; |
---|
762 | | - |
---|
763 | | - nic_rx_stats = &nic_dev->rx_stats; |
---|
764 | | - nic_tx_stats = &nic_dev->tx_stats; |
---|
765 | | - |
---|
766 | | - down(&nic_dev->mgmt_lock); |
---|
| 849 | + struct hinic_rxq_stats nic_rx_stats = {}; |
---|
| 850 | + struct hinic_txq_stats nic_tx_stats = {}; |
---|
767 | 851 | |
---|
768 | 852 | if (nic_dev->flags & HINIC_INTF_UP) |
---|
769 | | - update_nic_stats(nic_dev); |
---|
| 853 | + gather_nic_stats(nic_dev, &nic_rx_stats, &nic_tx_stats); |
---|
770 | 854 | |
---|
771 | | - up(&nic_dev->mgmt_lock); |
---|
| 855 | + stats->rx_bytes = nic_rx_stats.bytes; |
---|
| 856 | + stats->rx_packets = nic_rx_stats.pkts; |
---|
| 857 | + stats->rx_errors = nic_rx_stats.errors; |
---|
772 | 858 | |
---|
773 | | - stats->rx_bytes = nic_rx_stats->bytes; |
---|
774 | | - stats->rx_packets = nic_rx_stats->pkts; |
---|
| 859 | + stats->tx_bytes = nic_tx_stats.bytes; |
---|
| 860 | + stats->tx_packets = nic_tx_stats.pkts; |
---|
| 861 | + stats->tx_errors = nic_tx_stats.tx_dropped; |
---|
| 862 | +} |
---|
775 | 863 | |
---|
776 | | - stats->tx_bytes = nic_tx_stats->bytes; |
---|
777 | | - stats->tx_packets = nic_tx_stats->pkts; |
---|
778 | | - stats->tx_errors = nic_tx_stats->tx_dropped; |
---|
| 864 | +static int hinic_set_features(struct net_device *netdev, |
---|
| 865 | + netdev_features_t features) |
---|
| 866 | +{ |
---|
| 867 | + struct hinic_dev *nic_dev = netdev_priv(netdev); |
---|
| 868 | + |
---|
| 869 | + return set_features(nic_dev, nic_dev->netdev->features, |
---|
| 870 | + features, false); |
---|
| 871 | +} |
---|
| 872 | + |
---|
| 873 | +static netdev_features_t hinic_fix_features(struct net_device *netdev, |
---|
| 874 | + netdev_features_t features) |
---|
| 875 | +{ |
---|
| 876 | + struct hinic_dev *nic_dev = netdev_priv(netdev); |
---|
| 877 | + |
---|
| 878 | + /* If Rx checksum is disabled, then LRO should also be disabled */ |
---|
| 879 | + if (!(features & NETIF_F_RXCSUM)) { |
---|
| 880 | + netif_info(nic_dev, drv, netdev, "disabling LRO as RXCSUM is off\n"); |
---|
| 881 | + features &= ~NETIF_F_LRO; |
---|
| 882 | + } |
---|
| 883 | + |
---|
| 884 | + return features; |
---|
779 | 885 | } |
---|
780 | 886 | |
---|
781 | 887 | static const struct net_device_ops hinic_netdev_ops = { |
---|
.. | .. |
---|
790 | 896 | .ndo_start_xmit = hinic_xmit_frame, |
---|
791 | 897 | .ndo_tx_timeout = hinic_tx_timeout, |
---|
792 | 898 | .ndo_get_stats64 = hinic_get_stats64, |
---|
| 899 | + .ndo_fix_features = hinic_fix_features, |
---|
| 900 | + .ndo_set_features = hinic_set_features, |
---|
| 901 | + .ndo_set_vf_mac = hinic_ndo_set_vf_mac, |
---|
| 902 | + .ndo_set_vf_vlan = hinic_ndo_set_vf_vlan, |
---|
| 903 | + .ndo_get_vf_config = hinic_ndo_get_vf_config, |
---|
| 904 | + .ndo_set_vf_trust = hinic_ndo_set_vf_trust, |
---|
| 905 | + .ndo_set_vf_rate = hinic_ndo_set_vf_bw, |
---|
| 906 | + .ndo_set_vf_spoofchk = hinic_ndo_set_vf_spoofchk, |
---|
| 907 | + .ndo_set_vf_link_state = hinic_ndo_set_vf_link_state, |
---|
| 908 | +}; |
---|
| 909 | + |
---|
| 910 | +static const struct net_device_ops hinicvf_netdev_ops = { |
---|
| 911 | + .ndo_open = hinic_open, |
---|
| 912 | + .ndo_stop = hinic_close, |
---|
| 913 | + .ndo_change_mtu = hinic_change_mtu, |
---|
| 914 | + .ndo_set_mac_address = hinic_set_mac_addr, |
---|
| 915 | + .ndo_validate_addr = eth_validate_addr, |
---|
| 916 | + .ndo_vlan_rx_add_vid = hinic_vlan_rx_add_vid, |
---|
| 917 | + .ndo_vlan_rx_kill_vid = hinic_vlan_rx_kill_vid, |
---|
| 918 | + .ndo_set_rx_mode = hinic_set_rx_mode, |
---|
| 919 | + .ndo_start_xmit = hinic_xmit_frame, |
---|
| 920 | + .ndo_tx_timeout = hinic_tx_timeout, |
---|
| 921 | + .ndo_get_stats64 = hinic_get_stats64, |
---|
| 922 | + .ndo_fix_features = hinic_fix_features, |
---|
| 923 | + .ndo_set_features = hinic_set_features, |
---|
793 | 924 | }; |
---|
794 | 925 | |
---|
795 | 926 | static void netdev_features_init(struct net_device *netdev) |
---|
796 | 927 | { |
---|
797 | | - netdev->hw_features = NETIF_F_SG | NETIF_F_HIGHDMA; |
---|
| 928 | + netdev->hw_features = NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | |
---|
| 929 | + NETIF_F_IPV6_CSUM | NETIF_F_TSO | NETIF_F_TSO6 | |
---|
| 930 | + NETIF_F_RXCSUM | NETIF_F_LRO | |
---|
| 931 | + NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | |
---|
| 932 | + NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_UDP_TUNNEL_CSUM; |
---|
798 | 933 | |
---|
799 | 934 | netdev->vlan_features = netdev->hw_features; |
---|
800 | 935 | |
---|
801 | 936 | netdev->features = netdev->hw_features | NETIF_F_HW_VLAN_CTAG_FILTER; |
---|
| 937 | + |
---|
| 938 | + netdev->hw_enc_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SCTP_CRC | |
---|
| 939 | + NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN | |
---|
| 940 | + NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_UDP_TUNNEL; |
---|
| 941 | +} |
---|
| 942 | + |
---|
| 943 | +static void hinic_refresh_nic_cfg(struct hinic_dev *nic_dev) |
---|
| 944 | +{ |
---|
| 945 | + struct hinic_nic_cfg *nic_cfg = &nic_dev->hwdev->func_to_io.nic_cfg; |
---|
| 946 | + struct hinic_pause_config pause_info = {0}; |
---|
| 947 | + struct hinic_port_cap port_cap = {0}; |
---|
| 948 | + |
---|
| 949 | + if (hinic_port_get_cap(nic_dev, &port_cap)) |
---|
| 950 | + return; |
---|
| 951 | + |
---|
| 952 | + mutex_lock(&nic_cfg->cfg_mutex); |
---|
| 953 | + if (nic_cfg->pause_set || !port_cap.autoneg_state) { |
---|
| 954 | + nic_cfg->auto_neg = port_cap.autoneg_state; |
---|
| 955 | + pause_info.auto_neg = nic_cfg->auto_neg; |
---|
| 956 | + pause_info.rx_pause = nic_cfg->rx_pause; |
---|
| 957 | + pause_info.tx_pause = nic_cfg->tx_pause; |
---|
| 958 | + hinic_set_hw_pause_info(nic_dev->hwdev, &pause_info); |
---|
| 959 | + } |
---|
| 960 | + mutex_unlock(&nic_cfg->cfg_mutex); |
---|
802 | 961 | } |
---|
803 | 962 | |
---|
804 | 963 | /** |
---|
.. | .. |
---|
806 | 965 | * @handle: nic device for the handler |
---|
807 | 966 | * @buf_in: input buffer |
---|
808 | 967 | * @in_size: input size |
---|
809 | | - * @buf_in: output buffer |
---|
| 968 | + * @buf_out: output buffer |
---|
810 | 969 | * @out_size: returned output size |
---|
811 | 970 | * |
---|
812 | 971 | * Return 0 - Success, negative - Failure |
---|
.. | .. |
---|
823 | 982 | down(&nic_dev->mgmt_lock); |
---|
824 | 983 | |
---|
825 | 984 | nic_dev->flags |= HINIC_LINK_UP; |
---|
| 985 | + nic_dev->cable_unplugged = false; |
---|
| 986 | + nic_dev->module_unrecognized = false; |
---|
826 | 987 | |
---|
827 | 988 | if ((nic_dev->flags & (HINIC_LINK_UP | HINIC_INTF_UP)) == |
---|
828 | 989 | (HINIC_LINK_UP | HINIC_INTF_UP)) { |
---|
.. | .. |
---|
831 | 992 | } |
---|
832 | 993 | |
---|
833 | 994 | up(&nic_dev->mgmt_lock); |
---|
| 995 | + |
---|
| 996 | + if (!HINIC_IS_VF(nic_dev->hwdev->hwif)) |
---|
| 997 | + hinic_refresh_nic_cfg(nic_dev); |
---|
834 | 998 | |
---|
835 | 999 | netif_info(nic_dev, drv, nic_dev->netdev, "HINIC_Link is UP\n"); |
---|
836 | 1000 | } else { |
---|
.. | .. |
---|
846 | 1010 | netif_info(nic_dev, drv, nic_dev->netdev, "HINIC_Link is DOWN\n"); |
---|
847 | 1011 | } |
---|
848 | 1012 | |
---|
| 1013 | + if (!HINIC_IS_VF(nic_dev->hwdev->hwif)) |
---|
| 1014 | + hinic_notify_all_vfs_link_changed(nic_dev->hwdev, |
---|
| 1015 | + link_status->link); |
---|
| 1016 | + |
---|
849 | 1017 | ret_link_status = buf_out; |
---|
850 | 1018 | ret_link_status->status = 0; |
---|
851 | 1019 | |
---|
852 | 1020 | *out_size = sizeof(*ret_link_status); |
---|
| 1021 | +} |
---|
| 1022 | + |
---|
| 1023 | +static void cable_plug_event(void *handle, |
---|
| 1024 | + void *buf_in, u16 in_size, |
---|
| 1025 | + void *buf_out, u16 *out_size) |
---|
| 1026 | +{ |
---|
| 1027 | + struct hinic_cable_plug_event *plug_event = buf_in; |
---|
| 1028 | + struct hinic_dev *nic_dev = handle; |
---|
| 1029 | + |
---|
| 1030 | + nic_dev->cable_unplugged = plug_event->plugged ? false : true; |
---|
| 1031 | + |
---|
| 1032 | + *out_size = sizeof(*plug_event); |
---|
| 1033 | + plug_event = buf_out; |
---|
| 1034 | + plug_event->status = 0; |
---|
| 1035 | +} |
---|
| 1036 | + |
---|
| 1037 | +static void link_err_event(void *handle, |
---|
| 1038 | + void *buf_in, u16 in_size, |
---|
| 1039 | + void *buf_out, u16 *out_size) |
---|
| 1040 | +{ |
---|
| 1041 | + struct hinic_link_err_event *link_err = buf_in; |
---|
| 1042 | + struct hinic_dev *nic_dev = handle; |
---|
| 1043 | + |
---|
| 1044 | + if (link_err->err_type >= LINK_ERR_NUM) |
---|
| 1045 | + netif_info(nic_dev, link, nic_dev->netdev, |
---|
| 1046 | + "Link failed, Unknown error type: 0x%x\n", |
---|
| 1047 | + link_err->err_type); |
---|
| 1048 | + else |
---|
| 1049 | + nic_dev->module_unrecognized = true; |
---|
| 1050 | + |
---|
| 1051 | + *out_size = sizeof(*link_err); |
---|
| 1052 | + link_err = buf_out; |
---|
| 1053 | + link_err->status = 0; |
---|
| 1054 | +} |
---|
| 1055 | + |
---|
| 1056 | +static int set_features(struct hinic_dev *nic_dev, |
---|
| 1057 | + netdev_features_t pre_features, |
---|
| 1058 | + netdev_features_t features, bool force_change) |
---|
| 1059 | +{ |
---|
| 1060 | + netdev_features_t changed = force_change ? ~0 : pre_features ^ features; |
---|
| 1061 | + u32 csum_en = HINIC_RX_CSUM_OFFLOAD_EN; |
---|
| 1062 | + netdev_features_t failed_features = 0; |
---|
| 1063 | + int ret = 0; |
---|
| 1064 | + int err = 0; |
---|
| 1065 | + |
---|
| 1066 | + if (changed & NETIF_F_TSO) { |
---|
| 1067 | + ret = hinic_port_set_tso(nic_dev, (features & NETIF_F_TSO) ? |
---|
| 1068 | + HINIC_TSO_ENABLE : HINIC_TSO_DISABLE); |
---|
| 1069 | + if (ret) { |
---|
| 1070 | + err = ret; |
---|
| 1071 | + failed_features |= NETIF_F_TSO; |
---|
| 1072 | + } |
---|
| 1073 | + } |
---|
| 1074 | + |
---|
| 1075 | + if (changed & NETIF_F_RXCSUM) { |
---|
| 1076 | + ret = hinic_set_rx_csum_offload(nic_dev, csum_en); |
---|
| 1077 | + if (ret) { |
---|
| 1078 | + err = ret; |
---|
| 1079 | + failed_features |= NETIF_F_RXCSUM; |
---|
| 1080 | + } |
---|
| 1081 | + } |
---|
| 1082 | + |
---|
| 1083 | + if (changed & NETIF_F_LRO) { |
---|
| 1084 | + ret = hinic_set_rx_lro_state(nic_dev, |
---|
| 1085 | + !!(features & NETIF_F_LRO), |
---|
| 1086 | + HINIC_LRO_RX_TIMER_DEFAULT, |
---|
| 1087 | + HINIC_LRO_MAX_WQE_NUM_DEFAULT); |
---|
| 1088 | + if (ret) { |
---|
| 1089 | + err = ret; |
---|
| 1090 | + failed_features |= NETIF_F_LRO; |
---|
| 1091 | + } |
---|
| 1092 | + } |
---|
| 1093 | + |
---|
| 1094 | + if (changed & NETIF_F_HW_VLAN_CTAG_RX) { |
---|
| 1095 | + ret = hinic_set_rx_vlan_offload(nic_dev, |
---|
| 1096 | + !!(features & |
---|
| 1097 | + NETIF_F_HW_VLAN_CTAG_RX)); |
---|
| 1098 | + if (ret) { |
---|
| 1099 | + err = ret; |
---|
| 1100 | + failed_features |= NETIF_F_HW_VLAN_CTAG_RX; |
---|
| 1101 | + } |
---|
| 1102 | + } |
---|
| 1103 | + |
---|
| 1104 | + if (err) { |
---|
| 1105 | + nic_dev->netdev->features = features ^ failed_features; |
---|
| 1106 | + return -EIO; |
---|
| 1107 | + } |
---|
| 1108 | + |
---|
| 1109 | + return 0; |
---|
| 1110 | +} |
---|
| 1111 | + |
---|
| 1112 | +static int hinic_init_intr_coalesce(struct hinic_dev *nic_dev) |
---|
| 1113 | +{ |
---|
| 1114 | + u64 size; |
---|
| 1115 | + u16 i; |
---|
| 1116 | + |
---|
| 1117 | + size = sizeof(struct hinic_intr_coal_info) * nic_dev->max_qps; |
---|
| 1118 | + nic_dev->rx_intr_coalesce = kzalloc(size, GFP_KERNEL); |
---|
| 1119 | + if (!nic_dev->rx_intr_coalesce) |
---|
| 1120 | + return -ENOMEM; |
---|
| 1121 | + nic_dev->tx_intr_coalesce = kzalloc(size, GFP_KERNEL); |
---|
| 1122 | + if (!nic_dev->tx_intr_coalesce) { |
---|
| 1123 | + kfree(nic_dev->rx_intr_coalesce); |
---|
| 1124 | + return -ENOMEM; |
---|
| 1125 | + } |
---|
| 1126 | + |
---|
| 1127 | + for (i = 0; i < nic_dev->max_qps; i++) { |
---|
| 1128 | + nic_dev->rx_intr_coalesce[i].pending_limt = |
---|
| 1129 | + HINIC_DEAULT_TXRX_MSIX_PENDING_LIMIT; |
---|
| 1130 | + nic_dev->rx_intr_coalesce[i].coalesce_timer_cfg = |
---|
| 1131 | + HINIC_DEAULT_TXRX_MSIX_COALESC_TIMER_CFG; |
---|
| 1132 | + nic_dev->rx_intr_coalesce[i].resend_timer_cfg = |
---|
| 1133 | + HINIC_DEAULT_TXRX_MSIX_RESEND_TIMER_CFG; |
---|
| 1134 | + nic_dev->tx_intr_coalesce[i].pending_limt = |
---|
| 1135 | + HINIC_DEAULT_TXRX_MSIX_PENDING_LIMIT; |
---|
| 1136 | + nic_dev->tx_intr_coalesce[i].coalesce_timer_cfg = |
---|
| 1137 | + HINIC_DEAULT_TXRX_MSIX_COALESC_TIMER_CFG; |
---|
| 1138 | + nic_dev->tx_intr_coalesce[i].resend_timer_cfg = |
---|
| 1139 | + HINIC_DEAULT_TXRX_MSIX_RESEND_TIMER_CFG; |
---|
| 1140 | + } |
---|
| 1141 | + |
---|
| 1142 | + return 0; |
---|
| 1143 | +} |
---|
| 1144 | + |
---|
| 1145 | +static void hinic_free_intr_coalesce(struct hinic_dev *nic_dev) |
---|
| 1146 | +{ |
---|
| 1147 | + kfree(nic_dev->tx_intr_coalesce); |
---|
| 1148 | + kfree(nic_dev->rx_intr_coalesce); |
---|
853 | 1149 | } |
---|
854 | 1150 | |
---|
855 | 1151 | /** |
---|
.. | .. |
---|
861 | 1157 | static int nic_dev_init(struct pci_dev *pdev) |
---|
862 | 1158 | { |
---|
863 | 1159 | struct hinic_rx_mode_work *rx_mode_work; |
---|
864 | | - struct hinic_txq_stats *tx_stats; |
---|
865 | | - struct hinic_rxq_stats *rx_stats; |
---|
866 | 1160 | struct hinic_dev *nic_dev; |
---|
867 | 1161 | struct net_device *netdev; |
---|
868 | 1162 | struct hinic_hwdev *hwdev; |
---|
| 1163 | + struct devlink *devlink; |
---|
869 | 1164 | int err, num_qps; |
---|
870 | 1165 | |
---|
871 | | - hwdev = hinic_init_hwdev(pdev); |
---|
| 1166 | + devlink = hinic_devlink_alloc(); |
---|
| 1167 | + if (!devlink) { |
---|
| 1168 | + dev_err(&pdev->dev, "Hinic devlink alloc failed\n"); |
---|
| 1169 | + return -ENOMEM; |
---|
| 1170 | + } |
---|
| 1171 | + |
---|
| 1172 | + hwdev = hinic_init_hwdev(pdev, devlink); |
---|
872 | 1173 | if (IS_ERR(hwdev)) { |
---|
873 | 1174 | dev_err(&pdev->dev, "Failed to initialize HW device\n"); |
---|
| 1175 | + hinic_devlink_free(devlink); |
---|
874 | 1176 | return PTR_ERR(hwdev); |
---|
875 | 1177 | } |
---|
876 | 1178 | |
---|
.. | .. |
---|
888 | 1190 | goto err_alloc_etherdev; |
---|
889 | 1191 | } |
---|
890 | 1192 | |
---|
891 | | - netdev->netdev_ops = &hinic_netdev_ops; |
---|
892 | | - netdev->ethtool_ops = &hinic_ethtool_ops; |
---|
| 1193 | + if (!HINIC_IS_VF(hwdev->hwif)) |
---|
| 1194 | + netdev->netdev_ops = &hinic_netdev_ops; |
---|
| 1195 | + else |
---|
| 1196 | + netdev->netdev_ops = &hinicvf_netdev_ops; |
---|
| 1197 | + |
---|
893 | 1198 | netdev->max_mtu = ETH_MAX_MTU; |
---|
894 | 1199 | |
---|
895 | 1200 | nic_dev = netdev_priv(netdev); |
---|
.. | .. |
---|
901 | 1206 | nic_dev->rxqs = NULL; |
---|
902 | 1207 | nic_dev->tx_weight = tx_weight; |
---|
903 | 1208 | nic_dev->rx_weight = rx_weight; |
---|
| 1209 | + nic_dev->sq_depth = HINIC_SQ_DEPTH; |
---|
| 1210 | + nic_dev->rq_depth = HINIC_RQ_DEPTH; |
---|
| 1211 | + nic_dev->sriov_info.hwdev = hwdev; |
---|
| 1212 | + nic_dev->sriov_info.pdev = pdev; |
---|
| 1213 | + nic_dev->max_qps = num_qps; |
---|
| 1214 | + nic_dev->devlink = devlink; |
---|
| 1215 | + |
---|
| 1216 | + hinic_set_ethtool_ops(netdev); |
---|
904 | 1217 | |
---|
905 | 1218 | sema_init(&nic_dev->mgmt_lock, 1); |
---|
906 | 1219 | |
---|
907 | | - tx_stats = &nic_dev->tx_stats; |
---|
908 | | - rx_stats = &nic_dev->rx_stats; |
---|
909 | | - |
---|
910 | | - u64_stats_init(&tx_stats->syncp); |
---|
911 | | - u64_stats_init(&rx_stats->syncp); |
---|
912 | | - |
---|
913 | | - nic_dev->vlan_bitmap = devm_kzalloc(&pdev->dev, |
---|
914 | | - VLAN_BITMAP_SIZE(nic_dev), |
---|
915 | | - GFP_KERNEL); |
---|
| 1220 | + nic_dev->vlan_bitmap = devm_bitmap_zalloc(&pdev->dev, VLAN_N_VID, |
---|
| 1221 | + GFP_KERNEL); |
---|
916 | 1222 | if (!nic_dev->vlan_bitmap) { |
---|
917 | 1223 | err = -ENOMEM; |
---|
918 | 1224 | goto err_vlan_bitmap; |
---|
.. | .. |
---|
927 | 1233 | pci_set_drvdata(pdev, netdev); |
---|
928 | 1234 | |
---|
929 | 1235 | err = hinic_port_get_mac(nic_dev, netdev->dev_addr); |
---|
930 | | - if (err) |
---|
931 | | - dev_warn(&pdev->dev, "Failed to get mac address\n"); |
---|
| 1236 | + if (err) { |
---|
| 1237 | + dev_err(&pdev->dev, "Failed to get mac address\n"); |
---|
| 1238 | + goto err_get_mac; |
---|
| 1239 | + } |
---|
| 1240 | + |
---|
| 1241 | + if (!is_valid_ether_addr(netdev->dev_addr)) { |
---|
| 1242 | + if (!HINIC_IS_VF(nic_dev->hwdev->hwif)) { |
---|
| 1243 | + dev_err(&pdev->dev, "Invalid MAC address\n"); |
---|
| 1244 | + err = -EIO; |
---|
| 1245 | + goto err_add_mac; |
---|
| 1246 | + } |
---|
| 1247 | + |
---|
| 1248 | + dev_info(&pdev->dev, "Invalid MAC address %pM, using random\n", |
---|
| 1249 | + netdev->dev_addr); |
---|
| 1250 | + eth_hw_addr_random(netdev); |
---|
| 1251 | + } |
---|
932 | 1252 | |
---|
933 | 1253 | err = hinic_port_add_mac(nic_dev, netdev->dev_addr, 0); |
---|
934 | | - if (err) { |
---|
| 1254 | + if (err && err != HINIC_PF_SET_VF_ALREADY) { |
---|
935 | 1255 | dev_err(&pdev->dev, "Failed to add mac\n"); |
---|
936 | 1256 | goto err_add_mac; |
---|
937 | 1257 | } |
---|
.. | .. |
---|
951 | 1271 | |
---|
952 | 1272 | hinic_hwdev_cb_register(nic_dev->hwdev, HINIC_MGMT_MSG_CMD_LINK_STATUS, |
---|
953 | 1273 | nic_dev, link_status_event_handler); |
---|
| 1274 | + hinic_hwdev_cb_register(nic_dev->hwdev, |
---|
| 1275 | + HINIC_MGMT_MSG_CMD_CABLE_PLUG_EVENT, |
---|
| 1276 | + nic_dev, cable_plug_event); |
---|
| 1277 | + hinic_hwdev_cb_register(nic_dev->hwdev, |
---|
| 1278 | + HINIC_MGMT_MSG_CMD_LINK_ERR_EVENT, |
---|
| 1279 | + nic_dev, link_err_event); |
---|
| 1280 | + |
---|
| 1281 | + err = set_features(nic_dev, 0, nic_dev->netdev->features, true); |
---|
| 1282 | + if (err) |
---|
| 1283 | + goto err_set_features; |
---|
| 1284 | + |
---|
| 1285 | + /* enable pause and disable pfc by default */ |
---|
| 1286 | + err = hinic_dcb_set_pfc(nic_dev->hwdev, 0, 0); |
---|
| 1287 | + if (err) |
---|
| 1288 | + goto err_set_pfc; |
---|
954 | 1289 | |
---|
955 | 1290 | SET_NETDEV_DEV(netdev, &pdev->dev); |
---|
| 1291 | + |
---|
| 1292 | + err = hinic_init_intr_coalesce(nic_dev); |
---|
| 1293 | + if (err) { |
---|
| 1294 | + dev_err(&pdev->dev, "Failed to init_intr_coalesce\n"); |
---|
| 1295 | + goto err_init_intr; |
---|
| 1296 | + } |
---|
| 1297 | + |
---|
| 1298 | + hinic_dbg_init(nic_dev); |
---|
| 1299 | + |
---|
| 1300 | + hinic_func_tbl_dbgfs_init(nic_dev); |
---|
| 1301 | + |
---|
| 1302 | + err = hinic_func_table_debug_add(nic_dev); |
---|
| 1303 | + if (err) { |
---|
| 1304 | + dev_err(&pdev->dev, "Failed to add func_table debug\n"); |
---|
| 1305 | + goto err_add_func_table_dbg; |
---|
| 1306 | + } |
---|
| 1307 | + |
---|
956 | 1308 | err = register_netdev(netdev); |
---|
957 | 1309 | if (err) { |
---|
958 | 1310 | dev_err(&pdev->dev, "Failed to register netdev\n"); |
---|
.. | .. |
---|
962 | 1314 | return 0; |
---|
963 | 1315 | |
---|
964 | 1316 | err_reg_netdev: |
---|
| 1317 | + hinic_func_table_debug_rem(nic_dev); |
---|
| 1318 | +err_add_func_table_dbg: |
---|
| 1319 | + hinic_func_tbl_dbgfs_uninit(nic_dev); |
---|
| 1320 | + hinic_dbg_uninit(nic_dev); |
---|
| 1321 | + hinic_free_intr_coalesce(nic_dev); |
---|
| 1322 | +err_init_intr: |
---|
| 1323 | +err_set_pfc: |
---|
| 1324 | +err_set_features: |
---|
| 1325 | + hinic_hwdev_cb_unregister(nic_dev->hwdev, |
---|
| 1326 | + HINIC_MGMT_MSG_CMD_LINK_ERR_EVENT); |
---|
| 1327 | + hinic_hwdev_cb_unregister(nic_dev->hwdev, |
---|
| 1328 | + HINIC_MGMT_MSG_CMD_CABLE_PLUG_EVENT); |
---|
965 | 1329 | hinic_hwdev_cb_unregister(nic_dev->hwdev, |
---|
966 | 1330 | HINIC_MGMT_MSG_CMD_LINK_STATUS); |
---|
967 | 1331 | cancel_work_sync(&rx_mode_work->work); |
---|
968 | 1332 | |
---|
969 | 1333 | err_set_mtu: |
---|
| 1334 | + hinic_port_del_mac(nic_dev, netdev->dev_addr, 0); |
---|
970 | 1335 | err_add_mac: |
---|
| 1336 | +err_get_mac: |
---|
971 | 1337 | pci_set_drvdata(pdev, NULL); |
---|
972 | 1338 | destroy_workqueue(nic_dev->workq); |
---|
973 | | - |
---|
974 | 1339 | err_workq: |
---|
975 | 1340 | err_vlan_bitmap: |
---|
976 | 1341 | free_netdev(netdev); |
---|
.. | .. |
---|
978 | 1343 | err_alloc_etherdev: |
---|
979 | 1344 | err_num_qps: |
---|
980 | 1345 | hinic_free_hwdev(hwdev); |
---|
| 1346 | + hinic_devlink_free(devlink); |
---|
981 | 1347 | return err; |
---|
982 | 1348 | } |
---|
983 | 1349 | |
---|
.. | .. |
---|
1040 | 1406 | return err; |
---|
1041 | 1407 | } |
---|
1042 | 1408 | |
---|
| 1409 | +#define HINIC_WAIT_SRIOV_CFG_TIMEOUT 15000 |
---|
| 1410 | + |
---|
| 1411 | +static void wait_sriov_cfg_complete(struct hinic_dev *nic_dev) |
---|
| 1412 | +{ |
---|
| 1413 | + struct hinic_sriov_info *sriov_info = &nic_dev->sriov_info; |
---|
| 1414 | + u32 loop_cnt = 0; |
---|
| 1415 | + |
---|
| 1416 | + set_bit(HINIC_FUNC_REMOVE, &sriov_info->state); |
---|
| 1417 | + usleep_range(9900, 10000); |
---|
| 1418 | + |
---|
| 1419 | + while (loop_cnt < HINIC_WAIT_SRIOV_CFG_TIMEOUT) { |
---|
| 1420 | + if (!test_bit(HINIC_SRIOV_ENABLE, &sriov_info->state) && |
---|
| 1421 | + !test_bit(HINIC_SRIOV_DISABLE, &sriov_info->state)) |
---|
| 1422 | + return; |
---|
| 1423 | + |
---|
| 1424 | + usleep_range(9900, 10000); |
---|
| 1425 | + loop_cnt++; |
---|
| 1426 | + } |
---|
| 1427 | +} |
---|
| 1428 | + |
---|
1043 | 1429 | static void hinic_remove(struct pci_dev *pdev) |
---|
1044 | 1430 | { |
---|
1045 | 1431 | struct net_device *netdev = pci_get_drvdata(pdev); |
---|
1046 | 1432 | struct hinic_dev *nic_dev = netdev_priv(netdev); |
---|
| 1433 | + struct devlink *devlink = nic_dev->devlink; |
---|
1047 | 1434 | struct hinic_rx_mode_work *rx_mode_work; |
---|
| 1435 | + |
---|
| 1436 | + if (!HINIC_IS_VF(nic_dev->hwdev->hwif)) { |
---|
| 1437 | + wait_sriov_cfg_complete(nic_dev); |
---|
| 1438 | + hinic_pci_sriov_disable(pdev); |
---|
| 1439 | + } |
---|
1048 | 1440 | |
---|
1049 | 1441 | unregister_netdev(netdev); |
---|
1050 | 1442 | |
---|
| 1443 | + hinic_func_table_debug_rem(nic_dev); |
---|
| 1444 | + |
---|
| 1445 | + hinic_func_tbl_dbgfs_uninit(nic_dev); |
---|
| 1446 | + |
---|
| 1447 | + hinic_dbg_uninit(nic_dev); |
---|
| 1448 | + |
---|
| 1449 | + hinic_free_intr_coalesce(nic_dev); |
---|
| 1450 | + |
---|
| 1451 | + hinic_port_del_mac(nic_dev, netdev->dev_addr, 0); |
---|
| 1452 | + |
---|
| 1453 | + hinic_hwdev_cb_unregister(nic_dev->hwdev, |
---|
| 1454 | + HINIC_MGMT_MSG_CMD_LINK_ERR_EVENT); |
---|
| 1455 | + hinic_hwdev_cb_unregister(nic_dev->hwdev, |
---|
| 1456 | + HINIC_MGMT_MSG_CMD_CABLE_PLUG_EVENT); |
---|
1051 | 1457 | hinic_hwdev_cb_unregister(nic_dev->hwdev, |
---|
1052 | 1458 | HINIC_MGMT_MSG_CMD_LINK_STATUS); |
---|
1053 | 1459 | |
---|
.. | .. |
---|
1062 | 1468 | |
---|
1063 | 1469 | free_netdev(netdev); |
---|
1064 | 1470 | |
---|
| 1471 | + hinic_devlink_free(devlink); |
---|
| 1472 | + |
---|
1065 | 1473 | pci_release_regions(pdev); |
---|
1066 | 1474 | pci_disable_device(pdev); |
---|
1067 | 1475 | |
---|
1068 | 1476 | dev_info(&pdev->dev, "HiNIC driver - removed\n"); |
---|
1069 | 1477 | } |
---|
1070 | 1478 | |
---|
| 1479 | +static void hinic_shutdown(struct pci_dev *pdev) |
---|
| 1480 | +{ |
---|
| 1481 | + pci_disable_device(pdev); |
---|
| 1482 | +} |
---|
| 1483 | + |
---|
1071 | 1484 | static const struct pci_device_id hinic_pci_table[] = { |
---|
1072 | 1485 | { PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_QUAD_PORT_25GE), 0}, |
---|
1073 | | - { PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_DUAL_PORT_25GE), 0}, |
---|
1074 | 1486 | { PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_DUAL_PORT_100GE), 0}, |
---|
| 1487 | + { PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_DUAL_PORT_100GE_MEZZ), 0}, |
---|
| 1488 | + { PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_QUAD_PORT_25GE_MEZZ), 0}, |
---|
| 1489 | + { PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_VF), 0}, |
---|
1075 | 1490 | { 0, 0} |
---|
1076 | 1491 | }; |
---|
1077 | 1492 | MODULE_DEVICE_TABLE(pci, hinic_pci_table); |
---|
.. | .. |
---|
1081 | 1496 | .id_table = hinic_pci_table, |
---|
1082 | 1497 | .probe = hinic_probe, |
---|
1083 | 1498 | .remove = hinic_remove, |
---|
| 1499 | + .shutdown = hinic_shutdown, |
---|
| 1500 | + .sriov_configure = hinic_pci_sriov_configure, |
---|
1084 | 1501 | }; |
---|
1085 | 1502 | |
---|
1086 | | -module_pci_driver(hinic_driver); |
---|
| 1503 | +static int __init hinic_module_init(void) |
---|
| 1504 | +{ |
---|
| 1505 | + int ret; |
---|
| 1506 | + |
---|
| 1507 | + hinic_dbg_register_debugfs(HINIC_DRV_NAME); |
---|
| 1508 | + |
---|
| 1509 | + ret = pci_register_driver(&hinic_driver); |
---|
| 1510 | + if (ret) |
---|
| 1511 | + hinic_dbg_unregister_debugfs(); |
---|
| 1512 | + |
---|
| 1513 | + return ret; |
---|
| 1514 | +} |
---|
| 1515 | + |
---|
| 1516 | +static void __exit hinic_module_exit(void) |
---|
| 1517 | +{ |
---|
| 1518 | + pci_unregister_driver(&hinic_driver); |
---|
| 1519 | + hinic_dbg_unregister_debugfs(); |
---|
| 1520 | +} |
---|
| 1521 | + |
---|
| 1522 | +module_init(hinic_module_init); |
---|
| 1523 | +module_exit(hinic_module_exit); |
---|