Commit | Line | Data |
---|---|---|
51b35a45 EC |
1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /**************************************************************************** | |
3 | * Driver for Solarflare network controllers and boards | |
4 | * Copyright 2018 Solarflare Communications Inc. | |
5 | * Copyright 2019-2020 Xilinx Inc. | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify it | |
8 | * under the terms of the GNU General Public License version 2 as published | |
9 | * by the Free Software Foundation, incorporated herein by reference. | |
10 | */ | |
11 | ||
12 | #include "ef100_nic.h" | |
13 | #include "efx_common.h" | |
14 | #include "efx_channels.h" | |
15 | #include "io.h" | |
16 | #include "selftest.h" | |
17 | #include "ef100_regs.h" | |
18 | #include "mcdi.h" | |
19 | #include "mcdi_pcol.h" | |
20 | #include "mcdi_port_common.h" | |
21 | #include "mcdi_functions.h" | |
22 | #include "mcdi_filters.h" | |
23 | #include "ef100_rx.h" | |
24 | #include "ef100_tx.h" | |
25 | #include "ef100_netdev.h" | |
26 | ||
27 | #define EF100_MAX_VIS 4096 | |
2200e6d9 EC |
28 | #define EF100_NUM_MCDI_BUFFERS 1 |
29 | #define MCDI_BUF_LEN (8 + MCDI_CTL_SDU_LEN_MAX) | |
51b35a45 | 30 | |
c027f2a7 EC |
31 | #define EF100_RESET_PORT ((ETH_RESET_MAC | ETH_RESET_PHY) << ETH_RESET_SHARED_SHIFT) |
32 | ||
51b35a45 EC |
33 | /* MCDI |
34 | */ | |
2200e6d9 EC |
35 | static u8 *ef100_mcdi_buf(struct efx_nic *efx, u8 bufid, dma_addr_t *dma_addr) |
36 | { | |
37 | struct ef100_nic_data *nic_data = efx->nic_data; | |
38 | ||
39 | if (dma_addr) | |
40 | *dma_addr = nic_data->mcdi_buf.dma_addr + | |
41 | bufid * ALIGN(MCDI_BUF_LEN, 256); | |
42 | return nic_data->mcdi_buf.addr + bufid * ALIGN(MCDI_BUF_LEN, 256); | |
43 | } | |
44 | ||
51b35a45 EC |
45 | static int ef100_get_warm_boot_count(struct efx_nic *efx) |
46 | { | |
47 | efx_dword_t reg; | |
48 | ||
49 | efx_readd(efx, ®, efx_reg(efx, ER_GZ_MC_SFT_STATUS)); | |
50 | ||
51 | if (EFX_DWORD_FIELD(reg, EFX_DWORD_0) == 0xffffffff) { | |
52 | netif_err(efx, hw, efx->net_dev, "Hardware unavailable\n"); | |
53 | efx->state = STATE_DISABLED; | |
54 | return -ENETDOWN; | |
55 | } else { | |
56 | return EFX_DWORD_FIELD(reg, EFX_WORD_1) == 0xb007 ? | |
57 | EFX_DWORD_FIELD(reg, EFX_WORD_0) : -EIO; | |
58 | } | |
59 | } | |
60 | ||
2200e6d9 EC |
61 | static void ef100_mcdi_request(struct efx_nic *efx, |
62 | const efx_dword_t *hdr, size_t hdr_len, | |
63 | const efx_dword_t *sdu, size_t sdu_len) | |
64 | { | |
65 | dma_addr_t dma_addr; | |
66 | u8 *pdu = ef100_mcdi_buf(efx, 0, &dma_addr); | |
67 | ||
68 | memcpy(pdu, hdr, hdr_len); | |
69 | memcpy(pdu + hdr_len, sdu, sdu_len); | |
70 | wmb(); | |
71 | ||
72 | /* The hardware provides 'low' and 'high' (doorbell) registers | |
73 | * for passing the 64-bit address of an MCDI request to | |
74 | * firmware. However the dwords are swapped by firmware. The | |
75 | * least significant bits of the doorbell are then 0 for all | |
76 | * MCDI requests due to alignment. | |
77 | */ | |
78 | _efx_writed(efx, cpu_to_le32((u64)dma_addr >> 32), efx_reg(efx, ER_GZ_MC_DB_LWRD)); | |
79 | _efx_writed(efx, cpu_to_le32((u32)dma_addr), efx_reg(efx, ER_GZ_MC_DB_HWRD)); | |
80 | } | |
81 | ||
82 | static bool ef100_mcdi_poll_response(struct efx_nic *efx) | |
83 | { | |
84 | const efx_dword_t hdr = | |
85 | *(const efx_dword_t *)(ef100_mcdi_buf(efx, 0, NULL)); | |
86 | ||
87 | rmb(); | |
88 | return EFX_DWORD_FIELD(hdr, MCDI_HEADER_RESPONSE); | |
89 | } | |
90 | ||
91 | static void ef100_mcdi_read_response(struct efx_nic *efx, | |
92 | efx_dword_t *outbuf, size_t offset, | |
93 | size_t outlen) | |
94 | { | |
95 | const u8 *pdu = ef100_mcdi_buf(efx, 0, NULL); | |
96 | ||
97 | memcpy(outbuf, pdu + offset, outlen); | |
98 | } | |
99 | ||
100 | static int ef100_mcdi_poll_reboot(struct efx_nic *efx) | |
101 | { | |
102 | struct ef100_nic_data *nic_data = efx->nic_data; | |
103 | int rc; | |
104 | ||
105 | rc = ef100_get_warm_boot_count(efx); | |
106 | if (rc < 0) { | |
107 | /* The firmware is presumably in the process of | |
108 | * rebooting. However, we are supposed to report each | |
109 | * reboot just once, so we must only do that once we | |
110 | * can read and store the updated warm boot count. | |
111 | */ | |
112 | return 0; | |
113 | } | |
114 | ||
115 | if (rc == nic_data->warm_boot_count) | |
116 | return 0; | |
117 | ||
118 | nic_data->warm_boot_count = rc; | |
119 | ||
120 | return -EIO; | |
121 | } | |
122 | ||
123 | static void ef100_mcdi_reboot_detected(struct efx_nic *efx) | |
124 | { | |
125 | } | |
126 | ||
f6573120 EC |
127 | /* MCDI calls |
128 | */ | |
29ec1b27 EC |
129 | static int ef100_get_mac_address(struct efx_nic *efx, u8 *mac_address) |
130 | { | |
131 | MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_MAC_ADDRESSES_OUT_LEN); | |
132 | size_t outlen; | |
133 | int rc; | |
134 | ||
135 | BUILD_BUG_ON(MC_CMD_GET_MAC_ADDRESSES_IN_LEN != 0); | |
136 | ||
137 | rc = efx_mcdi_rpc(efx, MC_CMD_GET_MAC_ADDRESSES, NULL, 0, | |
138 | outbuf, sizeof(outbuf), &outlen); | |
139 | if (rc) | |
140 | return rc; | |
141 | if (outlen < MC_CMD_GET_MAC_ADDRESSES_OUT_LEN) | |
142 | return -EIO; | |
143 | ||
144 | ether_addr_copy(mac_address, | |
145 | MCDI_PTR(outbuf, GET_MAC_ADDRESSES_OUT_MAC_ADDR_BASE)); | |
146 | return 0; | |
147 | } | |
148 | ||
f6573120 EC |
149 | static int efx_ef100_init_datapath_caps(struct efx_nic *efx) |
150 | { | |
d802b0ae | 151 | MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CAPABILITIES_V7_OUT_LEN); |
f6573120 EC |
152 | struct ef100_nic_data *nic_data = efx->nic_data; |
153 | u8 vi_window_mode; | |
154 | size_t outlen; | |
155 | int rc; | |
156 | ||
157 | BUILD_BUG_ON(MC_CMD_GET_CAPABILITIES_IN_LEN != 0); | |
158 | ||
159 | rc = efx_mcdi_rpc(efx, MC_CMD_GET_CAPABILITIES, NULL, 0, | |
160 | outbuf, sizeof(outbuf), &outlen); | |
161 | if (rc) | |
162 | return rc; | |
163 | if (outlen < MC_CMD_GET_CAPABILITIES_V4_OUT_LEN) { | |
164 | netif_err(efx, drv, efx->net_dev, | |
165 | "unable to read datapath firmware capabilities\n"); | |
166 | return -EIO; | |
167 | } | |
168 | ||
169 | nic_data->datapath_caps = MCDI_DWORD(outbuf, | |
170 | GET_CAPABILITIES_OUT_FLAGS1); | |
171 | nic_data->datapath_caps2 = MCDI_DWORD(outbuf, | |
172 | GET_CAPABILITIES_V2_OUT_FLAGS2); | |
d802b0ae EC |
173 | if (outlen < MC_CMD_GET_CAPABILITIES_V7_OUT_LEN) |
174 | nic_data->datapath_caps3 = 0; | |
175 | else | |
176 | nic_data->datapath_caps3 = MCDI_DWORD(outbuf, | |
177 | GET_CAPABILITIES_V7_OUT_FLAGS3); | |
f6573120 EC |
178 | |
179 | vi_window_mode = MCDI_BYTE(outbuf, | |
180 | GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE); | |
181 | rc = efx_mcdi_window_mode_to_stride(efx, vi_window_mode); | |
182 | if (rc) | |
183 | return rc; | |
184 | ||
185 | if (efx_ef100_has_cap(nic_data->datapath_caps2, TX_TSO_V3)) | |
186 | efx->net_dev->features |= NETIF_F_TSO | NETIF_F_TSO6; | |
187 | efx->num_mac_stats = MCDI_WORD(outbuf, | |
188 | GET_CAPABILITIES_V4_OUT_MAC_STATS_NUM_STATS); | |
189 | netif_dbg(efx, probe, efx->net_dev, | |
190 | "firmware reports num_mac_stats = %u\n", | |
191 | efx->num_mac_stats); | |
192 | return 0; | |
193 | } | |
194 | ||
51b35a45 EC |
195 | /* Event handling |
196 | */ | |
197 | static int ef100_ev_probe(struct efx_channel *channel) | |
198 | { | |
199 | /* Allocate an extra descriptor for the QMDA status completion entry */ | |
200 | return efx_nic_alloc_buffer(channel->efx, &channel->eventq.buf, | |
201 | (channel->eventq_mask + 2) * | |
202 | sizeof(efx_qword_t), | |
203 | GFP_KERNEL); | |
204 | } | |
205 | ||
965b549f EC |
206 | static int ef100_ev_init(struct efx_channel *channel) |
207 | { | |
208 | struct ef100_nic_data *nic_data = channel->efx->nic_data; | |
209 | ||
210 | /* initial phase is 0 */ | |
211 | clear_bit(channel->channel, nic_data->evq_phases); | |
212 | ||
213 | return efx_mcdi_ev_init(channel, false, false); | |
214 | } | |
215 | ||
216 | static void ef100_ev_read_ack(struct efx_channel *channel) | |
217 | { | |
218 | efx_dword_t evq_prime; | |
219 | ||
220 | EFX_POPULATE_DWORD_2(evq_prime, | |
221 | ERF_GZ_EVQ_ID, channel->channel, | |
222 | ERF_GZ_IDX, channel->eventq_read_ptr & | |
223 | channel->eventq_mask); | |
224 | ||
225 | efx_writed(channel->efx, &evq_prime, | |
226 | efx_reg(channel->efx, ER_GZ_EVQ_INT_PRIME)); | |
227 | } | |
228 | ||
229 | static int ef100_ev_process(struct efx_channel *channel, int quota) | |
230 | { | |
5e4ef673 EC |
231 | struct efx_nic *efx = channel->efx; |
232 | struct ef100_nic_data *nic_data; | |
233 | bool evq_phase, old_evq_phase; | |
234 | unsigned int read_ptr; | |
235 | efx_qword_t *p_event; | |
236 | int spent = 0; | |
237 | bool ev_phase; | |
238 | int ev_type; | |
239 | ||
240 | if (unlikely(!channel->enabled)) | |
241 | return 0; | |
242 | ||
243 | nic_data = efx->nic_data; | |
244 | evq_phase = test_bit(channel->channel, nic_data->evq_phases); | |
245 | old_evq_phase = evq_phase; | |
246 | read_ptr = channel->eventq_read_ptr; | |
247 | BUILD_BUG_ON(ESF_GZ_EV_RXPKTS_PHASE_LBN != ESF_GZ_EV_TXCMPL_PHASE_LBN); | |
248 | ||
249 | while (spent < quota) { | |
250 | p_event = efx_event(channel, read_ptr); | |
251 | ||
252 | ev_phase = !!EFX_QWORD_FIELD(*p_event, ESF_GZ_EV_RXPKTS_PHASE); | |
253 | if (ev_phase != evq_phase) | |
254 | break; | |
255 | ||
256 | netif_vdbg(efx, drv, efx->net_dev, | |
257 | "processing event on %d " EFX_QWORD_FMT "\n", | |
258 | channel->channel, EFX_QWORD_VAL(*p_event)); | |
259 | ||
260 | ev_type = EFX_QWORD_FIELD(*p_event, ESF_GZ_E_TYPE); | |
261 | ||
262 | switch (ev_type) { | |
263 | case ESE_GZ_EF100_EV_MCDI: | |
264 | efx_mcdi_process_event(channel, p_event); | |
265 | break; | |
266 | case ESE_GZ_EF100_EV_DRIVER: | |
267 | netif_info(efx, drv, efx->net_dev, | |
268 | "Driver initiated event " EFX_QWORD_FMT "\n", | |
269 | EFX_QWORD_VAL(*p_event)); | |
270 | break; | |
271 | default: | |
272 | netif_info(efx, drv, efx->net_dev, | |
273 | "Unhandled event " EFX_QWORD_FMT "\n", | |
274 | EFX_QWORD_VAL(*p_event)); | |
275 | } | |
276 | ||
277 | ++read_ptr; | |
278 | if ((read_ptr & channel->eventq_mask) == 0) | |
279 | evq_phase = !evq_phase; | |
280 | } | |
281 | ||
282 | channel->eventq_read_ptr = read_ptr; | |
283 | if (evq_phase != old_evq_phase) | |
284 | change_bit(channel->channel, nic_data->evq_phases); | |
285 | ||
286 | return spent; | |
965b549f EC |
287 | } |
288 | ||
51b35a45 EC |
289 | static irqreturn_t ef100_msi_interrupt(int irq, void *dev_id) |
290 | { | |
291 | struct efx_msi_context *context = dev_id; | |
292 | struct efx_nic *efx = context->efx; | |
293 | ||
294 | netif_vdbg(efx, intr, efx->net_dev, | |
295 | "IRQ %d on CPU %d\n", irq, raw_smp_processor_id()); | |
296 | ||
297 | if (likely(READ_ONCE(efx->irq_soft_enabled))) { | |
298 | /* Note test interrupts */ | |
299 | if (context->index == efx->irq_level) | |
300 | efx->last_irq_cpu = raw_smp_processor_id(); | |
301 | ||
302 | /* Schedule processing of the channel */ | |
303 | efx_schedule_channel_irq(efx->channel[context->index]); | |
304 | } | |
305 | ||
306 | return IRQ_HANDLED; | |
307 | } | |
308 | ||
aa86a75f EC |
309 | static int ef100_phy_probe(struct efx_nic *efx) |
310 | { | |
99a23c11 EC |
311 | struct efx_mcdi_phy_data *phy_data; |
312 | int rc; | |
313 | ||
314 | /* Probe for the PHY */ | |
aa86a75f EC |
315 | efx->phy_data = kzalloc(sizeof(struct efx_mcdi_phy_data), GFP_KERNEL); |
316 | if (!efx->phy_data) | |
317 | return -ENOMEM; | |
318 | ||
99a23c11 EC |
319 | rc = efx_mcdi_get_phy_cfg(efx, efx->phy_data); |
320 | if (rc) | |
321 | return rc; | |
322 | ||
323 | /* Populate driver and ethtool settings */ | |
324 | phy_data = efx->phy_data; | |
325 | mcdi_to_ethtool_linkset(phy_data->media, phy_data->supported_cap, | |
326 | efx->link_advertising); | |
327 | efx->fec_config = mcdi_fec_caps_to_ethtool(phy_data->supported_cap, | |
328 | false); | |
329 | ||
330 | /* Default to Autonegotiated flow control if the PHY supports it */ | |
331 | efx->wanted_fc = EFX_FC_RX | EFX_FC_TX; | |
332 | if (phy_data->supported_cap & (1 << MC_CMD_PHY_CAP_AN_LBN)) | |
333 | efx->wanted_fc |= EFX_FC_AUTO; | |
334 | efx_link_set_wanted_fc(efx, efx->wanted_fc); | |
335 | ||
336 | /* Push settings to the PHY. Failure is not fatal, the user can try to | |
337 | * fix it using ethtool. | |
338 | */ | |
339 | rc = efx_mcdi_port_reconfigure(efx); | |
340 | if (rc && rc != -EPERM) | |
341 | netif_warn(efx, drv, efx->net_dev, | |
342 | "could not initialise PHY settings\n"); | |
343 | ||
aa86a75f EC |
344 | return 0; |
345 | } | |
346 | ||
c027f2a7 EC |
347 | /* Other |
348 | */ | |
99a23c11 EC |
349 | static int ef100_reconfigure_mac(struct efx_nic *efx, bool mtu_only) |
350 | { | |
351 | WARN_ON(!mutex_is_locked(&efx->mac_lock)); | |
352 | ||
353 | efx_mcdi_filter_sync_rx_mode(efx); | |
354 | ||
355 | if (mtu_only && efx_has_cap(efx, SET_MAC_ENHANCED)) | |
356 | return efx_mcdi_set_mtu(efx); | |
357 | return efx_mcdi_set_mac(efx); | |
358 | } | |
c027f2a7 EC |
359 | |
360 | static enum reset_type ef100_map_reset_reason(enum reset_type reason) | |
361 | { | |
362 | if (reason == RESET_TYPE_TX_WATCHDOG) | |
363 | return reason; | |
364 | return RESET_TYPE_DISABLE; | |
365 | } | |
366 | ||
367 | static int ef100_map_reset_flags(u32 *flags) | |
368 | { | |
369 | /* Only perform a RESET_TYPE_ALL because we don't support MC_REBOOTs */ | |
370 | if ((*flags & EF100_RESET_PORT)) { | |
371 | *flags &= ~EF100_RESET_PORT; | |
372 | return RESET_TYPE_ALL; | |
373 | } | |
374 | if (*flags & ETH_RESET_MGMT) { | |
375 | *flags &= ~ETH_RESET_MGMT; | |
376 | return RESET_TYPE_DISABLE; | |
377 | } | |
378 | ||
379 | return -EINVAL; | |
380 | } | |
381 | ||
382 | static int ef100_reset(struct efx_nic *efx, enum reset_type reset_type) | |
383 | { | |
384 | int rc; | |
385 | ||
386 | dev_close(efx->net_dev); | |
387 | ||
388 | if (reset_type == RESET_TYPE_TX_WATCHDOG) { | |
389 | netif_device_attach(efx->net_dev); | |
390 | __clear_bit(reset_type, &efx->reset_pending); | |
391 | rc = dev_open(efx->net_dev, NULL); | |
392 | } else if (reset_type == RESET_TYPE_ALL) { | |
4e5675bb EC |
393 | rc = efx_mcdi_reset(efx, reset_type); |
394 | if (rc) | |
395 | return rc; | |
396 | ||
c027f2a7 EC |
397 | netif_device_attach(efx->net_dev); |
398 | ||
399 | rc = dev_open(efx->net_dev, NULL); | |
400 | } else { | |
401 | rc = 1; /* Leave the device closed */ | |
402 | } | |
403 | return rc; | |
404 | } | |
405 | ||
1c748843 EC |
406 | static int efx_ef100_get_phys_port_id(struct efx_nic *efx, |
407 | struct netdev_phys_item_id *ppid) | |
408 | { | |
409 | struct ef100_nic_data *nic_data = efx->nic_data; | |
410 | ||
411 | if (!is_valid_ether_addr(nic_data->port_id)) | |
412 | return -EOPNOTSUPP; | |
413 | ||
414 | ppid->id_len = ETH_ALEN; | |
415 | memcpy(ppid->id, nic_data->port_id, ppid->id_len); | |
416 | ||
417 | return 0; | |
418 | } | |
419 | ||
965b549f EC |
420 | static unsigned int ef100_check_caps(const struct efx_nic *efx, |
421 | u8 flag, u32 offset) | |
422 | { | |
f6573120 EC |
423 | const struct ef100_nic_data *nic_data = efx->nic_data; |
424 | ||
425 | switch (offset) { | |
426 | case MC_CMD_GET_CAPABILITIES_V8_OUT_FLAGS1_OFST: | |
427 | return nic_data->datapath_caps & BIT_ULL(flag); | |
428 | case MC_CMD_GET_CAPABILITIES_V8_OUT_FLAGS2_OFST: | |
429 | return nic_data->datapath_caps2 & BIT_ULL(flag); | |
d802b0ae EC |
430 | case MC_CMD_GET_CAPABILITIES_V8_OUT_FLAGS3_OFST: |
431 | return nic_data->datapath_caps3 & BIT_ULL(flag); | |
f6573120 EC |
432 | default: |
433 | return 0; | |
434 | } | |
965b549f EC |
435 | } |
436 | ||
51b35a45 EC |
437 | /* NIC level access functions |
438 | */ | |
439 | const struct efx_nic_type ef100_pf_nic_type = { | |
440 | .revision = EFX_REV_EF100, | |
441 | .is_vf = false, | |
442 | .probe = ef100_probe_pf, | |
443 | .mcdi_max_ver = 2, | |
2200e6d9 EC |
444 | .mcdi_request = ef100_mcdi_request, |
445 | .mcdi_poll_response = ef100_mcdi_poll_response, | |
446 | .mcdi_read_response = ef100_mcdi_read_response, | |
447 | .mcdi_poll_reboot = ef100_mcdi_poll_reboot, | |
448 | .mcdi_reboot_detected = ef100_mcdi_reboot_detected, | |
51b35a45 EC |
449 | .irq_enable_master = efx_port_dummy_op_void, |
450 | .irq_disable_non_ev = efx_port_dummy_op_void, | |
451 | .push_irq_moderation = efx_channel_dummy_op_void, | |
452 | .min_interrupt_mode = EFX_INT_MODE_MSIX, | |
c027f2a7 EC |
453 | .map_reset_reason = ef100_map_reset_reason, |
454 | .map_reset_flags = ef100_map_reset_flags, | |
455 | .reset = ef100_reset, | |
51b35a45 | 456 | |
965b549f EC |
457 | .check_caps = ef100_check_caps, |
458 | ||
51b35a45 | 459 | .ev_probe = ef100_ev_probe, |
965b549f EC |
460 | .ev_init = ef100_ev_init, |
461 | .ev_fini = efx_mcdi_ev_fini, | |
462 | .ev_remove = efx_mcdi_ev_remove, | |
51b35a45 | 463 | .irq_handle_msi = ef100_msi_interrupt, |
965b549f EC |
464 | .ev_process = ef100_ev_process, |
465 | .ev_read_ack = ef100_ev_read_ack, | |
466 | .tx_probe = ef100_tx_probe, | |
467 | .tx_init = ef100_tx_init, | |
468 | .tx_write = ef100_tx_write, | |
469 | .tx_enqueue = ef100_enqueue_skb, | |
470 | .rx_probe = efx_mcdi_rx_probe, | |
471 | .rx_init = efx_mcdi_rx_init, | |
472 | .rx_remove = efx_mcdi_rx_remove, | |
473 | .rx_write = ef100_rx_write, | |
474 | .rx_packet = __ef100_rx_packet, | |
51b35a45 | 475 | |
1c748843 EC |
476 | .get_phys_port_id = efx_ef100_get_phys_port_id, |
477 | ||
99a23c11 EC |
478 | .reconfigure_mac = ef100_reconfigure_mac, |
479 | ||
51b35a45 EC |
480 | /* Per-type bar/size configuration not used on ef100. Location of |
481 | * registers is defined by extended capabilities. | |
482 | */ | |
483 | .mem_bar = NULL, | |
484 | .mem_map_size = NULL, | |
485 | ||
486 | }; | |
487 | ||
8e737145 EC |
488 | static int compare_versions(const char *a, const char *b) |
489 | { | |
490 | int a_major, a_minor, a_point, a_patch; | |
491 | int b_major, b_minor, b_point, b_patch; | |
492 | int a_matched, b_matched; | |
493 | ||
494 | a_matched = sscanf(a, "%d.%d.%d.%d", &a_major, &a_minor, &a_point, &a_patch); | |
495 | b_matched = sscanf(b, "%d.%d.%d.%d", &b_major, &b_minor, &b_point, &b_patch); | |
496 | ||
497 | if (a_matched == 4 && b_matched != 4) | |
498 | return +1; | |
499 | ||
500 | if (a_matched != 4 && b_matched == 4) | |
501 | return -1; | |
502 | ||
503 | if (a_matched != 4 && b_matched != 4) | |
504 | return 0; | |
505 | ||
506 | if (a_major != b_major) | |
507 | return a_major - b_major; | |
508 | ||
509 | if (a_minor != b_minor) | |
510 | return a_minor - b_minor; | |
511 | ||
512 | if (a_point != b_point) | |
513 | return a_point - b_point; | |
514 | ||
515 | return a_patch - b_patch; | |
516 | } | |
517 | ||
51b35a45 EC |
518 | /* NIC probe and remove |
519 | */ | |
520 | static int ef100_probe_main(struct efx_nic *efx) | |
521 | { | |
522 | unsigned int bar_size = resource_size(&efx->pci_dev->resource[efx->mem_bar]); | |
523 | struct net_device *net_dev = efx->net_dev; | |
524 | struct ef100_nic_data *nic_data; | |
8e737145 | 525 | char fw_version[32]; |
51b35a45 EC |
526 | int i, rc; |
527 | ||
528 | if (WARN_ON(bar_size == 0)) | |
529 | return -EIO; | |
530 | ||
531 | nic_data = kzalloc(sizeof(*nic_data), GFP_KERNEL); | |
532 | if (!nic_data) | |
533 | return -ENOMEM; | |
534 | efx->nic_data = nic_data; | |
535 | nic_data->efx = efx; | |
536 | net_dev->features |= efx->type->offload_features; | |
537 | net_dev->hw_features |= efx->type->offload_features; | |
538 | ||
2200e6d9 EC |
539 | /* we assume later that we can copy from this buffer in dwords */ |
540 | BUILD_BUG_ON(MCDI_CTL_SDU_LEN_MAX_V2 % 4); | |
541 | ||
542 | /* MCDI buffers must be 256 byte aligned. */ | |
543 | rc = efx_nic_alloc_buffer(efx, &nic_data->mcdi_buf, MCDI_BUF_LEN, | |
544 | GFP_KERNEL); | |
545 | if (rc) | |
546 | goto fail; | |
547 | ||
51b35a45 EC |
548 | /* Get the MC's warm boot count. In case it's rebooting right |
549 | * now, be prepared to retry. | |
550 | */ | |
551 | i = 0; | |
552 | for (;;) { | |
553 | rc = ef100_get_warm_boot_count(efx); | |
554 | if (rc >= 0) | |
555 | break; | |
556 | if (++i == 5) | |
557 | goto fail; | |
558 | ssleep(1); | |
559 | } | |
560 | nic_data->warm_boot_count = rc; | |
561 | ||
562 | /* In case we're recovering from a crash (kexec), we want to | |
563 | * cancel any outstanding request by the previous user of this | |
564 | * function. We send a special message using the least | |
565 | * significant bits of the 'high' (doorbell) register. | |
566 | */ | |
567 | _efx_writed(efx, cpu_to_le32(1), efx_reg(efx, ER_GZ_MC_DB_HWRD)); | |
568 | ||
569 | /* Post-IO section. */ | |
570 | ||
2200e6d9 EC |
571 | rc = efx_mcdi_init(efx); |
572 | if (!rc && efx->mcdi->fn_flags & | |
573 | (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_NO_ACTIVE_PORT)) { | |
574 | netif_info(efx, probe, efx->net_dev, | |
575 | "No network port on this PCI function"); | |
576 | rc = -ENODEV; | |
577 | } | |
578 | if (rc) | |
579 | goto fail; | |
4e5675bb EC |
580 | /* Reset (most) configuration for this function */ |
581 | rc = efx_mcdi_reset(efx, RESET_TYPE_ALL); | |
582 | if (rc) | |
583 | goto fail; | |
584 | ||
f6573120 EC |
585 | rc = efx_ef100_init_datapath_caps(efx); |
586 | if (rc < 0) | |
587 | goto fail; | |
2200e6d9 | 588 | |
51b35a45 EC |
589 | efx->max_vis = EF100_MAX_VIS; |
590 | ||
1c748843 EC |
591 | rc = efx_mcdi_port_get_number(efx); |
592 | if (rc < 0) | |
593 | goto fail; | |
594 | efx->port_num = rc; | |
595 | ||
8e737145 EC |
596 | efx_mcdi_print_fwver(efx, fw_version, sizeof(fw_version)); |
597 | netif_dbg(efx, drv, efx->net_dev, "Firmware version %s\n", fw_version); | |
598 | ||
599 | if (compare_versions(fw_version, "1.1.0.1000") < 0) { | |
600 | netif_info(efx, drv, efx->net_dev, "Firmware uses old event descriptors\n"); | |
601 | rc = -EINVAL; | |
602 | goto fail; | |
603 | } | |
604 | ||
aa86a75f EC |
605 | rc = ef100_phy_probe(efx); |
606 | if (rc) | |
607 | goto fail; | |
608 | ||
51b35a45 EC |
609 | rc = efx_init_channels(efx); |
610 | if (rc) | |
611 | goto fail; | |
612 | ||
613 | rc = ef100_register_netdev(efx); | |
614 | if (rc) | |
615 | goto fail; | |
616 | ||
617 | return 0; | |
618 | fail: | |
619 | return rc; | |
620 | } | |
621 | ||
622 | int ef100_probe_pf(struct efx_nic *efx) | |
623 | { | |
29ec1b27 EC |
624 | struct net_device *net_dev = efx->net_dev; |
625 | struct ef100_nic_data *nic_data; | |
626 | int rc = ef100_probe_main(efx); | |
627 | ||
628 | if (rc) | |
629 | goto fail; | |
630 | ||
631 | nic_data = efx->nic_data; | |
632 | rc = ef100_get_mac_address(efx, net_dev->perm_addr); | |
633 | if (rc) | |
634 | goto fail; | |
635 | /* Assign MAC address */ | |
636 | memcpy(net_dev->dev_addr, net_dev->perm_addr, ETH_ALEN); | |
637 | memcpy(nic_data->port_id, net_dev->perm_addr, ETH_ALEN); | |
638 | ||
639 | return 0; | |
640 | ||
641 | fail: | |
642 | return rc; | |
51b35a45 EC |
643 | } |
644 | ||
645 | void ef100_remove(struct efx_nic *efx) | |
646 | { | |
647 | struct ef100_nic_data *nic_data = efx->nic_data; | |
648 | ||
649 | ef100_unregister_netdev(efx); | |
650 | efx_fini_channels(efx); | |
651 | kfree(efx->phy_data); | |
652 | efx->phy_data = NULL; | |
2200e6d9 EC |
653 | efx_mcdi_detach(efx); |
654 | efx_mcdi_fini(efx); | |
655 | if (nic_data) | |
656 | efx_nic_free_buffer(efx, &nic_data->mcdi_buf); | |
51b35a45 EC |
657 | kfree(nic_data); |
658 | efx->nic_data = NULL; | |
659 | } |