xref: /OK3568_Linux_fs/kernel/drivers/net/ethernet/freescale/enetc/enetc_pf.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2*4882a593Smuzhiyun /* Copyright 2017-2019 NXP */
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun #include <linux/mdio.h>
5*4882a593Smuzhiyun #include <linux/module.h>
6*4882a593Smuzhiyun #include <linux/fsl/enetc_mdio.h>
7*4882a593Smuzhiyun #include <linux/of_mdio.h>
8*4882a593Smuzhiyun #include <linux/of_net.h>
9*4882a593Smuzhiyun #include "enetc_pf.h"
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #define ENETC_DRV_NAME_STR "ENETC PF driver"
12*4882a593Smuzhiyun 
enetc_pf_get_primary_mac_addr(struct enetc_hw * hw,int si,u8 * addr)13*4882a593Smuzhiyun static void enetc_pf_get_primary_mac_addr(struct enetc_hw *hw, int si, u8 *addr)
14*4882a593Smuzhiyun {
15*4882a593Smuzhiyun 	u32 upper = __raw_readl(hw->port + ENETC_PSIPMAR0(si));
16*4882a593Smuzhiyun 	u16 lower = __raw_readw(hw->port + ENETC_PSIPMAR1(si));
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun 	*(u32 *)addr = upper;
19*4882a593Smuzhiyun 	*(u16 *)(addr + 4) = lower;
20*4882a593Smuzhiyun }
21*4882a593Smuzhiyun 
enetc_pf_set_primary_mac_addr(struct enetc_hw * hw,int si,const u8 * addr)22*4882a593Smuzhiyun static void enetc_pf_set_primary_mac_addr(struct enetc_hw *hw, int si,
23*4882a593Smuzhiyun 					  const u8 *addr)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun 	u32 upper = *(const u32 *)addr;
26*4882a593Smuzhiyun 	u16 lower = *(const u16 *)(addr + 4);
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun 	__raw_writel(upper, hw->port + ENETC_PSIPMAR0(si));
29*4882a593Smuzhiyun 	__raw_writew(lower, hw->port + ENETC_PSIPMAR1(si));
30*4882a593Smuzhiyun }
31*4882a593Smuzhiyun 
enetc_pf_set_mac_addr(struct net_device * ndev,void * addr)32*4882a593Smuzhiyun static int enetc_pf_set_mac_addr(struct net_device *ndev, void *addr)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
35*4882a593Smuzhiyun 	struct sockaddr *saddr = addr;
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun 	if (!is_valid_ether_addr(saddr->sa_data))
38*4882a593Smuzhiyun 		return -EADDRNOTAVAIL;
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun 	memcpy(ndev->dev_addr, saddr->sa_data, ndev->addr_len);
41*4882a593Smuzhiyun 	enetc_pf_set_primary_mac_addr(&priv->si->hw, 0, saddr->sa_data);
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun 	return 0;
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun 
enetc_set_vlan_promisc(struct enetc_hw * hw,char si_map)46*4882a593Smuzhiyun static void enetc_set_vlan_promisc(struct enetc_hw *hw, char si_map)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun 	u32 val = enetc_port_rd(hw, ENETC_PSIPVMR);
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	val &= ~ENETC_PSIPVMR_SET_VP(ENETC_VLAN_PROMISC_MAP_ALL);
51*4882a593Smuzhiyun 	enetc_port_wr(hw, ENETC_PSIPVMR, ENETC_PSIPVMR_SET_VP(si_map) | val);
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun 
enetc_enable_si_vlan_promisc(struct enetc_pf * pf,int si_idx)54*4882a593Smuzhiyun static void enetc_enable_si_vlan_promisc(struct enetc_pf *pf, int si_idx)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun 	pf->vlan_promisc_simap |= BIT(si_idx);
57*4882a593Smuzhiyun 	enetc_set_vlan_promisc(&pf->si->hw, pf->vlan_promisc_simap);
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun 
enetc_disable_si_vlan_promisc(struct enetc_pf * pf,int si_idx)60*4882a593Smuzhiyun static void enetc_disable_si_vlan_promisc(struct enetc_pf *pf, int si_idx)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun 	pf->vlan_promisc_simap &= ~BIT(si_idx);
63*4882a593Smuzhiyun 	enetc_set_vlan_promisc(&pf->si->hw, pf->vlan_promisc_simap);
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun 
enetc_set_isol_vlan(struct enetc_hw * hw,int si,u16 vlan,u8 qos)66*4882a593Smuzhiyun static void enetc_set_isol_vlan(struct enetc_hw *hw, int si, u16 vlan, u8 qos)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun 	u32 val = 0;
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	if (vlan)
71*4882a593Smuzhiyun 		val = ENETC_PSIVLAN_EN | ENETC_PSIVLAN_SET_QOS(qos) | vlan;
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	enetc_port_wr(hw, ENETC_PSIVLANR(si), val);
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun 
enetc_mac_addr_hash_idx(const u8 * addr)76*4882a593Smuzhiyun static int enetc_mac_addr_hash_idx(const u8 *addr)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun 	u64 fold = __swab64(ether_addr_to_u64(addr)) >> 16;
79*4882a593Smuzhiyun 	u64 mask = 0;
80*4882a593Smuzhiyun 	int res = 0;
81*4882a593Smuzhiyun 	int i;
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	for (i = 0; i < 8; i++)
84*4882a593Smuzhiyun 		mask |= BIT_ULL(i * 6);
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	for (i = 0; i < 6; i++)
87*4882a593Smuzhiyun 		res |= (hweight64(fold & (mask << i)) & 0x1) << i;
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	return res;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun 
enetc_reset_mac_addr_filter(struct enetc_mac_filter * filter)92*4882a593Smuzhiyun static void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun 	filter->mac_addr_cnt = 0;
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 	bitmap_zero(filter->mac_hash_table,
97*4882a593Smuzhiyun 		    ENETC_MADDR_HASH_TBL_SZ);
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun 
enetc_add_mac_addr_em_filter(struct enetc_mac_filter * filter,const unsigned char * addr)100*4882a593Smuzhiyun static void enetc_add_mac_addr_em_filter(struct enetc_mac_filter *filter,
101*4882a593Smuzhiyun 					 const unsigned char *addr)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun 	/* add exact match addr */
104*4882a593Smuzhiyun 	ether_addr_copy(filter->mac_addr, addr);
105*4882a593Smuzhiyun 	filter->mac_addr_cnt++;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun 
enetc_add_mac_addr_ht_filter(struct enetc_mac_filter * filter,const unsigned char * addr)108*4882a593Smuzhiyun static void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
109*4882a593Smuzhiyun 					 const unsigned char *addr)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun 	int idx = enetc_mac_addr_hash_idx(addr);
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	/* add hash table entry */
114*4882a593Smuzhiyun 	__set_bit(idx, filter->mac_hash_table);
115*4882a593Smuzhiyun 	filter->mac_addr_cnt++;
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun 
enetc_clear_mac_ht_flt(struct enetc_si * si,int si_idx,int type)118*4882a593Smuzhiyun static void enetc_clear_mac_ht_flt(struct enetc_si *si, int si_idx, int type)
119*4882a593Smuzhiyun {
120*4882a593Smuzhiyun 	bool err = si->errata & ENETC_ERR_UCMCSWP;
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 	if (type == UC) {
123*4882a593Smuzhiyun 		enetc_port_wr(&si->hw, ENETC_PSIUMHFR0(si_idx, err), 0);
124*4882a593Smuzhiyun 		enetc_port_wr(&si->hw, ENETC_PSIUMHFR1(si_idx), 0);
125*4882a593Smuzhiyun 	} else { /* MC */
126*4882a593Smuzhiyun 		enetc_port_wr(&si->hw, ENETC_PSIMMHFR0(si_idx, err), 0);
127*4882a593Smuzhiyun 		enetc_port_wr(&si->hw, ENETC_PSIMMHFR1(si_idx), 0);
128*4882a593Smuzhiyun 	}
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun 
enetc_set_mac_ht_flt(struct enetc_si * si,int si_idx,int type,u32 * hash)131*4882a593Smuzhiyun static void enetc_set_mac_ht_flt(struct enetc_si *si, int si_idx, int type,
132*4882a593Smuzhiyun 				 u32 *hash)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun 	bool err = si->errata & ENETC_ERR_UCMCSWP;
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	if (type == UC) {
137*4882a593Smuzhiyun 		enetc_port_wr(&si->hw, ENETC_PSIUMHFR0(si_idx, err), *hash);
138*4882a593Smuzhiyun 		enetc_port_wr(&si->hw, ENETC_PSIUMHFR1(si_idx), *(hash + 1));
139*4882a593Smuzhiyun 	} else { /* MC */
140*4882a593Smuzhiyun 		enetc_port_wr(&si->hw, ENETC_PSIMMHFR0(si_idx, err), *hash);
141*4882a593Smuzhiyun 		enetc_port_wr(&si->hw, ENETC_PSIMMHFR1(si_idx), *(hash + 1));
142*4882a593Smuzhiyun 	}
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun 
enetc_sync_mac_filters(struct enetc_pf * pf)145*4882a593Smuzhiyun static void enetc_sync_mac_filters(struct enetc_pf *pf)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun 	struct enetc_mac_filter *f = pf->mac_filter;
148*4882a593Smuzhiyun 	struct enetc_si *si = pf->si;
149*4882a593Smuzhiyun 	int i, pos;
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	pos = EMETC_MAC_ADDR_FILT_RES;
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	for (i = 0; i < MADDR_TYPE; i++, f++) {
154*4882a593Smuzhiyun 		bool em = (f->mac_addr_cnt == 1) && (i == UC);
155*4882a593Smuzhiyun 		bool clear = !f->mac_addr_cnt;
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 		if (clear) {
158*4882a593Smuzhiyun 			if (i == UC)
159*4882a593Smuzhiyun 				enetc_clear_mac_flt_entry(si, pos);
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 			enetc_clear_mac_ht_flt(si, 0, i);
162*4882a593Smuzhiyun 			continue;
163*4882a593Smuzhiyun 		}
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 		/* exact match filter */
166*4882a593Smuzhiyun 		if (em) {
167*4882a593Smuzhiyun 			int err;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 			enetc_clear_mac_ht_flt(si, 0, UC);
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 			err = enetc_set_mac_flt_entry(si, pos, f->mac_addr,
172*4882a593Smuzhiyun 						      BIT(0));
173*4882a593Smuzhiyun 			if (!err)
174*4882a593Smuzhiyun 				continue;
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 			/* fallback to HT filtering */
177*4882a593Smuzhiyun 			dev_warn(&si->pdev->dev, "fallback to HT filt (%d)\n",
178*4882a593Smuzhiyun 				 err);
179*4882a593Smuzhiyun 		}
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 		/* hash table filter, clear EM filter for UC entries */
182*4882a593Smuzhiyun 		if (i == UC)
183*4882a593Smuzhiyun 			enetc_clear_mac_flt_entry(si, pos);
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 		enetc_set_mac_ht_flt(si, 0, i, (u32 *)f->mac_hash_table);
186*4882a593Smuzhiyun 	}
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun 
enetc_pf_set_rx_mode(struct net_device * ndev)189*4882a593Smuzhiyun static void enetc_pf_set_rx_mode(struct net_device *ndev)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
192*4882a593Smuzhiyun 	struct enetc_pf *pf = enetc_si_priv(priv->si);
193*4882a593Smuzhiyun 	struct enetc_hw *hw = &priv->si->hw;
194*4882a593Smuzhiyun 	bool uprom = false, mprom = false;
195*4882a593Smuzhiyun 	struct enetc_mac_filter *filter;
196*4882a593Smuzhiyun 	struct netdev_hw_addr *ha;
197*4882a593Smuzhiyun 	u32 psipmr = 0;
198*4882a593Smuzhiyun 	bool em;
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	if (ndev->flags & IFF_PROMISC) {
201*4882a593Smuzhiyun 		/* enable promisc mode for SI0 (PF) */
202*4882a593Smuzhiyun 		psipmr = ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0);
203*4882a593Smuzhiyun 		uprom = true;
204*4882a593Smuzhiyun 		mprom = true;
205*4882a593Smuzhiyun 	} else if (ndev->flags & IFF_ALLMULTI) {
206*4882a593Smuzhiyun 		/* enable multi cast promisc mode for SI0 (PF) */
207*4882a593Smuzhiyun 		psipmr = ENETC_PSIPMR_SET_MP(0);
208*4882a593Smuzhiyun 		mprom = true;
209*4882a593Smuzhiyun 	}
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	/* first 2 filter entries belong to PF */
212*4882a593Smuzhiyun 	if (!uprom) {
213*4882a593Smuzhiyun 		/* Update unicast filters */
214*4882a593Smuzhiyun 		filter = &pf->mac_filter[UC];
215*4882a593Smuzhiyun 		enetc_reset_mac_addr_filter(filter);
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 		em = (netdev_uc_count(ndev) == 1);
218*4882a593Smuzhiyun 		netdev_for_each_uc_addr(ha, ndev) {
219*4882a593Smuzhiyun 			if (em) {
220*4882a593Smuzhiyun 				enetc_add_mac_addr_em_filter(filter, ha->addr);
221*4882a593Smuzhiyun 				break;
222*4882a593Smuzhiyun 			}
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 			enetc_add_mac_addr_ht_filter(filter, ha->addr);
225*4882a593Smuzhiyun 		}
226*4882a593Smuzhiyun 	}
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 	if (!mprom) {
229*4882a593Smuzhiyun 		/* Update multicast filters */
230*4882a593Smuzhiyun 		filter = &pf->mac_filter[MC];
231*4882a593Smuzhiyun 		enetc_reset_mac_addr_filter(filter);
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 		netdev_for_each_mc_addr(ha, ndev) {
234*4882a593Smuzhiyun 			if (!is_multicast_ether_addr(ha->addr))
235*4882a593Smuzhiyun 				continue;
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 			enetc_add_mac_addr_ht_filter(filter, ha->addr);
238*4882a593Smuzhiyun 		}
239*4882a593Smuzhiyun 	}
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	if (!uprom || !mprom)
242*4882a593Smuzhiyun 		/* update PF entries */
243*4882a593Smuzhiyun 		enetc_sync_mac_filters(pf);
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	psipmr |= enetc_port_rd(hw, ENETC_PSIPMR) &
246*4882a593Smuzhiyun 		  ~(ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0));
247*4882a593Smuzhiyun 	enetc_port_wr(hw, ENETC_PSIPMR, psipmr);
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun 
enetc_set_vlan_ht_filter(struct enetc_hw * hw,int si_idx,u32 * hash)250*4882a593Smuzhiyun static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx,
251*4882a593Smuzhiyun 				     u32 *hash)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun 	enetc_port_wr(hw, ENETC_PSIVHFR0(si_idx), *hash);
254*4882a593Smuzhiyun 	enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), *(hash + 1));
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun 
enetc_vid_hash_idx(unsigned int vid)257*4882a593Smuzhiyun static int enetc_vid_hash_idx(unsigned int vid)
258*4882a593Smuzhiyun {
259*4882a593Smuzhiyun 	int res = 0;
260*4882a593Smuzhiyun 	int i;
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	for (i = 0; i < 6; i++)
263*4882a593Smuzhiyun 		res |= (hweight8(vid & (BIT(i) | BIT(i + 6))) & 0x1) << i;
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	return res;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun 
enetc_sync_vlan_ht_filter(struct enetc_pf * pf,bool rehash)268*4882a593Smuzhiyun static void enetc_sync_vlan_ht_filter(struct enetc_pf *pf, bool rehash)
269*4882a593Smuzhiyun {
270*4882a593Smuzhiyun 	int i;
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	if (rehash) {
273*4882a593Smuzhiyun 		bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun 		for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) {
276*4882a593Smuzhiyun 			int hidx = enetc_vid_hash_idx(i);
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 			__set_bit(hidx, pf->vlan_ht_filter);
279*4882a593Smuzhiyun 		}
280*4882a593Smuzhiyun 	}
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 	enetc_set_vlan_ht_filter(&pf->si->hw, 0, (u32 *)pf->vlan_ht_filter);
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun 
enetc_vlan_rx_add_vid(struct net_device * ndev,__be16 prot,u16 vid)285*4882a593Smuzhiyun static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
286*4882a593Smuzhiyun {
287*4882a593Smuzhiyun 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
288*4882a593Smuzhiyun 	struct enetc_pf *pf = enetc_si_priv(priv->si);
289*4882a593Smuzhiyun 	int idx;
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	__set_bit(vid, pf->active_vlans);
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	idx = enetc_vid_hash_idx(vid);
294*4882a593Smuzhiyun 	if (!__test_and_set_bit(idx, pf->vlan_ht_filter))
295*4882a593Smuzhiyun 		enetc_sync_vlan_ht_filter(pf, false);
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 	return 0;
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun 
enetc_vlan_rx_del_vid(struct net_device * ndev,__be16 prot,u16 vid)300*4882a593Smuzhiyun static int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid)
301*4882a593Smuzhiyun {
302*4882a593Smuzhiyun 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
303*4882a593Smuzhiyun 	struct enetc_pf *pf = enetc_si_priv(priv->si);
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	__clear_bit(vid, pf->active_vlans);
306*4882a593Smuzhiyun 	enetc_sync_vlan_ht_filter(pf, true);
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	return 0;
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun 
enetc_set_loopback(struct net_device * ndev,bool en)311*4882a593Smuzhiyun static void enetc_set_loopback(struct net_device *ndev, bool en)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
314*4882a593Smuzhiyun 	struct enetc_hw *hw = &priv->si->hw;
315*4882a593Smuzhiyun 	u32 reg;
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun 	reg = enetc_port_rd(hw, ENETC_PM0_IF_MODE);
318*4882a593Smuzhiyun 	if (reg & ENETC_PM0_IFM_RG) {
319*4882a593Smuzhiyun 		/* RGMII mode */
320*4882a593Smuzhiyun 		reg = (reg & ~ENETC_PM0_IFM_RLP) |
321*4882a593Smuzhiyun 		      (en ? ENETC_PM0_IFM_RLP : 0);
322*4882a593Smuzhiyun 		enetc_port_wr(hw, ENETC_PM0_IF_MODE, reg);
323*4882a593Smuzhiyun 	} else {
324*4882a593Smuzhiyun 		/* assume SGMII mode */
325*4882a593Smuzhiyun 		reg = enetc_port_rd(hw, ENETC_PM0_CMD_CFG);
326*4882a593Smuzhiyun 		reg = (reg & ~ENETC_PM0_CMD_XGLP) |
327*4882a593Smuzhiyun 		      (en ? ENETC_PM0_CMD_XGLP : 0);
328*4882a593Smuzhiyun 		reg = (reg & ~ENETC_PM0_CMD_PHY_TX_EN) |
329*4882a593Smuzhiyun 		      (en ? ENETC_PM0_CMD_PHY_TX_EN : 0);
330*4882a593Smuzhiyun 		enetc_port_wr(hw, ENETC_PM0_CMD_CFG, reg);
331*4882a593Smuzhiyun 		enetc_port_wr(hw, ENETC_PM1_CMD_CFG, reg);
332*4882a593Smuzhiyun 	}
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun 
enetc_pf_set_vf_mac(struct net_device * ndev,int vf,u8 * mac)335*4882a593Smuzhiyun static int enetc_pf_set_vf_mac(struct net_device *ndev, int vf, u8 *mac)
336*4882a593Smuzhiyun {
337*4882a593Smuzhiyun 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
338*4882a593Smuzhiyun 	struct enetc_pf *pf = enetc_si_priv(priv->si);
339*4882a593Smuzhiyun 	struct enetc_vf_state *vf_state;
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	if (vf >= pf->total_vfs)
342*4882a593Smuzhiyun 		return -EINVAL;
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 	if (!is_valid_ether_addr(mac))
345*4882a593Smuzhiyun 		return -EADDRNOTAVAIL;
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	vf_state = &pf->vf_state[vf];
348*4882a593Smuzhiyun 	vf_state->flags |= ENETC_VF_FLAG_PF_SET_MAC;
349*4882a593Smuzhiyun 	enetc_pf_set_primary_mac_addr(&priv->si->hw, vf + 1, mac);
350*4882a593Smuzhiyun 	return 0;
351*4882a593Smuzhiyun }
352*4882a593Smuzhiyun 
enetc_pf_set_vf_vlan(struct net_device * ndev,int vf,u16 vlan,u8 qos,__be16 proto)353*4882a593Smuzhiyun static int enetc_pf_set_vf_vlan(struct net_device *ndev, int vf, u16 vlan,
354*4882a593Smuzhiyun 				u8 qos, __be16 proto)
355*4882a593Smuzhiyun {
356*4882a593Smuzhiyun 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
357*4882a593Smuzhiyun 	struct enetc_pf *pf = enetc_si_priv(priv->si);
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 	if (priv->si->errata & ENETC_ERR_VLAN_ISOL)
360*4882a593Smuzhiyun 		return -EOPNOTSUPP;
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun 	if (vf >= pf->total_vfs)
363*4882a593Smuzhiyun 		return -EINVAL;
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 	if (proto != htons(ETH_P_8021Q))
366*4882a593Smuzhiyun 		/* only C-tags supported for now */
367*4882a593Smuzhiyun 		return -EPROTONOSUPPORT;
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 	enetc_set_isol_vlan(&priv->si->hw, vf + 1, vlan, qos);
370*4882a593Smuzhiyun 	return 0;
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun 
enetc_pf_set_vf_spoofchk(struct net_device * ndev,int vf,bool en)373*4882a593Smuzhiyun static int enetc_pf_set_vf_spoofchk(struct net_device *ndev, int vf, bool en)
374*4882a593Smuzhiyun {
375*4882a593Smuzhiyun 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
376*4882a593Smuzhiyun 	struct enetc_pf *pf = enetc_si_priv(priv->si);
377*4882a593Smuzhiyun 	u32 cfgr;
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun 	if (vf >= pf->total_vfs)
380*4882a593Smuzhiyun 		return -EINVAL;
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 	cfgr = enetc_port_rd(&priv->si->hw, ENETC_PSICFGR0(vf + 1));
383*4882a593Smuzhiyun 	cfgr = (cfgr & ~ENETC_PSICFGR0_ASE) | (en ? ENETC_PSICFGR0_ASE : 0);
384*4882a593Smuzhiyun 	enetc_port_wr(&priv->si->hw, ENETC_PSICFGR0(vf + 1), cfgr);
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 	return 0;
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun 
enetc_port_setup_primary_mac_address(struct enetc_si * si)389*4882a593Smuzhiyun static void enetc_port_setup_primary_mac_address(struct enetc_si *si)
390*4882a593Smuzhiyun {
391*4882a593Smuzhiyun 	unsigned char mac_addr[MAX_ADDR_LEN];
392*4882a593Smuzhiyun 	struct enetc_pf *pf = enetc_si_priv(si);
393*4882a593Smuzhiyun 	struct enetc_hw *hw = &si->hw;
394*4882a593Smuzhiyun 	int i;
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	/* check MAC addresses for PF and all VFs, if any is 0 set it ro rand */
397*4882a593Smuzhiyun 	for (i = 0; i < pf->total_vfs + 1; i++) {
398*4882a593Smuzhiyun 		enetc_pf_get_primary_mac_addr(hw, i, mac_addr);
399*4882a593Smuzhiyun 		if (!is_zero_ether_addr(mac_addr))
400*4882a593Smuzhiyun 			continue;
401*4882a593Smuzhiyun 		eth_random_addr(mac_addr);
402*4882a593Smuzhiyun 		dev_info(&si->pdev->dev, "no MAC address specified for SI%d, using %pM\n",
403*4882a593Smuzhiyun 			 i, mac_addr);
404*4882a593Smuzhiyun 		enetc_pf_set_primary_mac_addr(hw, i, mac_addr);
405*4882a593Smuzhiyun 	}
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun 
enetc_port_assign_rfs_entries(struct enetc_si * si)408*4882a593Smuzhiyun static void enetc_port_assign_rfs_entries(struct enetc_si *si)
409*4882a593Smuzhiyun {
410*4882a593Smuzhiyun 	struct enetc_pf *pf = enetc_si_priv(si);
411*4882a593Smuzhiyun 	struct enetc_hw *hw = &si->hw;
412*4882a593Smuzhiyun 	int num_entries, vf_entries, i;
413*4882a593Smuzhiyun 	u32 val;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 	/* split RFS entries between functions */
416*4882a593Smuzhiyun 	val = enetc_port_rd(hw, ENETC_PRFSCAPR);
417*4882a593Smuzhiyun 	num_entries = ENETC_PRFSCAPR_GET_NUM_RFS(val);
418*4882a593Smuzhiyun 	vf_entries = num_entries / (pf->total_vfs + 1);
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun 	for (i = 0; i < pf->total_vfs; i++)
421*4882a593Smuzhiyun 		enetc_port_wr(hw, ENETC_PSIRFSCFGR(i + 1), vf_entries);
422*4882a593Smuzhiyun 	enetc_port_wr(hw, ENETC_PSIRFSCFGR(0),
423*4882a593Smuzhiyun 		      num_entries - vf_entries * pf->total_vfs);
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	/* enable RFS on port */
426*4882a593Smuzhiyun 	enetc_port_wr(hw, ENETC_PRFSMR, ENETC_PRFSMR_RFSE);
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun 
enetc_port_si_configure(struct enetc_si * si)429*4882a593Smuzhiyun static void enetc_port_si_configure(struct enetc_si *si)
430*4882a593Smuzhiyun {
431*4882a593Smuzhiyun 	struct enetc_pf *pf = enetc_si_priv(si);
432*4882a593Smuzhiyun 	struct enetc_hw *hw = &si->hw;
433*4882a593Smuzhiyun 	int num_rings, i;
434*4882a593Smuzhiyun 	u32 val;
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun 	val = enetc_port_rd(hw, ENETC_PCAPR0);
437*4882a593Smuzhiyun 	num_rings = min(ENETC_PCAPR0_RXBDR(val), ENETC_PCAPR0_TXBDR(val));
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 	val = ENETC_PSICFGR0_SET_TXBDR(ENETC_PF_NUM_RINGS);
440*4882a593Smuzhiyun 	val |= ENETC_PSICFGR0_SET_RXBDR(ENETC_PF_NUM_RINGS);
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 	if (unlikely(num_rings < ENETC_PF_NUM_RINGS)) {
443*4882a593Smuzhiyun 		val = ENETC_PSICFGR0_SET_TXBDR(num_rings);
444*4882a593Smuzhiyun 		val |= ENETC_PSICFGR0_SET_RXBDR(num_rings);
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 		dev_warn(&si->pdev->dev, "Found %d rings, expected %d!\n",
447*4882a593Smuzhiyun 			 num_rings, ENETC_PF_NUM_RINGS);
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 		num_rings = 0;
450*4882a593Smuzhiyun 	}
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 	/* Add default one-time settings for SI0 (PF) */
453*4882a593Smuzhiyun 	val |= ENETC_PSICFGR0_SIVC(ENETC_VLAN_TYPE_C | ENETC_VLAN_TYPE_S);
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun 	enetc_port_wr(hw, ENETC_PSICFGR0(0), val);
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun 	if (num_rings)
458*4882a593Smuzhiyun 		num_rings -= ENETC_PF_NUM_RINGS;
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 	/* Configure the SIs for each available VF */
461*4882a593Smuzhiyun 	val = ENETC_PSICFGR0_SIVC(ENETC_VLAN_TYPE_C | ENETC_VLAN_TYPE_S);
462*4882a593Smuzhiyun 	val |= ENETC_PSICFGR0_VTE | ENETC_PSICFGR0_SIVIE;
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 	if (num_rings) {
465*4882a593Smuzhiyun 		num_rings /= pf->total_vfs;
466*4882a593Smuzhiyun 		val |= ENETC_PSICFGR0_SET_TXBDR(num_rings);
467*4882a593Smuzhiyun 		val |= ENETC_PSICFGR0_SET_RXBDR(num_rings);
468*4882a593Smuzhiyun 	}
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 	for (i = 0; i < pf->total_vfs; i++)
471*4882a593Smuzhiyun 		enetc_port_wr(hw, ENETC_PSICFGR0(i + 1), val);
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun 	/* Port level VLAN settings */
474*4882a593Smuzhiyun 	val = ENETC_PVCLCTR_OVTPIDL(ENETC_VLAN_TYPE_C | ENETC_VLAN_TYPE_S);
475*4882a593Smuzhiyun 	enetc_port_wr(hw, ENETC_PVCLCTR, val);
476*4882a593Smuzhiyun 	/* use outer tag for VLAN filtering */
477*4882a593Smuzhiyun 	enetc_port_wr(hw, ENETC_PSIVLANFMR, ENETC_PSIVLANFMR_VS);
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun 
enetc_configure_port_mac(struct enetc_hw * hw)480*4882a593Smuzhiyun static void enetc_configure_port_mac(struct enetc_hw *hw)
481*4882a593Smuzhiyun {
482*4882a593Smuzhiyun 	enetc_port_wr(hw, ENETC_PM0_MAXFRM,
483*4882a593Smuzhiyun 		      ENETC_SET_MAXFRM(ENETC_RX_MAXFRM_SIZE));
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 	enetc_port_wr(hw, ENETC_PTCMSDUR(0), ENETC_MAC_MAXFRM_SIZE);
486*4882a593Smuzhiyun 	enetc_port_wr(hw, ENETC_PTXMBAR, 2 * ENETC_MAC_MAXFRM_SIZE);
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 	enetc_port_wr(hw, ENETC_PM0_CMD_CFG, ENETC_PM0_CMD_PHY_TX_EN |
489*4882a593Smuzhiyun 		      ENETC_PM0_CMD_TXP	| ENETC_PM0_PROMISC);
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 	enetc_port_wr(hw, ENETC_PM1_CMD_CFG, ENETC_PM0_CMD_PHY_TX_EN |
492*4882a593Smuzhiyun 		      ENETC_PM0_CMD_TXP	| ENETC_PM0_PROMISC);
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	/* On LS1028A, the MAC RX FIFO defaults to 2, which is too high
495*4882a593Smuzhiyun 	 * and may lead to RX lock-up under traffic. Set it to 1 instead,
496*4882a593Smuzhiyun 	 * as recommended by the hardware team.
497*4882a593Smuzhiyun 	 */
498*4882a593Smuzhiyun 	enetc_port_wr(hw, ENETC_PM0_RX_FIFO, ENETC_PM0_RX_FIFO_VAL);
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun 
enetc_mac_config(struct enetc_hw * hw,phy_interface_t phy_mode)501*4882a593Smuzhiyun static void enetc_mac_config(struct enetc_hw *hw, phy_interface_t phy_mode)
502*4882a593Smuzhiyun {
503*4882a593Smuzhiyun 	u32 val;
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	if (phy_interface_mode_is_rgmii(phy_mode)) {
506*4882a593Smuzhiyun 		val = enetc_port_rd(hw, ENETC_PM0_IF_MODE);
507*4882a593Smuzhiyun 		val &= ~(ENETC_PM0_IFM_EN_AUTO | ENETC_PM0_IFM_IFMODE_MASK);
508*4882a593Smuzhiyun 		val |= ENETC_PM0_IFM_IFMODE_GMII | ENETC_PM0_IFM_RG;
509*4882a593Smuzhiyun 		enetc_port_wr(hw, ENETC_PM0_IF_MODE, val);
510*4882a593Smuzhiyun 	}
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun 	if (phy_mode == PHY_INTERFACE_MODE_USXGMII) {
513*4882a593Smuzhiyun 		val = ENETC_PM0_IFM_FULL_DPX | ENETC_PM0_IFM_IFMODE_XGMII;
514*4882a593Smuzhiyun 		enetc_port_wr(hw, ENETC_PM0_IF_MODE, val);
515*4882a593Smuzhiyun 	}
516*4882a593Smuzhiyun }
517*4882a593Smuzhiyun 
enetc_mac_enable(struct enetc_hw * hw,bool en)518*4882a593Smuzhiyun static void enetc_mac_enable(struct enetc_hw *hw, bool en)
519*4882a593Smuzhiyun {
520*4882a593Smuzhiyun 	u32 val = enetc_port_rd(hw, ENETC_PM0_CMD_CFG);
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun 	val &= ~(ENETC_PM0_TX_EN | ENETC_PM0_RX_EN);
523*4882a593Smuzhiyun 	val |= en ? (ENETC_PM0_TX_EN | ENETC_PM0_RX_EN) : 0;
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 	enetc_port_wr(hw, ENETC_PM0_CMD_CFG, val);
526*4882a593Smuzhiyun 	enetc_port_wr(hw, ENETC_PM1_CMD_CFG, val);
527*4882a593Smuzhiyun }
528*4882a593Smuzhiyun 
enetc_configure_port_pmac(struct enetc_hw * hw)529*4882a593Smuzhiyun static void enetc_configure_port_pmac(struct enetc_hw *hw)
530*4882a593Smuzhiyun {
531*4882a593Smuzhiyun 	u32 temp;
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun 	/* Set pMAC step lock */
534*4882a593Smuzhiyun 	temp = enetc_port_rd(hw, ENETC_PFPMR);
535*4882a593Smuzhiyun 	enetc_port_wr(hw, ENETC_PFPMR,
536*4882a593Smuzhiyun 		      temp | ENETC_PFPMR_PMACE | ENETC_PFPMR_MWLM);
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun 	temp = enetc_port_rd(hw, ENETC_MMCSR);
539*4882a593Smuzhiyun 	enetc_port_wr(hw, ENETC_MMCSR, temp | ENETC_MMCSR_ME);
540*4882a593Smuzhiyun }
541*4882a593Smuzhiyun 
enetc_configure_port(struct enetc_pf * pf)542*4882a593Smuzhiyun static void enetc_configure_port(struct enetc_pf *pf)
543*4882a593Smuzhiyun {
544*4882a593Smuzhiyun 	u8 hash_key[ENETC_RSSHASH_KEY_SIZE];
545*4882a593Smuzhiyun 	struct enetc_hw *hw = &pf->si->hw;
546*4882a593Smuzhiyun 
547*4882a593Smuzhiyun 	enetc_configure_port_pmac(hw);
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun 	enetc_configure_port_mac(hw);
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun 	enetc_port_si_configure(pf->si);
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 	/* set up hash key */
554*4882a593Smuzhiyun 	get_random_bytes(hash_key, ENETC_RSSHASH_KEY_SIZE);
555*4882a593Smuzhiyun 	enetc_set_rss_key(hw, hash_key);
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun 	/* split up RFS entries */
558*4882a593Smuzhiyun 	enetc_port_assign_rfs_entries(pf->si);
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun 	/* fix-up primary MAC addresses, if not set already */
561*4882a593Smuzhiyun 	enetc_port_setup_primary_mac_address(pf->si);
562*4882a593Smuzhiyun 
563*4882a593Smuzhiyun 	/* enforce VLAN promisc mode for all SIs */
564*4882a593Smuzhiyun 	pf->vlan_promisc_simap = ENETC_VLAN_PROMISC_MAP_ALL;
565*4882a593Smuzhiyun 	enetc_set_vlan_promisc(hw, pf->vlan_promisc_simap);
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 	enetc_port_wr(hw, ENETC_PSIPMR, 0);
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun 	/* enable port */
570*4882a593Smuzhiyun 	enetc_port_wr(hw, ENETC_PMR, ENETC_PMR_EN);
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun /* Messaging */
enetc_msg_pf_set_vf_primary_mac_addr(struct enetc_pf * pf,int vf_id)574*4882a593Smuzhiyun static u16 enetc_msg_pf_set_vf_primary_mac_addr(struct enetc_pf *pf,
575*4882a593Smuzhiyun 						int vf_id)
576*4882a593Smuzhiyun {
577*4882a593Smuzhiyun 	struct enetc_vf_state *vf_state = &pf->vf_state[vf_id];
578*4882a593Smuzhiyun 	struct enetc_msg_swbd *msg = &pf->rxmsg[vf_id];
579*4882a593Smuzhiyun 	struct enetc_msg_cmd_set_primary_mac *cmd;
580*4882a593Smuzhiyun 	struct device *dev = &pf->si->pdev->dev;
581*4882a593Smuzhiyun 	u16 cmd_id;
582*4882a593Smuzhiyun 	char *addr;
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun 	cmd = (struct enetc_msg_cmd_set_primary_mac *)msg->vaddr;
585*4882a593Smuzhiyun 	cmd_id = cmd->header.id;
586*4882a593Smuzhiyun 	if (cmd_id != ENETC_MSG_CMD_MNG_ADD)
587*4882a593Smuzhiyun 		return ENETC_MSG_CMD_STATUS_FAIL;
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun 	addr = cmd->mac.sa_data;
590*4882a593Smuzhiyun 	if (vf_state->flags & ENETC_VF_FLAG_PF_SET_MAC)
591*4882a593Smuzhiyun 		dev_warn(dev, "Attempt to override PF set mac addr for VF%d\n",
592*4882a593Smuzhiyun 			 vf_id);
593*4882a593Smuzhiyun 	else
594*4882a593Smuzhiyun 		enetc_pf_set_primary_mac_addr(&pf->si->hw, vf_id + 1, addr);
595*4882a593Smuzhiyun 
596*4882a593Smuzhiyun 	return ENETC_MSG_CMD_STATUS_OK;
597*4882a593Smuzhiyun }
598*4882a593Smuzhiyun 
enetc_msg_handle_rxmsg(struct enetc_pf * pf,int vf_id,u16 * status)599*4882a593Smuzhiyun void enetc_msg_handle_rxmsg(struct enetc_pf *pf, int vf_id, u16 *status)
600*4882a593Smuzhiyun {
601*4882a593Smuzhiyun 	struct enetc_msg_swbd *msg = &pf->rxmsg[vf_id];
602*4882a593Smuzhiyun 	struct device *dev = &pf->si->pdev->dev;
603*4882a593Smuzhiyun 	struct enetc_msg_cmd_header *cmd_hdr;
604*4882a593Smuzhiyun 	u16 cmd_type;
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun 	*status = ENETC_MSG_CMD_STATUS_OK;
607*4882a593Smuzhiyun 	cmd_hdr = (struct enetc_msg_cmd_header *)msg->vaddr;
608*4882a593Smuzhiyun 	cmd_type = cmd_hdr->type;
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun 	switch (cmd_type) {
611*4882a593Smuzhiyun 	case ENETC_MSG_CMD_MNG_MAC:
612*4882a593Smuzhiyun 		*status = enetc_msg_pf_set_vf_primary_mac_addr(pf, vf_id);
613*4882a593Smuzhiyun 		break;
614*4882a593Smuzhiyun 	default:
615*4882a593Smuzhiyun 		dev_err(dev, "command not supported (cmd_type: 0x%x)\n",
616*4882a593Smuzhiyun 			cmd_type);
617*4882a593Smuzhiyun 	}
618*4882a593Smuzhiyun }
619*4882a593Smuzhiyun 
620*4882a593Smuzhiyun #ifdef CONFIG_PCI_IOV
enetc_sriov_configure(struct pci_dev * pdev,int num_vfs)621*4882a593Smuzhiyun static int enetc_sriov_configure(struct pci_dev *pdev, int num_vfs)
622*4882a593Smuzhiyun {
623*4882a593Smuzhiyun 	struct enetc_si *si = pci_get_drvdata(pdev);
624*4882a593Smuzhiyun 	struct enetc_pf *pf = enetc_si_priv(si);
625*4882a593Smuzhiyun 	int err;
626*4882a593Smuzhiyun 
627*4882a593Smuzhiyun 	if (!num_vfs) {
628*4882a593Smuzhiyun 		enetc_msg_psi_free(pf);
629*4882a593Smuzhiyun 		kfree(pf->vf_state);
630*4882a593Smuzhiyun 		pf->num_vfs = 0;
631*4882a593Smuzhiyun 		pci_disable_sriov(pdev);
632*4882a593Smuzhiyun 	} else {
633*4882a593Smuzhiyun 		pf->num_vfs = num_vfs;
634*4882a593Smuzhiyun 
635*4882a593Smuzhiyun 		pf->vf_state = kcalloc(num_vfs, sizeof(struct enetc_vf_state),
636*4882a593Smuzhiyun 				       GFP_KERNEL);
637*4882a593Smuzhiyun 		if (!pf->vf_state) {
638*4882a593Smuzhiyun 			pf->num_vfs = 0;
639*4882a593Smuzhiyun 			return -ENOMEM;
640*4882a593Smuzhiyun 		}
641*4882a593Smuzhiyun 
642*4882a593Smuzhiyun 		err = enetc_msg_psi_init(pf);
643*4882a593Smuzhiyun 		if (err) {
644*4882a593Smuzhiyun 			dev_err(&pdev->dev, "enetc_msg_psi_init (%d)\n", err);
645*4882a593Smuzhiyun 			goto err_msg_psi;
646*4882a593Smuzhiyun 		}
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun 		err = pci_enable_sriov(pdev, num_vfs);
649*4882a593Smuzhiyun 		if (err) {
650*4882a593Smuzhiyun 			dev_err(&pdev->dev, "pci_enable_sriov err %d\n", err);
651*4882a593Smuzhiyun 			goto err_en_sriov;
652*4882a593Smuzhiyun 		}
653*4882a593Smuzhiyun 	}
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun 	return num_vfs;
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun err_en_sriov:
658*4882a593Smuzhiyun 	enetc_msg_psi_free(pf);
659*4882a593Smuzhiyun err_msg_psi:
660*4882a593Smuzhiyun 	kfree(pf->vf_state);
661*4882a593Smuzhiyun 	pf->num_vfs = 0;
662*4882a593Smuzhiyun 
663*4882a593Smuzhiyun 	return err;
664*4882a593Smuzhiyun }
665*4882a593Smuzhiyun #else
666*4882a593Smuzhiyun #define enetc_sriov_configure(pdev, num_vfs)	(void)0
667*4882a593Smuzhiyun #endif
668*4882a593Smuzhiyun 
enetc_pf_set_features(struct net_device * ndev,netdev_features_t features)669*4882a593Smuzhiyun static int enetc_pf_set_features(struct net_device *ndev,
670*4882a593Smuzhiyun 				 netdev_features_t features)
671*4882a593Smuzhiyun {
672*4882a593Smuzhiyun 	netdev_features_t changed = ndev->features ^ features;
673*4882a593Smuzhiyun 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
674*4882a593Smuzhiyun 	int err;
675*4882a593Smuzhiyun 
676*4882a593Smuzhiyun 	if (changed & NETIF_F_HW_TC) {
677*4882a593Smuzhiyun 		err = enetc_set_psfp(ndev, !!(features & NETIF_F_HW_TC));
678*4882a593Smuzhiyun 		if (err)
679*4882a593Smuzhiyun 			return err;
680*4882a593Smuzhiyun 	}
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 	if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
683*4882a593Smuzhiyun 		struct enetc_pf *pf = enetc_si_priv(priv->si);
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun 		if (!!(features & NETIF_F_HW_VLAN_CTAG_FILTER))
686*4882a593Smuzhiyun 			enetc_disable_si_vlan_promisc(pf, 0);
687*4882a593Smuzhiyun 		else
688*4882a593Smuzhiyun 			enetc_enable_si_vlan_promisc(pf, 0);
689*4882a593Smuzhiyun 	}
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun 	if (changed & NETIF_F_LOOPBACK)
692*4882a593Smuzhiyun 		enetc_set_loopback(ndev, !!(features & NETIF_F_LOOPBACK));
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun 	enetc_set_features(ndev, features);
695*4882a593Smuzhiyun 
696*4882a593Smuzhiyun 	return 0;
697*4882a593Smuzhiyun }
698*4882a593Smuzhiyun 
699*4882a593Smuzhiyun static const struct net_device_ops enetc_ndev_ops = {
700*4882a593Smuzhiyun 	.ndo_open		= enetc_open,
701*4882a593Smuzhiyun 	.ndo_stop		= enetc_close,
702*4882a593Smuzhiyun 	.ndo_start_xmit		= enetc_xmit,
703*4882a593Smuzhiyun 	.ndo_get_stats		= enetc_get_stats,
704*4882a593Smuzhiyun 	.ndo_set_mac_address	= enetc_pf_set_mac_addr,
705*4882a593Smuzhiyun 	.ndo_set_rx_mode	= enetc_pf_set_rx_mode,
706*4882a593Smuzhiyun 	.ndo_vlan_rx_add_vid	= enetc_vlan_rx_add_vid,
707*4882a593Smuzhiyun 	.ndo_vlan_rx_kill_vid	= enetc_vlan_rx_del_vid,
708*4882a593Smuzhiyun 	.ndo_set_vf_mac		= enetc_pf_set_vf_mac,
709*4882a593Smuzhiyun 	.ndo_set_vf_vlan	= enetc_pf_set_vf_vlan,
710*4882a593Smuzhiyun 	.ndo_set_vf_spoofchk	= enetc_pf_set_vf_spoofchk,
711*4882a593Smuzhiyun 	.ndo_set_features	= enetc_pf_set_features,
712*4882a593Smuzhiyun 	.ndo_do_ioctl		= enetc_ioctl,
713*4882a593Smuzhiyun 	.ndo_setup_tc		= enetc_setup_tc,
714*4882a593Smuzhiyun };
715*4882a593Smuzhiyun 
enetc_pf_netdev_setup(struct enetc_si * si,struct net_device * ndev,const struct net_device_ops * ndev_ops)716*4882a593Smuzhiyun static void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
717*4882a593Smuzhiyun 				  const struct net_device_ops *ndev_ops)
718*4882a593Smuzhiyun {
719*4882a593Smuzhiyun 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
720*4882a593Smuzhiyun 
721*4882a593Smuzhiyun 	SET_NETDEV_DEV(ndev, &si->pdev->dev);
722*4882a593Smuzhiyun 	priv->ndev = ndev;
723*4882a593Smuzhiyun 	priv->si = si;
724*4882a593Smuzhiyun 	priv->dev = &si->pdev->dev;
725*4882a593Smuzhiyun 	si->ndev = ndev;
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun 	priv->msg_enable = (NETIF_MSG_WOL << 1) - 1;
728*4882a593Smuzhiyun 	ndev->netdev_ops = ndev_ops;
729*4882a593Smuzhiyun 	enetc_set_ethtool_ops(ndev);
730*4882a593Smuzhiyun 	ndev->watchdog_timeo = 5 * HZ;
731*4882a593Smuzhiyun 	ndev->max_mtu = ENETC_MAX_MTU;
732*4882a593Smuzhiyun 
733*4882a593Smuzhiyun 	ndev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM | NETIF_F_HW_CSUM |
734*4882a593Smuzhiyun 			    NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
735*4882a593Smuzhiyun 			    NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_LOOPBACK;
736*4882a593Smuzhiyun 	ndev->features = NETIF_F_HIGHDMA | NETIF_F_SG |
737*4882a593Smuzhiyun 			 NETIF_F_RXCSUM | NETIF_F_HW_CSUM |
738*4882a593Smuzhiyun 			 NETIF_F_HW_VLAN_CTAG_TX |
739*4882a593Smuzhiyun 			 NETIF_F_HW_VLAN_CTAG_RX;
740*4882a593Smuzhiyun 
741*4882a593Smuzhiyun 	if (si->num_rss)
742*4882a593Smuzhiyun 		ndev->hw_features |= NETIF_F_RXHASH;
743*4882a593Smuzhiyun 
744*4882a593Smuzhiyun 	if (si->errata & ENETC_ERR_TXCSUM) {
745*4882a593Smuzhiyun 		ndev->hw_features &= ~NETIF_F_HW_CSUM;
746*4882a593Smuzhiyun 		ndev->features &= ~NETIF_F_HW_CSUM;
747*4882a593Smuzhiyun 	}
748*4882a593Smuzhiyun 
749*4882a593Smuzhiyun 	ndev->priv_flags |= IFF_UNICAST_FLT;
750*4882a593Smuzhiyun 
751*4882a593Smuzhiyun 	if (si->hw_features & ENETC_SI_F_PSFP && !enetc_psfp_enable(priv)) {
752*4882a593Smuzhiyun 		priv->active_offloads |= ENETC_F_QCI;
753*4882a593Smuzhiyun 		ndev->features |= NETIF_F_HW_TC;
754*4882a593Smuzhiyun 		ndev->hw_features |= NETIF_F_HW_TC;
755*4882a593Smuzhiyun 	}
756*4882a593Smuzhiyun 
757*4882a593Smuzhiyun 	/* pick up primary MAC address from SI */
758*4882a593Smuzhiyun 	enetc_get_primary_mac_addr(&si->hw, ndev->dev_addr);
759*4882a593Smuzhiyun }
760*4882a593Smuzhiyun 
enetc_mdio_probe(struct enetc_pf * pf,struct device_node * np)761*4882a593Smuzhiyun static int enetc_mdio_probe(struct enetc_pf *pf, struct device_node *np)
762*4882a593Smuzhiyun {
763*4882a593Smuzhiyun 	struct device *dev = &pf->si->pdev->dev;
764*4882a593Smuzhiyun 	struct enetc_mdio_priv *mdio_priv;
765*4882a593Smuzhiyun 	struct mii_bus *bus;
766*4882a593Smuzhiyun 	int err;
767*4882a593Smuzhiyun 
768*4882a593Smuzhiyun 	bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
769*4882a593Smuzhiyun 	if (!bus)
770*4882a593Smuzhiyun 		return -ENOMEM;
771*4882a593Smuzhiyun 
772*4882a593Smuzhiyun 	bus->name = "Freescale ENETC MDIO Bus";
773*4882a593Smuzhiyun 	bus->read = enetc_mdio_read;
774*4882a593Smuzhiyun 	bus->write = enetc_mdio_write;
775*4882a593Smuzhiyun 	bus->parent = dev;
776*4882a593Smuzhiyun 	mdio_priv = bus->priv;
777*4882a593Smuzhiyun 	mdio_priv->hw = &pf->si->hw;
778*4882a593Smuzhiyun 	mdio_priv->mdio_base = ENETC_EMDIO_BASE;
779*4882a593Smuzhiyun 	snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
780*4882a593Smuzhiyun 
781*4882a593Smuzhiyun 	err = of_mdiobus_register(bus, np);
782*4882a593Smuzhiyun 	if (err) {
783*4882a593Smuzhiyun 		dev_err(dev, "cannot register MDIO bus\n");
784*4882a593Smuzhiyun 		return err;
785*4882a593Smuzhiyun 	}
786*4882a593Smuzhiyun 
787*4882a593Smuzhiyun 	pf->mdio = bus;
788*4882a593Smuzhiyun 
789*4882a593Smuzhiyun 	return 0;
790*4882a593Smuzhiyun }
791*4882a593Smuzhiyun 
enetc_mdio_remove(struct enetc_pf * pf)792*4882a593Smuzhiyun static void enetc_mdio_remove(struct enetc_pf *pf)
793*4882a593Smuzhiyun {
794*4882a593Smuzhiyun 	if (pf->mdio)
795*4882a593Smuzhiyun 		mdiobus_unregister(pf->mdio);
796*4882a593Smuzhiyun }
797*4882a593Smuzhiyun 
enetc_imdio_create(struct enetc_pf * pf)798*4882a593Smuzhiyun static int enetc_imdio_create(struct enetc_pf *pf)
799*4882a593Smuzhiyun {
800*4882a593Smuzhiyun 	struct device *dev = &pf->si->pdev->dev;
801*4882a593Smuzhiyun 	struct enetc_mdio_priv *mdio_priv;
802*4882a593Smuzhiyun 	struct lynx_pcs *pcs_lynx;
803*4882a593Smuzhiyun 	struct mdio_device *pcs;
804*4882a593Smuzhiyun 	struct mii_bus *bus;
805*4882a593Smuzhiyun 	int err;
806*4882a593Smuzhiyun 
807*4882a593Smuzhiyun 	bus = mdiobus_alloc_size(sizeof(*mdio_priv));
808*4882a593Smuzhiyun 	if (!bus)
809*4882a593Smuzhiyun 		return -ENOMEM;
810*4882a593Smuzhiyun 
811*4882a593Smuzhiyun 	bus->name = "Freescale ENETC internal MDIO Bus";
812*4882a593Smuzhiyun 	bus->read = enetc_mdio_read;
813*4882a593Smuzhiyun 	bus->write = enetc_mdio_write;
814*4882a593Smuzhiyun 	bus->parent = dev;
815*4882a593Smuzhiyun 	bus->phy_mask = ~0;
816*4882a593Smuzhiyun 	mdio_priv = bus->priv;
817*4882a593Smuzhiyun 	mdio_priv->hw = &pf->si->hw;
818*4882a593Smuzhiyun 	mdio_priv->mdio_base = ENETC_PM_IMDIO_BASE;
819*4882a593Smuzhiyun 	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-imdio", dev_name(dev));
820*4882a593Smuzhiyun 
821*4882a593Smuzhiyun 	err = mdiobus_register(bus);
822*4882a593Smuzhiyun 	if (err) {
823*4882a593Smuzhiyun 		dev_err(dev, "cannot register internal MDIO bus (%d)\n", err);
824*4882a593Smuzhiyun 		goto free_mdio_bus;
825*4882a593Smuzhiyun 	}
826*4882a593Smuzhiyun 
827*4882a593Smuzhiyun 	pcs = mdio_device_create(bus, 0);
828*4882a593Smuzhiyun 	if (IS_ERR(pcs)) {
829*4882a593Smuzhiyun 		err = PTR_ERR(pcs);
830*4882a593Smuzhiyun 		dev_err(dev, "cannot create pcs (%d)\n", err);
831*4882a593Smuzhiyun 		goto unregister_mdiobus;
832*4882a593Smuzhiyun 	}
833*4882a593Smuzhiyun 
834*4882a593Smuzhiyun 	pcs_lynx = lynx_pcs_create(pcs);
835*4882a593Smuzhiyun 	if (!pcs_lynx) {
836*4882a593Smuzhiyun 		mdio_device_free(pcs);
837*4882a593Smuzhiyun 		err = -ENOMEM;
838*4882a593Smuzhiyun 		dev_err(dev, "cannot create lynx pcs (%d)\n", err);
839*4882a593Smuzhiyun 		goto unregister_mdiobus;
840*4882a593Smuzhiyun 	}
841*4882a593Smuzhiyun 
842*4882a593Smuzhiyun 	pf->imdio = bus;
843*4882a593Smuzhiyun 	pf->pcs = pcs_lynx;
844*4882a593Smuzhiyun 
845*4882a593Smuzhiyun 	return 0;
846*4882a593Smuzhiyun 
847*4882a593Smuzhiyun unregister_mdiobus:
848*4882a593Smuzhiyun 	mdiobus_unregister(bus);
849*4882a593Smuzhiyun free_mdio_bus:
850*4882a593Smuzhiyun 	mdiobus_free(bus);
851*4882a593Smuzhiyun 	return err;
852*4882a593Smuzhiyun }
853*4882a593Smuzhiyun 
enetc_imdio_remove(struct enetc_pf * pf)854*4882a593Smuzhiyun static void enetc_imdio_remove(struct enetc_pf *pf)
855*4882a593Smuzhiyun {
856*4882a593Smuzhiyun 	if (pf->pcs) {
857*4882a593Smuzhiyun 		mdio_device_free(pf->pcs->mdio);
858*4882a593Smuzhiyun 		lynx_pcs_destroy(pf->pcs);
859*4882a593Smuzhiyun 	}
860*4882a593Smuzhiyun 	if (pf->imdio) {
861*4882a593Smuzhiyun 		mdiobus_unregister(pf->imdio);
862*4882a593Smuzhiyun 		mdiobus_free(pf->imdio);
863*4882a593Smuzhiyun 	}
864*4882a593Smuzhiyun }
865*4882a593Smuzhiyun 
enetc_port_has_pcs(struct enetc_pf * pf)866*4882a593Smuzhiyun static bool enetc_port_has_pcs(struct enetc_pf *pf)
867*4882a593Smuzhiyun {
868*4882a593Smuzhiyun 	return (pf->if_mode == PHY_INTERFACE_MODE_SGMII ||
869*4882a593Smuzhiyun 		pf->if_mode == PHY_INTERFACE_MODE_2500BASEX ||
870*4882a593Smuzhiyun 		pf->if_mode == PHY_INTERFACE_MODE_USXGMII);
871*4882a593Smuzhiyun }
872*4882a593Smuzhiyun 
enetc_mdiobus_create(struct enetc_pf * pf,struct device_node * node)873*4882a593Smuzhiyun static int enetc_mdiobus_create(struct enetc_pf *pf, struct device_node *node)
874*4882a593Smuzhiyun {
875*4882a593Smuzhiyun 	struct device_node *mdio_np;
876*4882a593Smuzhiyun 	int err;
877*4882a593Smuzhiyun 
878*4882a593Smuzhiyun 	mdio_np = of_get_child_by_name(node, "mdio");
879*4882a593Smuzhiyun 	if (mdio_np) {
880*4882a593Smuzhiyun 		err = enetc_mdio_probe(pf, mdio_np);
881*4882a593Smuzhiyun 
882*4882a593Smuzhiyun 		of_node_put(mdio_np);
883*4882a593Smuzhiyun 		if (err)
884*4882a593Smuzhiyun 			return err;
885*4882a593Smuzhiyun 	}
886*4882a593Smuzhiyun 
887*4882a593Smuzhiyun 	if (enetc_port_has_pcs(pf)) {
888*4882a593Smuzhiyun 		err = enetc_imdio_create(pf);
889*4882a593Smuzhiyun 		if (err) {
890*4882a593Smuzhiyun 			enetc_mdio_remove(pf);
891*4882a593Smuzhiyun 			return err;
892*4882a593Smuzhiyun 		}
893*4882a593Smuzhiyun 	}
894*4882a593Smuzhiyun 
895*4882a593Smuzhiyun 	return 0;
896*4882a593Smuzhiyun }
897*4882a593Smuzhiyun 
enetc_mdiobus_destroy(struct enetc_pf * pf)898*4882a593Smuzhiyun static void enetc_mdiobus_destroy(struct enetc_pf *pf)
899*4882a593Smuzhiyun {
900*4882a593Smuzhiyun 	enetc_mdio_remove(pf);
901*4882a593Smuzhiyun 	enetc_imdio_remove(pf);
902*4882a593Smuzhiyun }
903*4882a593Smuzhiyun 
enetc_pl_mac_validate(struct phylink_config * config,unsigned long * supported,struct phylink_link_state * state)904*4882a593Smuzhiyun static void enetc_pl_mac_validate(struct phylink_config *config,
905*4882a593Smuzhiyun 				  unsigned long *supported,
906*4882a593Smuzhiyun 				  struct phylink_link_state *state)
907*4882a593Smuzhiyun {
908*4882a593Smuzhiyun 	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
909*4882a593Smuzhiyun 
910*4882a593Smuzhiyun 	if (state->interface != PHY_INTERFACE_MODE_NA &&
911*4882a593Smuzhiyun 	    state->interface != PHY_INTERFACE_MODE_INTERNAL &&
912*4882a593Smuzhiyun 	    state->interface != PHY_INTERFACE_MODE_SGMII &&
913*4882a593Smuzhiyun 	    state->interface != PHY_INTERFACE_MODE_2500BASEX &&
914*4882a593Smuzhiyun 	    state->interface != PHY_INTERFACE_MODE_USXGMII &&
915*4882a593Smuzhiyun 	    !phy_interface_mode_is_rgmii(state->interface)) {
916*4882a593Smuzhiyun 		bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
917*4882a593Smuzhiyun 		return;
918*4882a593Smuzhiyun 	}
919*4882a593Smuzhiyun 
920*4882a593Smuzhiyun 	phylink_set_port_modes(mask);
921*4882a593Smuzhiyun 	phylink_set(mask, Autoneg);
922*4882a593Smuzhiyun 	phylink_set(mask, Pause);
923*4882a593Smuzhiyun 	phylink_set(mask, Asym_Pause);
924*4882a593Smuzhiyun 	phylink_set(mask, 10baseT_Half);
925*4882a593Smuzhiyun 	phylink_set(mask, 10baseT_Full);
926*4882a593Smuzhiyun 	phylink_set(mask, 100baseT_Half);
927*4882a593Smuzhiyun 	phylink_set(mask, 100baseT_Full);
928*4882a593Smuzhiyun 	phylink_set(mask, 100baseT_Half);
929*4882a593Smuzhiyun 	phylink_set(mask, 1000baseT_Half);
930*4882a593Smuzhiyun 	phylink_set(mask, 1000baseT_Full);
931*4882a593Smuzhiyun 
932*4882a593Smuzhiyun 	if (state->interface == PHY_INTERFACE_MODE_INTERNAL ||
933*4882a593Smuzhiyun 	    state->interface == PHY_INTERFACE_MODE_2500BASEX ||
934*4882a593Smuzhiyun 	    state->interface == PHY_INTERFACE_MODE_USXGMII) {
935*4882a593Smuzhiyun 		phylink_set(mask, 2500baseT_Full);
936*4882a593Smuzhiyun 		phylink_set(mask, 2500baseX_Full);
937*4882a593Smuzhiyun 	}
938*4882a593Smuzhiyun 
939*4882a593Smuzhiyun 	bitmap_and(supported, supported, mask,
940*4882a593Smuzhiyun 		   __ETHTOOL_LINK_MODE_MASK_NBITS);
941*4882a593Smuzhiyun 	bitmap_and(state->advertising, state->advertising, mask,
942*4882a593Smuzhiyun 		   __ETHTOOL_LINK_MODE_MASK_NBITS);
943*4882a593Smuzhiyun }
944*4882a593Smuzhiyun 
enetc_pl_mac_config(struct phylink_config * config,unsigned int mode,const struct phylink_link_state * state)945*4882a593Smuzhiyun static void enetc_pl_mac_config(struct phylink_config *config,
946*4882a593Smuzhiyun 				unsigned int mode,
947*4882a593Smuzhiyun 				const struct phylink_link_state *state)
948*4882a593Smuzhiyun {
949*4882a593Smuzhiyun 	struct enetc_pf *pf = phylink_to_enetc_pf(config);
950*4882a593Smuzhiyun 	struct enetc_ndev_priv *priv;
951*4882a593Smuzhiyun 
952*4882a593Smuzhiyun 	enetc_mac_config(&pf->si->hw, state->interface);
953*4882a593Smuzhiyun 
954*4882a593Smuzhiyun 	priv = netdev_priv(pf->si->ndev);
955*4882a593Smuzhiyun 	if (pf->pcs)
956*4882a593Smuzhiyun 		phylink_set_pcs(priv->phylink, &pf->pcs->pcs);
957*4882a593Smuzhiyun }
958*4882a593Smuzhiyun 
enetc_force_rgmii_mac(struct enetc_hw * hw,int speed,int duplex)959*4882a593Smuzhiyun static void enetc_force_rgmii_mac(struct enetc_hw *hw, int speed, int duplex)
960*4882a593Smuzhiyun {
961*4882a593Smuzhiyun 	u32 old_val, val;
962*4882a593Smuzhiyun 
963*4882a593Smuzhiyun 	old_val = val = enetc_port_rd(hw, ENETC_PM0_IF_MODE);
964*4882a593Smuzhiyun 
965*4882a593Smuzhiyun 	if (speed == SPEED_1000) {
966*4882a593Smuzhiyun 		val &= ~ENETC_PM0_IFM_SSP_MASK;
967*4882a593Smuzhiyun 		val |= ENETC_PM0_IFM_SSP_1000;
968*4882a593Smuzhiyun 	} else if (speed == SPEED_100) {
969*4882a593Smuzhiyun 		val &= ~ENETC_PM0_IFM_SSP_MASK;
970*4882a593Smuzhiyun 		val |= ENETC_PM0_IFM_SSP_100;
971*4882a593Smuzhiyun 	} else if (speed == SPEED_10) {
972*4882a593Smuzhiyun 		val &= ~ENETC_PM0_IFM_SSP_MASK;
973*4882a593Smuzhiyun 		val |= ENETC_PM0_IFM_SSP_10;
974*4882a593Smuzhiyun 	}
975*4882a593Smuzhiyun 
976*4882a593Smuzhiyun 	if (duplex == DUPLEX_FULL)
977*4882a593Smuzhiyun 		val |= ENETC_PM0_IFM_FULL_DPX;
978*4882a593Smuzhiyun 	else
979*4882a593Smuzhiyun 		val &= ~ENETC_PM0_IFM_FULL_DPX;
980*4882a593Smuzhiyun 
981*4882a593Smuzhiyun 	if (val == old_val)
982*4882a593Smuzhiyun 		return;
983*4882a593Smuzhiyun 
984*4882a593Smuzhiyun 	enetc_port_wr(hw, ENETC_PM0_IF_MODE, val);
985*4882a593Smuzhiyun }
986*4882a593Smuzhiyun 
enetc_pl_mac_link_up(struct phylink_config * config,struct phy_device * phy,unsigned int mode,phy_interface_t interface,int speed,int duplex,bool tx_pause,bool rx_pause)987*4882a593Smuzhiyun static void enetc_pl_mac_link_up(struct phylink_config *config,
988*4882a593Smuzhiyun 				 struct phy_device *phy, unsigned int mode,
989*4882a593Smuzhiyun 				 phy_interface_t interface, int speed,
990*4882a593Smuzhiyun 				 int duplex, bool tx_pause, bool rx_pause)
991*4882a593Smuzhiyun {
992*4882a593Smuzhiyun 	struct enetc_pf *pf = phylink_to_enetc_pf(config);
993*4882a593Smuzhiyun 	struct enetc_ndev_priv *priv;
994*4882a593Smuzhiyun 
995*4882a593Smuzhiyun 	priv = netdev_priv(pf->si->ndev);
996*4882a593Smuzhiyun 
997*4882a593Smuzhiyun 	if (pf->si->hw_features & ENETC_SI_F_QBV)
998*4882a593Smuzhiyun 		enetc_sched_speed_set(priv, speed);
999*4882a593Smuzhiyun 
1000*4882a593Smuzhiyun 	if (!phylink_autoneg_inband(mode) &&
1001*4882a593Smuzhiyun 	    phy_interface_mode_is_rgmii(interface))
1002*4882a593Smuzhiyun 		enetc_force_rgmii_mac(&pf->si->hw, speed, duplex);
1003*4882a593Smuzhiyun 
1004*4882a593Smuzhiyun 	enetc_mac_enable(&pf->si->hw, true);
1005*4882a593Smuzhiyun }
1006*4882a593Smuzhiyun 
enetc_pl_mac_link_down(struct phylink_config * config,unsigned int mode,phy_interface_t interface)1007*4882a593Smuzhiyun static void enetc_pl_mac_link_down(struct phylink_config *config,
1008*4882a593Smuzhiyun 				   unsigned int mode,
1009*4882a593Smuzhiyun 				   phy_interface_t interface)
1010*4882a593Smuzhiyun {
1011*4882a593Smuzhiyun 	struct enetc_pf *pf = phylink_to_enetc_pf(config);
1012*4882a593Smuzhiyun 
1013*4882a593Smuzhiyun 	enetc_mac_enable(&pf->si->hw, false);
1014*4882a593Smuzhiyun }
1015*4882a593Smuzhiyun 
1016*4882a593Smuzhiyun static const struct phylink_mac_ops enetc_mac_phylink_ops = {
1017*4882a593Smuzhiyun 	.validate = enetc_pl_mac_validate,
1018*4882a593Smuzhiyun 	.mac_config = enetc_pl_mac_config,
1019*4882a593Smuzhiyun 	.mac_link_up = enetc_pl_mac_link_up,
1020*4882a593Smuzhiyun 	.mac_link_down = enetc_pl_mac_link_down,
1021*4882a593Smuzhiyun };
1022*4882a593Smuzhiyun 
enetc_phylink_create(struct enetc_ndev_priv * priv,struct device_node * node)1023*4882a593Smuzhiyun static int enetc_phylink_create(struct enetc_ndev_priv *priv,
1024*4882a593Smuzhiyun 				struct device_node *node)
1025*4882a593Smuzhiyun {
1026*4882a593Smuzhiyun 	struct enetc_pf *pf = enetc_si_priv(priv->si);
1027*4882a593Smuzhiyun 	struct phylink *phylink;
1028*4882a593Smuzhiyun 	int err;
1029*4882a593Smuzhiyun 
1030*4882a593Smuzhiyun 	pf->phylink_config.dev = &priv->ndev->dev;
1031*4882a593Smuzhiyun 	pf->phylink_config.type = PHYLINK_NETDEV;
1032*4882a593Smuzhiyun 
1033*4882a593Smuzhiyun 	phylink = phylink_create(&pf->phylink_config, of_fwnode_handle(node),
1034*4882a593Smuzhiyun 				 pf->if_mode, &enetc_mac_phylink_ops);
1035*4882a593Smuzhiyun 	if (IS_ERR(phylink)) {
1036*4882a593Smuzhiyun 		err = PTR_ERR(phylink);
1037*4882a593Smuzhiyun 		return err;
1038*4882a593Smuzhiyun 	}
1039*4882a593Smuzhiyun 
1040*4882a593Smuzhiyun 	priv->phylink = phylink;
1041*4882a593Smuzhiyun 
1042*4882a593Smuzhiyun 	return 0;
1043*4882a593Smuzhiyun }
1044*4882a593Smuzhiyun 
enetc_phylink_destroy(struct enetc_ndev_priv * priv)1045*4882a593Smuzhiyun static void enetc_phylink_destroy(struct enetc_ndev_priv *priv)
1046*4882a593Smuzhiyun {
1047*4882a593Smuzhiyun 	if (priv->phylink)
1048*4882a593Smuzhiyun 		phylink_destroy(priv->phylink);
1049*4882a593Smuzhiyun }
1050*4882a593Smuzhiyun 
1051*4882a593Smuzhiyun /* Initialize the entire shared memory for the flow steering entries
1052*4882a593Smuzhiyun  * of this port (PF + VFs)
1053*4882a593Smuzhiyun  */
enetc_init_port_rfs_memory(struct enetc_si * si)1054*4882a593Smuzhiyun static int enetc_init_port_rfs_memory(struct enetc_si *si)
1055*4882a593Smuzhiyun {
1056*4882a593Smuzhiyun 	struct enetc_cmd_rfse rfse = {0};
1057*4882a593Smuzhiyun 	struct enetc_hw *hw = &si->hw;
1058*4882a593Smuzhiyun 	int num_rfs, i, err = 0;
1059*4882a593Smuzhiyun 	u32 val;
1060*4882a593Smuzhiyun 
1061*4882a593Smuzhiyun 	val = enetc_port_rd(hw, ENETC_PRFSCAPR);
1062*4882a593Smuzhiyun 	num_rfs = ENETC_PRFSCAPR_GET_NUM_RFS(val);
1063*4882a593Smuzhiyun 
1064*4882a593Smuzhiyun 	for (i = 0; i < num_rfs; i++) {
1065*4882a593Smuzhiyun 		err = enetc_set_fs_entry(si, &rfse, i);
1066*4882a593Smuzhiyun 		if (err)
1067*4882a593Smuzhiyun 			break;
1068*4882a593Smuzhiyun 	}
1069*4882a593Smuzhiyun 
1070*4882a593Smuzhiyun 	return err;
1071*4882a593Smuzhiyun }
1072*4882a593Smuzhiyun 
enetc_init_port_rss_memory(struct enetc_si * si)1073*4882a593Smuzhiyun static int enetc_init_port_rss_memory(struct enetc_si *si)
1074*4882a593Smuzhiyun {
1075*4882a593Smuzhiyun 	struct enetc_hw *hw = &si->hw;
1076*4882a593Smuzhiyun 	int num_rss, err;
1077*4882a593Smuzhiyun 	int *rss_table;
1078*4882a593Smuzhiyun 	u32 val;
1079*4882a593Smuzhiyun 
1080*4882a593Smuzhiyun 	val = enetc_port_rd(hw, ENETC_PRSSCAPR);
1081*4882a593Smuzhiyun 	num_rss = ENETC_PRSSCAPR_GET_NUM_RSS(val);
1082*4882a593Smuzhiyun 	if (!num_rss)
1083*4882a593Smuzhiyun 		return 0;
1084*4882a593Smuzhiyun 
1085*4882a593Smuzhiyun 	rss_table = kcalloc(num_rss, sizeof(*rss_table), GFP_KERNEL);
1086*4882a593Smuzhiyun 	if (!rss_table)
1087*4882a593Smuzhiyun 		return -ENOMEM;
1088*4882a593Smuzhiyun 
1089*4882a593Smuzhiyun 	err = enetc_set_rss_table(si, rss_table, num_rss);
1090*4882a593Smuzhiyun 
1091*4882a593Smuzhiyun 	kfree(rss_table);
1092*4882a593Smuzhiyun 
1093*4882a593Smuzhiyun 	return err;
1094*4882a593Smuzhiyun }
1095*4882a593Smuzhiyun 
enetc_init_unused_port(struct enetc_si * si)1096*4882a593Smuzhiyun static void enetc_init_unused_port(struct enetc_si *si)
1097*4882a593Smuzhiyun {
1098*4882a593Smuzhiyun 	struct device *dev = &si->pdev->dev;
1099*4882a593Smuzhiyun 	struct enetc_hw *hw = &si->hw;
1100*4882a593Smuzhiyun 	int err;
1101*4882a593Smuzhiyun 
1102*4882a593Smuzhiyun 	si->cbd_ring.bd_count = ENETC_CBDR_DEFAULT_SIZE;
1103*4882a593Smuzhiyun 	err = enetc_alloc_cbdr(dev, &si->cbd_ring);
1104*4882a593Smuzhiyun 	if (err)
1105*4882a593Smuzhiyun 		return;
1106*4882a593Smuzhiyun 
1107*4882a593Smuzhiyun 	enetc_setup_cbdr(hw, &si->cbd_ring);
1108*4882a593Smuzhiyun 
1109*4882a593Smuzhiyun 	enetc_init_port_rfs_memory(si);
1110*4882a593Smuzhiyun 	enetc_init_port_rss_memory(si);
1111*4882a593Smuzhiyun 
1112*4882a593Smuzhiyun 	enetc_clear_cbdr(hw);
1113*4882a593Smuzhiyun 	enetc_free_cbdr(dev, &si->cbd_ring);
1114*4882a593Smuzhiyun }
1115*4882a593Smuzhiyun 
enetc_pf_probe(struct pci_dev * pdev,const struct pci_device_id * ent)1116*4882a593Smuzhiyun static int enetc_pf_probe(struct pci_dev *pdev,
1117*4882a593Smuzhiyun 			  const struct pci_device_id *ent)
1118*4882a593Smuzhiyun {
1119*4882a593Smuzhiyun 	struct device_node *node = pdev->dev.of_node;
1120*4882a593Smuzhiyun 	struct enetc_ndev_priv *priv;
1121*4882a593Smuzhiyun 	struct net_device *ndev;
1122*4882a593Smuzhiyun 	struct enetc_si *si;
1123*4882a593Smuzhiyun 	struct enetc_pf *pf;
1124*4882a593Smuzhiyun 	int err;
1125*4882a593Smuzhiyun 
1126*4882a593Smuzhiyun 	err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(*pf));
1127*4882a593Smuzhiyun 	if (err) {
1128*4882a593Smuzhiyun 		dev_err(&pdev->dev, "PCI probing failed\n");
1129*4882a593Smuzhiyun 		return err;
1130*4882a593Smuzhiyun 	}
1131*4882a593Smuzhiyun 
1132*4882a593Smuzhiyun 	si = pci_get_drvdata(pdev);
1133*4882a593Smuzhiyun 	if (!si->hw.port || !si->hw.global) {
1134*4882a593Smuzhiyun 		err = -ENODEV;
1135*4882a593Smuzhiyun 		dev_err(&pdev->dev, "could not map PF space, probing a VF?\n");
1136*4882a593Smuzhiyun 		goto err_map_pf_space;
1137*4882a593Smuzhiyun 	}
1138*4882a593Smuzhiyun 
1139*4882a593Smuzhiyun 	if (node && !of_device_is_available(node)) {
1140*4882a593Smuzhiyun 		enetc_init_unused_port(si);
1141*4882a593Smuzhiyun 		dev_info(&pdev->dev, "device is disabled, skipping\n");
1142*4882a593Smuzhiyun 		err = -ENODEV;
1143*4882a593Smuzhiyun 		goto err_device_disabled;
1144*4882a593Smuzhiyun 	}
1145*4882a593Smuzhiyun 
1146*4882a593Smuzhiyun 	pf = enetc_si_priv(si);
1147*4882a593Smuzhiyun 	pf->si = si;
1148*4882a593Smuzhiyun 	pf->total_vfs = pci_sriov_get_totalvfs(pdev);
1149*4882a593Smuzhiyun 
1150*4882a593Smuzhiyun 	enetc_configure_port(pf);
1151*4882a593Smuzhiyun 
1152*4882a593Smuzhiyun 	enetc_get_si_caps(si);
1153*4882a593Smuzhiyun 
1154*4882a593Smuzhiyun 	ndev = alloc_etherdev_mq(sizeof(*priv), ENETC_MAX_NUM_TXQS);
1155*4882a593Smuzhiyun 	if (!ndev) {
1156*4882a593Smuzhiyun 		err = -ENOMEM;
1157*4882a593Smuzhiyun 		dev_err(&pdev->dev, "netdev creation failed\n");
1158*4882a593Smuzhiyun 		goto err_alloc_netdev;
1159*4882a593Smuzhiyun 	}
1160*4882a593Smuzhiyun 
1161*4882a593Smuzhiyun 	enetc_pf_netdev_setup(si, ndev, &enetc_ndev_ops);
1162*4882a593Smuzhiyun 
1163*4882a593Smuzhiyun 	priv = netdev_priv(ndev);
1164*4882a593Smuzhiyun 
1165*4882a593Smuzhiyun 	enetc_init_si_rings_params(priv);
1166*4882a593Smuzhiyun 
1167*4882a593Smuzhiyun 	err = enetc_alloc_si_resources(priv);
1168*4882a593Smuzhiyun 	if (err) {
1169*4882a593Smuzhiyun 		dev_err(&pdev->dev, "SI resource alloc failed\n");
1170*4882a593Smuzhiyun 		goto err_alloc_si_res;
1171*4882a593Smuzhiyun 	}
1172*4882a593Smuzhiyun 
1173*4882a593Smuzhiyun 	err = enetc_init_port_rfs_memory(si);
1174*4882a593Smuzhiyun 	if (err) {
1175*4882a593Smuzhiyun 		dev_err(&pdev->dev, "Failed to initialize RFS memory\n");
1176*4882a593Smuzhiyun 		goto err_init_port_rfs;
1177*4882a593Smuzhiyun 	}
1178*4882a593Smuzhiyun 
1179*4882a593Smuzhiyun 	err = enetc_init_port_rss_memory(si);
1180*4882a593Smuzhiyun 	if (err) {
1181*4882a593Smuzhiyun 		dev_err(&pdev->dev, "Failed to initialize RSS memory\n");
1182*4882a593Smuzhiyun 		goto err_init_port_rss;
1183*4882a593Smuzhiyun 	}
1184*4882a593Smuzhiyun 
1185*4882a593Smuzhiyun 	err = enetc_configure_si(priv);
1186*4882a593Smuzhiyun 	if (err) {
1187*4882a593Smuzhiyun 		dev_err(&pdev->dev, "Failed to configure SI\n");
1188*4882a593Smuzhiyun 		goto err_config_si;
1189*4882a593Smuzhiyun 	}
1190*4882a593Smuzhiyun 
1191*4882a593Smuzhiyun 	err = enetc_alloc_msix(priv);
1192*4882a593Smuzhiyun 	if (err) {
1193*4882a593Smuzhiyun 		dev_err(&pdev->dev, "MSIX alloc failed\n");
1194*4882a593Smuzhiyun 		goto err_alloc_msix;
1195*4882a593Smuzhiyun 	}
1196*4882a593Smuzhiyun 
1197*4882a593Smuzhiyun 	if (!of_get_phy_mode(node, &pf->if_mode)) {
1198*4882a593Smuzhiyun 		err = enetc_mdiobus_create(pf, node);
1199*4882a593Smuzhiyun 		if (err)
1200*4882a593Smuzhiyun 			goto err_mdiobus_create;
1201*4882a593Smuzhiyun 
1202*4882a593Smuzhiyun 		err = enetc_phylink_create(priv, node);
1203*4882a593Smuzhiyun 		if (err)
1204*4882a593Smuzhiyun 			goto err_phylink_create;
1205*4882a593Smuzhiyun 	}
1206*4882a593Smuzhiyun 
1207*4882a593Smuzhiyun 	err = register_netdev(ndev);
1208*4882a593Smuzhiyun 	if (err)
1209*4882a593Smuzhiyun 		goto err_reg_netdev;
1210*4882a593Smuzhiyun 
1211*4882a593Smuzhiyun 	return 0;
1212*4882a593Smuzhiyun 
1213*4882a593Smuzhiyun err_reg_netdev:
1214*4882a593Smuzhiyun 	enetc_phylink_destroy(priv);
1215*4882a593Smuzhiyun err_phylink_create:
1216*4882a593Smuzhiyun 	enetc_mdiobus_destroy(pf);
1217*4882a593Smuzhiyun err_mdiobus_create:
1218*4882a593Smuzhiyun 	enetc_free_msix(priv);
1219*4882a593Smuzhiyun err_config_si:
1220*4882a593Smuzhiyun err_init_port_rss:
1221*4882a593Smuzhiyun err_init_port_rfs:
1222*4882a593Smuzhiyun err_alloc_msix:
1223*4882a593Smuzhiyun 	enetc_free_si_resources(priv);
1224*4882a593Smuzhiyun err_alloc_si_res:
1225*4882a593Smuzhiyun 	si->ndev = NULL;
1226*4882a593Smuzhiyun 	free_netdev(ndev);
1227*4882a593Smuzhiyun err_alloc_netdev:
1228*4882a593Smuzhiyun err_device_disabled:
1229*4882a593Smuzhiyun err_map_pf_space:
1230*4882a593Smuzhiyun 	enetc_pci_remove(pdev);
1231*4882a593Smuzhiyun 
1232*4882a593Smuzhiyun 	return err;
1233*4882a593Smuzhiyun }
1234*4882a593Smuzhiyun 
enetc_pf_remove(struct pci_dev * pdev)1235*4882a593Smuzhiyun static void enetc_pf_remove(struct pci_dev *pdev)
1236*4882a593Smuzhiyun {
1237*4882a593Smuzhiyun 	struct enetc_si *si = pci_get_drvdata(pdev);
1238*4882a593Smuzhiyun 	struct enetc_pf *pf = enetc_si_priv(si);
1239*4882a593Smuzhiyun 	struct enetc_ndev_priv *priv;
1240*4882a593Smuzhiyun 
1241*4882a593Smuzhiyun 	priv = netdev_priv(si->ndev);
1242*4882a593Smuzhiyun 
1243*4882a593Smuzhiyun 	if (pf->num_vfs)
1244*4882a593Smuzhiyun 		enetc_sriov_configure(pdev, 0);
1245*4882a593Smuzhiyun 
1246*4882a593Smuzhiyun 	unregister_netdev(si->ndev);
1247*4882a593Smuzhiyun 
1248*4882a593Smuzhiyun 	enetc_phylink_destroy(priv);
1249*4882a593Smuzhiyun 	enetc_mdiobus_destroy(pf);
1250*4882a593Smuzhiyun 
1251*4882a593Smuzhiyun 	enetc_free_msix(priv);
1252*4882a593Smuzhiyun 
1253*4882a593Smuzhiyun 	enetc_free_si_resources(priv);
1254*4882a593Smuzhiyun 
1255*4882a593Smuzhiyun 	free_netdev(si->ndev);
1256*4882a593Smuzhiyun 
1257*4882a593Smuzhiyun 	enetc_pci_remove(pdev);
1258*4882a593Smuzhiyun }
1259*4882a593Smuzhiyun 
1260*4882a593Smuzhiyun static const struct pci_device_id enetc_pf_id_table[] = {
1261*4882a593Smuzhiyun 	{ PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PF) },
1262*4882a593Smuzhiyun 	{ 0, } /* End of table. */
1263*4882a593Smuzhiyun };
1264*4882a593Smuzhiyun MODULE_DEVICE_TABLE(pci, enetc_pf_id_table);
1265*4882a593Smuzhiyun 
1266*4882a593Smuzhiyun static struct pci_driver enetc_pf_driver = {
1267*4882a593Smuzhiyun 	.name = KBUILD_MODNAME,
1268*4882a593Smuzhiyun 	.id_table = enetc_pf_id_table,
1269*4882a593Smuzhiyun 	.probe = enetc_pf_probe,
1270*4882a593Smuzhiyun 	.remove = enetc_pf_remove,
1271*4882a593Smuzhiyun #ifdef CONFIG_PCI_IOV
1272*4882a593Smuzhiyun 	.sriov_configure = enetc_sriov_configure,
1273*4882a593Smuzhiyun #endif
1274*4882a593Smuzhiyun };
1275*4882a593Smuzhiyun module_pci_driver(enetc_pf_driver);
1276*4882a593Smuzhiyun 
1277*4882a593Smuzhiyun MODULE_DESCRIPTION(ENETC_DRV_NAME_STR);
1278*4882a593Smuzhiyun MODULE_LICENSE("Dual BSD/GPL");
1279