xref: /OK3568_Linux_fs/kernel/drivers/net/ethernet/aquantia/atlantic/aq_nic.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /* Atlantic Network Driver
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (C) 2014-2019 aQuantia Corporation
5*4882a593Smuzhiyun  * Copyright (C) 2019-2020 Marvell International Ltd.
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun /* File aq_nic.c: Definition of common code for NIC. */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include "aq_nic.h"
11*4882a593Smuzhiyun #include "aq_ring.h"
12*4882a593Smuzhiyun #include "aq_vec.h"
13*4882a593Smuzhiyun #include "aq_hw.h"
14*4882a593Smuzhiyun #include "aq_pci_func.h"
15*4882a593Smuzhiyun #include "aq_macsec.h"
16*4882a593Smuzhiyun #include "aq_main.h"
17*4882a593Smuzhiyun #include "aq_phy.h"
18*4882a593Smuzhiyun #include "aq_ptp.h"
19*4882a593Smuzhiyun #include "aq_filters.h"
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #include <linux/moduleparam.h>
22*4882a593Smuzhiyun #include <linux/netdevice.h>
23*4882a593Smuzhiyun #include <linux/etherdevice.h>
24*4882a593Smuzhiyun #include <linux/timer.h>
25*4882a593Smuzhiyun #include <linux/cpu.h>
26*4882a593Smuzhiyun #include <linux/ip.h>
27*4882a593Smuzhiyun #include <linux/tcp.h>
28*4882a593Smuzhiyun #include <net/ip.h>
29*4882a593Smuzhiyun #include <net/pkt_cls.h>
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun static unsigned int aq_itr = AQ_CFG_INTERRUPT_MODERATION_AUTO;
32*4882a593Smuzhiyun module_param_named(aq_itr, aq_itr, uint, 0644);
33*4882a593Smuzhiyun MODULE_PARM_DESC(aq_itr, "Interrupt throttling mode");
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun static unsigned int aq_itr_tx;
36*4882a593Smuzhiyun module_param_named(aq_itr_tx, aq_itr_tx, uint, 0644);
37*4882a593Smuzhiyun MODULE_PARM_DESC(aq_itr_tx, "TX interrupt throttle rate");
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun static unsigned int aq_itr_rx;
40*4882a593Smuzhiyun module_param_named(aq_itr_rx, aq_itr_rx, uint, 0644);
41*4882a593Smuzhiyun MODULE_PARM_DESC(aq_itr_rx, "RX interrupt throttle rate");
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun static void aq_nic_update_ndev_stats(struct aq_nic_s *self);
44*4882a593Smuzhiyun 
aq_nic_rss_init(struct aq_nic_s * self,unsigned int num_rss_queues)45*4882a593Smuzhiyun static void aq_nic_rss_init(struct aq_nic_s *self, unsigned int num_rss_queues)
46*4882a593Smuzhiyun {
47*4882a593Smuzhiyun 	static u8 rss_key[AQ_CFG_RSS_HASHKEY_SIZE] = {
48*4882a593Smuzhiyun 		0x1e, 0xad, 0x71, 0x87, 0x65, 0xfc, 0x26, 0x7d,
49*4882a593Smuzhiyun 		0x0d, 0x45, 0x67, 0x74, 0xcd, 0x06, 0x1a, 0x18,
50*4882a593Smuzhiyun 		0xb6, 0xc1, 0xf0, 0xc7, 0xbb, 0x18, 0xbe, 0xf8,
51*4882a593Smuzhiyun 		0x19, 0x13, 0x4b, 0xa9, 0xd0, 0x3e, 0xfe, 0x70,
52*4882a593Smuzhiyun 		0x25, 0x03, 0xab, 0x50, 0x6a, 0x8b, 0x82, 0x0c
53*4882a593Smuzhiyun 	};
54*4882a593Smuzhiyun 	struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg;
55*4882a593Smuzhiyun 	struct aq_rss_parameters *rss_params;
56*4882a593Smuzhiyun 	int i = 0;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	rss_params = &cfg->aq_rss;
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	rss_params->hash_secret_key_size = sizeof(rss_key);
61*4882a593Smuzhiyun 	memcpy(rss_params->hash_secret_key, rss_key, sizeof(rss_key));
62*4882a593Smuzhiyun 	rss_params->indirection_table_size = AQ_CFG_RSS_INDIRECTION_TABLE_MAX;
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 	for (i = rss_params->indirection_table_size; i--;)
65*4882a593Smuzhiyun 		rss_params->indirection_table[i] = i & (num_rss_queues - 1);
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun /* Recalculate the number of vectors */
aq_nic_cfg_update_num_vecs(struct aq_nic_s * self)69*4882a593Smuzhiyun static void aq_nic_cfg_update_num_vecs(struct aq_nic_s *self)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun 	struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg;
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	cfg->vecs = min(cfg->aq_hw_caps->vecs, AQ_CFG_VECS_DEF);
74*4882a593Smuzhiyun 	cfg->vecs = min(cfg->vecs, num_online_cpus());
75*4882a593Smuzhiyun 	if (self->irqvecs > AQ_HW_SERVICE_IRQS)
76*4882a593Smuzhiyun 		cfg->vecs = min(cfg->vecs, self->irqvecs - AQ_HW_SERVICE_IRQS);
77*4882a593Smuzhiyun 	/* cfg->vecs should be power of 2 for RSS */
78*4882a593Smuzhiyun 	cfg->vecs = rounddown_pow_of_two(cfg->vecs);
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	if (ATL_HW_IS_CHIP_FEATURE(self->aq_hw, ANTIGUA)) {
81*4882a593Smuzhiyun 		if (cfg->tcs > 2)
82*4882a593Smuzhiyun 			cfg->vecs = min(cfg->vecs, 4U);
83*4882a593Smuzhiyun 	}
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	if (cfg->vecs <= 4)
86*4882a593Smuzhiyun 		cfg->tc_mode = AQ_TC_MODE_8TCS;
87*4882a593Smuzhiyun 	else
88*4882a593Smuzhiyun 		cfg->tc_mode = AQ_TC_MODE_4TCS;
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	/*rss rings */
91*4882a593Smuzhiyun 	cfg->num_rss_queues = min(cfg->vecs, AQ_CFG_NUM_RSS_QUEUES_DEF);
92*4882a593Smuzhiyun 	aq_nic_rss_init(self, cfg->num_rss_queues);
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun /* Checks hw_caps and 'corrects' aq_nic_cfg in runtime */
aq_nic_cfg_start(struct aq_nic_s * self)96*4882a593Smuzhiyun void aq_nic_cfg_start(struct aq_nic_s *self)
97*4882a593Smuzhiyun {
98*4882a593Smuzhiyun 	struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg;
99*4882a593Smuzhiyun 	int i;
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	cfg->tcs = AQ_CFG_TCS_DEF;
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	cfg->is_polling = AQ_CFG_IS_POLLING_DEF;
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	cfg->itr = aq_itr;
106*4882a593Smuzhiyun 	cfg->tx_itr = aq_itr_tx;
107*4882a593Smuzhiyun 	cfg->rx_itr = aq_itr_rx;
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	cfg->rxpageorder = AQ_CFG_RX_PAGEORDER;
110*4882a593Smuzhiyun 	cfg->is_rss = AQ_CFG_IS_RSS_DEF;
111*4882a593Smuzhiyun 	cfg->aq_rss.base_cpu_number = AQ_CFG_RSS_BASE_CPU_NUM_DEF;
112*4882a593Smuzhiyun 	cfg->fc.req = AQ_CFG_FC_MODE;
113*4882a593Smuzhiyun 	cfg->wol = AQ_CFG_WOL_MODES;
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	cfg->mtu = AQ_CFG_MTU_DEF;
116*4882a593Smuzhiyun 	cfg->link_speed_msk = AQ_CFG_SPEED_MSK;
117*4882a593Smuzhiyun 	cfg->is_autoneg = AQ_CFG_IS_AUTONEG_DEF;
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	cfg->is_lro = AQ_CFG_IS_LRO_DEF;
120*4882a593Smuzhiyun 	cfg->is_ptp = true;
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 	/*descriptors */
123*4882a593Smuzhiyun 	cfg->rxds = min(cfg->aq_hw_caps->rxds_max, AQ_CFG_RXDS_DEF);
124*4882a593Smuzhiyun 	cfg->txds = min(cfg->aq_hw_caps->txds_max, AQ_CFG_TXDS_DEF);
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	aq_nic_cfg_update_num_vecs(self);
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	cfg->irq_type = aq_pci_func_get_irq_type(self);
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	if ((cfg->irq_type == AQ_HW_IRQ_LEGACY) ||
131*4882a593Smuzhiyun 	    (cfg->aq_hw_caps->vecs == 1U) ||
132*4882a593Smuzhiyun 	    (cfg->vecs == 1U)) {
133*4882a593Smuzhiyun 		cfg->is_rss = 0U;
134*4882a593Smuzhiyun 		cfg->vecs = 1U;
135*4882a593Smuzhiyun 	}
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	/* Check if we have enough vectors allocated for
138*4882a593Smuzhiyun 	 * link status IRQ. If no - we'll know link state from
139*4882a593Smuzhiyun 	 * slower service task.
140*4882a593Smuzhiyun 	 */
141*4882a593Smuzhiyun 	if (AQ_HW_SERVICE_IRQS > 0 && cfg->vecs + 1 <= self->irqvecs)
142*4882a593Smuzhiyun 		cfg->link_irq_vec = cfg->vecs;
143*4882a593Smuzhiyun 	else
144*4882a593Smuzhiyun 		cfg->link_irq_vec = 0;
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 	cfg->link_speed_msk &= cfg->aq_hw_caps->link_speed_msk;
147*4882a593Smuzhiyun 	cfg->features = cfg->aq_hw_caps->hw_features;
148*4882a593Smuzhiyun 	cfg->is_vlan_rx_strip = !!(cfg->features & NETIF_F_HW_VLAN_CTAG_RX);
149*4882a593Smuzhiyun 	cfg->is_vlan_tx_insert = !!(cfg->features & NETIF_F_HW_VLAN_CTAG_TX);
150*4882a593Smuzhiyun 	cfg->is_vlan_force_promisc = true;
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	for (i = 0; i < sizeof(cfg->prio_tc_map); i++)
153*4882a593Smuzhiyun 		cfg->prio_tc_map[i] = cfg->tcs * i / 8;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun 
aq_nic_update_link_status(struct aq_nic_s * self)156*4882a593Smuzhiyun static int aq_nic_update_link_status(struct aq_nic_s *self)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun 	int err = self->aq_fw_ops->update_link_status(self->aq_hw);
159*4882a593Smuzhiyun 	u32 fc = 0;
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	if (err)
162*4882a593Smuzhiyun 		return err;
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	if (self->aq_fw_ops->get_flow_control)
165*4882a593Smuzhiyun 		self->aq_fw_ops->get_flow_control(self->aq_hw, &fc);
166*4882a593Smuzhiyun 	self->aq_nic_cfg.fc.cur = fc;
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 	if (self->link_status.mbps != self->aq_hw->aq_link_status.mbps) {
169*4882a593Smuzhiyun 		netdev_info(self->ndev, "%s: link change old %d new %d\n",
170*4882a593Smuzhiyun 			    AQ_CFG_DRV_NAME, self->link_status.mbps,
171*4882a593Smuzhiyun 			    self->aq_hw->aq_link_status.mbps);
172*4882a593Smuzhiyun 		aq_nic_update_interrupt_moderation_settings(self);
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 		if (self->aq_ptp) {
175*4882a593Smuzhiyun 			aq_ptp_clock_init(self);
176*4882a593Smuzhiyun 			aq_ptp_tm_offset_set(self,
177*4882a593Smuzhiyun 					     self->aq_hw->aq_link_status.mbps);
178*4882a593Smuzhiyun 			aq_ptp_link_change(self);
179*4882a593Smuzhiyun 		}
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 		/* Driver has to update flow control settings on RX block
182*4882a593Smuzhiyun 		 * on any link event.
183*4882a593Smuzhiyun 		 * We should query FW whether it negotiated FC.
184*4882a593Smuzhiyun 		 */
185*4882a593Smuzhiyun 		if (self->aq_hw_ops->hw_set_fc)
186*4882a593Smuzhiyun 			self->aq_hw_ops->hw_set_fc(self->aq_hw, fc, 0);
187*4882a593Smuzhiyun 	}
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	self->link_status = self->aq_hw->aq_link_status;
190*4882a593Smuzhiyun 	if (!netif_carrier_ok(self->ndev) && self->link_status.mbps) {
191*4882a593Smuzhiyun 		aq_utils_obj_set(&self->flags,
192*4882a593Smuzhiyun 				 AQ_NIC_FLAG_STARTED);
193*4882a593Smuzhiyun 		aq_utils_obj_clear(&self->flags,
194*4882a593Smuzhiyun 				   AQ_NIC_LINK_DOWN);
195*4882a593Smuzhiyun 		netif_carrier_on(self->ndev);
196*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_MACSEC)
197*4882a593Smuzhiyun 		aq_macsec_enable(self);
198*4882a593Smuzhiyun #endif
199*4882a593Smuzhiyun 		if (self->aq_hw_ops->hw_tc_rate_limit_set)
200*4882a593Smuzhiyun 			self->aq_hw_ops->hw_tc_rate_limit_set(self->aq_hw);
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun 		netif_tx_wake_all_queues(self->ndev);
203*4882a593Smuzhiyun 	}
204*4882a593Smuzhiyun 	if (netif_carrier_ok(self->ndev) && !self->link_status.mbps) {
205*4882a593Smuzhiyun 		netif_carrier_off(self->ndev);
206*4882a593Smuzhiyun 		netif_tx_disable(self->ndev);
207*4882a593Smuzhiyun 		aq_utils_obj_set(&self->flags, AQ_NIC_LINK_DOWN);
208*4882a593Smuzhiyun 	}
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	return 0;
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun 
aq_linkstate_threaded_isr(int irq,void * private)213*4882a593Smuzhiyun static irqreturn_t aq_linkstate_threaded_isr(int irq, void *private)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun 	struct aq_nic_s *self = private;
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	if (!self)
218*4882a593Smuzhiyun 		return IRQ_NONE;
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	aq_nic_update_link_status(self);
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	self->aq_hw_ops->hw_irq_enable(self->aq_hw,
223*4882a593Smuzhiyun 				       BIT(self->aq_nic_cfg.link_irq_vec));
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	return IRQ_HANDLED;
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun 
aq_nic_service_task(struct work_struct * work)228*4882a593Smuzhiyun static void aq_nic_service_task(struct work_struct *work)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun 	struct aq_nic_s *self = container_of(work, struct aq_nic_s,
231*4882a593Smuzhiyun 					     service_task);
232*4882a593Smuzhiyun 	int err;
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	aq_ptp_service_task(self);
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	if (aq_utils_obj_test(&self->flags, AQ_NIC_FLAGS_IS_NOT_READY))
237*4882a593Smuzhiyun 		return;
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	err = aq_nic_update_link_status(self);
240*4882a593Smuzhiyun 	if (err)
241*4882a593Smuzhiyun 		return;
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_MACSEC)
244*4882a593Smuzhiyun 	aq_macsec_work(self);
245*4882a593Smuzhiyun #endif
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	mutex_lock(&self->fwreq_mutex);
248*4882a593Smuzhiyun 	if (self->aq_fw_ops->update_stats)
249*4882a593Smuzhiyun 		self->aq_fw_ops->update_stats(self->aq_hw);
250*4882a593Smuzhiyun 	mutex_unlock(&self->fwreq_mutex);
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	aq_nic_update_ndev_stats(self);
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun 
aq_nic_service_timer_cb(struct timer_list * t)255*4882a593Smuzhiyun static void aq_nic_service_timer_cb(struct timer_list *t)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun 	struct aq_nic_s *self = from_timer(self, t, service_timer);
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	mod_timer(&self->service_timer,
260*4882a593Smuzhiyun 		  jiffies + AQ_CFG_SERVICE_TIMER_INTERVAL);
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	aq_ndev_schedule_work(&self->service_task);
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun 
aq_nic_polling_timer_cb(struct timer_list * t)265*4882a593Smuzhiyun static void aq_nic_polling_timer_cb(struct timer_list *t)
266*4882a593Smuzhiyun {
267*4882a593Smuzhiyun 	struct aq_nic_s *self = from_timer(self, t, polling_timer);
268*4882a593Smuzhiyun 	unsigned int i = 0U;
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 	for (i = 0U; self->aq_vecs > i; ++i)
271*4882a593Smuzhiyun 		aq_vec_isr(i, (void *)self->aq_vec[i]);
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	mod_timer(&self->polling_timer, jiffies +
274*4882a593Smuzhiyun 		  AQ_CFG_POLLING_TIMER_INTERVAL);
275*4882a593Smuzhiyun }
276*4882a593Smuzhiyun 
aq_nic_hw_prepare(struct aq_nic_s * self)277*4882a593Smuzhiyun static int aq_nic_hw_prepare(struct aq_nic_s *self)
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun 	int err = 0;
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	err = self->aq_hw_ops->hw_soft_reset(self->aq_hw);
282*4882a593Smuzhiyun 	if (err)
283*4882a593Smuzhiyun 		goto exit;
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	err = self->aq_hw_ops->hw_prepare(self->aq_hw, &self->aq_fw_ops);
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun exit:
288*4882a593Smuzhiyun 	return err;
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun 
aq_nic_is_valid_ether_addr(const u8 * addr)291*4882a593Smuzhiyun static bool aq_nic_is_valid_ether_addr(const u8 *addr)
292*4882a593Smuzhiyun {
293*4882a593Smuzhiyun 	/* Some engineering samples of Aquantia NICs are provisioned with a
294*4882a593Smuzhiyun 	 * partially populated MAC, which is still invalid.
295*4882a593Smuzhiyun 	 */
296*4882a593Smuzhiyun 	return !(addr[0] == 0 && addr[1] == 0 && addr[2] == 0);
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun 
aq_nic_ndev_register(struct aq_nic_s * self)299*4882a593Smuzhiyun int aq_nic_ndev_register(struct aq_nic_s *self)
300*4882a593Smuzhiyun {
301*4882a593Smuzhiyun 	int err = 0;
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun 	if (!self->ndev) {
304*4882a593Smuzhiyun 		err = -EINVAL;
305*4882a593Smuzhiyun 		goto err_exit;
306*4882a593Smuzhiyun 	}
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	err = aq_nic_hw_prepare(self);
309*4882a593Smuzhiyun 	if (err)
310*4882a593Smuzhiyun 		goto err_exit;
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_MACSEC)
313*4882a593Smuzhiyun 	aq_macsec_init(self);
314*4882a593Smuzhiyun #endif
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 	mutex_lock(&self->fwreq_mutex);
317*4882a593Smuzhiyun 	err = self->aq_fw_ops->get_mac_permanent(self->aq_hw,
318*4882a593Smuzhiyun 			    self->ndev->dev_addr);
319*4882a593Smuzhiyun 	mutex_unlock(&self->fwreq_mutex);
320*4882a593Smuzhiyun 	if (err)
321*4882a593Smuzhiyun 		goto err_exit;
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 	if (!is_valid_ether_addr(self->ndev->dev_addr) ||
324*4882a593Smuzhiyun 	    !aq_nic_is_valid_ether_addr(self->ndev->dev_addr)) {
325*4882a593Smuzhiyun 		netdev_warn(self->ndev, "MAC is invalid, will use random.");
326*4882a593Smuzhiyun 		eth_hw_addr_random(self->ndev);
327*4882a593Smuzhiyun 	}
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun #if defined(AQ_CFG_MAC_ADDR_PERMANENT)
330*4882a593Smuzhiyun 	{
331*4882a593Smuzhiyun 		static u8 mac_addr_permanent[] = AQ_CFG_MAC_ADDR_PERMANENT;
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 		ether_addr_copy(self->ndev->dev_addr, mac_addr_permanent);
334*4882a593Smuzhiyun 	}
335*4882a593Smuzhiyun #endif
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	for (self->aq_vecs = 0; self->aq_vecs < aq_nic_get_cfg(self)->vecs;
338*4882a593Smuzhiyun 	     self->aq_vecs++) {
339*4882a593Smuzhiyun 		self->aq_vec[self->aq_vecs] =
340*4882a593Smuzhiyun 		    aq_vec_alloc(self, self->aq_vecs, aq_nic_get_cfg(self));
341*4882a593Smuzhiyun 		if (!self->aq_vec[self->aq_vecs]) {
342*4882a593Smuzhiyun 			err = -ENOMEM;
343*4882a593Smuzhiyun 			goto err_exit;
344*4882a593Smuzhiyun 		}
345*4882a593Smuzhiyun 	}
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	netif_carrier_off(self->ndev);
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	netif_tx_disable(self->ndev);
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	err = register_netdev(self->ndev);
352*4882a593Smuzhiyun 	if (err)
353*4882a593Smuzhiyun 		goto err_exit;
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun err_exit:
356*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_MACSEC)
357*4882a593Smuzhiyun 	if (err)
358*4882a593Smuzhiyun 		aq_macsec_free(self);
359*4882a593Smuzhiyun #endif
360*4882a593Smuzhiyun 	return err;
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun 
aq_nic_ndev_init(struct aq_nic_s * self)363*4882a593Smuzhiyun void aq_nic_ndev_init(struct aq_nic_s *self)
364*4882a593Smuzhiyun {
365*4882a593Smuzhiyun 	const struct aq_hw_caps_s *aq_hw_caps = self->aq_nic_cfg.aq_hw_caps;
366*4882a593Smuzhiyun 	struct aq_nic_cfg_s *aq_nic_cfg = &self->aq_nic_cfg;
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	self->ndev->hw_features |= aq_hw_caps->hw_features;
369*4882a593Smuzhiyun 	self->ndev->features = aq_hw_caps->hw_features;
370*4882a593Smuzhiyun 	self->ndev->vlan_features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM |
371*4882a593Smuzhiyun 				     NETIF_F_RXHASH | NETIF_F_SG |
372*4882a593Smuzhiyun 				     NETIF_F_LRO | NETIF_F_TSO | NETIF_F_TSO6;
373*4882a593Smuzhiyun 	self->ndev->gso_partial_features = NETIF_F_GSO_UDP_L4;
374*4882a593Smuzhiyun 	self->ndev->priv_flags = aq_hw_caps->hw_priv_flags;
375*4882a593Smuzhiyun 	self->ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun 	self->msg_enable = NETIF_MSG_DRV | NETIF_MSG_LINK;
378*4882a593Smuzhiyun 	self->ndev->mtu = aq_nic_cfg->mtu - ETH_HLEN;
379*4882a593Smuzhiyun 	self->ndev->max_mtu = aq_hw_caps->mtu - ETH_FCS_LEN - ETH_HLEN;
380*4882a593Smuzhiyun 
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun 
aq_nic_set_tx_ring(struct aq_nic_s * self,unsigned int idx,struct aq_ring_s * ring)383*4882a593Smuzhiyun void aq_nic_set_tx_ring(struct aq_nic_s *self, unsigned int idx,
384*4882a593Smuzhiyun 			struct aq_ring_s *ring)
385*4882a593Smuzhiyun {
386*4882a593Smuzhiyun 	self->aq_ring_tx[idx] = ring;
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun 
aq_nic_get_ndev(struct aq_nic_s * self)389*4882a593Smuzhiyun struct net_device *aq_nic_get_ndev(struct aq_nic_s *self)
390*4882a593Smuzhiyun {
391*4882a593Smuzhiyun 	return self->ndev;
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun 
aq_nic_init(struct aq_nic_s * self)394*4882a593Smuzhiyun int aq_nic_init(struct aq_nic_s *self)
395*4882a593Smuzhiyun {
396*4882a593Smuzhiyun 	struct aq_vec_s *aq_vec = NULL;
397*4882a593Smuzhiyun 	unsigned int i = 0U;
398*4882a593Smuzhiyun 	int err = 0;
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun 	self->power_state = AQ_HW_POWER_STATE_D0;
401*4882a593Smuzhiyun 	mutex_lock(&self->fwreq_mutex);
402*4882a593Smuzhiyun 	err = self->aq_hw_ops->hw_reset(self->aq_hw);
403*4882a593Smuzhiyun 	mutex_unlock(&self->fwreq_mutex);
404*4882a593Smuzhiyun 	if (err < 0)
405*4882a593Smuzhiyun 		goto err_exit;
406*4882a593Smuzhiyun 	/* Restore default settings */
407*4882a593Smuzhiyun 	aq_nic_set_downshift(self, self->aq_nic_cfg.downshift_counter);
408*4882a593Smuzhiyun 	aq_nic_set_media_detect(self, self->aq_nic_cfg.is_media_detect ?
409*4882a593Smuzhiyun 				AQ_HW_MEDIA_DETECT_CNT : 0);
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	err = self->aq_hw_ops->hw_init(self->aq_hw,
412*4882a593Smuzhiyun 				       aq_nic_get_ndev(self)->dev_addr);
413*4882a593Smuzhiyun 	if (err < 0)
414*4882a593Smuzhiyun 		goto err_exit;
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 	if (ATL_HW_IS_CHIP_FEATURE(self->aq_hw, ATLANTIC) &&
417*4882a593Smuzhiyun 	    self->aq_nic_cfg.aq_hw_caps->media_type == AQ_HW_MEDIA_TYPE_TP) {
418*4882a593Smuzhiyun 		self->aq_hw->phy_id = HW_ATL_PHY_ID_MAX;
419*4882a593Smuzhiyun 		err = aq_phy_init(self->aq_hw);
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 		/* Disable the PTP on NICs where it's known to cause datapath
422*4882a593Smuzhiyun 		 * problems.
423*4882a593Smuzhiyun 		 * Ideally this should have been done by PHY provisioning, but
424*4882a593Smuzhiyun 		 * many units have been shipped with enabled PTP block already.
425*4882a593Smuzhiyun 		 */
426*4882a593Smuzhiyun 		if (self->aq_nic_cfg.aq_hw_caps->quirks & AQ_NIC_QUIRK_BAD_PTP)
427*4882a593Smuzhiyun 			if (self->aq_hw->phy_id != HW_ATL_PHY_ID_MAX)
428*4882a593Smuzhiyun 				aq_phy_disable_ptp(self->aq_hw);
429*4882a593Smuzhiyun 	}
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun 	for (i = 0U; i < self->aq_vecs; i++) {
432*4882a593Smuzhiyun 		aq_vec = self->aq_vec[i];
433*4882a593Smuzhiyun 		err = aq_vec_ring_alloc(aq_vec, self, i,
434*4882a593Smuzhiyun 					aq_nic_get_cfg(self));
435*4882a593Smuzhiyun 		if (err)
436*4882a593Smuzhiyun 			goto err_exit;
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 		aq_vec_init(aq_vec, self->aq_hw_ops, self->aq_hw);
439*4882a593Smuzhiyun 	}
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 	if (aq_nic_get_cfg(self)->is_ptp) {
442*4882a593Smuzhiyun 		err = aq_ptp_init(self, self->irqvecs - 1);
443*4882a593Smuzhiyun 		if (err < 0)
444*4882a593Smuzhiyun 			goto err_exit;
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 		err = aq_ptp_ring_alloc(self);
447*4882a593Smuzhiyun 		if (err < 0)
448*4882a593Smuzhiyun 			goto err_exit;
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 		err = aq_ptp_ring_init(self);
451*4882a593Smuzhiyun 		if (err < 0)
452*4882a593Smuzhiyun 			goto err_exit;
453*4882a593Smuzhiyun 	}
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun 	netif_carrier_off(self->ndev);
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun err_exit:
458*4882a593Smuzhiyun 	return err;
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun 
aq_nic_start(struct aq_nic_s * self)461*4882a593Smuzhiyun int aq_nic_start(struct aq_nic_s *self)
462*4882a593Smuzhiyun {
463*4882a593Smuzhiyun 	struct aq_vec_s *aq_vec = NULL;
464*4882a593Smuzhiyun 	struct aq_nic_cfg_s *cfg;
465*4882a593Smuzhiyun 	unsigned int i = 0U;
466*4882a593Smuzhiyun 	int err = 0;
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun 	cfg = aq_nic_get_cfg(self);
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 	err = self->aq_hw_ops->hw_multicast_list_set(self->aq_hw,
471*4882a593Smuzhiyun 						     self->mc_list.ar,
472*4882a593Smuzhiyun 						     self->mc_list.count);
473*4882a593Smuzhiyun 	if (err < 0)
474*4882a593Smuzhiyun 		goto err_exit;
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 	err = self->aq_hw_ops->hw_packet_filter_set(self->aq_hw,
477*4882a593Smuzhiyun 						    self->packet_filter);
478*4882a593Smuzhiyun 	if (err < 0)
479*4882a593Smuzhiyun 		goto err_exit;
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 	for (i = 0U; self->aq_vecs > i; ++i) {
482*4882a593Smuzhiyun 		aq_vec = self->aq_vec[i];
483*4882a593Smuzhiyun 		err = aq_vec_start(aq_vec);
484*4882a593Smuzhiyun 		if (err < 0)
485*4882a593Smuzhiyun 			goto err_exit;
486*4882a593Smuzhiyun 	}
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 	err = aq_ptp_ring_start(self);
489*4882a593Smuzhiyun 	if (err < 0)
490*4882a593Smuzhiyun 		goto err_exit;
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun 	aq_nic_set_loopback(self);
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	err = self->aq_hw_ops->hw_start(self->aq_hw);
495*4882a593Smuzhiyun 	if (err < 0)
496*4882a593Smuzhiyun 		goto err_exit;
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun 	err = aq_nic_update_interrupt_moderation_settings(self);
499*4882a593Smuzhiyun 	if (err)
500*4882a593Smuzhiyun 		goto err_exit;
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun 	INIT_WORK(&self->service_task, aq_nic_service_task);
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun 	timer_setup(&self->service_timer, aq_nic_service_timer_cb, 0);
505*4882a593Smuzhiyun 	aq_nic_service_timer_cb(&self->service_timer);
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 	if (cfg->is_polling) {
508*4882a593Smuzhiyun 		timer_setup(&self->polling_timer, aq_nic_polling_timer_cb, 0);
509*4882a593Smuzhiyun 		mod_timer(&self->polling_timer, jiffies +
510*4882a593Smuzhiyun 			  AQ_CFG_POLLING_TIMER_INTERVAL);
511*4882a593Smuzhiyun 	} else {
512*4882a593Smuzhiyun 		for (i = 0U; self->aq_vecs > i; ++i) {
513*4882a593Smuzhiyun 			aq_vec = self->aq_vec[i];
514*4882a593Smuzhiyun 			err = aq_pci_func_alloc_irq(self, i, self->ndev->name,
515*4882a593Smuzhiyun 						    aq_vec_isr, aq_vec,
516*4882a593Smuzhiyun 						    aq_vec_get_affinity_mask(aq_vec));
517*4882a593Smuzhiyun 			if (err < 0)
518*4882a593Smuzhiyun 				goto err_exit;
519*4882a593Smuzhiyun 		}
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun 		err = aq_ptp_irq_alloc(self);
522*4882a593Smuzhiyun 		if (err < 0)
523*4882a593Smuzhiyun 			goto err_exit;
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 		if (cfg->link_irq_vec) {
526*4882a593Smuzhiyun 			int irqvec = pci_irq_vector(self->pdev,
527*4882a593Smuzhiyun 						    cfg->link_irq_vec);
528*4882a593Smuzhiyun 			err = request_threaded_irq(irqvec, NULL,
529*4882a593Smuzhiyun 						   aq_linkstate_threaded_isr,
530*4882a593Smuzhiyun 						   IRQF_SHARED | IRQF_ONESHOT,
531*4882a593Smuzhiyun 						   self->ndev->name, self);
532*4882a593Smuzhiyun 			if (err < 0)
533*4882a593Smuzhiyun 				goto err_exit;
534*4882a593Smuzhiyun 			self->msix_entry_mask |= (1 << cfg->link_irq_vec);
535*4882a593Smuzhiyun 		}
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 		err = self->aq_hw_ops->hw_irq_enable(self->aq_hw,
538*4882a593Smuzhiyun 						     AQ_CFG_IRQ_MASK);
539*4882a593Smuzhiyun 		if (err < 0)
540*4882a593Smuzhiyun 			goto err_exit;
541*4882a593Smuzhiyun 	}
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun 	err = netif_set_real_num_tx_queues(self->ndev,
544*4882a593Smuzhiyun 					   self->aq_vecs * cfg->tcs);
545*4882a593Smuzhiyun 	if (err < 0)
546*4882a593Smuzhiyun 		goto err_exit;
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun 	err = netif_set_real_num_rx_queues(self->ndev,
549*4882a593Smuzhiyun 					   self->aq_vecs * cfg->tcs);
550*4882a593Smuzhiyun 	if (err < 0)
551*4882a593Smuzhiyun 		goto err_exit;
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 	for (i = 0; i < cfg->tcs; i++) {
554*4882a593Smuzhiyun 		u16 offset = self->aq_vecs * i;
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun 		netdev_set_tc_queue(self->ndev, i, self->aq_vecs, offset);
557*4882a593Smuzhiyun 	}
558*4882a593Smuzhiyun 	netif_tx_start_all_queues(self->ndev);
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun err_exit:
561*4882a593Smuzhiyun 	return err;
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun 
aq_nic_map_skb(struct aq_nic_s * self,struct sk_buff * skb,struct aq_ring_s * ring)564*4882a593Smuzhiyun unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb,
565*4882a593Smuzhiyun 			    struct aq_ring_s *ring)
566*4882a593Smuzhiyun {
567*4882a593Smuzhiyun 	unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
568*4882a593Smuzhiyun 	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(self);
569*4882a593Smuzhiyun 	struct device *dev = aq_nic_get_dev(self);
570*4882a593Smuzhiyun 	struct aq_ring_buff_s *first = NULL;
571*4882a593Smuzhiyun 	u8 ipver = ip_hdr(skb)->version;
572*4882a593Smuzhiyun 	struct aq_ring_buff_s *dx_buff;
573*4882a593Smuzhiyun 	bool need_context_tag = false;
574*4882a593Smuzhiyun 	unsigned int frag_count = 0U;
575*4882a593Smuzhiyun 	unsigned int ret = 0U;
576*4882a593Smuzhiyun 	unsigned int dx;
577*4882a593Smuzhiyun 	u8 l4proto = 0;
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun 	if (ipver == 4)
580*4882a593Smuzhiyun 		l4proto = ip_hdr(skb)->protocol;
581*4882a593Smuzhiyun 	else if (ipver == 6)
582*4882a593Smuzhiyun 		l4proto = ipv6_hdr(skb)->nexthdr;
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun 	dx = ring->sw_tail;
585*4882a593Smuzhiyun 	dx_buff = &ring->buff_ring[dx];
586*4882a593Smuzhiyun 	dx_buff->flags = 0U;
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun 	if (unlikely(skb_is_gso(skb))) {
589*4882a593Smuzhiyun 		dx_buff->mss = skb_shinfo(skb)->gso_size;
590*4882a593Smuzhiyun 		if (l4proto == IPPROTO_TCP) {
591*4882a593Smuzhiyun 			dx_buff->is_gso_tcp = 1U;
592*4882a593Smuzhiyun 			dx_buff->len_l4 = tcp_hdrlen(skb);
593*4882a593Smuzhiyun 		} else if (l4proto == IPPROTO_UDP) {
594*4882a593Smuzhiyun 			dx_buff->is_gso_udp = 1U;
595*4882a593Smuzhiyun 			dx_buff->len_l4 = sizeof(struct udphdr);
596*4882a593Smuzhiyun 			/* UDP GSO Hardware does not replace packet length. */
597*4882a593Smuzhiyun 			udp_hdr(skb)->len = htons(dx_buff->mss +
598*4882a593Smuzhiyun 						  dx_buff->len_l4);
599*4882a593Smuzhiyun 		} else {
600*4882a593Smuzhiyun 			WARN_ONCE(true, "Bad GSO mode");
601*4882a593Smuzhiyun 			goto exit;
602*4882a593Smuzhiyun 		}
603*4882a593Smuzhiyun 		dx_buff->len_pkt = skb->len;
604*4882a593Smuzhiyun 		dx_buff->len_l2 = ETH_HLEN;
605*4882a593Smuzhiyun 		dx_buff->len_l3 = skb_network_header_len(skb);
606*4882a593Smuzhiyun 		dx_buff->eop_index = 0xffffU;
607*4882a593Smuzhiyun 		dx_buff->is_ipv6 = (ipver == 6);
608*4882a593Smuzhiyun 		need_context_tag = true;
609*4882a593Smuzhiyun 	}
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun 	if (cfg->is_vlan_tx_insert && skb_vlan_tag_present(skb)) {
612*4882a593Smuzhiyun 		dx_buff->vlan_tx_tag = skb_vlan_tag_get(skb);
613*4882a593Smuzhiyun 		dx_buff->len_pkt = skb->len;
614*4882a593Smuzhiyun 		dx_buff->is_vlan = 1U;
615*4882a593Smuzhiyun 		need_context_tag = true;
616*4882a593Smuzhiyun 	}
617*4882a593Smuzhiyun 
618*4882a593Smuzhiyun 	if (need_context_tag) {
619*4882a593Smuzhiyun 		dx = aq_ring_next_dx(ring, dx);
620*4882a593Smuzhiyun 		dx_buff = &ring->buff_ring[dx];
621*4882a593Smuzhiyun 		dx_buff->flags = 0U;
622*4882a593Smuzhiyun 		++ret;
623*4882a593Smuzhiyun 	}
624*4882a593Smuzhiyun 
625*4882a593Smuzhiyun 	dx_buff->len = skb_headlen(skb);
626*4882a593Smuzhiyun 	dx_buff->pa = dma_map_single(dev,
627*4882a593Smuzhiyun 				     skb->data,
628*4882a593Smuzhiyun 				     dx_buff->len,
629*4882a593Smuzhiyun 				     DMA_TO_DEVICE);
630*4882a593Smuzhiyun 
631*4882a593Smuzhiyun 	if (unlikely(dma_mapping_error(dev, dx_buff->pa))) {
632*4882a593Smuzhiyun 		ret = 0;
633*4882a593Smuzhiyun 		goto exit;
634*4882a593Smuzhiyun 	}
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun 	first = dx_buff;
637*4882a593Smuzhiyun 	dx_buff->len_pkt = skb->len;
638*4882a593Smuzhiyun 	dx_buff->is_sop = 1U;
639*4882a593Smuzhiyun 	dx_buff->is_mapped = 1U;
640*4882a593Smuzhiyun 	++ret;
641*4882a593Smuzhiyun 
642*4882a593Smuzhiyun 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
643*4882a593Smuzhiyun 		dx_buff->is_ip_cso = (htons(ETH_P_IP) == skb->protocol);
644*4882a593Smuzhiyun 		dx_buff->is_tcp_cso = (l4proto == IPPROTO_TCP);
645*4882a593Smuzhiyun 		dx_buff->is_udp_cso = (l4proto == IPPROTO_UDP);
646*4882a593Smuzhiyun 	}
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun 	for (; nr_frags--; ++frag_count) {
649*4882a593Smuzhiyun 		unsigned int frag_len = 0U;
650*4882a593Smuzhiyun 		unsigned int buff_offset = 0U;
651*4882a593Smuzhiyun 		unsigned int buff_size = 0U;
652*4882a593Smuzhiyun 		dma_addr_t frag_pa;
653*4882a593Smuzhiyun 		skb_frag_t *frag = &skb_shinfo(skb)->frags[frag_count];
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun 		frag_len = skb_frag_size(frag);
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun 		while (frag_len) {
658*4882a593Smuzhiyun 			if (frag_len > AQ_CFG_TX_FRAME_MAX)
659*4882a593Smuzhiyun 				buff_size = AQ_CFG_TX_FRAME_MAX;
660*4882a593Smuzhiyun 			else
661*4882a593Smuzhiyun 				buff_size = frag_len;
662*4882a593Smuzhiyun 
663*4882a593Smuzhiyun 			frag_pa = skb_frag_dma_map(dev,
664*4882a593Smuzhiyun 						   frag,
665*4882a593Smuzhiyun 						   buff_offset,
666*4882a593Smuzhiyun 						   buff_size,
667*4882a593Smuzhiyun 						   DMA_TO_DEVICE);
668*4882a593Smuzhiyun 
669*4882a593Smuzhiyun 			if (unlikely(dma_mapping_error(dev,
670*4882a593Smuzhiyun 						       frag_pa)))
671*4882a593Smuzhiyun 				goto mapping_error;
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun 			dx = aq_ring_next_dx(ring, dx);
674*4882a593Smuzhiyun 			dx_buff = &ring->buff_ring[dx];
675*4882a593Smuzhiyun 
676*4882a593Smuzhiyun 			dx_buff->flags = 0U;
677*4882a593Smuzhiyun 			dx_buff->len = buff_size;
678*4882a593Smuzhiyun 			dx_buff->pa = frag_pa;
679*4882a593Smuzhiyun 			dx_buff->is_mapped = 1U;
680*4882a593Smuzhiyun 			dx_buff->eop_index = 0xffffU;
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 			frag_len -= buff_size;
683*4882a593Smuzhiyun 			buff_offset += buff_size;
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun 			++ret;
686*4882a593Smuzhiyun 		}
687*4882a593Smuzhiyun 	}
688*4882a593Smuzhiyun 
689*4882a593Smuzhiyun 	first->eop_index = dx;
690*4882a593Smuzhiyun 	dx_buff->is_eop = 1U;
691*4882a593Smuzhiyun 	dx_buff->skb = skb;
692*4882a593Smuzhiyun 	goto exit;
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun mapping_error:
695*4882a593Smuzhiyun 	for (dx = ring->sw_tail;
696*4882a593Smuzhiyun 	     ret > 0;
697*4882a593Smuzhiyun 	     --ret, dx = aq_ring_next_dx(ring, dx)) {
698*4882a593Smuzhiyun 		dx_buff = &ring->buff_ring[dx];
699*4882a593Smuzhiyun 
700*4882a593Smuzhiyun 		if (!(dx_buff->is_gso_tcp || dx_buff->is_gso_udp) &&
701*4882a593Smuzhiyun 		    !dx_buff->is_vlan && dx_buff->pa) {
702*4882a593Smuzhiyun 			if (unlikely(dx_buff->is_sop)) {
703*4882a593Smuzhiyun 				dma_unmap_single(dev,
704*4882a593Smuzhiyun 						 dx_buff->pa,
705*4882a593Smuzhiyun 						 dx_buff->len,
706*4882a593Smuzhiyun 						 DMA_TO_DEVICE);
707*4882a593Smuzhiyun 			} else {
708*4882a593Smuzhiyun 				dma_unmap_page(dev,
709*4882a593Smuzhiyun 					       dx_buff->pa,
710*4882a593Smuzhiyun 					       dx_buff->len,
711*4882a593Smuzhiyun 					       DMA_TO_DEVICE);
712*4882a593Smuzhiyun 			}
713*4882a593Smuzhiyun 		}
714*4882a593Smuzhiyun 	}
715*4882a593Smuzhiyun 
716*4882a593Smuzhiyun exit:
717*4882a593Smuzhiyun 	return ret;
718*4882a593Smuzhiyun }
719*4882a593Smuzhiyun 
aq_nic_xmit(struct aq_nic_s * self,struct sk_buff * skb)720*4882a593Smuzhiyun int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb)
721*4882a593Smuzhiyun {
722*4882a593Smuzhiyun 	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(self);
723*4882a593Smuzhiyun 	unsigned int vec = skb->queue_mapping % cfg->vecs;
724*4882a593Smuzhiyun 	unsigned int tc = skb->queue_mapping / cfg->vecs;
725*4882a593Smuzhiyun 	struct aq_ring_s *ring = NULL;
726*4882a593Smuzhiyun 	unsigned int frags = 0U;
727*4882a593Smuzhiyun 	int err = NETDEV_TX_OK;
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun 	frags = skb_shinfo(skb)->nr_frags + 1;
730*4882a593Smuzhiyun 
731*4882a593Smuzhiyun 	ring = self->aq_ring_tx[AQ_NIC_CFG_TCVEC2RING(cfg, tc, vec)];
732*4882a593Smuzhiyun 
733*4882a593Smuzhiyun 	if (frags > AQ_CFG_SKB_FRAGS_MAX) {
734*4882a593Smuzhiyun 		dev_kfree_skb_any(skb);
735*4882a593Smuzhiyun 		goto err_exit;
736*4882a593Smuzhiyun 	}
737*4882a593Smuzhiyun 
738*4882a593Smuzhiyun 	aq_ring_update_queue_state(ring);
739*4882a593Smuzhiyun 
740*4882a593Smuzhiyun 	if (cfg->priv_flags & BIT(AQ_HW_LOOPBACK_DMA_NET)) {
741*4882a593Smuzhiyun 		err = NETDEV_TX_BUSY;
742*4882a593Smuzhiyun 		goto err_exit;
743*4882a593Smuzhiyun 	}
744*4882a593Smuzhiyun 
745*4882a593Smuzhiyun 	/* Above status update may stop the queue. Check this. */
746*4882a593Smuzhiyun 	if (__netif_subqueue_stopped(self->ndev,
747*4882a593Smuzhiyun 				     AQ_NIC_RING2QMAP(self, ring->idx))) {
748*4882a593Smuzhiyun 		err = NETDEV_TX_BUSY;
749*4882a593Smuzhiyun 		goto err_exit;
750*4882a593Smuzhiyun 	}
751*4882a593Smuzhiyun 
752*4882a593Smuzhiyun 	frags = aq_nic_map_skb(self, skb, ring);
753*4882a593Smuzhiyun 
754*4882a593Smuzhiyun 	if (likely(frags)) {
755*4882a593Smuzhiyun 		err = self->aq_hw_ops->hw_ring_tx_xmit(self->aq_hw,
756*4882a593Smuzhiyun 						       ring, frags);
757*4882a593Smuzhiyun 	} else {
758*4882a593Smuzhiyun 		err = NETDEV_TX_BUSY;
759*4882a593Smuzhiyun 	}
760*4882a593Smuzhiyun 
761*4882a593Smuzhiyun err_exit:
762*4882a593Smuzhiyun 	return err;
763*4882a593Smuzhiyun }
764*4882a593Smuzhiyun 
aq_nic_update_interrupt_moderation_settings(struct aq_nic_s * self)765*4882a593Smuzhiyun int aq_nic_update_interrupt_moderation_settings(struct aq_nic_s *self)
766*4882a593Smuzhiyun {
767*4882a593Smuzhiyun 	return self->aq_hw_ops->hw_interrupt_moderation_set(self->aq_hw);
768*4882a593Smuzhiyun }
769*4882a593Smuzhiyun 
aq_nic_set_packet_filter(struct aq_nic_s * self,unsigned int flags)770*4882a593Smuzhiyun int aq_nic_set_packet_filter(struct aq_nic_s *self, unsigned int flags)
771*4882a593Smuzhiyun {
772*4882a593Smuzhiyun 	int err = 0;
773*4882a593Smuzhiyun 
774*4882a593Smuzhiyun 	err = self->aq_hw_ops->hw_packet_filter_set(self->aq_hw, flags);
775*4882a593Smuzhiyun 	if (err < 0)
776*4882a593Smuzhiyun 		goto err_exit;
777*4882a593Smuzhiyun 
778*4882a593Smuzhiyun 	self->packet_filter = flags;
779*4882a593Smuzhiyun 
780*4882a593Smuzhiyun err_exit:
781*4882a593Smuzhiyun 	return err;
782*4882a593Smuzhiyun }
783*4882a593Smuzhiyun 
aq_nic_set_multicast_list(struct aq_nic_s * self,struct net_device * ndev)784*4882a593Smuzhiyun int aq_nic_set_multicast_list(struct aq_nic_s *self, struct net_device *ndev)
785*4882a593Smuzhiyun {
786*4882a593Smuzhiyun 	const struct aq_hw_ops *hw_ops = self->aq_hw_ops;
787*4882a593Smuzhiyun 	struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg;
788*4882a593Smuzhiyun 	unsigned int packet_filter = ndev->flags;
789*4882a593Smuzhiyun 	struct netdev_hw_addr *ha = NULL;
790*4882a593Smuzhiyun 	unsigned int i = 0U;
791*4882a593Smuzhiyun 	int err = 0;
792*4882a593Smuzhiyun 
793*4882a593Smuzhiyun 	self->mc_list.count = 0;
794*4882a593Smuzhiyun 	if (netdev_uc_count(ndev) > AQ_HW_MULTICAST_ADDRESS_MAX) {
795*4882a593Smuzhiyun 		packet_filter |= IFF_PROMISC;
796*4882a593Smuzhiyun 	} else {
797*4882a593Smuzhiyun 		netdev_for_each_uc_addr(ha, ndev) {
798*4882a593Smuzhiyun 			ether_addr_copy(self->mc_list.ar[i++], ha->addr);
799*4882a593Smuzhiyun 		}
800*4882a593Smuzhiyun 	}
801*4882a593Smuzhiyun 
802*4882a593Smuzhiyun 	cfg->is_mc_list_enabled = !!(packet_filter & IFF_MULTICAST);
803*4882a593Smuzhiyun 	if (cfg->is_mc_list_enabled) {
804*4882a593Smuzhiyun 		if (i + netdev_mc_count(ndev) > AQ_HW_MULTICAST_ADDRESS_MAX) {
805*4882a593Smuzhiyun 			packet_filter |= IFF_ALLMULTI;
806*4882a593Smuzhiyun 		} else {
807*4882a593Smuzhiyun 			netdev_for_each_mc_addr(ha, ndev) {
808*4882a593Smuzhiyun 				ether_addr_copy(self->mc_list.ar[i++],
809*4882a593Smuzhiyun 						ha->addr);
810*4882a593Smuzhiyun 			}
811*4882a593Smuzhiyun 		}
812*4882a593Smuzhiyun 	}
813*4882a593Smuzhiyun 
814*4882a593Smuzhiyun 	if (i > 0 && i <= AQ_HW_MULTICAST_ADDRESS_MAX) {
815*4882a593Smuzhiyun 		self->mc_list.count = i;
816*4882a593Smuzhiyun 		err = hw_ops->hw_multicast_list_set(self->aq_hw,
817*4882a593Smuzhiyun 						    self->mc_list.ar,
818*4882a593Smuzhiyun 						    self->mc_list.count);
819*4882a593Smuzhiyun 		if (err < 0)
820*4882a593Smuzhiyun 			return err;
821*4882a593Smuzhiyun 	}
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun 	return aq_nic_set_packet_filter(self, packet_filter);
824*4882a593Smuzhiyun }
825*4882a593Smuzhiyun 
aq_nic_set_mtu(struct aq_nic_s * self,int new_mtu)826*4882a593Smuzhiyun int aq_nic_set_mtu(struct aq_nic_s *self, int new_mtu)
827*4882a593Smuzhiyun {
828*4882a593Smuzhiyun 	self->aq_nic_cfg.mtu = new_mtu;
829*4882a593Smuzhiyun 
830*4882a593Smuzhiyun 	return 0;
831*4882a593Smuzhiyun }
832*4882a593Smuzhiyun 
aq_nic_set_mac(struct aq_nic_s * self,struct net_device * ndev)833*4882a593Smuzhiyun int aq_nic_set_mac(struct aq_nic_s *self, struct net_device *ndev)
834*4882a593Smuzhiyun {
835*4882a593Smuzhiyun 	return self->aq_hw_ops->hw_set_mac_address(self->aq_hw, ndev->dev_addr);
836*4882a593Smuzhiyun }
837*4882a593Smuzhiyun 
aq_nic_get_link_speed(struct aq_nic_s * self)838*4882a593Smuzhiyun unsigned int aq_nic_get_link_speed(struct aq_nic_s *self)
839*4882a593Smuzhiyun {
840*4882a593Smuzhiyun 	return self->link_status.mbps;
841*4882a593Smuzhiyun }
842*4882a593Smuzhiyun 
aq_nic_get_regs(struct aq_nic_s * self,struct ethtool_regs * regs,void * p)843*4882a593Smuzhiyun int aq_nic_get_regs(struct aq_nic_s *self, struct ethtool_regs *regs, void *p)
844*4882a593Smuzhiyun {
845*4882a593Smuzhiyun 	u32 *regs_buff = p;
846*4882a593Smuzhiyun 	int err = 0;
847*4882a593Smuzhiyun 
848*4882a593Smuzhiyun 	if (unlikely(!self->aq_hw_ops->hw_get_regs))
849*4882a593Smuzhiyun 		return -EOPNOTSUPP;
850*4882a593Smuzhiyun 
851*4882a593Smuzhiyun 	regs->version = 1;
852*4882a593Smuzhiyun 
853*4882a593Smuzhiyun 	err = self->aq_hw_ops->hw_get_regs(self->aq_hw,
854*4882a593Smuzhiyun 					   self->aq_nic_cfg.aq_hw_caps,
855*4882a593Smuzhiyun 					   regs_buff);
856*4882a593Smuzhiyun 	if (err < 0)
857*4882a593Smuzhiyun 		goto err_exit;
858*4882a593Smuzhiyun 
859*4882a593Smuzhiyun err_exit:
860*4882a593Smuzhiyun 	return err;
861*4882a593Smuzhiyun }
862*4882a593Smuzhiyun 
aq_nic_get_regs_count(struct aq_nic_s * self)863*4882a593Smuzhiyun int aq_nic_get_regs_count(struct aq_nic_s *self)
864*4882a593Smuzhiyun {
865*4882a593Smuzhiyun 	if (unlikely(!self->aq_hw_ops->hw_get_regs))
866*4882a593Smuzhiyun 		return 0;
867*4882a593Smuzhiyun 
868*4882a593Smuzhiyun 	return self->aq_nic_cfg.aq_hw_caps->mac_regs_count;
869*4882a593Smuzhiyun }
870*4882a593Smuzhiyun 
aq_nic_get_stats(struct aq_nic_s * self,u64 * data)871*4882a593Smuzhiyun u64 *aq_nic_get_stats(struct aq_nic_s *self, u64 *data)
872*4882a593Smuzhiyun {
873*4882a593Smuzhiyun 	struct aq_stats_s *stats;
874*4882a593Smuzhiyun 	unsigned int count = 0U;
875*4882a593Smuzhiyun 	unsigned int i = 0U;
876*4882a593Smuzhiyun 	unsigned int tc;
877*4882a593Smuzhiyun 
878*4882a593Smuzhiyun 	if (self->aq_fw_ops->update_stats) {
879*4882a593Smuzhiyun 		mutex_lock(&self->fwreq_mutex);
880*4882a593Smuzhiyun 		self->aq_fw_ops->update_stats(self->aq_hw);
881*4882a593Smuzhiyun 		mutex_unlock(&self->fwreq_mutex);
882*4882a593Smuzhiyun 	}
883*4882a593Smuzhiyun 	stats = self->aq_hw_ops->hw_get_hw_stats(self->aq_hw);
884*4882a593Smuzhiyun 
885*4882a593Smuzhiyun 	if (!stats)
886*4882a593Smuzhiyun 		goto err_exit;
887*4882a593Smuzhiyun 
888*4882a593Smuzhiyun 	data[i] = stats->uprc + stats->mprc + stats->bprc;
889*4882a593Smuzhiyun 	data[++i] = stats->uprc;
890*4882a593Smuzhiyun 	data[++i] = stats->mprc;
891*4882a593Smuzhiyun 	data[++i] = stats->bprc;
892*4882a593Smuzhiyun 	data[++i] = stats->erpt;
893*4882a593Smuzhiyun 	data[++i] = stats->uptc + stats->mptc + stats->bptc;
894*4882a593Smuzhiyun 	data[++i] = stats->uptc;
895*4882a593Smuzhiyun 	data[++i] = stats->mptc;
896*4882a593Smuzhiyun 	data[++i] = stats->bptc;
897*4882a593Smuzhiyun 	data[++i] = stats->ubrc;
898*4882a593Smuzhiyun 	data[++i] = stats->ubtc;
899*4882a593Smuzhiyun 	data[++i] = stats->mbrc;
900*4882a593Smuzhiyun 	data[++i] = stats->mbtc;
901*4882a593Smuzhiyun 	data[++i] = stats->bbrc;
902*4882a593Smuzhiyun 	data[++i] = stats->bbtc;
903*4882a593Smuzhiyun 	if (stats->brc)
904*4882a593Smuzhiyun 		data[++i] = stats->brc;
905*4882a593Smuzhiyun 	else
906*4882a593Smuzhiyun 		data[++i] = stats->ubrc + stats->mbrc + stats->bbrc;
907*4882a593Smuzhiyun 	if (stats->btc)
908*4882a593Smuzhiyun 		data[++i] = stats->btc;
909*4882a593Smuzhiyun 	else
910*4882a593Smuzhiyun 		data[++i] = stats->ubtc + stats->mbtc + stats->bbtc;
911*4882a593Smuzhiyun 	data[++i] = stats->dma_pkt_rc;
912*4882a593Smuzhiyun 	data[++i] = stats->dma_pkt_tc;
913*4882a593Smuzhiyun 	data[++i] = stats->dma_oct_rc;
914*4882a593Smuzhiyun 	data[++i] = stats->dma_oct_tc;
915*4882a593Smuzhiyun 	data[++i] = stats->dpc;
916*4882a593Smuzhiyun 
917*4882a593Smuzhiyun 	i++;
918*4882a593Smuzhiyun 
919*4882a593Smuzhiyun 	data += i;
920*4882a593Smuzhiyun 
921*4882a593Smuzhiyun 	for (tc = 0U; tc < self->aq_nic_cfg.tcs; tc++) {
922*4882a593Smuzhiyun 		for (i = 0U; self->aq_vecs > i; ++i) {
923*4882a593Smuzhiyun 			if (!self->aq_vec[i])
924*4882a593Smuzhiyun 				break;
925*4882a593Smuzhiyun 			data += count;
926*4882a593Smuzhiyun 			count = aq_vec_get_sw_stats(self->aq_vec[i], tc, data);
927*4882a593Smuzhiyun 		}
928*4882a593Smuzhiyun 	}
929*4882a593Smuzhiyun 
930*4882a593Smuzhiyun 	data += count;
931*4882a593Smuzhiyun 
932*4882a593Smuzhiyun err_exit:
933*4882a593Smuzhiyun 	return data;
934*4882a593Smuzhiyun }
935*4882a593Smuzhiyun 
aq_nic_update_ndev_stats(struct aq_nic_s * self)936*4882a593Smuzhiyun static void aq_nic_update_ndev_stats(struct aq_nic_s *self)
937*4882a593Smuzhiyun {
938*4882a593Smuzhiyun 	struct aq_stats_s *stats = self->aq_hw_ops->hw_get_hw_stats(self->aq_hw);
939*4882a593Smuzhiyun 	struct net_device *ndev = self->ndev;
940*4882a593Smuzhiyun 
941*4882a593Smuzhiyun 	ndev->stats.rx_packets = stats->dma_pkt_rc;
942*4882a593Smuzhiyun 	ndev->stats.rx_bytes = stats->dma_oct_rc;
943*4882a593Smuzhiyun 	ndev->stats.rx_errors = stats->erpr;
944*4882a593Smuzhiyun 	ndev->stats.rx_dropped = stats->dpc;
945*4882a593Smuzhiyun 	ndev->stats.tx_packets = stats->dma_pkt_tc;
946*4882a593Smuzhiyun 	ndev->stats.tx_bytes = stats->dma_oct_tc;
947*4882a593Smuzhiyun 	ndev->stats.tx_errors = stats->erpt;
948*4882a593Smuzhiyun 	ndev->stats.multicast = stats->mprc;
949*4882a593Smuzhiyun }
950*4882a593Smuzhiyun 
aq_nic_get_link_ksettings(struct aq_nic_s * self,struct ethtool_link_ksettings * cmd)951*4882a593Smuzhiyun void aq_nic_get_link_ksettings(struct aq_nic_s *self,
952*4882a593Smuzhiyun 			       struct ethtool_link_ksettings *cmd)
953*4882a593Smuzhiyun {
954*4882a593Smuzhiyun 	u32 lp_link_speed_msk;
955*4882a593Smuzhiyun 
956*4882a593Smuzhiyun 	if (self->aq_nic_cfg.aq_hw_caps->media_type == AQ_HW_MEDIA_TYPE_FIBRE)
957*4882a593Smuzhiyun 		cmd->base.port = PORT_FIBRE;
958*4882a593Smuzhiyun 	else
959*4882a593Smuzhiyun 		cmd->base.port = PORT_TP;
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun 	cmd->base.duplex = DUPLEX_UNKNOWN;
962*4882a593Smuzhiyun 	if (self->link_status.mbps)
963*4882a593Smuzhiyun 		cmd->base.duplex = self->link_status.full_duplex ?
964*4882a593Smuzhiyun 				   DUPLEX_FULL : DUPLEX_HALF;
965*4882a593Smuzhiyun 	cmd->base.autoneg = self->aq_nic_cfg.is_autoneg;
966*4882a593Smuzhiyun 
967*4882a593Smuzhiyun 	ethtool_link_ksettings_zero_link_mode(cmd, supported);
968*4882a593Smuzhiyun 
969*4882a593Smuzhiyun 	if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_10G)
970*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, supported,
971*4882a593Smuzhiyun 						     10000baseT_Full);
972*4882a593Smuzhiyun 
973*4882a593Smuzhiyun 	if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_5G)
974*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, supported,
975*4882a593Smuzhiyun 						     5000baseT_Full);
976*4882a593Smuzhiyun 
977*4882a593Smuzhiyun 	if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_2G5)
978*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, supported,
979*4882a593Smuzhiyun 						     2500baseT_Full);
980*4882a593Smuzhiyun 
981*4882a593Smuzhiyun 	if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_1G)
982*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, supported,
983*4882a593Smuzhiyun 						     1000baseT_Full);
984*4882a593Smuzhiyun 
985*4882a593Smuzhiyun 	if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_1G_HALF)
986*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, supported,
987*4882a593Smuzhiyun 						     1000baseT_Half);
988*4882a593Smuzhiyun 
989*4882a593Smuzhiyun 	if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_100M)
990*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, supported,
991*4882a593Smuzhiyun 						     100baseT_Full);
992*4882a593Smuzhiyun 
993*4882a593Smuzhiyun 	if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_100M_HALF)
994*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, supported,
995*4882a593Smuzhiyun 						     100baseT_Half);
996*4882a593Smuzhiyun 
997*4882a593Smuzhiyun 	if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_10M)
998*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, supported,
999*4882a593Smuzhiyun 						     10baseT_Full);
1000*4882a593Smuzhiyun 
1001*4882a593Smuzhiyun 	if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_10M_HALF)
1002*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, supported,
1003*4882a593Smuzhiyun 						     10baseT_Half);
1004*4882a593Smuzhiyun 
1005*4882a593Smuzhiyun 	if (self->aq_nic_cfg.aq_hw_caps->flow_control) {
1006*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, supported,
1007*4882a593Smuzhiyun 						     Pause);
1008*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, supported,
1009*4882a593Smuzhiyun 						     Asym_Pause);
1010*4882a593Smuzhiyun 	}
1011*4882a593Smuzhiyun 
1012*4882a593Smuzhiyun 	ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
1013*4882a593Smuzhiyun 
1014*4882a593Smuzhiyun 	if (self->aq_nic_cfg.aq_hw_caps->media_type == AQ_HW_MEDIA_TYPE_FIBRE)
1015*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
1016*4882a593Smuzhiyun 	else
1017*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
1018*4882a593Smuzhiyun 
1019*4882a593Smuzhiyun 	ethtool_link_ksettings_zero_link_mode(cmd, advertising);
1020*4882a593Smuzhiyun 
1021*4882a593Smuzhiyun 	if (self->aq_nic_cfg.is_autoneg)
1022*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
1023*4882a593Smuzhiyun 
1024*4882a593Smuzhiyun 	if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_10G)
1025*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, advertising,
1026*4882a593Smuzhiyun 						     10000baseT_Full);
1027*4882a593Smuzhiyun 
1028*4882a593Smuzhiyun 	if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_5G)
1029*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, advertising,
1030*4882a593Smuzhiyun 						     5000baseT_Full);
1031*4882a593Smuzhiyun 
1032*4882a593Smuzhiyun 	if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_2G5)
1033*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, advertising,
1034*4882a593Smuzhiyun 						     2500baseT_Full);
1035*4882a593Smuzhiyun 
1036*4882a593Smuzhiyun 	if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_1G)
1037*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, advertising,
1038*4882a593Smuzhiyun 						     1000baseT_Full);
1039*4882a593Smuzhiyun 
1040*4882a593Smuzhiyun 	if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_1G_HALF)
1041*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, advertising,
1042*4882a593Smuzhiyun 						     1000baseT_Half);
1043*4882a593Smuzhiyun 
1044*4882a593Smuzhiyun 	if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_100M)
1045*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, advertising,
1046*4882a593Smuzhiyun 						     100baseT_Full);
1047*4882a593Smuzhiyun 
1048*4882a593Smuzhiyun 	if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_100M_HALF)
1049*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, advertising,
1050*4882a593Smuzhiyun 						     100baseT_Half);
1051*4882a593Smuzhiyun 
1052*4882a593Smuzhiyun 	if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_10M)
1053*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, advertising,
1054*4882a593Smuzhiyun 						     10baseT_Full);
1055*4882a593Smuzhiyun 
1056*4882a593Smuzhiyun 	if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_10M_HALF)
1057*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, advertising,
1058*4882a593Smuzhiyun 						     10baseT_Half);
1059*4882a593Smuzhiyun 
1060*4882a593Smuzhiyun 	if (self->aq_nic_cfg.fc.cur & AQ_NIC_FC_RX)
1061*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, advertising,
1062*4882a593Smuzhiyun 						     Pause);
1063*4882a593Smuzhiyun 
1064*4882a593Smuzhiyun 	/* Asym is when either RX or TX, but not both */
1065*4882a593Smuzhiyun 	if (!!(self->aq_nic_cfg.fc.cur & AQ_NIC_FC_TX) ^
1066*4882a593Smuzhiyun 	    !!(self->aq_nic_cfg.fc.cur & AQ_NIC_FC_RX))
1067*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, advertising,
1068*4882a593Smuzhiyun 						     Asym_Pause);
1069*4882a593Smuzhiyun 
1070*4882a593Smuzhiyun 	if (self->aq_nic_cfg.aq_hw_caps->media_type == AQ_HW_MEDIA_TYPE_FIBRE)
1071*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE);
1072*4882a593Smuzhiyun 	else
1073*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
1074*4882a593Smuzhiyun 
1075*4882a593Smuzhiyun 	ethtool_link_ksettings_zero_link_mode(cmd, lp_advertising);
1076*4882a593Smuzhiyun 	lp_link_speed_msk = self->aq_hw->aq_link_status.lp_link_speed_msk;
1077*4882a593Smuzhiyun 
1078*4882a593Smuzhiyun 	if (lp_link_speed_msk & AQ_NIC_RATE_10G)
1079*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, lp_advertising,
1080*4882a593Smuzhiyun 						     10000baseT_Full);
1081*4882a593Smuzhiyun 
1082*4882a593Smuzhiyun 	if (lp_link_speed_msk & AQ_NIC_RATE_5G)
1083*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, lp_advertising,
1084*4882a593Smuzhiyun 						     5000baseT_Full);
1085*4882a593Smuzhiyun 
1086*4882a593Smuzhiyun 	if (lp_link_speed_msk & AQ_NIC_RATE_2G5)
1087*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, lp_advertising,
1088*4882a593Smuzhiyun 						     2500baseT_Full);
1089*4882a593Smuzhiyun 
1090*4882a593Smuzhiyun 	if (lp_link_speed_msk & AQ_NIC_RATE_1G)
1091*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, lp_advertising,
1092*4882a593Smuzhiyun 						     1000baseT_Full);
1093*4882a593Smuzhiyun 
1094*4882a593Smuzhiyun 	if (lp_link_speed_msk & AQ_NIC_RATE_1G_HALF)
1095*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, lp_advertising,
1096*4882a593Smuzhiyun 						     1000baseT_Half);
1097*4882a593Smuzhiyun 
1098*4882a593Smuzhiyun 	if (lp_link_speed_msk & AQ_NIC_RATE_100M)
1099*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, lp_advertising,
1100*4882a593Smuzhiyun 						     100baseT_Full);
1101*4882a593Smuzhiyun 
1102*4882a593Smuzhiyun 	if (lp_link_speed_msk & AQ_NIC_RATE_100M_HALF)
1103*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, lp_advertising,
1104*4882a593Smuzhiyun 						     100baseT_Half);
1105*4882a593Smuzhiyun 
1106*4882a593Smuzhiyun 	if (lp_link_speed_msk & AQ_NIC_RATE_10M)
1107*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, lp_advertising,
1108*4882a593Smuzhiyun 						     10baseT_Full);
1109*4882a593Smuzhiyun 
1110*4882a593Smuzhiyun 	if (lp_link_speed_msk & AQ_NIC_RATE_10M_HALF)
1111*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, lp_advertising,
1112*4882a593Smuzhiyun 						     10baseT_Half);
1113*4882a593Smuzhiyun 
1114*4882a593Smuzhiyun 	if (self->aq_hw->aq_link_status.lp_flow_control & AQ_NIC_FC_RX)
1115*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, lp_advertising,
1116*4882a593Smuzhiyun 						     Pause);
1117*4882a593Smuzhiyun 	if (!!(self->aq_hw->aq_link_status.lp_flow_control & AQ_NIC_FC_TX) ^
1118*4882a593Smuzhiyun 	    !!(self->aq_hw->aq_link_status.lp_flow_control & AQ_NIC_FC_RX))
1119*4882a593Smuzhiyun 		ethtool_link_ksettings_add_link_mode(cmd, lp_advertising,
1120*4882a593Smuzhiyun 						     Asym_Pause);
1121*4882a593Smuzhiyun }
1122*4882a593Smuzhiyun 
aq_nic_set_link_ksettings(struct aq_nic_s * self,const struct ethtool_link_ksettings * cmd)1123*4882a593Smuzhiyun int aq_nic_set_link_ksettings(struct aq_nic_s *self,
1124*4882a593Smuzhiyun 			      const struct ethtool_link_ksettings *cmd)
1125*4882a593Smuzhiyun {
1126*4882a593Smuzhiyun 	int fduplex = (cmd->base.duplex == DUPLEX_FULL);
1127*4882a593Smuzhiyun 	u32 speed = cmd->base.speed;
1128*4882a593Smuzhiyun 	u32 rate = 0U;
1129*4882a593Smuzhiyun 	int err = 0;
1130*4882a593Smuzhiyun 
1131*4882a593Smuzhiyun 	if (!fduplex && speed > SPEED_1000) {
1132*4882a593Smuzhiyun 		err = -EINVAL;
1133*4882a593Smuzhiyun 		goto err_exit;
1134*4882a593Smuzhiyun 	}
1135*4882a593Smuzhiyun 
1136*4882a593Smuzhiyun 	if (cmd->base.autoneg == AUTONEG_ENABLE) {
1137*4882a593Smuzhiyun 		rate = self->aq_nic_cfg.aq_hw_caps->link_speed_msk;
1138*4882a593Smuzhiyun 		self->aq_nic_cfg.is_autoneg = true;
1139*4882a593Smuzhiyun 	} else {
1140*4882a593Smuzhiyun 		switch (speed) {
1141*4882a593Smuzhiyun 		case SPEED_10:
1142*4882a593Smuzhiyun 			rate = fduplex ? AQ_NIC_RATE_10M : AQ_NIC_RATE_10M_HALF;
1143*4882a593Smuzhiyun 			break;
1144*4882a593Smuzhiyun 
1145*4882a593Smuzhiyun 		case SPEED_100:
1146*4882a593Smuzhiyun 			rate = fduplex ? AQ_NIC_RATE_100M
1147*4882a593Smuzhiyun 				       : AQ_NIC_RATE_100M_HALF;
1148*4882a593Smuzhiyun 			break;
1149*4882a593Smuzhiyun 
1150*4882a593Smuzhiyun 		case SPEED_1000:
1151*4882a593Smuzhiyun 			rate = fduplex ? AQ_NIC_RATE_1G : AQ_NIC_RATE_1G_HALF;
1152*4882a593Smuzhiyun 			break;
1153*4882a593Smuzhiyun 
1154*4882a593Smuzhiyun 		case SPEED_2500:
1155*4882a593Smuzhiyun 			rate = AQ_NIC_RATE_2G5;
1156*4882a593Smuzhiyun 			break;
1157*4882a593Smuzhiyun 
1158*4882a593Smuzhiyun 		case SPEED_5000:
1159*4882a593Smuzhiyun 			rate = AQ_NIC_RATE_5G;
1160*4882a593Smuzhiyun 			break;
1161*4882a593Smuzhiyun 
1162*4882a593Smuzhiyun 		case SPEED_10000:
1163*4882a593Smuzhiyun 			rate = AQ_NIC_RATE_10G;
1164*4882a593Smuzhiyun 			break;
1165*4882a593Smuzhiyun 
1166*4882a593Smuzhiyun 		default:
1167*4882a593Smuzhiyun 			err = -1;
1168*4882a593Smuzhiyun 			goto err_exit;
1169*4882a593Smuzhiyun 		}
1170*4882a593Smuzhiyun 		if (!(self->aq_nic_cfg.aq_hw_caps->link_speed_msk & rate)) {
1171*4882a593Smuzhiyun 			err = -1;
1172*4882a593Smuzhiyun 			goto err_exit;
1173*4882a593Smuzhiyun 		}
1174*4882a593Smuzhiyun 
1175*4882a593Smuzhiyun 		self->aq_nic_cfg.is_autoneg = false;
1176*4882a593Smuzhiyun 	}
1177*4882a593Smuzhiyun 
1178*4882a593Smuzhiyun 	mutex_lock(&self->fwreq_mutex);
1179*4882a593Smuzhiyun 	err = self->aq_fw_ops->set_link_speed(self->aq_hw, rate);
1180*4882a593Smuzhiyun 	mutex_unlock(&self->fwreq_mutex);
1181*4882a593Smuzhiyun 	if (err < 0)
1182*4882a593Smuzhiyun 		goto err_exit;
1183*4882a593Smuzhiyun 
1184*4882a593Smuzhiyun 	self->aq_nic_cfg.link_speed_msk = rate;
1185*4882a593Smuzhiyun 
1186*4882a593Smuzhiyun err_exit:
1187*4882a593Smuzhiyun 	return err;
1188*4882a593Smuzhiyun }
1189*4882a593Smuzhiyun 
aq_nic_get_cfg(struct aq_nic_s * self)1190*4882a593Smuzhiyun struct aq_nic_cfg_s *aq_nic_get_cfg(struct aq_nic_s *self)
1191*4882a593Smuzhiyun {
1192*4882a593Smuzhiyun 	return &self->aq_nic_cfg;
1193*4882a593Smuzhiyun }
1194*4882a593Smuzhiyun 
aq_nic_get_fw_version(struct aq_nic_s * self)1195*4882a593Smuzhiyun u32 aq_nic_get_fw_version(struct aq_nic_s *self)
1196*4882a593Smuzhiyun {
1197*4882a593Smuzhiyun 	return self->aq_hw_ops->hw_get_fw_version(self->aq_hw);
1198*4882a593Smuzhiyun }
1199*4882a593Smuzhiyun 
aq_nic_set_loopback(struct aq_nic_s * self)1200*4882a593Smuzhiyun int aq_nic_set_loopback(struct aq_nic_s *self)
1201*4882a593Smuzhiyun {
1202*4882a593Smuzhiyun 	struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg;
1203*4882a593Smuzhiyun 
1204*4882a593Smuzhiyun 	if (!self->aq_hw_ops->hw_set_loopback ||
1205*4882a593Smuzhiyun 	    !self->aq_fw_ops->set_phyloopback)
1206*4882a593Smuzhiyun 		return -EOPNOTSUPP;
1207*4882a593Smuzhiyun 
1208*4882a593Smuzhiyun 	mutex_lock(&self->fwreq_mutex);
1209*4882a593Smuzhiyun 	self->aq_hw_ops->hw_set_loopback(self->aq_hw,
1210*4882a593Smuzhiyun 					 AQ_HW_LOOPBACK_DMA_SYS,
1211*4882a593Smuzhiyun 					 !!(cfg->priv_flags &
1212*4882a593Smuzhiyun 					    BIT(AQ_HW_LOOPBACK_DMA_SYS)));
1213*4882a593Smuzhiyun 
1214*4882a593Smuzhiyun 	self->aq_hw_ops->hw_set_loopback(self->aq_hw,
1215*4882a593Smuzhiyun 					 AQ_HW_LOOPBACK_PKT_SYS,
1216*4882a593Smuzhiyun 					 !!(cfg->priv_flags &
1217*4882a593Smuzhiyun 					    BIT(AQ_HW_LOOPBACK_PKT_SYS)));
1218*4882a593Smuzhiyun 
1219*4882a593Smuzhiyun 	self->aq_hw_ops->hw_set_loopback(self->aq_hw,
1220*4882a593Smuzhiyun 					 AQ_HW_LOOPBACK_DMA_NET,
1221*4882a593Smuzhiyun 					 !!(cfg->priv_flags &
1222*4882a593Smuzhiyun 					    BIT(AQ_HW_LOOPBACK_DMA_NET)));
1223*4882a593Smuzhiyun 
1224*4882a593Smuzhiyun 	self->aq_fw_ops->set_phyloopback(self->aq_hw,
1225*4882a593Smuzhiyun 					 AQ_HW_LOOPBACK_PHYINT_SYS,
1226*4882a593Smuzhiyun 					 !!(cfg->priv_flags &
1227*4882a593Smuzhiyun 					    BIT(AQ_HW_LOOPBACK_PHYINT_SYS)));
1228*4882a593Smuzhiyun 
1229*4882a593Smuzhiyun 	self->aq_fw_ops->set_phyloopback(self->aq_hw,
1230*4882a593Smuzhiyun 					 AQ_HW_LOOPBACK_PHYEXT_SYS,
1231*4882a593Smuzhiyun 					 !!(cfg->priv_flags &
1232*4882a593Smuzhiyun 					    BIT(AQ_HW_LOOPBACK_PHYEXT_SYS)));
1233*4882a593Smuzhiyun 	mutex_unlock(&self->fwreq_mutex);
1234*4882a593Smuzhiyun 
1235*4882a593Smuzhiyun 	return 0;
1236*4882a593Smuzhiyun }
1237*4882a593Smuzhiyun 
aq_nic_stop(struct aq_nic_s * self)1238*4882a593Smuzhiyun int aq_nic_stop(struct aq_nic_s *self)
1239*4882a593Smuzhiyun {
1240*4882a593Smuzhiyun 	unsigned int i = 0U;
1241*4882a593Smuzhiyun 
1242*4882a593Smuzhiyun 	netif_tx_disable(self->ndev);
1243*4882a593Smuzhiyun 	netif_carrier_off(self->ndev);
1244*4882a593Smuzhiyun 
1245*4882a593Smuzhiyun 	del_timer_sync(&self->service_timer);
1246*4882a593Smuzhiyun 	cancel_work_sync(&self->service_task);
1247*4882a593Smuzhiyun 
1248*4882a593Smuzhiyun 	self->aq_hw_ops->hw_irq_disable(self->aq_hw, AQ_CFG_IRQ_MASK);
1249*4882a593Smuzhiyun 
1250*4882a593Smuzhiyun 	if (self->aq_nic_cfg.is_polling)
1251*4882a593Smuzhiyun 		del_timer_sync(&self->polling_timer);
1252*4882a593Smuzhiyun 	else
1253*4882a593Smuzhiyun 		aq_pci_func_free_irqs(self);
1254*4882a593Smuzhiyun 
1255*4882a593Smuzhiyun 	aq_ptp_irq_free(self);
1256*4882a593Smuzhiyun 
1257*4882a593Smuzhiyun 	for (i = 0U; self->aq_vecs > i; ++i)
1258*4882a593Smuzhiyun 		aq_vec_stop(self->aq_vec[i]);
1259*4882a593Smuzhiyun 
1260*4882a593Smuzhiyun 	aq_ptp_ring_stop(self);
1261*4882a593Smuzhiyun 
1262*4882a593Smuzhiyun 	return self->aq_hw_ops->hw_stop(self->aq_hw);
1263*4882a593Smuzhiyun }
1264*4882a593Smuzhiyun 
aq_nic_set_power(struct aq_nic_s * self)1265*4882a593Smuzhiyun void aq_nic_set_power(struct aq_nic_s *self)
1266*4882a593Smuzhiyun {
1267*4882a593Smuzhiyun 	if (self->power_state != AQ_HW_POWER_STATE_D0 ||
1268*4882a593Smuzhiyun 	    self->aq_hw->aq_nic_cfg->wol)
1269*4882a593Smuzhiyun 		if (likely(self->aq_fw_ops->set_power)) {
1270*4882a593Smuzhiyun 			mutex_lock(&self->fwreq_mutex);
1271*4882a593Smuzhiyun 			self->aq_fw_ops->set_power(self->aq_hw,
1272*4882a593Smuzhiyun 						   self->power_state,
1273*4882a593Smuzhiyun 						   self->ndev->dev_addr);
1274*4882a593Smuzhiyun 			mutex_unlock(&self->fwreq_mutex);
1275*4882a593Smuzhiyun 		}
1276*4882a593Smuzhiyun }
1277*4882a593Smuzhiyun 
aq_nic_deinit(struct aq_nic_s * self,bool link_down)1278*4882a593Smuzhiyun void aq_nic_deinit(struct aq_nic_s *self, bool link_down)
1279*4882a593Smuzhiyun {
1280*4882a593Smuzhiyun 	struct aq_vec_s *aq_vec = NULL;
1281*4882a593Smuzhiyun 	unsigned int i = 0U;
1282*4882a593Smuzhiyun 
1283*4882a593Smuzhiyun 	if (!self)
1284*4882a593Smuzhiyun 		goto err_exit;
1285*4882a593Smuzhiyun 
1286*4882a593Smuzhiyun 	for (i = 0U; i < self->aq_vecs; i++) {
1287*4882a593Smuzhiyun 		aq_vec = self->aq_vec[i];
1288*4882a593Smuzhiyun 		aq_vec_deinit(aq_vec);
1289*4882a593Smuzhiyun 		aq_vec_ring_free(aq_vec);
1290*4882a593Smuzhiyun 	}
1291*4882a593Smuzhiyun 
1292*4882a593Smuzhiyun 	aq_ptp_unregister(self);
1293*4882a593Smuzhiyun 	aq_ptp_ring_deinit(self);
1294*4882a593Smuzhiyun 	aq_ptp_ring_free(self);
1295*4882a593Smuzhiyun 	aq_ptp_free(self);
1296*4882a593Smuzhiyun 
1297*4882a593Smuzhiyun 	if (likely(self->aq_fw_ops->deinit) && link_down) {
1298*4882a593Smuzhiyun 		mutex_lock(&self->fwreq_mutex);
1299*4882a593Smuzhiyun 		self->aq_fw_ops->deinit(self->aq_hw);
1300*4882a593Smuzhiyun 		mutex_unlock(&self->fwreq_mutex);
1301*4882a593Smuzhiyun 	}
1302*4882a593Smuzhiyun 
1303*4882a593Smuzhiyun err_exit:;
1304*4882a593Smuzhiyun }
1305*4882a593Smuzhiyun 
aq_nic_free_vectors(struct aq_nic_s * self)1306*4882a593Smuzhiyun void aq_nic_free_vectors(struct aq_nic_s *self)
1307*4882a593Smuzhiyun {
1308*4882a593Smuzhiyun 	unsigned int i = 0U;
1309*4882a593Smuzhiyun 
1310*4882a593Smuzhiyun 	if (!self)
1311*4882a593Smuzhiyun 		goto err_exit;
1312*4882a593Smuzhiyun 
1313*4882a593Smuzhiyun 	for (i = ARRAY_SIZE(self->aq_vec); i--;) {
1314*4882a593Smuzhiyun 		if (self->aq_vec[i]) {
1315*4882a593Smuzhiyun 			aq_vec_free(self->aq_vec[i]);
1316*4882a593Smuzhiyun 			self->aq_vec[i] = NULL;
1317*4882a593Smuzhiyun 		}
1318*4882a593Smuzhiyun 	}
1319*4882a593Smuzhiyun 
1320*4882a593Smuzhiyun err_exit:;
1321*4882a593Smuzhiyun }
1322*4882a593Smuzhiyun 
aq_nic_realloc_vectors(struct aq_nic_s * self)1323*4882a593Smuzhiyun int aq_nic_realloc_vectors(struct aq_nic_s *self)
1324*4882a593Smuzhiyun {
1325*4882a593Smuzhiyun 	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(self);
1326*4882a593Smuzhiyun 
1327*4882a593Smuzhiyun 	aq_nic_free_vectors(self);
1328*4882a593Smuzhiyun 
1329*4882a593Smuzhiyun 	for (self->aq_vecs = 0; self->aq_vecs < cfg->vecs; self->aq_vecs++) {
1330*4882a593Smuzhiyun 		self->aq_vec[self->aq_vecs] = aq_vec_alloc(self, self->aq_vecs,
1331*4882a593Smuzhiyun 							   cfg);
1332*4882a593Smuzhiyun 		if (unlikely(!self->aq_vec[self->aq_vecs]))
1333*4882a593Smuzhiyun 			return -ENOMEM;
1334*4882a593Smuzhiyun 	}
1335*4882a593Smuzhiyun 
1336*4882a593Smuzhiyun 	return 0;
1337*4882a593Smuzhiyun }
1338*4882a593Smuzhiyun 
aq_nic_shutdown(struct aq_nic_s * self)1339*4882a593Smuzhiyun void aq_nic_shutdown(struct aq_nic_s *self)
1340*4882a593Smuzhiyun {
1341*4882a593Smuzhiyun 	int err = 0;
1342*4882a593Smuzhiyun 
1343*4882a593Smuzhiyun 	if (!self->ndev)
1344*4882a593Smuzhiyun 		return;
1345*4882a593Smuzhiyun 
1346*4882a593Smuzhiyun 	rtnl_lock();
1347*4882a593Smuzhiyun 
1348*4882a593Smuzhiyun 	netif_device_detach(self->ndev);
1349*4882a593Smuzhiyun 
1350*4882a593Smuzhiyun 	if (netif_running(self->ndev)) {
1351*4882a593Smuzhiyun 		err = aq_nic_stop(self);
1352*4882a593Smuzhiyun 		if (err < 0)
1353*4882a593Smuzhiyun 			goto err_exit;
1354*4882a593Smuzhiyun 	}
1355*4882a593Smuzhiyun 	aq_nic_deinit(self, !self->aq_hw->aq_nic_cfg->wol);
1356*4882a593Smuzhiyun 	aq_nic_set_power(self);
1357*4882a593Smuzhiyun 
1358*4882a593Smuzhiyun err_exit:
1359*4882a593Smuzhiyun 	rtnl_unlock();
1360*4882a593Smuzhiyun }
1361*4882a593Smuzhiyun 
aq_nic_reserve_filter(struct aq_nic_s * self,enum aq_rx_filter_type type)1362*4882a593Smuzhiyun u8 aq_nic_reserve_filter(struct aq_nic_s *self, enum aq_rx_filter_type type)
1363*4882a593Smuzhiyun {
1364*4882a593Smuzhiyun 	u8 location = 0xFF;
1365*4882a593Smuzhiyun 	u32 fltr_cnt;
1366*4882a593Smuzhiyun 	u32 n_bit;
1367*4882a593Smuzhiyun 
1368*4882a593Smuzhiyun 	switch (type) {
1369*4882a593Smuzhiyun 	case aq_rx_filter_ethertype:
1370*4882a593Smuzhiyun 		location = AQ_RX_LAST_LOC_FETHERT - AQ_RX_FIRST_LOC_FETHERT -
1371*4882a593Smuzhiyun 			   self->aq_hw_rx_fltrs.fet_reserved_count;
1372*4882a593Smuzhiyun 		self->aq_hw_rx_fltrs.fet_reserved_count++;
1373*4882a593Smuzhiyun 		break;
1374*4882a593Smuzhiyun 	case aq_rx_filter_l3l4:
1375*4882a593Smuzhiyun 		fltr_cnt = AQ_RX_LAST_LOC_FL3L4 - AQ_RX_FIRST_LOC_FL3L4;
1376*4882a593Smuzhiyun 		n_bit = fltr_cnt - self->aq_hw_rx_fltrs.fl3l4.reserved_count;
1377*4882a593Smuzhiyun 
1378*4882a593Smuzhiyun 		self->aq_hw_rx_fltrs.fl3l4.active_ipv4 |= BIT(n_bit);
1379*4882a593Smuzhiyun 		self->aq_hw_rx_fltrs.fl3l4.reserved_count++;
1380*4882a593Smuzhiyun 		location = n_bit;
1381*4882a593Smuzhiyun 		break;
1382*4882a593Smuzhiyun 	default:
1383*4882a593Smuzhiyun 		break;
1384*4882a593Smuzhiyun 	}
1385*4882a593Smuzhiyun 
1386*4882a593Smuzhiyun 	return location;
1387*4882a593Smuzhiyun }
1388*4882a593Smuzhiyun 
aq_nic_release_filter(struct aq_nic_s * self,enum aq_rx_filter_type type,u32 location)1389*4882a593Smuzhiyun void aq_nic_release_filter(struct aq_nic_s *self, enum aq_rx_filter_type type,
1390*4882a593Smuzhiyun 			   u32 location)
1391*4882a593Smuzhiyun {
1392*4882a593Smuzhiyun 	switch (type) {
1393*4882a593Smuzhiyun 	case aq_rx_filter_ethertype:
1394*4882a593Smuzhiyun 		self->aq_hw_rx_fltrs.fet_reserved_count--;
1395*4882a593Smuzhiyun 		break;
1396*4882a593Smuzhiyun 	case aq_rx_filter_l3l4:
1397*4882a593Smuzhiyun 		self->aq_hw_rx_fltrs.fl3l4.reserved_count--;
1398*4882a593Smuzhiyun 		self->aq_hw_rx_fltrs.fl3l4.active_ipv4 &= ~BIT(location);
1399*4882a593Smuzhiyun 		break;
1400*4882a593Smuzhiyun 	default:
1401*4882a593Smuzhiyun 		break;
1402*4882a593Smuzhiyun 	}
1403*4882a593Smuzhiyun }
1404*4882a593Smuzhiyun 
aq_nic_set_downshift(struct aq_nic_s * self,int val)1405*4882a593Smuzhiyun int aq_nic_set_downshift(struct aq_nic_s *self, int val)
1406*4882a593Smuzhiyun {
1407*4882a593Smuzhiyun 	int err = 0;
1408*4882a593Smuzhiyun 	struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg;
1409*4882a593Smuzhiyun 
1410*4882a593Smuzhiyun 	if (!self->aq_fw_ops->set_downshift)
1411*4882a593Smuzhiyun 		return -EOPNOTSUPP;
1412*4882a593Smuzhiyun 
1413*4882a593Smuzhiyun 	if (val > 15) {
1414*4882a593Smuzhiyun 		netdev_err(self->ndev, "downshift counter should be <= 15\n");
1415*4882a593Smuzhiyun 		return -EINVAL;
1416*4882a593Smuzhiyun 	}
1417*4882a593Smuzhiyun 	cfg->downshift_counter = val;
1418*4882a593Smuzhiyun 
1419*4882a593Smuzhiyun 	mutex_lock(&self->fwreq_mutex);
1420*4882a593Smuzhiyun 	err = self->aq_fw_ops->set_downshift(self->aq_hw, cfg->downshift_counter);
1421*4882a593Smuzhiyun 	mutex_unlock(&self->fwreq_mutex);
1422*4882a593Smuzhiyun 
1423*4882a593Smuzhiyun 	return err;
1424*4882a593Smuzhiyun }
1425*4882a593Smuzhiyun 
aq_nic_set_media_detect(struct aq_nic_s * self,int val)1426*4882a593Smuzhiyun int aq_nic_set_media_detect(struct aq_nic_s *self, int val)
1427*4882a593Smuzhiyun {
1428*4882a593Smuzhiyun 	struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg;
1429*4882a593Smuzhiyun 	int err = 0;
1430*4882a593Smuzhiyun 
1431*4882a593Smuzhiyun 	if (!self->aq_fw_ops->set_media_detect)
1432*4882a593Smuzhiyun 		return -EOPNOTSUPP;
1433*4882a593Smuzhiyun 
1434*4882a593Smuzhiyun 	if (val > 0 && val != AQ_HW_MEDIA_DETECT_CNT) {
1435*4882a593Smuzhiyun 		netdev_err(self->ndev, "EDPD on this device could have only fixed value of %d\n",
1436*4882a593Smuzhiyun 			   AQ_HW_MEDIA_DETECT_CNT);
1437*4882a593Smuzhiyun 		return -EINVAL;
1438*4882a593Smuzhiyun 	}
1439*4882a593Smuzhiyun 
1440*4882a593Smuzhiyun 	mutex_lock(&self->fwreq_mutex);
1441*4882a593Smuzhiyun 	err = self->aq_fw_ops->set_media_detect(self->aq_hw, !!val);
1442*4882a593Smuzhiyun 	mutex_unlock(&self->fwreq_mutex);
1443*4882a593Smuzhiyun 
1444*4882a593Smuzhiyun 	/* msecs plays no role - configuration is always fixed in PHY */
1445*4882a593Smuzhiyun 	if (!err)
1446*4882a593Smuzhiyun 		cfg->is_media_detect = !!val;
1447*4882a593Smuzhiyun 
1448*4882a593Smuzhiyun 	return err;
1449*4882a593Smuzhiyun }
1450*4882a593Smuzhiyun 
aq_nic_setup_tc_mqprio(struct aq_nic_s * self,u32 tcs,u8 * prio_tc_map)1451*4882a593Smuzhiyun int aq_nic_setup_tc_mqprio(struct aq_nic_s *self, u32 tcs, u8 *prio_tc_map)
1452*4882a593Smuzhiyun {
1453*4882a593Smuzhiyun 	struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg;
1454*4882a593Smuzhiyun 	const unsigned int prev_vecs = cfg->vecs;
1455*4882a593Smuzhiyun 	bool ndev_running;
1456*4882a593Smuzhiyun 	int err = 0;
1457*4882a593Smuzhiyun 	int i;
1458*4882a593Smuzhiyun 
1459*4882a593Smuzhiyun 	/* if already the same configuration or
1460*4882a593Smuzhiyun 	 * disable request (tcs is 0) and we already is disabled
1461*4882a593Smuzhiyun 	 */
1462*4882a593Smuzhiyun 	if (tcs == cfg->tcs || (tcs == 0 && !cfg->is_qos))
1463*4882a593Smuzhiyun 		return 0;
1464*4882a593Smuzhiyun 
1465*4882a593Smuzhiyun 	ndev_running = netif_running(self->ndev);
1466*4882a593Smuzhiyun 	if (ndev_running)
1467*4882a593Smuzhiyun 		dev_close(self->ndev);
1468*4882a593Smuzhiyun 
1469*4882a593Smuzhiyun 	cfg->tcs = tcs;
1470*4882a593Smuzhiyun 	if (cfg->tcs == 0)
1471*4882a593Smuzhiyun 		cfg->tcs = 1;
1472*4882a593Smuzhiyun 	if (prio_tc_map)
1473*4882a593Smuzhiyun 		memcpy(cfg->prio_tc_map, prio_tc_map, sizeof(cfg->prio_tc_map));
1474*4882a593Smuzhiyun 	else
1475*4882a593Smuzhiyun 		for (i = 0; i < sizeof(cfg->prio_tc_map); i++)
1476*4882a593Smuzhiyun 			cfg->prio_tc_map[i] = cfg->tcs * i / 8;
1477*4882a593Smuzhiyun 
1478*4882a593Smuzhiyun 	cfg->is_qos = (tcs != 0 ? true : false);
1479*4882a593Smuzhiyun 	cfg->is_ptp = (cfg->tcs <= AQ_HW_PTP_TC);
1480*4882a593Smuzhiyun 	if (!cfg->is_ptp)
1481*4882a593Smuzhiyun 		netdev_warn(self->ndev, "%s\n",
1482*4882a593Smuzhiyun 			    "PTP is auto disabled due to requested TC count.");
1483*4882a593Smuzhiyun 
1484*4882a593Smuzhiyun 	netdev_set_num_tc(self->ndev, cfg->tcs);
1485*4882a593Smuzhiyun 
1486*4882a593Smuzhiyun 	/* Changing the number of TCs might change the number of vectors */
1487*4882a593Smuzhiyun 	aq_nic_cfg_update_num_vecs(self);
1488*4882a593Smuzhiyun 	if (prev_vecs != cfg->vecs) {
1489*4882a593Smuzhiyun 		err = aq_nic_realloc_vectors(self);
1490*4882a593Smuzhiyun 		if (err)
1491*4882a593Smuzhiyun 			goto err_exit;
1492*4882a593Smuzhiyun 	}
1493*4882a593Smuzhiyun 
1494*4882a593Smuzhiyun 	if (ndev_running)
1495*4882a593Smuzhiyun 		err = dev_open(self->ndev, NULL);
1496*4882a593Smuzhiyun 
1497*4882a593Smuzhiyun err_exit:
1498*4882a593Smuzhiyun 	return err;
1499*4882a593Smuzhiyun }
1500*4882a593Smuzhiyun 
aq_nic_setup_tc_max_rate(struct aq_nic_s * self,const unsigned int tc,const u32 max_rate)1501*4882a593Smuzhiyun int aq_nic_setup_tc_max_rate(struct aq_nic_s *self, const unsigned int tc,
1502*4882a593Smuzhiyun 			     const u32 max_rate)
1503*4882a593Smuzhiyun {
1504*4882a593Smuzhiyun 	struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg;
1505*4882a593Smuzhiyun 
1506*4882a593Smuzhiyun 	if (tc >= AQ_CFG_TCS_MAX)
1507*4882a593Smuzhiyun 		return -EINVAL;
1508*4882a593Smuzhiyun 
1509*4882a593Smuzhiyun 	if (max_rate && max_rate < 10) {
1510*4882a593Smuzhiyun 		netdev_warn(self->ndev,
1511*4882a593Smuzhiyun 			"Setting %s to the minimum usable value of %dMbps.\n",
1512*4882a593Smuzhiyun 			"max rate", 10);
1513*4882a593Smuzhiyun 		cfg->tc_max_rate[tc] = 10;
1514*4882a593Smuzhiyun 	} else {
1515*4882a593Smuzhiyun 		cfg->tc_max_rate[tc] = max_rate;
1516*4882a593Smuzhiyun 	}
1517*4882a593Smuzhiyun 
1518*4882a593Smuzhiyun 	return 0;
1519*4882a593Smuzhiyun }
1520*4882a593Smuzhiyun 
aq_nic_setup_tc_min_rate(struct aq_nic_s * self,const unsigned int tc,const u32 min_rate)1521*4882a593Smuzhiyun int aq_nic_setup_tc_min_rate(struct aq_nic_s *self, const unsigned int tc,
1522*4882a593Smuzhiyun 			     const u32 min_rate)
1523*4882a593Smuzhiyun {
1524*4882a593Smuzhiyun 	struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg;
1525*4882a593Smuzhiyun 
1526*4882a593Smuzhiyun 	if (tc >= AQ_CFG_TCS_MAX)
1527*4882a593Smuzhiyun 		return -EINVAL;
1528*4882a593Smuzhiyun 
1529*4882a593Smuzhiyun 	if (min_rate)
1530*4882a593Smuzhiyun 		set_bit(tc, &cfg->tc_min_rate_msk);
1531*4882a593Smuzhiyun 	else
1532*4882a593Smuzhiyun 		clear_bit(tc, &cfg->tc_min_rate_msk);
1533*4882a593Smuzhiyun 
1534*4882a593Smuzhiyun 	if (min_rate && min_rate < 20) {
1535*4882a593Smuzhiyun 		netdev_warn(self->ndev,
1536*4882a593Smuzhiyun 			"Setting %s to the minimum usable value of %dMbps.\n",
1537*4882a593Smuzhiyun 			"min rate", 20);
1538*4882a593Smuzhiyun 		cfg->tc_min_rate[tc] = 20;
1539*4882a593Smuzhiyun 	} else {
1540*4882a593Smuzhiyun 		cfg->tc_min_rate[tc] = min_rate;
1541*4882a593Smuzhiyun 	}
1542*4882a593Smuzhiyun 
1543*4882a593Smuzhiyun 	return 0;
1544*4882a593Smuzhiyun }
1545