net: aquantia: Change confusing no_ff_addr to more meaningful name
[linux-2.6-block.git] / drivers / net / ethernet / aquantia / atlantic / hw_atl / hw_atl_a0.c
CommitLineData
bab6de8f
DV
1/*
2 * aQuantia Corporation Network Driver
3 * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
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
10/* File hw_atl_a0.c: Definition of Atlantic hardware specific functions. */
11
12#include "../aq_hw.h"
13#include "../aq_hw_utils.h"
14#include "../aq_ring.h"
db550615 15#include "../aq_nic.h"
bab6de8f
DV
16#include "hw_atl_a0.h"
17#include "hw_atl_utils.h"
18#include "hw_atl_llh.h"
19#include "hw_atl_a0_internal.h"
20
4948293f
IR
21#define DEFAULT_A0_BOARD_BASIC_CAPABILITIES \
22 .is_64_dma = true, \
23 .msix_irqs = 4U, \
24 .irq_mask = ~0U, \
25 .vecs = HW_ATL_A0_RSS_MAX, \
26 .tcs = HW_ATL_A0_TC_MAX, \
27 .rxd_alignment = 1U, \
28 .rxd_size = HW_ATL_A0_RXD_SIZE, \
29 .rxds = 248U, \
30 .txd_alignment = 1U, \
31 .txd_size = HW_ATL_A0_TXD_SIZE, \
32 .txds = 8U * 1024U, \
33 .txhwb_alignment = 4096U, \
34 .tx_rings = HW_ATL_A0_TX_RINGS, \
35 .rx_rings = HW_ATL_A0_RX_RINGS, \
36 .hw_features = NETIF_F_HW_CSUM | \
37 NETIF_F_RXHASH | \
38 NETIF_F_RXCSUM | \
39 NETIF_F_SG | \
40 NETIF_F_TSO, \
41 .hw_priv_flags = IFF_UNICAST_FLT, \
42 .flow_control = true, \
43 .mtu = HW_ATL_A0_MTU_JUMBO, \
76c19c6c
IR
44 .mac_regs_count = 88, \
45 .hw_alive_check_addr = 0x10U
4948293f
IR
46
47const struct aq_hw_caps_s hw_atl_a0_caps_aqc100 = {
48 DEFAULT_A0_BOARD_BASIC_CAPABILITIES,
49 .media_type = AQ_HW_MEDIA_TYPE_FIBRE,
50 .link_speed_msk = HW_ATL_A0_RATE_5G |
51 HW_ATL_A0_RATE_2G5 |
52 HW_ATL_A0_RATE_1G |
53 HW_ATL_A0_RATE_100M,
54};
e4d02ca0 55
4948293f
IR
56const struct aq_hw_caps_s hw_atl_a0_caps_aqc107 = {
57 DEFAULT_A0_BOARD_BASIC_CAPABILITIES,
58 .media_type = AQ_HW_MEDIA_TYPE_TP,
59 .link_speed_msk = HW_ATL_A0_RATE_10G |
60 HW_ATL_A0_RATE_5G |
61 HW_ATL_A0_RATE_2G5 |
62 HW_ATL_A0_RATE_1G |
63 HW_ATL_A0_RATE_100M,
64};
e4d02ca0 65
4948293f
IR
66const struct aq_hw_caps_s hw_atl_a0_caps_aqc108 = {
67 DEFAULT_A0_BOARD_BASIC_CAPABILITIES,
68 .media_type = AQ_HW_MEDIA_TYPE_TP,
69 .link_speed_msk = HW_ATL_A0_RATE_5G |
70 HW_ATL_A0_RATE_2G5 |
71 HW_ATL_A0_RATE_1G |
72 HW_ATL_A0_RATE_100M,
73};
74
75const struct aq_hw_caps_s hw_atl_a0_caps_aqc109 = {
76 DEFAULT_A0_BOARD_BASIC_CAPABILITIES,
77 .media_type = AQ_HW_MEDIA_TYPE_TP,
78 .link_speed_msk = HW_ATL_A0_RATE_2G5 |
79 HW_ATL_A0_RATE_1G |
80 HW_ATL_A0_RATE_100M,
81};
e4d02ca0 82
bab6de8f
DV
83static int hw_atl_a0_hw_reset(struct aq_hw_s *self)
84{
85 int err = 0;
86
8e1c072f
IR
87 hw_atl_glb_glb_reg_res_dis_set(self, 1U);
88 hw_atl_pci_pci_reg_res_dis_set(self, 0U);
89 hw_atl_rx_rx_reg_res_dis_set(self, 0U);
90 hw_atl_tx_tx_reg_res_dis_set(self, 0U);
bab6de8f
DV
91
92 HW_ATL_FLUSH();
8e1c072f 93 hw_atl_glb_soft_res_set(self, 1);
bab6de8f
DV
94
95 /* check 10 times by 1ms */
8e1c072f 96 AQ_HW_WAIT_FOR(hw_atl_glb_soft_res_get(self) == 0, 1000U, 10U);
bab6de8f
DV
97 if (err < 0)
98 goto err_exit;
99
8e1c072f
IR
100 hw_atl_itr_irq_reg_res_dis_set(self, 0U);
101 hw_atl_itr_res_irq_set(self, 1U);
bab6de8f
DV
102
103 /* check 10 times by 1ms */
8e1c072f 104 AQ_HW_WAIT_FOR(hw_atl_itr_res_irq_get(self) == 0, 1000U, 10U);
bab6de8f
DV
105 if (err < 0)
106 goto err_exit;
107
108 hw_atl_utils_mpi_set(self, MPI_RESET, 0x0U);
109
110 err = aq_hw_err_from_flags(self);
111
112err_exit:
113 return err;
114}
115
116static int hw_atl_a0_hw_qos_set(struct aq_hw_s *self)
117{
118 u32 tc = 0U;
119 u32 buff_size = 0U;
120 unsigned int i_priority = 0U;
121 bool is_rx_flow_control = false;
122
123 /* TPS Descriptor rate init */
8e1c072f
IR
124 hw_atl_tps_tx_pkt_shed_desc_rate_curr_time_res_set(self, 0x0U);
125 hw_atl_tps_tx_pkt_shed_desc_rate_lim_set(self, 0xA);
bab6de8f
DV
126
127 /* TPS VM init */
8e1c072f 128 hw_atl_tps_tx_pkt_shed_desc_vm_arb_mode_set(self, 0U);
bab6de8f
DV
129
130 /* TPS TC credits init */
8e1c072f
IR
131 hw_atl_tps_tx_pkt_shed_desc_tc_arb_mode_set(self, 0U);
132 hw_atl_tps_tx_pkt_shed_data_arb_mode_set(self, 0U);
bab6de8f 133
8e1c072f
IR
134 hw_atl_tps_tx_pkt_shed_tc_data_max_credit_set(self, 0xFFF, 0U);
135 hw_atl_tps_tx_pkt_shed_tc_data_weight_set(self, 0x64, 0U);
136 hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(self, 0x50, 0U);
137 hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(self, 0x1E, 0U);
bab6de8f
DV
138
139 /* Tx buf size */
140 buff_size = HW_ATL_A0_TXBUF_MAX;
141
8e1c072f
IR
142 hw_atl_tpb_tx_pkt_buff_size_per_tc_set(self, buff_size, tc);
143 hw_atl_tpb_tx_buff_hi_threshold_per_tc_set(self,
144 (buff_size *
145 (1024 / 32U) * 66U) /
146 100U, tc);
147 hw_atl_tpb_tx_buff_lo_threshold_per_tc_set(self,
148 (buff_size *
149 (1024 / 32U) * 50U) /
150 100U, tc);
bab6de8f
DV
151
152 /* QoS Rx buf size per TC */
153 tc = 0;
154 is_rx_flow_control = (AQ_NIC_FC_RX & self->aq_nic_cfg->flow_control);
155 buff_size = HW_ATL_A0_RXBUF_MAX;
156
8e1c072f
IR
157 hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, buff_size, tc);
158 hw_atl_rpb_rx_buff_hi_threshold_per_tc_set(self,
159 (buff_size *
160 (1024U / 32U) * 66U) /
161 100U, tc);
162 hw_atl_rpb_rx_buff_lo_threshold_per_tc_set(self,
163 (buff_size *
164 (1024U / 32U) * 50U) /
165 100U, tc);
166 hw_atl_rpb_rx_xoff_en_per_tc_set(self, is_rx_flow_control ? 1U : 0U, tc);
bab6de8f
DV
167
168 /* QoS 802.1p priority -> TC mapping */
169 for (i_priority = 8U; i_priority--;)
8e1c072f 170 hw_atl_rpf_rpb_user_priority_tc_map_set(self, i_priority, 0U);
bab6de8f
DV
171
172 return aq_hw_err_from_flags(self);
173}
174
175static int hw_atl_a0_hw_rss_hash_set(struct aq_hw_s *self,
176 struct aq_rss_parameters *rss_params)
177{
1a713f87 178 struct aq_nic_cfg_s *cfg = self->aq_nic_cfg;
bab6de8f
DV
179 int err = 0;
180 unsigned int i = 0U;
181 unsigned int addr = 0U;
182
bab6de8f
DV
183 for (i = 10, addr = 0U; i--; ++addr) {
184 u32 key_data = cfg->is_rss ?
185 __swab32(rss_params->hash_secret_key[i]) : 0U;
8e1c072f
IR
186 hw_atl_rpf_rss_key_wr_data_set(self, key_data);
187 hw_atl_rpf_rss_key_addr_set(self, addr);
188 hw_atl_rpf_rss_key_wr_en_set(self, 1U);
189 AQ_HW_WAIT_FOR(hw_atl_rpf_rss_key_wr_en_get(self) == 0,
190 1000U, 10U);
bab6de8f
DV
191 if (err < 0)
192 goto err_exit;
193 }
194
195 err = aq_hw_err_from_flags(self);
196
197err_exit:
198 return err;
199}
200
201static int hw_atl_a0_hw_rss_set(struct aq_hw_s *self,
202 struct aq_rss_parameters *rss_params)
203{
204 u8 *indirection_table = rss_params->indirection_table;
205 u32 i = 0U;
206 u32 num_rss_queues = max(1U, self->aq_nic_cfg->num_rss_queues);
207 int err = 0;
208 u16 bitary[(HW_ATL_A0_RSS_REDIRECTION_MAX *
209 HW_ATL_A0_RSS_REDIRECTION_BITS / 16U)];
210
211 memset(bitary, 0, sizeof(bitary));
212
213 for (i = HW_ATL_A0_RSS_REDIRECTION_MAX; i--; ) {
214 (*(u32 *)(bitary + ((i * 3U) / 16U))) |=
215 ((indirection_table[i] % num_rss_queues) <<
216 ((i * 3U) & 0xFU));
217 }
218
08b5cf08 219 for (i = ARRAY_SIZE(bitary); i--;) {
8e1c072f
IR
220 hw_atl_rpf_rss_redir_tbl_wr_data_set(self, bitary[i]);
221 hw_atl_rpf_rss_redir_tbl_addr_set(self, i);
222 hw_atl_rpf_rss_redir_wr_en_set(self, 1U);
223 AQ_HW_WAIT_FOR(hw_atl_rpf_rss_redir_wr_en_get(self) == 0,
224 1000U, 10U);
bab6de8f
DV
225 if (err < 0)
226 goto err_exit;
227 }
228
229 err = aq_hw_err_from_flags(self);
230
231err_exit:
232 return err;
233}
234
235static int hw_atl_a0_hw_offload_set(struct aq_hw_s *self,
236 struct aq_nic_cfg_s *aq_nic_cfg)
237{
bab6de8f 238 /* TX checksums offloads*/
8e1c072f
IR
239 hw_atl_tpo_ipv4header_crc_offload_en_set(self, 1);
240 hw_atl_tpo_tcp_udp_crc_offload_en_set(self, 1);
bab6de8f
DV
241
242 /* RX checksums offloads*/
8e1c072f
IR
243 hw_atl_rpo_ipv4header_crc_offload_en_set(self, 1);
244 hw_atl_rpo_tcp_udp_crc_offload_en_set(self, 1);
bab6de8f
DV
245
246 /* LSO offloads*/
8e1c072f 247 hw_atl_tdm_large_send_offload_en_set(self, 0xFFFFFFFFU);
bab6de8f 248
d2be3667 249 return aq_hw_err_from_flags(self);
bab6de8f
DV
250}
251
252static int hw_atl_a0_hw_init_tx_path(struct aq_hw_s *self)
253{
8e1c072f
IR
254 hw_atl_thm_lso_tcp_flag_of_first_pkt_set(self, 0x0FF6U);
255 hw_atl_thm_lso_tcp_flag_of_middle_pkt_set(self, 0x0FF6U);
256 hw_atl_thm_lso_tcp_flag_of_last_pkt_set(self, 0x0F7FU);
bab6de8f
DV
257
258 /* Tx interrupts */
8e1c072f 259 hw_atl_tdm_tx_desc_wr_wb_irq_en_set(self, 1U);
bab6de8f
DV
260
261 /* misc */
262 aq_hw_write_reg(self, 0x00007040U, IS_CHIP_FEATURE(TPO2) ?
263 0x00010000U : 0x00000000U);
8e1c072f
IR
264 hw_atl_tdm_tx_dca_en_set(self, 0U);
265 hw_atl_tdm_tx_dca_mode_set(self, 0U);
bab6de8f 266
8e1c072f 267 hw_atl_tpb_tx_path_scp_ins_en_set(self, 1U);
bab6de8f
DV
268
269 return aq_hw_err_from_flags(self);
270}
271
272static int hw_atl_a0_hw_init_rx_path(struct aq_hw_s *self)
273{
274 struct aq_nic_cfg_s *cfg = self->aq_nic_cfg;
275 int i;
276
277 /* Rx TC/RSS number config */
8e1c072f 278 hw_atl_rpb_rpf_rx_traf_class_mode_set(self, 1U);
bab6de8f
DV
279
280 /* Rx flow control */
8e1c072f 281 hw_atl_rpb_rx_flow_ctl_mode_set(self, 1U);
bab6de8f
DV
282
283 /* RSS Ring selection */
8e1c072f 284 hw_atl_reg_rx_flr_rss_control1set(self, cfg->is_rss ?
bab6de8f
DV
285 0xB3333333U : 0x00000000U);
286
287 /* Multicast filters */
288 for (i = HW_ATL_A0_MAC_MAX; i--;) {
8e1c072f
IR
289 hw_atl_rpfl2_uc_flr_en_set(self, (i == 0U) ? 1U : 0U, i);
290 hw_atl_rpfl2unicast_flr_act_set(self, 1U, i);
bab6de8f
DV
291 }
292
8e1c072f
IR
293 hw_atl_reg_rx_flr_mcst_flr_msk_set(self, 0x00000000U);
294 hw_atl_reg_rx_flr_mcst_flr_set(self, 0x00010FFFU, 0U);
bab6de8f
DV
295
296 /* Vlan filters */
8e1c072f
IR
297 hw_atl_rpf_vlan_outer_etht_set(self, 0x88A8U);
298 hw_atl_rpf_vlan_inner_etht_set(self, 0x8100U);
299 hw_atl_rpf_vlan_prom_mode_en_set(self, 1);
bab6de8f
DV
300
301 /* Rx Interrupts */
8e1c072f 302 hw_atl_rdm_rx_desc_wr_wb_irq_en_set(self, 1U);
bab6de8f
DV
303
304 /* misc */
8e1c072f
IR
305 hw_atl_rpfl2broadcast_flr_act_set(self, 1U);
306 hw_atl_rpfl2broadcast_count_threshold_set(self, 0xFFFFU & (~0U / 256U));
bab6de8f 307
8e1c072f
IR
308 hw_atl_rdm_rx_dca_en_set(self, 0U);
309 hw_atl_rdm_rx_dca_mode_set(self, 0U);
bab6de8f
DV
310
311 return aq_hw_err_from_flags(self);
312}
313
314static int hw_atl_a0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr)
315{
316 int err = 0;
317 unsigned int h = 0U;
318 unsigned int l = 0U;
319
320 if (!mac_addr) {
321 err = -EINVAL;
322 goto err_exit;
323 }
324 h = (mac_addr[0] << 8) | (mac_addr[1]);
325 l = (mac_addr[2] << 24) | (mac_addr[3] << 16) |
326 (mac_addr[4] << 8) | mac_addr[5];
327
8e1c072f
IR
328 hw_atl_rpfl2_uc_flr_en_set(self, 0U, HW_ATL_A0_MAC);
329 hw_atl_rpfl2unicast_dest_addresslsw_set(self, l, HW_ATL_A0_MAC);
330 hw_atl_rpfl2unicast_dest_addressmsw_set(self, h, HW_ATL_A0_MAC);
331 hw_atl_rpfl2_uc_flr_en_set(self, 1U, HW_ATL_A0_MAC);
bab6de8f
DV
332
333 err = aq_hw_err_from_flags(self);
334
335err_exit:
336 return err;
337}
338
1a713f87 339static int hw_atl_a0_hw_init(struct aq_hw_s *self, u8 *mac_addr)
bab6de8f
DV
340{
341 static u32 aq_hw_atl_igcr_table_[4][2] = {
342 { 0x20000000U, 0x20000000U }, /* AQ_IRQ_INVALID */
343 { 0x20000080U, 0x20000080U }, /* AQ_IRQ_LEGACY */
344 { 0x20000021U, 0x20000025U }, /* AQ_IRQ_MSI */
345 { 0x20000022U, 0x20000026U } /* AQ_IRQ_MSIX */
346 };
347
348 int err = 0;
349
1a713f87 350 struct aq_nic_cfg_s *aq_nic_cfg = self->aq_nic_cfg;
bab6de8f
DV
351
352 hw_atl_a0_hw_init_tx_path(self);
353 hw_atl_a0_hw_init_rx_path(self);
354
355 hw_atl_a0_hw_mac_addr_set(self, mac_addr);
356
357 hw_atl_utils_mpi_set(self, MPI_INIT, aq_nic_cfg->link_speed_msk);
358
8e1c072f
IR
359 hw_atl_reg_tx_dma_debug_ctl_set(self, 0x800000b8U);
360 hw_atl_reg_tx_dma_debug_ctl_set(self, 0x000000b8U);
bab6de8f
DV
361
362 hw_atl_a0_hw_qos_set(self);
363 hw_atl_a0_hw_rss_set(self, &aq_nic_cfg->aq_rss);
364 hw_atl_a0_hw_rss_hash_set(self, &aq_nic_cfg->aq_rss);
365
f3e27784
IR
366 /* Reset link status and read out initial hardware counters */
367 self->aq_link_status.mbps = 0;
368 hw_atl_utils_update_stats(self);
369
bab6de8f
DV
370 err = aq_hw_err_from_flags(self);
371 if (err < 0)
372 goto err_exit;
373
374 /* Interrupts */
8e1c072f
IR
375 hw_atl_reg_irq_glb_ctl_set(self,
376 aq_hw_atl_igcr_table_[aq_nic_cfg->irq_type]
377 [(aq_nic_cfg->vecs > 1U) ? 1 : 0]);
bab6de8f 378
8e1c072f 379 hw_atl_itr_irq_auto_masklsw_set(self, aq_nic_cfg->aq_hw_caps->irq_mask);
bab6de8f
DV
380
381 /* Interrupts */
8e1c072f
IR
382 hw_atl_reg_gen_irq_map_set(self,
383 ((HW_ATL_A0_ERR_INT << 0x18) | (1U << 0x1F)) |
384 ((HW_ATL_A0_ERR_INT << 0x10) | (1U << 0x17)) |
385 ((HW_ATL_A0_ERR_INT << 8) | (1U << 0xF)) |
386 ((HW_ATL_A0_ERR_INT) | (1U << 0x7)), 0U);
bab6de8f
DV
387
388 hw_atl_a0_hw_offload_set(self, aq_nic_cfg);
389
390err_exit:
391 return err;
392}
393
394static int hw_atl_a0_hw_ring_tx_start(struct aq_hw_s *self,
395 struct aq_ring_s *ring)
396{
8e1c072f 397 hw_atl_tdm_tx_desc_en_set(self, 1, ring->idx);
bab6de8f
DV
398 return aq_hw_err_from_flags(self);
399}
400
401static int hw_atl_a0_hw_ring_rx_start(struct aq_hw_s *self,
402 struct aq_ring_s *ring)
403{
8e1c072f 404 hw_atl_rdm_rx_desc_en_set(self, 1, ring->idx);
bab6de8f
DV
405 return aq_hw_err_from_flags(self);
406}
407
408static int hw_atl_a0_hw_start(struct aq_hw_s *self)
409{
8e1c072f
IR
410 hw_atl_tpb_tx_buff_en_set(self, 1);
411 hw_atl_rpb_rx_buff_en_set(self, 1);
bab6de8f
DV
412 return aq_hw_err_from_flags(self);
413}
414
415static int hw_atl_a0_hw_tx_ring_tail_update(struct aq_hw_s *self,
416 struct aq_ring_s *ring)
417{
8e1c072f 418 hw_atl_reg_tx_dma_desc_tail_ptr_set(self, ring->sw_tail, ring->idx);
bab6de8f
DV
419 return 0;
420}
421
422static int hw_atl_a0_hw_ring_tx_xmit(struct aq_hw_s *self,
423 struct aq_ring_s *ring,
424 unsigned int frags)
425{
426 struct aq_ring_buff_s *buff = NULL;
427 struct hw_atl_txd_s *txd = NULL;
428 unsigned int buff_pa_len = 0U;
429 unsigned int pkt_len = 0U;
430 unsigned int frag_count = 0U;
431 bool is_gso = false;
432
433 buff = &ring->buff_ring[ring->sw_tail];
434 pkt_len = (buff->is_eop && buff->is_sop) ? buff->len : buff->len_pkt;
435
436 for (frag_count = 0; frag_count < frags; frag_count++) {
437 txd = (struct hw_atl_txd_s *)&ring->dx_ring[ring->sw_tail *
438 HW_ATL_A0_TXD_SIZE];
439 txd->ctl = 0;
440 txd->ctl2 = 0;
441 txd->buf_addr = 0;
442
443 buff = &ring->buff_ring[ring->sw_tail];
444
445 if (buff->is_txc) {
446 txd->ctl |= (buff->len_l3 << 31) |
447 (buff->len_l2 << 24) |
448 HW_ATL_A0_TXD_CTL_CMD_TCP |
449 HW_ATL_A0_TXD_CTL_DESC_TYPE_TXC;
450 txd->ctl2 |= (buff->mss << 16) |
451 (buff->len_l4 << 8) |
452 (buff->len_l3 >> 1);
453
454 pkt_len -= (buff->len_l4 +
455 buff->len_l3 +
456 buff->len_l2);
457 is_gso = true;
386aff88
PB
458
459 if (buff->is_ipv6)
460 txd->ctl |= HW_ATL_A0_TXD_CTL_CMD_IPV6;
bab6de8f
DV
461 } else {
462 buff_pa_len = buff->len;
463
464 txd->buf_addr = buff->pa;
465 txd->ctl |= (HW_ATL_A0_TXD_CTL_BLEN &
466 ((u32)buff_pa_len << 4));
467 txd->ctl |= HW_ATL_A0_TXD_CTL_DESC_TYPE_TXD;
468 /* PAY_LEN */
469 txd->ctl2 |= HW_ATL_A0_TXD_CTL2_LEN & (pkt_len << 14);
470
471 if (is_gso) {
472 txd->ctl |= HW_ATL_A0_TXD_CTL_CMD_LSO;
473 txd->ctl2 |= HW_ATL_A0_TXD_CTL2_CTX_EN;
474 }
475
476 /* Tx checksum offloads */
477 if (buff->is_ip_cso)
478 txd->ctl |= HW_ATL_A0_TXD_CTL_CMD_IPCSO;
479
480 if (buff->is_udp_cso || buff->is_tcp_cso)
481 txd->ctl |= HW_ATL_A0_TXD_CTL_CMD_TUCSO;
482
483 if (unlikely(buff->is_eop)) {
484 txd->ctl |= HW_ATL_A0_TXD_CTL_EOP;
485 txd->ctl |= HW_ATL_A0_TXD_CTL_CMD_WB;
5d73bb86 486 is_gso = false;
bab6de8f
DV
487 }
488 }
489
490 ring->sw_tail = aq_ring_next_dx(ring, ring->sw_tail);
491 }
492
493 hw_atl_a0_hw_tx_ring_tail_update(self, ring);
494 return aq_hw_err_from_flags(self);
495}
496
497static int hw_atl_a0_hw_ring_rx_init(struct aq_hw_s *self,
498 struct aq_ring_s *aq_ring,
499 struct aq_ring_param_s *aq_ring_param)
500{
501 u32 dma_desc_addr_lsw = (u32)aq_ring->dx_ring_pa;
502 u32 dma_desc_addr_msw = (u32)(((u64)aq_ring->dx_ring_pa) >> 32);
503
8e1c072f 504 hw_atl_rdm_rx_desc_en_set(self, false, aq_ring->idx);
bab6de8f 505
8e1c072f 506 hw_atl_rdm_rx_desc_head_splitting_set(self, 0U, aq_ring->idx);
bab6de8f 507
8e1c072f
IR
508 hw_atl_reg_rx_dma_desc_base_addresslswset(self, dma_desc_addr_lsw,
509 aq_ring->idx);
bab6de8f 510
8e1c072f
IR
511 hw_atl_reg_rx_dma_desc_base_addressmswset(self,
512 dma_desc_addr_msw,
513 aq_ring->idx);
bab6de8f 514
8e1c072f 515 hw_atl_rdm_rx_desc_len_set(self, aq_ring->size / 8U, aq_ring->idx);
bab6de8f 516
8e1c072f
IR
517 hw_atl_rdm_rx_desc_data_buff_size_set(self,
518 AQ_CFG_RX_FRAME_MAX / 1024U,
bab6de8f
DV
519 aq_ring->idx);
520
8e1c072f
IR
521 hw_atl_rdm_rx_desc_head_buff_size_set(self, 0U, aq_ring->idx);
522 hw_atl_rdm_rx_desc_head_splitting_set(self, 0U, aq_ring->idx);
523 hw_atl_rpo_rx_desc_vlan_stripping_set(self, 0U, aq_ring->idx);
bab6de8f
DV
524
525 /* Rx ring set mode */
526
527 /* Mapping interrupt vector */
8e1c072f
IR
528 hw_atl_itr_irq_map_rx_set(self, aq_ring_param->vec_idx, aq_ring->idx);
529 hw_atl_itr_irq_map_en_rx_set(self, true, aq_ring->idx);
bab6de8f 530
8e1c072f
IR
531 hw_atl_rdm_cpu_id_set(self, aq_ring_param->cpu, aq_ring->idx);
532 hw_atl_rdm_rx_desc_dca_en_set(self, 0U, aq_ring->idx);
533 hw_atl_rdm_rx_head_dca_en_set(self, 0U, aq_ring->idx);
534 hw_atl_rdm_rx_pld_dca_en_set(self, 0U, aq_ring->idx);
bab6de8f
DV
535
536 return aq_hw_err_from_flags(self);
537}
538
539static int hw_atl_a0_hw_ring_tx_init(struct aq_hw_s *self,
540 struct aq_ring_s *aq_ring,
541 struct aq_ring_param_s *aq_ring_param)
542{
543 u32 dma_desc_lsw_addr = (u32)aq_ring->dx_ring_pa;
544 u32 dma_desc_msw_addr = (u32)(((u64)aq_ring->dx_ring_pa) >> 32);
545
8e1c072f
IR
546 hw_atl_reg_tx_dma_desc_base_addresslswset(self, dma_desc_lsw_addr,
547 aq_ring->idx);
bab6de8f 548
8e1c072f
IR
549 hw_atl_reg_tx_dma_desc_base_addressmswset(self, dma_desc_msw_addr,
550 aq_ring->idx);
bab6de8f 551
8e1c072f 552 hw_atl_tdm_tx_desc_len_set(self, aq_ring->size / 8U, aq_ring->idx);
bab6de8f
DV
553
554 hw_atl_a0_hw_tx_ring_tail_update(self, aq_ring);
555
556 /* Set Tx threshold */
8e1c072f 557 hw_atl_tdm_tx_desc_wr_wb_threshold_set(self, 0U, aq_ring->idx);
bab6de8f
DV
558
559 /* Mapping interrupt vector */
8e1c072f
IR
560 hw_atl_itr_irq_map_tx_set(self, aq_ring_param->vec_idx, aq_ring->idx);
561 hw_atl_itr_irq_map_en_tx_set(self, true, aq_ring->idx);
bab6de8f 562
8e1c072f
IR
563 hw_atl_tdm_cpu_id_set(self, aq_ring_param->cpu, aq_ring->idx);
564 hw_atl_tdm_tx_desc_dca_en_set(self, 0U, aq_ring->idx);
bab6de8f
DV
565
566 return aq_hw_err_from_flags(self);
567}
568
569static int hw_atl_a0_hw_ring_rx_fill(struct aq_hw_s *self,
570 struct aq_ring_s *ring,
571 unsigned int sw_tail_old)
572{
573 for (; sw_tail_old != ring->sw_tail;
574 sw_tail_old = aq_ring_next_dx(ring, sw_tail_old)) {
575 struct hw_atl_rxd_s *rxd =
576 (struct hw_atl_rxd_s *)&ring->dx_ring[sw_tail_old *
577 HW_ATL_A0_RXD_SIZE];
578
579 struct aq_ring_buff_s *buff = &ring->buff_ring[sw_tail_old];
580
581 rxd->buf_addr = buff->pa;
582 rxd->hdr_addr = 0U;
583 }
584
8e1c072f 585 hw_atl_reg_rx_dma_desc_tail_ptr_set(self, sw_tail_old, ring->idx);
bab6de8f
DV
586
587 return aq_hw_err_from_flags(self);
588}
589
590static int hw_atl_a0_hw_ring_tx_head_update(struct aq_hw_s *self,
591 struct aq_ring_s *ring)
592{
593 int err = 0;
8e1c072f 594 unsigned int hw_head = hw_atl_tdm_tx_desc_head_ptr_get(self, ring->idx);
bab6de8f 595
78f5193d 596 if (aq_utils_obj_test(&self->flags, AQ_HW_FLAG_ERR_UNPLUG)) {
bab6de8f
DV
597 err = -ENXIO;
598 goto err_exit;
599 }
8e1c072f 600 ring->hw_head = hw_head;
bab6de8f
DV
601 err = aq_hw_err_from_flags(self);
602
603err_exit:
604 return err;
605}
606
607static int hw_atl_a0_hw_ring_rx_receive(struct aq_hw_s *self,
608 struct aq_ring_s *ring)
609{
610 struct device *ndev = aq_nic_get_dev(ring->aq_nic);
611
612 for (; ring->hw_head != ring->sw_tail;
613 ring->hw_head = aq_ring_next_dx(ring, ring->hw_head)) {
614 struct aq_ring_buff_s *buff = NULL;
615 struct hw_atl_rxd_wb_s *rxd_wb = (struct hw_atl_rxd_wb_s *)
616 &ring->dx_ring[ring->hw_head * HW_ATL_A0_RXD_SIZE];
617
618 unsigned int is_err = 1U;
619 unsigned int is_rx_check_sum_enabled = 0U;
620 unsigned int pkt_type = 0U;
621
622 if (!(rxd_wb->status & 0x5U)) { /* RxD is not done */
623 if ((1U << 4) &
8e1c072f
IR
624 hw_atl_reg_rx_dma_desc_status_get(self, ring->idx)) {
625 hw_atl_rdm_rx_desc_en_set(self, false, ring->idx);
626 hw_atl_rdm_rx_desc_res_set(self, true, ring->idx);
627 hw_atl_rdm_rx_desc_res_set(self, false, ring->idx);
628 hw_atl_rdm_rx_desc_en_set(self, true, ring->idx);
bab6de8f
DV
629 }
630
631 if (ring->hw_head ||
8e1c072f
IR
632 (hw_atl_rdm_rx_desc_head_ptr_get(self,
633 ring->idx) < 2U)) {
bab6de8f
DV
634 break;
635 } else if (!(rxd_wb->status & 0x1U)) {
636 struct hw_atl_rxd_wb_s *rxd_wb1 =
637 (struct hw_atl_rxd_wb_s *)
638 (&ring->dx_ring[(1U) *
639 HW_ATL_A0_RXD_SIZE]);
640
641 if ((rxd_wb1->status & 0x1U)) {
642 rxd_wb->pkt_len = 1514U;
643 rxd_wb->status = 3U;
644 } else {
645 break;
646 }
647 }
648 }
649
650 buff = &ring->buff_ring[ring->hw_head];
651
652 if (0x3U != (rxd_wb->status & 0x3U))
653 rxd_wb->status |= 4;
654
655 is_err = (0x0000001CU & rxd_wb->status);
656 is_rx_check_sum_enabled = (rxd_wb->type) & (0x3U << 19);
657 pkt_type = 0xFFU & (rxd_wb->type >> 4);
658
659 if (is_rx_check_sum_enabled) {
660 if (0x0U == (pkt_type & 0x3U))
661 buff->is_ip_cso = (is_err & 0x08U) ? 0 : 1;
662
663 if (0x4U == (pkt_type & 0x1CU))
664 buff->is_udp_cso = (is_err & 0x10U) ? 0 : 1;
665 else if (0x0U == (pkt_type & 0x1CU))
666 buff->is_tcp_cso = (is_err & 0x10U) ? 0 : 1;
0a402e7b
PB
667
668 /* Checksum offload workaround for small packets */
669 if (rxd_wb->pkt_len <= 60) {
670 buff->is_ip_cso = 0U;
671 buff->is_cso_err = 0U;
672 }
bab6de8f
DV
673 }
674
675 is_err &= ~0x18U;
676 is_err &= ~0x04U;
677
678 dma_unmap_page(ndev, buff->pa, buff->len, DMA_FROM_DEVICE);
679
680 if (is_err || rxd_wb->type & 0x1000U) {
681 /* status error or DMA error */
682 buff->is_error = 1U;
683 } else {
684 if (self->aq_nic_cfg->is_rss) {
685 /* last 4 byte */
686 u16 rss_type = rxd_wb->type & 0xFU;
687
688 if (rss_type && rss_type < 0x8U) {
689 buff->is_hash_l4 = (rss_type == 0x4 ||
690 rss_type == 0x5);
691 buff->rss_hash = rxd_wb->rss_hash;
692 }
693 }
694
695 if (HW_ATL_A0_RXD_WB_STAT2_EOP & rxd_wb->status) {
c0788f74
PB
696 buff->len = rxd_wb->pkt_len %
697 AQ_CFG_RX_FRAME_MAX;
bab6de8f
DV
698 buff->len = buff->len ?
699 buff->len : AQ_CFG_RX_FRAME_MAX;
700 buff->next = 0U;
701 buff->is_eop = 1U;
702 } else {
703 /* jumbo */
704 buff->next = aq_ring_next_dx(ring,
705 ring->hw_head);
706 ++ring->stats.rx.jumbo_packets;
707 }
708 }
709 }
710
711 return aq_hw_err_from_flags(self);
712}
713
714static int hw_atl_a0_hw_irq_enable(struct aq_hw_s *self, u64 mask)
715{
8e1c072f 716 hw_atl_itr_irq_msk_setlsw_set(self, LODWORD(mask) |
bab6de8f
DV
717 (1U << HW_ATL_A0_ERR_INT));
718 return aq_hw_err_from_flags(self);
719}
720
721static int hw_atl_a0_hw_irq_disable(struct aq_hw_s *self, u64 mask)
722{
8e1c072f
IR
723 hw_atl_itr_irq_msk_clearlsw_set(self, LODWORD(mask));
724 hw_atl_itr_irq_status_clearlsw_set(self, LODWORD(mask));
bab6de8f 725
8e1c072f 726 if ((1U << 16) & hw_atl_reg_gen_irq_status_get(self))
1a713f87 727 atomic_inc(&self->dpc);
bab6de8f
DV
728
729 return aq_hw_err_from_flags(self);
730}
731
732static int hw_atl_a0_hw_irq_read(struct aq_hw_s *self, u64 *mask)
733{
8e1c072f 734 *mask = hw_atl_itr_irq_statuslsw_get(self);
bab6de8f
DV
735 return aq_hw_err_from_flags(self);
736}
737
738#define IS_FILTER_ENABLED(_F_) ((packet_filter & (_F_)) ? 1U : 0U)
739
740static int hw_atl_a0_hw_packet_filter_set(struct aq_hw_s *self,
741 unsigned int packet_filter)
742{
743 unsigned int i = 0U;
744
8e1c072f
IR
745 hw_atl_rpfl2promiscuous_mode_en_set(self,
746 IS_FILTER_ENABLED(IFF_PROMISC));
747 hw_atl_rpfl2multicast_flr_en_set(self,
748 IS_FILTER_ENABLED(IFF_MULTICAST), 0);
749 hw_atl_rpfl2broadcast_en_set(self, IS_FILTER_ENABLED(IFF_BROADCAST));
bab6de8f
DV
750
751 self->aq_nic_cfg->is_mc_list_enabled =
752 IS_FILTER_ENABLED(IFF_MULTICAST);
753
754 for (i = HW_ATL_A0_MAC_MIN; i < HW_ATL_A0_MAC_MAX; ++i)
8e1c072f
IR
755 hw_atl_rpfl2_uc_flr_en_set(self,
756 (self->aq_nic_cfg->is_mc_list_enabled &&
757 (i <= self->aq_nic_cfg->mc_list_count)) ?
758 1U : 0U, i);
bab6de8f
DV
759
760 return aq_hw_err_from_flags(self);
761}
762
763#undef IS_FILTER_ENABLED
764
765static int hw_atl_a0_hw_multicast_list_set(struct aq_hw_s *self,
766 u8 ar_mac
767 [AQ_CFG_MULTICAST_ADDRESS_MAX]
768 [ETH_ALEN],
769 u32 count)
770{
771 int err = 0;
772
773 if (count > (HW_ATL_A0_MAC_MAX - HW_ATL_A0_MAC_MIN)) {
774 err = EBADRQC;
775 goto err_exit;
776 }
777 for (self->aq_nic_cfg->mc_list_count = 0U;
778 self->aq_nic_cfg->mc_list_count < count;
779 ++self->aq_nic_cfg->mc_list_count) {
780 u32 i = self->aq_nic_cfg->mc_list_count;
781 u32 h = (ar_mac[i][0] << 8) | (ar_mac[i][1]);
782 u32 l = (ar_mac[i][2] << 24) | (ar_mac[i][3] << 16) |
783 (ar_mac[i][4] << 8) | ar_mac[i][5];
784
8e1c072f 785 hw_atl_rpfl2_uc_flr_en_set(self, 0U, HW_ATL_A0_MAC_MIN + i);
bab6de8f 786
8e1c072f
IR
787 hw_atl_rpfl2unicast_dest_addresslsw_set(self,
788 l,
789 HW_ATL_A0_MAC_MIN + i);
bab6de8f 790
8e1c072f
IR
791 hw_atl_rpfl2unicast_dest_addressmsw_set(self,
792 h,
793 HW_ATL_A0_MAC_MIN + i);
bab6de8f 794
8e1c072f
IR
795 hw_atl_rpfl2_uc_flr_en_set(self,
796 (self->aq_nic_cfg->is_mc_list_enabled),
797 HW_ATL_A0_MAC_MIN + i);
bab6de8f
DV
798 }
799
800 err = aq_hw_err_from_flags(self);
801
802err_exit:
803 return err;
804}
805
b82ee71a 806static int hw_atl_a0_hw_interrupt_moderation_set(struct aq_hw_s *self)
bab6de8f
DV
807{
808 unsigned int i = 0U;
b82ee71a 809 u32 itr_rx;
bab6de8f 810
b82ee71a
IR
811 if (self->aq_nic_cfg->itr) {
812 if (self->aq_nic_cfg->itr != AQ_CFG_INTERRUPT_MODERATION_AUTO) {
bab6de8f
DV
813 u32 itr_ = (self->aq_nic_cfg->itr >> 1);
814
815 itr_ = min(AQ_CFG_IRQ_MASK, itr_);
816
b82ee71a 817 itr_rx = 0x80000000U | (itr_ << 0x10);
bab6de8f
DV
818 } else {
819 u32 n = 0xFFFFU & aq_hw_read_reg(self, 0x00002A00U);
820
821 if (n < self->aq_link_status.mbps) {
b82ee71a 822 itr_rx = 0U;
bab6de8f
DV
823 } else {
824 static unsigned int hw_timers_tbl_[] = {
825 0x01CU, /* 10Gbit */
826 0x039U, /* 5Gbit */
827 0x039U, /* 5Gbit 5GS */
828 0x073U, /* 2.5Gbit */
829 0x120U, /* 1Gbit */
830 0x1FFU, /* 100Mbit */
831 };
832
833 unsigned int speed_index =
834 hw_atl_utils_mbps_2_speed_index(
835 self->aq_link_status.mbps);
836
b82ee71a 837 itr_rx = 0x80000000U |
bab6de8f
DV
838 (hw_timers_tbl_[speed_index] << 0x10U);
839 }
840
841 aq_hw_write_reg(self, 0x00002A00U, 0x40000000U);
842 aq_hw_write_reg(self, 0x00002A00U, 0x8D000000U);
843 }
844 } else {
b82ee71a 845 itr_rx = 0U;
bab6de8f
DV
846 }
847
848 for (i = HW_ATL_A0_RINGS_MAX; i--;)
8e1c072f 849 hw_atl_reg_irq_thr_set(self, itr_rx, i);
bab6de8f
DV
850
851 return aq_hw_err_from_flags(self);
852}
853
854static int hw_atl_a0_hw_stop(struct aq_hw_s *self)
855{
856 hw_atl_a0_hw_irq_disable(self, HW_ATL_A0_INT_MASK);
857 return aq_hw_err_from_flags(self);
858}
859
860static int hw_atl_a0_hw_ring_tx_stop(struct aq_hw_s *self,
861 struct aq_ring_s *ring)
862{
8e1c072f 863 hw_atl_tdm_tx_desc_en_set(self, 0U, ring->idx);
bab6de8f
DV
864 return aq_hw_err_from_flags(self);
865}
866
867static int hw_atl_a0_hw_ring_rx_stop(struct aq_hw_s *self,
868 struct aq_ring_s *ring)
869{
8e1c072f 870 hw_atl_rdm_rx_desc_en_set(self, 0U, ring->idx);
bab6de8f
DV
871 return aq_hw_err_from_flags(self);
872}
873
874static int hw_atl_a0_hw_set_speed(struct aq_hw_s *self, u32 speed)
875{
876 int err = 0;
877
878 err = hw_atl_utils_mpi_set_speed(self, speed, MPI_INIT);
879 if (err < 0)
880 goto err_exit;
881
882err_exit:
883 return err;
884}
885
4948293f 886const struct aq_hw_ops hw_atl_ops_a0 = {
bab6de8f
DV
887 .hw_get_mac_permanent = hw_atl_utils_get_mac_permanent,
888 .hw_set_mac_address = hw_atl_a0_hw_mac_addr_set,
889 .hw_get_link_status = hw_atl_utils_mpi_get_link_status,
890 .hw_set_link_speed = hw_atl_a0_hw_set_speed,
891 .hw_init = hw_atl_a0_hw_init,
892 .hw_deinit = hw_atl_utils_hw_deinit,
893 .hw_set_power = hw_atl_utils_hw_set_power,
894 .hw_reset = hw_atl_a0_hw_reset,
895 .hw_start = hw_atl_a0_hw_start,
896 .hw_ring_tx_start = hw_atl_a0_hw_ring_tx_start,
897 .hw_ring_tx_stop = hw_atl_a0_hw_ring_tx_stop,
898 .hw_ring_rx_start = hw_atl_a0_hw_ring_rx_start,
899 .hw_ring_rx_stop = hw_atl_a0_hw_ring_rx_stop,
900 .hw_stop = hw_atl_a0_hw_stop,
901
902 .hw_ring_tx_xmit = hw_atl_a0_hw_ring_tx_xmit,
903 .hw_ring_tx_head_update = hw_atl_a0_hw_ring_tx_head_update,
904
905 .hw_ring_rx_receive = hw_atl_a0_hw_ring_rx_receive,
906 .hw_ring_rx_fill = hw_atl_a0_hw_ring_rx_fill,
907
908 .hw_irq_enable = hw_atl_a0_hw_irq_enable,
909 .hw_irq_disable = hw_atl_a0_hw_irq_disable,
910 .hw_irq_read = hw_atl_a0_hw_irq_read,
911
912 .hw_ring_rx_init = hw_atl_a0_hw_ring_rx_init,
913 .hw_ring_tx_init = hw_atl_a0_hw_ring_tx_init,
914 .hw_packet_filter_set = hw_atl_a0_hw_packet_filter_set,
915 .hw_multicast_list_set = hw_atl_a0_hw_multicast_list_set,
916 .hw_interrupt_moderation_set = hw_atl_a0_hw_interrupt_moderation_set,
917 .hw_rss_set = hw_atl_a0_hw_rss_set,
918 .hw_rss_hash_set = hw_atl_a0_hw_rss_hash_set,
919 .hw_get_regs = hw_atl_utils_hw_get_regs,
65e665e6 920 .hw_update_stats = hw_atl_utils_update_stats,
bab6de8f
DV
921 .hw_get_hw_stats = hw_atl_utils_get_hw_stats,
922 .hw_get_fw_version = hw_atl_utils_get_fw_version,
923};