]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/dpdk/drivers/net/atlantic/hw_atl/hw_atl_utils_fw2x.c
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / dpdk / drivers / net / atlantic / hw_atl / hw_atl_utils_fw2x.c
1 // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2 /* Copyright (C) 2014-2017 aQuantia Corporation. */
3
4 /* File hw_atl_utils_fw2x.c: Definition of firmware 2.x functions for
5 * Atlantic hardware abstraction layer.
6 */
7
8 #include <rte_ether.h>
9 #include <pthread.h>
10 #include "../atl_hw_regs.h"
11
12 #include "../atl_types.h"
13 #include "hw_atl_utils.h"
14 #include "hw_atl_llh.h"
15
16 #define HW_ATL_FW2X_MPI_EFUSE_ADDR 0x364
17 #define HW_ATL_FW2X_MPI_MBOX_ADDR 0x360
18 #define HW_ATL_FW2X_MPI_RPC_ADDR 0x334
19
20 #define HW_ATL_FW2X_MPI_CONTROL_ADDR 0x368
21 #define HW_ATL_FW2X_MPI_CONTROL2_ADDR 0x36C
22 #define HW_ATL_FW2X_MPI_LED_ADDR 0x31c
23
24 #define HW_ATL_FW2X_MPI_STATE_ADDR 0x370
25 #define HW_ATL_FW2X_MPI_STATE2_ADDR 0x374
26
27 #define HW_ATL_FW2X_CAP_SLEEP_PROXY BIT(CAPS_HI_SLEEP_PROXY)
28 #define HW_ATL_FW2X_CAP_WOL BIT(CAPS_HI_WOL)
29
30 #define HW_ATL_FW2X_CAP_EEE_1G_MASK BIT(CAPS_HI_1000BASET_FD_EEE)
31 #define HW_ATL_FW2X_CAP_EEE_2G5_MASK BIT(CAPS_HI_2P5GBASET_FD_EEE)
32 #define HW_ATL_FW2X_CAP_EEE_5G_MASK BIT(CAPS_HI_5GBASET_FD_EEE)
33 #define HW_ATL_FW2X_CAP_EEE_10G_MASK BIT(CAPS_HI_10GBASET_FD_EEE)
34
35 #define HAL_ATLANTIC_WOL_FILTERS_COUNT 8
36 #define HAL_ATLANTIC_UTILS_FW2X_MSG_WOL 0x0E
37
38 #define HW_ATL_FW_FEATURE_LED 0x03010026
39
40 struct fw2x_msg_wol_pattern {
41 u8 mask[16];
42 u32 crc;
43 } __rte_packed;
44
45 struct fw2x_msg_wol {
46 u32 msg_id;
47 u8 hw_addr[6];
48 u8 magic_packet_enabled;
49 u8 filter_count;
50 struct fw2x_msg_wol_pattern filter[HAL_ATLANTIC_WOL_FILTERS_COUNT];
51 u8 link_up_enabled;
52 u8 link_down_enabled;
53 u16 reserved;
54 u32 link_up_timeout;
55 u32 link_down_timeout;
56 } __rte_packed;
57
58 static int aq_fw2x_set_link_speed(struct aq_hw_s *self, u32 speed);
59 static int aq_fw2x_set_state(struct aq_hw_s *self,
60 enum hal_atl_utils_fw_state_e state);
61
62 static int aq_fw2x_init(struct aq_hw_s *self)
63 {
64 int err = 0;
65 struct hw_aq_atl_utils_mbox mbox;
66
67 /* check 10 times by 1ms */
68 AQ_HW_WAIT_FOR(0U != (self->mbox_addr =
69 aq_hw_read_reg(self, HW_ATL_FW2X_MPI_MBOX_ADDR)),
70 1000U, 10U);
71 AQ_HW_WAIT_FOR(0U != (self->rpc_addr =
72 aq_hw_read_reg(self, HW_ATL_FW2X_MPI_RPC_ADDR)),
73 1000U, 100U);
74
75 /* Read caps */
76 hw_atl_utils_mpi_read_stats(self, &mbox);
77
78 self->caps_lo = mbox.info.caps_lo;
79
80 return err;
81 }
82
83 static int aq_fw2x_deinit(struct aq_hw_s *self)
84 {
85 int err = aq_fw2x_set_link_speed(self, 0);
86
87 if (!err)
88 err = aq_fw2x_set_state(self, MPI_DEINIT);
89
90 return err;
91 }
92
93 static enum hw_atl_fw2x_rate link_speed_mask_2fw2x_ratemask(u32 speed)
94 {
95 enum hw_atl_fw2x_rate rate = 0;
96
97 if (speed & AQ_NIC_RATE_10G)
98 rate |= FW2X_RATE_10G;
99
100 if (speed & AQ_NIC_RATE_5G)
101 rate |= FW2X_RATE_5G;
102
103 if (speed & AQ_NIC_RATE_5G5R)
104 rate |= FW2X_RATE_5G;
105
106 if (speed & AQ_NIC_RATE_2G5)
107 rate |= FW2X_RATE_2G5;
108
109 if (speed & AQ_NIC_RATE_1G)
110 rate |= FW2X_RATE_1G;
111
112 if (speed & AQ_NIC_RATE_100M)
113 rate |= FW2X_RATE_100M;
114
115 return rate;
116 }
117
118 static u32 fw2x_to_eee_mask(u32 speed)
119 {
120 u32 rate = 0;
121
122 if (speed & HW_ATL_FW2X_CAP_EEE_10G_MASK)
123 rate |= AQ_NIC_RATE_EEE_10G;
124
125 if (speed & HW_ATL_FW2X_CAP_EEE_5G_MASK)
126 rate |= AQ_NIC_RATE_EEE_5G;
127
128 if (speed & HW_ATL_FW2X_CAP_EEE_2G5_MASK)
129 rate |= AQ_NIC_RATE_EEE_2G5;
130
131 if (speed & HW_ATL_FW2X_CAP_EEE_1G_MASK)
132 rate |= AQ_NIC_RATE_EEE_1G;
133
134 return rate;
135 }
136
137 static int aq_fw2x_set_link_speed(struct aq_hw_s *self, u32 speed)
138 {
139 u32 rate_mask = link_speed_mask_2fw2x_ratemask(speed);
140 u32 reg_val = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR);
141 u32 val = rate_mask | ((BIT(CAPS_LO_SMBUS_READ) |
142 BIT(CAPS_LO_SMBUS_WRITE) |
143 BIT(CAPS_LO_MACSEC)) & reg_val);
144
145 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR, val);
146
147 return 0;
148 }
149
150 static void aq_fw2x_set_mpi_flow_control(struct aq_hw_s *self, u32 *mpi_state)
151 {
152 if (self->aq_nic_cfg->flow_control & AQ_NIC_FC_RX)
153 *mpi_state |= BIT(CAPS_HI_PAUSE);
154 else
155 *mpi_state &= ~BIT(CAPS_HI_PAUSE);
156
157 if (self->aq_nic_cfg->flow_control & AQ_NIC_FC_TX)
158 *mpi_state |= BIT(CAPS_HI_ASYMMETRIC_PAUSE);
159 else
160 *mpi_state &= ~BIT(CAPS_HI_ASYMMETRIC_PAUSE);
161 }
162
163 static int aq_fw2x_set_state(struct aq_hw_s *self,
164 enum hal_atl_utils_fw_state_e state)
165 {
166 u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
167
168 switch (state) {
169 case MPI_INIT:
170 mpi_state &= ~BIT(CAPS_HI_LINK_DROP);
171 aq_fw2x_set_mpi_flow_control(self, &mpi_state);
172 break;
173 case MPI_DEINIT:
174 mpi_state |= BIT(CAPS_HI_LINK_DROP);
175 break;
176 case MPI_RESET:
177 case MPI_POWER:
178 /* No actions */
179 break;
180 }
181 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_state);
182 return 0;
183 }
184
185 static int aq_fw2x_update_link_status(struct aq_hw_s *self)
186 {
187 u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR);
188 u32 speed = mpi_state & (FW2X_RATE_100M | FW2X_RATE_1G |
189 FW2X_RATE_2G5 | FW2X_RATE_5G | FW2X_RATE_10G);
190 struct aq_hw_link_status_s *link_status = &self->aq_link_status;
191
192 if (speed) {
193 if (speed & FW2X_RATE_10G)
194 link_status->mbps = 10000;
195 else if (speed & FW2X_RATE_5G)
196 link_status->mbps = 5000;
197 else if (speed & FW2X_RATE_2G5)
198 link_status->mbps = 2500;
199 else if (speed & FW2X_RATE_1G)
200 link_status->mbps = 1000;
201 else if (speed & FW2X_RATE_100M)
202 link_status->mbps = 100;
203 else
204 link_status->mbps = 10000;
205 } else {
206 link_status->mbps = 0;
207 }
208
209 return 0;
210 }
211
212 static
213 int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac)
214 {
215 int err = 0;
216 u32 h = 0U;
217 u32 l = 0U;
218 u32 mac_addr[2] = { 0 };
219 u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR);
220
221 pthread_mutex_lock(&self->mbox_mutex);
222
223 if (efuse_addr != 0) {
224 err = hw_atl_utils_fw_downld_dwords(self,
225 efuse_addr + (40U * 4U),
226 mac_addr,
227 ARRAY_SIZE(mac_addr));
228 if (err)
229 goto exit;
230 mac_addr[0] = rte_constant_bswap32(mac_addr[0]);
231 mac_addr[1] = rte_constant_bswap32(mac_addr[1]);
232 }
233
234 rte_ether_addr_copy((struct rte_ether_addr *)mac_addr,
235 (struct rte_ether_addr *)mac);
236
237 if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
238 unsigned int rnd = (uint32_t)rte_rand();
239
240 //get_random_bytes(&rnd, sizeof(unsigned int));
241
242 l = 0xE3000000U
243 | (0xFFFFU & rnd)
244 | (0x00 << 16);
245 h = 0x8001300EU;
246
247 mac[5] = (u8)(0xFFU & l);
248 l >>= 8;
249 mac[4] = (u8)(0xFFU & l);
250 l >>= 8;
251 mac[3] = (u8)(0xFFU & l);
252 l >>= 8;
253 mac[2] = (u8)(0xFFU & l);
254 mac[1] = (u8)(0xFFU & h);
255 h >>= 8;
256 mac[0] = (u8)(0xFFU & h);
257 }
258
259 exit:
260 pthread_mutex_unlock(&self->mbox_mutex);
261
262 return err;
263 }
264
265 static int aq_fw2x_update_stats(struct aq_hw_s *self)
266 {
267 int err = 0;
268 u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
269 u32 orig_stats_val = mpi_opts & BIT(CAPS_HI_STATISTICS);
270
271
272 pthread_mutex_lock(&self->mbox_mutex);
273
274 /* Toggle statistics bit for FW to update */
275 mpi_opts = mpi_opts ^ BIT(CAPS_HI_STATISTICS);
276 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
277
278 /* Wait FW to report back */
279 AQ_HW_WAIT_FOR(orig_stats_val !=
280 (aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) &
281 BIT(CAPS_HI_STATISTICS)),
282 1U, 10000U);
283 if (err)
284 goto exit;
285
286 err = hw_atl_utils_update_stats(self);
287
288 exit:
289 pthread_mutex_unlock(&self->mbox_mutex);
290
291 return err;
292
293 }
294
295 static int aq_fw2x_get_temp(struct aq_hw_s *self, int *temp)
296 {
297 int err = 0;
298 u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
299 u32 temp_val = mpi_opts & BIT(CAPS_HI_TEMPERATURE);
300 u32 temp_res;
301
302 pthread_mutex_lock(&self->mbox_mutex);
303
304 /* Toggle statistics bit for FW to 0x36C.18 (CAPS_HI_TEMPERATURE) */
305 mpi_opts = mpi_opts ^ BIT(CAPS_HI_TEMPERATURE);
306 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
307
308 /* Wait FW to report back */
309 AQ_HW_WAIT_FOR(temp_val !=
310 (aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) &
311 BIT(CAPS_HI_TEMPERATURE)), 1U, 10000U);
312 err = hw_atl_utils_fw_downld_dwords(self,
313 self->mbox_addr +
314 offsetof(struct hw_aq_atl_utils_mbox, info) +
315 offsetof(struct hw_aq_info, phy_temperature),
316 &temp_res,
317 sizeof(temp_res) / sizeof(u32));
318
319
320 pthread_mutex_unlock(&self->mbox_mutex);
321
322 if (err)
323 return err;
324
325 *temp = temp_res * 100 / 256;
326 return 0;
327 }
328
329 static int aq_fw2x_get_cable_len(struct aq_hw_s *self, int *cable_len)
330 {
331 int err = 0;
332 u32 cable_len_res;
333
334 err = hw_atl_utils_fw_downld_dwords(self,
335 self->mbox_addr +
336 offsetof(struct hw_aq_atl_utils_mbox, info) +
337 offsetof(struct hw_aq_info, phy_temperature),
338 &cable_len_res,
339 sizeof(cable_len_res) / sizeof(u32));
340
341 if (err)
342 return err;
343
344 *cable_len = (cable_len_res >> 16) & 0xFF;
345 return 0;
346 }
347
348 #ifndef ETH_ALEN
349 #define ETH_ALEN 6
350 #endif
351
352 static int aq_fw2x_set_sleep_proxy(struct aq_hw_s *self, u8 *mac)
353 {
354 int err = 0;
355 struct hw_aq_atl_utils_fw_rpc *rpc = NULL;
356 struct offload_info *cfg = NULL;
357 unsigned int rpc_size = 0U;
358 u32 mpi_opts;
359
360 rpc_size = sizeof(rpc->msg_id) + sizeof(*cfg);
361
362 err = hw_atl_utils_fw_rpc_wait(self, &rpc);
363 if (err < 0)
364 goto err_exit;
365
366 memset(rpc, 0, rpc_size);
367 cfg = (struct offload_info *)(&rpc->msg_id + 1);
368
369 memcpy(cfg->mac_addr, mac, ETH_ALEN);
370 cfg->len = sizeof(*cfg);
371
372 /* Clear bit 0x36C.23 */
373 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
374 mpi_opts &= ~HW_ATL_FW2X_CAP_SLEEP_PROXY;
375
376 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
377
378 err = hw_atl_utils_fw_rpc_call(self, rpc_size);
379 if (err < 0)
380 goto err_exit;
381
382 /* Set bit 0x36C.23 */
383 mpi_opts |= HW_ATL_FW2X_CAP_SLEEP_PROXY;
384 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
385
386 AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) &
387 HW_ATL_FW2X_CAP_SLEEP_PROXY), 1U, 10000U);
388 err_exit:
389 return err;
390 }
391
392 static int aq_fw2x_set_wol_params(struct aq_hw_s *self, u8 *mac)
393 {
394 int err = 0;
395 struct fw2x_msg_wol *msg = NULL;
396 u32 mpi_opts;
397
398 struct hw_aq_atl_utils_fw_rpc *rpc = NULL;
399
400 err = hw_atl_utils_fw_rpc_wait(self, &rpc);
401 if (err < 0)
402 goto err_exit;
403
404 msg = (struct fw2x_msg_wol *)rpc;
405
406 msg->msg_id = HAL_ATLANTIC_UTILS_FW2X_MSG_WOL;
407 msg->magic_packet_enabled = true;
408 memcpy(msg->hw_addr, mac, ETH_ALEN);
409
410 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
411 mpi_opts &= ~(HW_ATL_FW2X_CAP_SLEEP_PROXY | HW_ATL_FW2X_CAP_WOL);
412
413 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
414
415 err = hw_atl_utils_fw_rpc_call(self, sizeof(*msg));
416 if (err < 0)
417 goto err_exit;
418
419 /* Set bit 0x36C.24 */
420 mpi_opts |= HW_ATL_FW2X_CAP_WOL;
421 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
422
423 AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) &
424 HW_ATL_FW2X_CAP_WOL), 1U, 10000U);
425 err_exit:
426 return err;
427 }
428
429 static int aq_fw2x_set_power(struct aq_hw_s *self,
430 unsigned int power_state __rte_unused,
431 u8 *mac)
432 {
433 int err = 0;
434
435 if (self->aq_nic_cfg->wol & AQ_NIC_WOL_ENABLED) {
436 err = aq_fw2x_set_sleep_proxy(self, mac);
437 if (err < 0)
438 goto err_exit;
439 err = aq_fw2x_set_wol_params(self, mac);
440 if (err < 0)
441 goto err_exit;
442 }
443 err_exit:
444 return err;
445 }
446
447 static int aq_fw2x_set_eee_rate(struct aq_hw_s *self, u32 speed)
448 {
449 u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
450 mpi_opts &= ~(HW_ATL_FW2X_CAP_EEE_1G_MASK |
451 HW_ATL_FW2X_CAP_EEE_2G5_MASK | HW_ATL_FW2X_CAP_EEE_5G_MASK |
452 HW_ATL_FW2X_CAP_EEE_10G_MASK);
453
454 if (speed & AQ_NIC_RATE_EEE_10G)
455 mpi_opts |= HW_ATL_FW2X_CAP_EEE_10G_MASK;
456
457 if (speed & AQ_NIC_RATE_EEE_5G)
458 mpi_opts |= HW_ATL_FW2X_CAP_EEE_5G_MASK;
459
460 if (speed & AQ_NIC_RATE_EEE_2G5)
461 mpi_opts |= HW_ATL_FW2X_CAP_EEE_2G5_MASK;
462
463 if (speed & AQ_NIC_RATE_EEE_1G)
464 mpi_opts |= HW_ATL_FW2X_CAP_EEE_1G_MASK;
465
466 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts);
467
468 return 0;
469 }
470
471 static int aq_fw2x_get_eee_rate(struct aq_hw_s *self, u32 *rate,
472 u32 *supported_rates)
473 {
474 int err = 0;
475 u32 caps_hi;
476 u32 mpi_state;
477
478 err = hw_atl_utils_fw_downld_dwords(self,
479 self->mbox_addr +
480 offsetof(struct hw_aq_atl_utils_mbox, info) +
481 offsetof(struct hw_aq_info, caps_hi),
482 &caps_hi,
483 sizeof(caps_hi) / sizeof(u32));
484
485 if (err)
486 return err;
487
488 *supported_rates = fw2x_to_eee_mask(caps_hi);
489
490 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR);
491 *rate = fw2x_to_eee_mask(mpi_state);
492
493 return err;
494 }
495
496 static int aq_fw2x_get_flow_control(struct aq_hw_s *self, u32 *fc)
497 {
498 u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
499
500 *fc = ((mpi_state & BIT(CAPS_HI_PAUSE)) ? AQ_NIC_FC_RX : 0) |
501 ((mpi_state & BIT(CAPS_HI_ASYMMETRIC_PAUSE)) ? AQ_NIC_FC_TX : 0);
502
503 return 0;
504 }
505
506 static int aq_fw2x_set_flow_control(struct aq_hw_s *self)
507 {
508 u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
509
510 aq_fw2x_set_mpi_flow_control(self, &mpi_state);
511
512 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_state);
513
514 return 0;
515 }
516
517 static int aq_fw2x_led_control(struct aq_hw_s *self, u32 mode)
518 {
519 if (self->fw_ver_actual < HW_ATL_FW_FEATURE_LED)
520 return -EOPNOTSUPP;
521
522 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_LED_ADDR, mode);
523 return 0;
524 }
525
526 static int aq_fw2x_get_eeprom(struct aq_hw_s *self, int dev_addr,
527 u32 *data, u32 len, u32 offset)
528 {
529 u32 bytes_remains = len % sizeof(u32);
530 u32 num_dwords = len / sizeof(u32);
531 struct smbus_request request;
532 u32 result = 0;
533 u32 mpi_opts;
534 int err = 0;
535
536 if ((self->caps_lo & BIT(CAPS_LO_SMBUS_READ)) == 0)
537 return -EOPNOTSUPP;
538
539 pthread_mutex_lock(&self->mbox_mutex);
540
541 request.msg_id = 0;
542 request.device_id = dev_addr;
543 request.address = offset;
544 request.length = len;
545
546 /* Write SMBUS request to cfg memory */
547 err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
548 (u32 *)(void *)&request,
549 sizeof(request) / sizeof(u32));
550
551 if (err < 0)
552 goto exit;
553
554 /* Toggle 0x368.CAPS_LO_SMBUS_READ bit */
555 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR);
556 mpi_opts ^= BIT(CAPS_LO_SMBUS_READ);
557
558 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR, mpi_opts);
559
560 /* Wait until REQUEST_BIT matched in 0x370 */
561
562 AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR) &
563 BIT(CAPS_LO_SMBUS_READ)) == (mpi_opts & BIT(CAPS_LO_SMBUS_READ)),
564 10U, 10000U);
565
566 if (err < 0)
567 goto exit;
568
569 err = hw_atl_utils_fw_downld_dwords(self, self->rpc_addr + sizeof(u32),
570 &result,
571 sizeof(result) / sizeof(u32));
572
573 if (err < 0)
574 goto exit;
575
576 if (result) {
577 err = -EIO;
578 goto exit;
579 }
580
581 if (num_dwords) {
582 err = hw_atl_utils_fw_downld_dwords(self,
583 self->rpc_addr + sizeof(u32) * 2,
584 data,
585 num_dwords);
586
587 if (err < 0)
588 goto exit;
589 }
590
591 if (bytes_remains) {
592 u32 val = 0;
593
594 err = hw_atl_utils_fw_downld_dwords(self,
595 self->rpc_addr + (sizeof(u32) * 2) +
596 (num_dwords * sizeof(u32)),
597 &val,
598 1);
599
600 if (err < 0)
601 goto exit;
602
603 rte_memcpy((u8 *)data + len - bytes_remains,
604 &val, bytes_remains);
605 }
606
607 exit:
608 pthread_mutex_unlock(&self->mbox_mutex);
609
610 return err;
611 }
612
613
614 static int aq_fw2x_set_eeprom(struct aq_hw_s *self, int dev_addr,
615 u32 *data, u32 len, u32 offset)
616 {
617 struct smbus_request request;
618 u32 mpi_opts, result = 0;
619 int err = 0;
620
621 if ((self->caps_lo & BIT(CAPS_LO_SMBUS_WRITE)) == 0)
622 return -EOPNOTSUPP;
623
624 request.msg_id = 0;
625 request.device_id = dev_addr;
626 request.address = offset;
627 request.length = len;
628
629 pthread_mutex_lock(&self->mbox_mutex);
630
631 /* Write SMBUS request to cfg memory */
632 err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
633 (u32 *)(void *)&request,
634 sizeof(request) / sizeof(u32));
635
636 if (err < 0)
637 goto exit;
638
639 /* Write SMBUS data to cfg memory */
640 u32 num_dwords = len / sizeof(u32);
641 u32 bytes_remains = len % sizeof(u32);
642
643 if (num_dwords) {
644 err = hw_atl_utils_fw_upload_dwords(self,
645 self->rpc_addr + sizeof(request),
646 (u32 *)(void *)data,
647 num_dwords);
648
649 if (err < 0)
650 goto exit;
651 }
652
653 if (bytes_remains) {
654 u32 val = 0;
655
656 rte_memcpy(&val, (u8 *)data + (sizeof(u32) * num_dwords),
657 bytes_remains);
658
659 err = hw_atl_utils_fw_upload_dwords(self,
660 self->rpc_addr + sizeof(request) +
661 (num_dwords * sizeof(u32)),
662 &val,
663 1);
664
665 if (err < 0)
666 goto exit;
667 }
668
669 /* Toggle 0x368.CAPS_LO_SMBUS_WRITE bit */
670 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR);
671 mpi_opts ^= BIT(CAPS_LO_SMBUS_WRITE);
672
673 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR, mpi_opts);
674
675 /* Wait until REQUEST_BIT matched in 0x370 */
676 AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR) &
677 BIT(CAPS_LO_SMBUS_WRITE)) == (mpi_opts & BIT(CAPS_LO_SMBUS_WRITE)),
678 10U, 10000U);
679
680 if (err < 0)
681 goto exit;
682
683 /* Read status of write operation */
684 err = hw_atl_utils_fw_downld_dwords(self, self->rpc_addr + sizeof(u32),
685 &result,
686 sizeof(result) / sizeof(u32));
687
688 if (err < 0)
689 goto exit;
690
691 if (result) {
692 err = -EIO;
693 goto exit;
694 }
695
696 exit:
697 pthread_mutex_unlock(&self->mbox_mutex);
698
699 return err;
700 }
701
702 static int aq_fw2x_send_macsec_request(struct aq_hw_s *self,
703 struct macsec_msg_fw_request *req,
704 struct macsec_msg_fw_response *response)
705 {
706 int err = 0;
707 u32 mpi_opts = 0;
708
709 if (!req || !response)
710 return 0;
711
712 if ((self->caps_lo & BIT(CAPS_LO_MACSEC)) == 0)
713 return -EOPNOTSUPP;
714
715 pthread_mutex_lock(&self->mbox_mutex);
716
717 /* Write macsec request to cfg memory */
718 err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
719 (u32 *)(void *)req,
720 RTE_ALIGN(sizeof(*req) / sizeof(u32), sizeof(u32)));
721
722 if (err < 0)
723 goto exit;
724
725 /* Toggle 0x368.CAPS_LO_MACSEC bit */
726 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR);
727 mpi_opts ^= BIT(CAPS_LO_MACSEC);
728
729 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR, mpi_opts);
730
731 /* Wait until REQUEST_BIT matched in 0x370 */
732 AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR) &
733 BIT(CAPS_LO_MACSEC)) == (mpi_opts & BIT(CAPS_LO_MACSEC)),
734 1000U, 10000U);
735
736 if (err < 0)
737 goto exit;
738
739 /* Read status of write operation */
740 err = hw_atl_utils_fw_downld_dwords(self, self->rpc_addr + sizeof(u32),
741 (u32 *)(void *)response,
742 RTE_ALIGN(sizeof(*response) / sizeof(u32), sizeof(u32)));
743
744 exit:
745 pthread_mutex_unlock(&self->mbox_mutex);
746
747 return err;
748 }
749
750 const struct aq_fw_ops aq_fw_2x_ops = {
751 .init = aq_fw2x_init,
752 .deinit = aq_fw2x_deinit,
753 .reset = NULL,
754 .get_mac_permanent = aq_fw2x_get_mac_permanent,
755 .set_link_speed = aq_fw2x_set_link_speed,
756 .set_state = aq_fw2x_set_state,
757 .update_link_status = aq_fw2x_update_link_status,
758 .update_stats = aq_fw2x_update_stats,
759 .set_power = aq_fw2x_set_power,
760 .get_temp = aq_fw2x_get_temp,
761 .get_cable_len = aq_fw2x_get_cable_len,
762 .set_eee_rate = aq_fw2x_set_eee_rate,
763 .get_eee_rate = aq_fw2x_get_eee_rate,
764 .get_flow_control = aq_fw2x_get_flow_control,
765 .set_flow_control = aq_fw2x_set_flow_control,
766 .led_control = aq_fw2x_led_control,
767 .get_eeprom = aq_fw2x_get_eeprom,
768 .set_eeprom = aq_fw2x_set_eeprom,
769 .send_macsec_req = aq_fw2x_send_macsec_request,
770 };