1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Atlantic Network Driver
3 * Copyright (C) 2020 Marvell International Ltd.
4 */
5
6 #include <linux/iopoll.h>
7
8 #include "aq_hw.h"
9 #include "aq_hw_utils.h"
10 #include "aq_nic.h"
11 #include "hw_atl/hw_atl_llh.h"
12 #include "hw_atl2_utils.h"
13 #include "hw_atl2_llh.h"
14 #include "hw_atl2_internal.h"
15
16 #define AQ_A2_FW_READ_TRY_MAX 1000
17
18 #define hw_atl2_shared_buffer_write(HW, ITEM, VARIABLE) \
19 {\
20 BUILD_BUG_ON_MSG((offsetof(struct fw_interface_in, ITEM) % \
21 sizeof(u32)) != 0,\
22 "Unaligned write " # ITEM);\
23 BUILD_BUG_ON_MSG((sizeof(VARIABLE) % sizeof(u32)) != 0,\
24 "Unaligned write length " # ITEM);\
25 hw_atl2_mif_shared_buf_write(HW,\
26 (offsetof(struct fw_interface_in, ITEM) / sizeof(u32)),\
27 (u32 *)&(VARIABLE), sizeof(VARIABLE) / sizeof(u32));\
28 }
29
30 #define hw_atl2_shared_buffer_get(HW, ITEM, VARIABLE) \
31 {\
32 BUILD_BUG_ON_MSG((offsetof(struct fw_interface_in, ITEM) % \
33 sizeof(u32)) != 0,\
34 "Unaligned get " # ITEM);\
35 BUILD_BUG_ON_MSG((sizeof(VARIABLE) % sizeof(u32)) != 0,\
36 "Unaligned get length " # ITEM);\
37 hw_atl2_mif_shared_buf_get(HW, \
38 (offsetof(struct fw_interface_in, ITEM) / sizeof(u32)),\
39 (u32 *)&(VARIABLE), \
40 sizeof(VARIABLE) / sizeof(u32));\
41 }
42
43 /* This should never be used on non atomic fields,
44 * treat any > u32 read as non atomic.
45 */
46 #define hw_atl2_shared_buffer_read(HW, ITEM, VARIABLE) \
47 {\
48 BUILD_BUG_ON_MSG((offsetof(struct fw_interface_out, ITEM) % \
49 sizeof(u32)) != 0,\
50 "Unaligned read " # ITEM);\
51 BUILD_BUG_ON_MSG((sizeof(VARIABLE) % sizeof(u32)) != 0,\
52 "Unaligned read length " # ITEM);\
53 BUILD_BUG_ON_MSG(sizeof(VARIABLE) > sizeof(u32),\
54 "Non atomic read " # ITEM);\
55 hw_atl2_mif_shared_buf_read(HW, \
56 (offsetof(struct fw_interface_out, ITEM) / sizeof(u32)),\
57 (u32 *)&(VARIABLE), sizeof(VARIABLE) / sizeof(u32));\
58 }
59
60 #define hw_atl2_shared_buffer_read_safe(HW, ITEM, DATA) \
61 ({\
62 BUILD_BUG_ON_MSG((offsetof(struct fw_interface_out, ITEM) % \
63 sizeof(u32)) != 0,\
64 "Unaligned read_safe " # ITEM);\
65 BUILD_BUG_ON_MSG((sizeof(((struct fw_interface_out *)0)->ITEM) % \
66 sizeof(u32)) != 0,\
67 "Unaligned read_safe length " # ITEM);\
68 hw_atl2_shared_buffer_read_block((HW), \
69 (offsetof(struct fw_interface_out, ITEM) / sizeof(u32)),\
70 sizeof(((struct fw_interface_out *)0)->ITEM) / sizeof(u32),\
71 (DATA));\
72 })
73
hw_atl2_shared_buffer_read_block(struct aq_hw_s * self,u32 offset,u32 dwords,void * data)74 static int hw_atl2_shared_buffer_read_block(struct aq_hw_s *self,
75 u32 offset, u32 dwords, void *data)
76 {
77 struct transaction_counter_s tid1, tid2;
78 int cnt = 0;
79
80 do {
81 do {
82 hw_atl2_shared_buffer_read(self, transaction_id, tid1);
83 cnt++;
84 if (cnt > AQ_A2_FW_READ_TRY_MAX)
85 return -ETIME;
86 if (tid1.transaction_cnt_a != tid1.transaction_cnt_b)
87 udelay(1);
88 } while (tid1.transaction_cnt_a != tid1.transaction_cnt_b);
89
90 hw_atl2_mif_shared_buf_read(self, offset, (u32 *)data, dwords);
91
92 hw_atl2_shared_buffer_read(self, transaction_id, tid2);
93
94 cnt++;
95 if (cnt > AQ_A2_FW_READ_TRY_MAX)
96 return -ETIME;
97 } while (tid2.transaction_cnt_a != tid2.transaction_cnt_b ||
98 tid1.transaction_cnt_a != tid2.transaction_cnt_a);
99
100 return 0;
101 }
102
hw_atl2_shared_buffer_finish_ack(struct aq_hw_s * self)103 static inline int hw_atl2_shared_buffer_finish_ack(struct aq_hw_s *self)
104 {
105 u32 val;
106 int err;
107
108 hw_atl2_mif_host_finished_write_set(self, 1U);
109 err = readx_poll_timeout_atomic(hw_atl2_mif_mcp_finished_read_get,
110 self, val, val == 0U,
111 100, 100000U);
112 WARN(err, "hw_atl2_shared_buffer_finish_ack");
113
114 return err;
115 }
116
aq_a2_fw_init(struct aq_hw_s * self)117 static int aq_a2_fw_init(struct aq_hw_s *self)
118 {
119 struct link_control_s link_control;
120 u32 mtu;
121 u32 val;
122 int err;
123
124 hw_atl2_shared_buffer_get(self, link_control, link_control);
125 link_control.mode = AQ_HOST_MODE_ACTIVE;
126 hw_atl2_shared_buffer_write(self, link_control, link_control);
127
128 hw_atl2_shared_buffer_get(self, mtu, mtu);
129 mtu = HW_ATL2_MTU_JUMBO;
130 hw_atl2_shared_buffer_write(self, mtu, mtu);
131
132 hw_atl2_mif_host_finished_write_set(self, 1U);
133 err = readx_poll_timeout_atomic(hw_atl2_mif_mcp_finished_read_get,
134 self, val, val == 0U,
135 100, 5000000U);
136 WARN(err, "hw_atl2_shared_buffer_finish_ack");
137
138 return err;
139 }
140
aq_a2_fw_deinit(struct aq_hw_s * self)141 static int aq_a2_fw_deinit(struct aq_hw_s *self)
142 {
143 struct link_control_s link_control;
144
145 hw_atl2_shared_buffer_get(self, link_control, link_control);
146 link_control.mode = AQ_HOST_MODE_SHUTDOWN;
147 hw_atl2_shared_buffer_write(self, link_control, link_control);
148
149 return hw_atl2_shared_buffer_finish_ack(self);
150 }
151
a2_link_speed_mask2fw(u32 speed,struct link_options_s * link_options)152 static void a2_link_speed_mask2fw(u32 speed,
153 struct link_options_s *link_options)
154 {
155 link_options->rate_10G = !!(speed & AQ_NIC_RATE_10G);
156 link_options->rate_5G = !!(speed & AQ_NIC_RATE_5G);
157 link_options->rate_N5G = !!(speed & AQ_NIC_RATE_5GSR);
158 link_options->rate_2P5G = !!(speed & AQ_NIC_RATE_2G5);
159 link_options->rate_N2P5G = link_options->rate_2P5G;
160 link_options->rate_1G = !!(speed & AQ_NIC_RATE_1G);
161 link_options->rate_100M = !!(speed & AQ_NIC_RATE_100M);
162 link_options->rate_10M = !!(speed & AQ_NIC_RATE_10M);
163
164 link_options->rate_1G_hd = !!(speed & AQ_NIC_RATE_1G_HALF);
165 link_options->rate_100M_hd = !!(speed & AQ_NIC_RATE_100M_HALF);
166 link_options->rate_10M_hd = !!(speed & AQ_NIC_RATE_10M_HALF);
167 }
168
a2_fw_dev_to_eee_mask(struct device_link_caps_s * device_link_caps)169 static u32 a2_fw_dev_to_eee_mask(struct device_link_caps_s *device_link_caps)
170 {
171 u32 rate = 0;
172
173 if (device_link_caps->eee_10G)
174 rate |= AQ_NIC_RATE_EEE_10G;
175 if (device_link_caps->eee_5G)
176 rate |= AQ_NIC_RATE_EEE_5G;
177 if (device_link_caps->eee_2P5G)
178 rate |= AQ_NIC_RATE_EEE_2G5;
179 if (device_link_caps->eee_1G)
180 rate |= AQ_NIC_RATE_EEE_1G;
181 if (device_link_caps->eee_100M)
182 rate |= AQ_NIC_RATE_EEE_100M;
183
184 return rate;
185 }
186
a2_fw_lkp_to_mask(struct lkp_link_caps_s * lkp_link_caps)187 static u32 a2_fw_lkp_to_mask(struct lkp_link_caps_s *lkp_link_caps)
188 {
189 u32 rate = 0;
190
191 if (lkp_link_caps->rate_10G)
192 rate |= AQ_NIC_RATE_10G;
193 if (lkp_link_caps->rate_5G)
194 rate |= AQ_NIC_RATE_5G;
195 if (lkp_link_caps->rate_N5G)
196 rate |= AQ_NIC_RATE_5GSR;
197 if (lkp_link_caps->rate_2P5G)
198 rate |= AQ_NIC_RATE_2G5;
199 if (lkp_link_caps->rate_1G)
200 rate |= AQ_NIC_RATE_1G;
201 if (lkp_link_caps->rate_1G_hd)
202 rate |= AQ_NIC_RATE_1G_HALF;
203 if (lkp_link_caps->rate_100M)
204 rate |= AQ_NIC_RATE_100M;
205 if (lkp_link_caps->rate_100M_hd)
206 rate |= AQ_NIC_RATE_100M_HALF;
207 if (lkp_link_caps->rate_10M)
208 rate |= AQ_NIC_RATE_10M;
209 if (lkp_link_caps->rate_10M_hd)
210 rate |= AQ_NIC_RATE_10M_HALF;
211
212 if (lkp_link_caps->eee_10G)
213 rate |= AQ_NIC_RATE_EEE_10G;
214 if (lkp_link_caps->eee_5G)
215 rate |= AQ_NIC_RATE_EEE_5G;
216 if (lkp_link_caps->eee_2P5G)
217 rate |= AQ_NIC_RATE_EEE_2G5;
218 if (lkp_link_caps->eee_1G)
219 rate |= AQ_NIC_RATE_EEE_1G;
220 if (lkp_link_caps->eee_100M)
221 rate |= AQ_NIC_RATE_EEE_100M;
222
223 return rate;
224 }
225
aq_a2_fw_set_link_speed(struct aq_hw_s * self,u32 speed)226 static int aq_a2_fw_set_link_speed(struct aq_hw_s *self, u32 speed)
227 {
228 struct link_options_s link_options;
229
230 hw_atl2_shared_buffer_get(self, link_options, link_options);
231 link_options.link_up = 1U;
232 a2_link_speed_mask2fw(speed, &link_options);
233 hw_atl2_shared_buffer_write(self, link_options, link_options);
234
235 return hw_atl2_shared_buffer_finish_ack(self);
236 }
237
aq_a2_fw_set_mpi_flow_control(struct aq_hw_s * self,struct link_options_s * link_options)238 static void aq_a2_fw_set_mpi_flow_control(struct aq_hw_s *self,
239 struct link_options_s *link_options)
240 {
241 u32 flow_control = self->aq_nic_cfg->fc.req;
242
243 link_options->pause_rx = !!(flow_control & AQ_NIC_FC_RX);
244 link_options->pause_tx = !!(flow_control & AQ_NIC_FC_TX);
245 }
246
aq_a2_fw_upd_eee_rate_bits(struct aq_hw_s * self,struct link_options_s * link_options,u32 eee_speeds)247 static void aq_a2_fw_upd_eee_rate_bits(struct aq_hw_s *self,
248 struct link_options_s *link_options,
249 u32 eee_speeds)
250 {
251 link_options->eee_10G = !!(eee_speeds & AQ_NIC_RATE_EEE_10G);
252 link_options->eee_5G = !!(eee_speeds & AQ_NIC_RATE_EEE_5G);
253 link_options->eee_2P5G = !!(eee_speeds & AQ_NIC_RATE_EEE_2G5);
254 link_options->eee_1G = !!(eee_speeds & AQ_NIC_RATE_EEE_1G);
255 link_options->eee_100M = !!(eee_speeds & AQ_NIC_RATE_EEE_100M);
256 }
257
aq_a2_fw_set_state(struct aq_hw_s * self,enum hal_atl_utils_fw_state_e state)258 static int aq_a2_fw_set_state(struct aq_hw_s *self,
259 enum hal_atl_utils_fw_state_e state)
260 {
261 struct link_options_s link_options;
262
263 hw_atl2_shared_buffer_get(self, link_options, link_options);
264
265 switch (state) {
266 case MPI_INIT:
267 link_options.link_up = 1U;
268 aq_a2_fw_upd_eee_rate_bits(self, &link_options,
269 self->aq_nic_cfg->eee_speeds);
270 aq_a2_fw_set_mpi_flow_control(self, &link_options);
271 break;
272 case MPI_DEINIT:
273 link_options.link_up = 0U;
274 break;
275 case MPI_RESET:
276 case MPI_POWER:
277 /* No actions */
278 break;
279 }
280
281 hw_atl2_shared_buffer_write(self, link_options, link_options);
282
283 return hw_atl2_shared_buffer_finish_ack(self);
284 }
285
aq_a2_fw_update_link_status(struct aq_hw_s * self)286 static int aq_a2_fw_update_link_status(struct aq_hw_s *self)
287 {
288 struct lkp_link_caps_s lkp_link_caps;
289 struct link_status_s link_status;
290
291 hw_atl2_shared_buffer_read(self, link_status, link_status);
292
293 switch (link_status.link_rate) {
294 case AQ_A2_FW_LINK_RATE_10G:
295 self->aq_link_status.mbps = 10000;
296 break;
297 case AQ_A2_FW_LINK_RATE_5G:
298 self->aq_link_status.mbps = 5000;
299 break;
300 case AQ_A2_FW_LINK_RATE_2G5:
301 self->aq_link_status.mbps = 2500;
302 break;
303 case AQ_A2_FW_LINK_RATE_1G:
304 self->aq_link_status.mbps = 1000;
305 break;
306 case AQ_A2_FW_LINK_RATE_100M:
307 self->aq_link_status.mbps = 100;
308 break;
309 case AQ_A2_FW_LINK_RATE_10M:
310 self->aq_link_status.mbps = 10;
311 break;
312 default:
313 self->aq_link_status.mbps = 0;
314 }
315 self->aq_link_status.full_duplex = link_status.duplex;
316
317 hw_atl2_shared_buffer_read(self, lkp_link_caps, lkp_link_caps);
318
319 self->aq_link_status.lp_link_speed_msk =
320 a2_fw_lkp_to_mask(&lkp_link_caps);
321 self->aq_link_status.lp_flow_control =
322 ((lkp_link_caps.pause_rx) ? AQ_NIC_FC_RX : 0) |
323 ((lkp_link_caps.pause_tx) ? AQ_NIC_FC_TX : 0);
324
325 return 0;
326 }
327
aq_a2_fw_get_mac_permanent(struct aq_hw_s * self,u8 * mac)328 static int aq_a2_fw_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
329 {
330 struct mac_address_aligned_s mac_address;
331
332 hw_atl2_shared_buffer_get(self, mac_address, mac_address);
333 ether_addr_copy(mac, (u8 *)mac_address.aligned.mac_address);
334
335 return 0;
336 }
337
aq_a2_fw_update_stats(struct aq_hw_s * self)338 static int aq_a2_fw_update_stats(struct aq_hw_s *self)
339 {
340 struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv;
341 struct statistics_s stats;
342
343 hw_atl2_shared_buffer_read_safe(self, stats, &stats);
344
345 #define AQ_SDELTA(_N_, _F_) (self->curr_stats._N_ += \
346 stats.msm._F_ - priv->last_stats.msm._F_)
347
348 if (self->aq_link_status.mbps) {
349 AQ_SDELTA(uprc, rx_unicast_frames);
350 AQ_SDELTA(mprc, rx_multicast_frames);
351 AQ_SDELTA(bprc, rx_broadcast_frames);
352 AQ_SDELTA(erpr, rx_error_frames);
353
354 AQ_SDELTA(uptc, tx_unicast_frames);
355 AQ_SDELTA(mptc, tx_multicast_frames);
356 AQ_SDELTA(bptc, tx_broadcast_frames);
357 AQ_SDELTA(erpt, tx_errors);
358
359 AQ_SDELTA(ubrc, rx_unicast_octets);
360 AQ_SDELTA(ubtc, tx_unicast_octets);
361 AQ_SDELTA(mbrc, rx_multicast_octets);
362 AQ_SDELTA(mbtc, tx_multicast_octets);
363 AQ_SDELTA(bbrc, rx_broadcast_octets);
364 AQ_SDELTA(bbtc, tx_broadcast_octets);
365 }
366 #undef AQ_SDELTA
367 self->curr_stats.dma_pkt_rc =
368 hw_atl_stats_rx_dma_good_pkt_counter_get(self);
369 self->curr_stats.dma_pkt_tc =
370 hw_atl_stats_tx_dma_good_pkt_counter_get(self);
371 self->curr_stats.dma_oct_rc =
372 hw_atl_stats_rx_dma_good_octet_counter_get(self);
373 self->curr_stats.dma_oct_tc =
374 hw_atl_stats_tx_dma_good_octet_counter_get(self);
375 self->curr_stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self);
376
377 memcpy(&priv->last_stats, &stats, sizeof(stats));
378
379 return 0;
380 }
381
aq_a2_fw_get_phy_temp(struct aq_hw_s * self,int * temp)382 static int aq_a2_fw_get_phy_temp(struct aq_hw_s *self, int *temp)
383 {
384 struct phy_health_monitor_s phy_health_monitor;
385
386 hw_atl2_shared_buffer_read_safe(self, phy_health_monitor,
387 &phy_health_monitor);
388
389 *temp = (int8_t)phy_health_monitor.phy_temperature * 1000;
390 return 0;
391 }
392
aq_a2_fw_get_mac_temp(struct aq_hw_s * self,int * temp)393 static int aq_a2_fw_get_mac_temp(struct aq_hw_s *self, int *temp)
394 {
395 /* There's only one temperature sensor on A2, use it for
396 * both MAC and PHY.
397 */
398 return aq_a2_fw_get_phy_temp(self, temp);
399 }
400
aq_a2_fw_set_eee_rate(struct aq_hw_s * self,u32 speed)401 static int aq_a2_fw_set_eee_rate(struct aq_hw_s *self, u32 speed)
402 {
403 struct link_options_s link_options;
404
405 hw_atl2_shared_buffer_get(self, link_options, link_options);
406
407 aq_a2_fw_upd_eee_rate_bits(self, &link_options, speed);
408
409 hw_atl2_shared_buffer_write(self, link_options, link_options);
410
411 return hw_atl2_shared_buffer_finish_ack(self);
412 }
413
aq_a2_fw_get_eee_rate(struct aq_hw_s * self,u32 * rate,u32 * supported_rates)414 static int aq_a2_fw_get_eee_rate(struct aq_hw_s *self, u32 *rate,
415 u32 *supported_rates)
416 {
417 struct device_link_caps_s device_link_caps;
418 struct lkp_link_caps_s lkp_link_caps;
419
420 hw_atl2_shared_buffer_read(self, device_link_caps, device_link_caps);
421 hw_atl2_shared_buffer_read(self, lkp_link_caps, lkp_link_caps);
422
423 *supported_rates = a2_fw_dev_to_eee_mask(&device_link_caps);
424 *rate = a2_fw_lkp_to_mask(&lkp_link_caps);
425
426 return 0;
427 }
428
aq_a2_fw_renegotiate(struct aq_hw_s * self)429 static int aq_a2_fw_renegotiate(struct aq_hw_s *self)
430 {
431 struct link_options_s link_options;
432 int err;
433
434 hw_atl2_shared_buffer_get(self, link_options, link_options);
435 link_options.link_renegotiate = 1U;
436 hw_atl2_shared_buffer_write(self, link_options, link_options);
437
438 err = hw_atl2_shared_buffer_finish_ack(self);
439
440 /* We should put renegotiate status back to zero
441 * after command completes
442 */
443 link_options.link_renegotiate = 0U;
444 hw_atl2_shared_buffer_write(self, link_options, link_options);
445
446 return err;
447 }
448
aq_a2_fw_set_flow_control(struct aq_hw_s * self)449 static int aq_a2_fw_set_flow_control(struct aq_hw_s *self)
450 {
451 struct link_options_s link_options;
452
453 hw_atl2_shared_buffer_get(self, link_options, link_options);
454
455 aq_a2_fw_set_mpi_flow_control(self, &link_options);
456
457 hw_atl2_shared_buffer_write(self, link_options, link_options);
458
459 return hw_atl2_shared_buffer_finish_ack(self);
460 }
461
aq_a2_fw_get_flow_control(struct aq_hw_s * self,u32 * fcmode)462 static u32 aq_a2_fw_get_flow_control(struct aq_hw_s *self, u32 *fcmode)
463 {
464 struct link_status_s link_status;
465
466 hw_atl2_shared_buffer_read(self, link_status, link_status);
467
468 *fcmode = ((link_status.pause_rx) ? AQ_NIC_FC_RX : 0) |
469 ((link_status.pause_tx) ? AQ_NIC_FC_TX : 0);
470 return 0;
471 }
472
aq_a2_fw_set_phyloopback(struct aq_hw_s * self,u32 mode,bool enable)473 static int aq_a2_fw_set_phyloopback(struct aq_hw_s *self, u32 mode, bool enable)
474 {
475 struct link_options_s link_options;
476
477 hw_atl2_shared_buffer_get(self, link_options, link_options);
478
479 switch (mode) {
480 case AQ_HW_LOOPBACK_PHYINT_SYS:
481 link_options.internal_loopback = enable;
482 break;
483 case AQ_HW_LOOPBACK_PHYEXT_SYS:
484 link_options.external_loopback = enable;
485 break;
486 default:
487 return -EINVAL;
488 }
489
490 hw_atl2_shared_buffer_write(self, link_options, link_options);
491
492 return hw_atl2_shared_buffer_finish_ack(self);
493 }
494
hw_atl2_utils_get_fw_version(struct aq_hw_s * self)495 u32 hw_atl2_utils_get_fw_version(struct aq_hw_s *self)
496 {
497 struct version_s version;
498
499 hw_atl2_shared_buffer_read_safe(self, version, &version);
500
501 /* A2 FW version is stored in reverse order */
502 return version.mac.major << 24 |
503 version.mac.minor << 16 |
504 version.mac.build;
505 }
506
hw_atl2_utils_get_action_resolve_table_caps(struct aq_hw_s * self,u8 * base_index,u8 * count)507 int hw_atl2_utils_get_action_resolve_table_caps(struct aq_hw_s *self,
508 u8 *base_index, u8 *count)
509 {
510 struct filter_caps_s filter_caps;
511 int err;
512
513 err = hw_atl2_shared_buffer_read_safe(self, filter_caps, &filter_caps);
514 if (err)
515 return err;
516
517 *base_index = filter_caps.rslv_tbl_base_index;
518 *count = filter_caps.rslv_tbl_count;
519 return 0;
520 }
521
aq_a2_fw_set_downshift(struct aq_hw_s * self,u32 counter)522 static int aq_a2_fw_set_downshift(struct aq_hw_s *self, u32 counter)
523 {
524 struct link_options_s link_options;
525
526 hw_atl2_shared_buffer_get(self, link_options, link_options);
527 link_options.downshift = !!counter;
528 link_options.downshift_retry = counter;
529 hw_atl2_shared_buffer_write(self, link_options, link_options);
530
531 return hw_atl2_shared_buffer_finish_ack(self);
532 }
533
534 const struct aq_fw_ops aq_a2_fw_ops = {
535 .init = aq_a2_fw_init,
536 .deinit = aq_a2_fw_deinit,
537 .reset = NULL,
538 .renegotiate = aq_a2_fw_renegotiate,
539 .get_mac_permanent = aq_a2_fw_get_mac_permanent,
540 .set_link_speed = aq_a2_fw_set_link_speed,
541 .set_state = aq_a2_fw_set_state,
542 .update_link_status = aq_a2_fw_update_link_status,
543 .update_stats = aq_a2_fw_update_stats,
544 .get_mac_temp = aq_a2_fw_get_mac_temp,
545 .get_phy_temp = aq_a2_fw_get_phy_temp,
546 .set_eee_rate = aq_a2_fw_set_eee_rate,
547 .get_eee_rate = aq_a2_fw_get_eee_rate,
548 .set_flow_control = aq_a2_fw_set_flow_control,
549 .get_flow_control = aq_a2_fw_get_flow_control,
550 .set_phyloopback = aq_a2_fw_set_phyloopback,
551 .set_downshift = aq_a2_fw_set_downshift,
552 };
553