Commit | Line | Data |
---|---|---|
d4fd0404 CM |
1 | // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) |
2 | /* Copyright 2017-2019 NXP */ | |
3 | ||
4 | #include <linux/module.h> | |
6517798d | 5 | #include <linux/fsl/enetc_mdio.h> |
d4fd0404 CM |
6 | #include <linux/of_mdio.h> |
7 | #include <linux/of_net.h> | |
8 | #include "enetc_pf.h" | |
9 | ||
d4fd0404 | 10 | #define ENETC_DRV_NAME_STR "ENETC PF driver" |
d4fd0404 CM |
11 | |
12 | static void enetc_pf_get_primary_mac_addr(struct enetc_hw *hw, int si, u8 *addr) | |
13 | { | |
14 | u32 upper = __raw_readl(hw->port + ENETC_PSIPMAR0(si)); | |
15 | u16 lower = __raw_readw(hw->port + ENETC_PSIPMAR1(si)); | |
16 | ||
17 | *(u32 *)addr = upper; | |
18 | *(u16 *)(addr + 4) = lower; | |
19 | } | |
20 | ||
21 | static void enetc_pf_set_primary_mac_addr(struct enetc_hw *hw, int si, | |
22 | const u8 *addr) | |
23 | { | |
24 | u32 upper = *(const u32 *)addr; | |
25 | u16 lower = *(const u16 *)(addr + 4); | |
26 | ||
27 | __raw_writel(upper, hw->port + ENETC_PSIPMAR0(si)); | |
28 | __raw_writew(lower, hw->port + ENETC_PSIPMAR1(si)); | |
29 | } | |
30 | ||
31 | static int enetc_pf_set_mac_addr(struct net_device *ndev, void *addr) | |
32 | { | |
33 | struct enetc_ndev_priv *priv = netdev_priv(ndev); | |
34 | struct sockaddr *saddr = addr; | |
35 | ||
36 | if (!is_valid_ether_addr(saddr->sa_data)) | |
37 | return -EADDRNOTAVAIL; | |
38 | ||
39 | memcpy(ndev->dev_addr, saddr->sa_data, ndev->addr_len); | |
40 | enetc_pf_set_primary_mac_addr(&priv->si->hw, 0, saddr->sa_data); | |
41 | ||
42 | return 0; | |
43 | } | |
44 | ||
45 | static void enetc_set_vlan_promisc(struct enetc_hw *hw, char si_map) | |
46 | { | |
47 | u32 val = enetc_port_rd(hw, ENETC_PSIPVMR); | |
48 | ||
49 | val &= ~ENETC_PSIPVMR_SET_VP(ENETC_VLAN_PROMISC_MAP_ALL); | |
50 | enetc_port_wr(hw, ENETC_PSIPVMR, ENETC_PSIPVMR_SET_VP(si_map) | val); | |
51 | } | |
52 | ||
53 | static bool enetc_si_vlan_promisc_is_on(struct enetc_pf *pf, int si_idx) | |
54 | { | |
55 | return pf->vlan_promisc_simap & BIT(si_idx); | |
56 | } | |
57 | ||
58 | static bool enetc_vlan_filter_is_on(struct enetc_pf *pf) | |
59 | { | |
60 | int i; | |
61 | ||
62 | for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) | |
63 | return true; | |
64 | ||
65 | return false; | |
66 | } | |
67 | ||
68 | static void enetc_enable_si_vlan_promisc(struct enetc_pf *pf, int si_idx) | |
69 | { | |
70 | pf->vlan_promisc_simap |= BIT(si_idx); | |
71 | enetc_set_vlan_promisc(&pf->si->hw, pf->vlan_promisc_simap); | |
72 | } | |
73 | ||
74 | static void enetc_disable_si_vlan_promisc(struct enetc_pf *pf, int si_idx) | |
75 | { | |
76 | pf->vlan_promisc_simap &= ~BIT(si_idx); | |
77 | enetc_set_vlan_promisc(&pf->si->hw, pf->vlan_promisc_simap); | |
78 | } | |
79 | ||
80 | static void enetc_set_isol_vlan(struct enetc_hw *hw, int si, u16 vlan, u8 qos) | |
81 | { | |
82 | u32 val = 0; | |
83 | ||
84 | if (vlan) | |
85 | val = ENETC_PSIVLAN_EN | ENETC_PSIVLAN_SET_QOS(qos) | vlan; | |
86 | ||
87 | enetc_port_wr(hw, ENETC_PSIVLANR(si), val); | |
88 | } | |
89 | ||
90 | static int enetc_mac_addr_hash_idx(const u8 *addr) | |
91 | { | |
92 | u64 fold = __swab64(ether_addr_to_u64(addr)) >> 16; | |
93 | u64 mask = 0; | |
94 | int res = 0; | |
95 | int i; | |
96 | ||
97 | for (i = 0; i < 8; i++) | |
98 | mask |= BIT_ULL(i * 6); | |
99 | ||
100 | for (i = 0; i < 6; i++) | |
101 | res |= (hweight64(fold & (mask << i)) & 0x1) << i; | |
102 | ||
103 | return res; | |
104 | } | |
105 | ||
106 | static void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter) | |
107 | { | |
108 | filter->mac_addr_cnt = 0; | |
109 | ||
110 | bitmap_zero(filter->mac_hash_table, | |
111 | ENETC_MADDR_HASH_TBL_SZ); | |
112 | } | |
113 | ||
114 | static void enetc_add_mac_addr_em_filter(struct enetc_mac_filter *filter, | |
115 | const unsigned char *addr) | |
116 | { | |
117 | /* add exact match addr */ | |
118 | ether_addr_copy(filter->mac_addr, addr); | |
119 | filter->mac_addr_cnt++; | |
120 | } | |
121 | ||
122 | static void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter, | |
123 | const unsigned char *addr) | |
124 | { | |
125 | int idx = enetc_mac_addr_hash_idx(addr); | |
126 | ||
127 | /* add hash table entry */ | |
128 | __set_bit(idx, filter->mac_hash_table); | |
129 | filter->mac_addr_cnt++; | |
130 | } | |
131 | ||
132 | static void enetc_clear_mac_ht_flt(struct enetc_si *si, int si_idx, int type) | |
133 | { | |
134 | bool err = si->errata & ENETC_ERR_UCMCSWP; | |
135 | ||
136 | if (type == UC) { | |
137 | enetc_port_wr(&si->hw, ENETC_PSIUMHFR0(si_idx, err), 0); | |
138 | enetc_port_wr(&si->hw, ENETC_PSIUMHFR1(si_idx), 0); | |
139 | } else { /* MC */ | |
140 | enetc_port_wr(&si->hw, ENETC_PSIMMHFR0(si_idx, err), 0); | |
141 | enetc_port_wr(&si->hw, ENETC_PSIMMHFR1(si_idx), 0); | |
142 | } | |
143 | } | |
144 | ||
145 | static void enetc_set_mac_ht_flt(struct enetc_si *si, int si_idx, int type, | |
146 | u32 *hash) | |
147 | { | |
148 | bool err = si->errata & ENETC_ERR_UCMCSWP; | |
149 | ||
150 | if (type == UC) { | |
151 | enetc_port_wr(&si->hw, ENETC_PSIUMHFR0(si_idx, err), *hash); | |
152 | enetc_port_wr(&si->hw, ENETC_PSIUMHFR1(si_idx), *(hash + 1)); | |
153 | } else { /* MC */ | |
154 | enetc_port_wr(&si->hw, ENETC_PSIMMHFR0(si_idx, err), *hash); | |
155 | enetc_port_wr(&si->hw, ENETC_PSIMMHFR1(si_idx), *(hash + 1)); | |
156 | } | |
157 | } | |
158 | ||
159 | static void enetc_sync_mac_filters(struct enetc_pf *pf) | |
160 | { | |
161 | struct enetc_mac_filter *f = pf->mac_filter; | |
162 | struct enetc_si *si = pf->si; | |
163 | int i, pos; | |
164 | ||
165 | pos = EMETC_MAC_ADDR_FILT_RES; | |
166 | ||
167 | for (i = 0; i < MADDR_TYPE; i++, f++) { | |
168 | bool em = (f->mac_addr_cnt == 1) && (i == UC); | |
169 | bool clear = !f->mac_addr_cnt; | |
170 | ||
171 | if (clear) { | |
172 | if (i == UC) | |
173 | enetc_clear_mac_flt_entry(si, pos); | |
174 | ||
175 | enetc_clear_mac_ht_flt(si, 0, i); | |
176 | continue; | |
177 | } | |
178 | ||
179 | /* exact match filter */ | |
180 | if (em) { | |
181 | int err; | |
182 | ||
183 | enetc_clear_mac_ht_flt(si, 0, UC); | |
184 | ||
185 | err = enetc_set_mac_flt_entry(si, pos, f->mac_addr, | |
186 | BIT(0)); | |
187 | if (!err) | |
188 | continue; | |
189 | ||
190 | /* fallback to HT filtering */ | |
191 | dev_warn(&si->pdev->dev, "fallback to HT filt (%d)\n", | |
192 | err); | |
193 | } | |
194 | ||
195 | /* hash table filter, clear EM filter for UC entries */ | |
196 | if (i == UC) | |
197 | enetc_clear_mac_flt_entry(si, pos); | |
198 | ||
199 | enetc_set_mac_ht_flt(si, 0, i, (u32 *)f->mac_hash_table); | |
200 | } | |
201 | } | |
202 | ||
203 | static void enetc_pf_set_rx_mode(struct net_device *ndev) | |
204 | { | |
205 | struct enetc_ndev_priv *priv = netdev_priv(ndev); | |
206 | struct enetc_pf *pf = enetc_si_priv(priv->si); | |
207 | struct enetc_hw *hw = &priv->si->hw; | |
208 | bool uprom = false, mprom = false; | |
209 | struct enetc_mac_filter *filter; | |
210 | struct netdev_hw_addr *ha; | |
211 | u32 psipmr = 0; | |
212 | bool em; | |
213 | ||
214 | if (ndev->flags & IFF_PROMISC) { | |
215 | /* enable promisc mode for SI0 (PF) */ | |
216 | psipmr = ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0); | |
217 | uprom = true; | |
218 | mprom = true; | |
219 | /* enable VLAN promisc mode for SI0 */ | |
220 | if (!enetc_si_vlan_promisc_is_on(pf, 0)) | |
221 | enetc_enable_si_vlan_promisc(pf, 0); | |
222 | ||
223 | } else if (ndev->flags & IFF_ALLMULTI) { | |
224 | /* enable multi cast promisc mode for SI0 (PF) */ | |
225 | psipmr = ENETC_PSIPMR_SET_MP(0); | |
226 | mprom = true; | |
227 | } | |
228 | ||
229 | /* first 2 filter entries belong to PF */ | |
230 | if (!uprom) { | |
231 | /* Update unicast filters */ | |
232 | filter = &pf->mac_filter[UC]; | |
233 | enetc_reset_mac_addr_filter(filter); | |
234 | ||
235 | em = (netdev_uc_count(ndev) == 1); | |
236 | netdev_for_each_uc_addr(ha, ndev) { | |
237 | if (em) { | |
238 | enetc_add_mac_addr_em_filter(filter, ha->addr); | |
239 | break; | |
240 | } | |
241 | ||
242 | enetc_add_mac_addr_ht_filter(filter, ha->addr); | |
243 | } | |
244 | } | |
245 | ||
246 | if (!mprom) { | |
247 | /* Update multicast filters */ | |
248 | filter = &pf->mac_filter[MC]; | |
249 | enetc_reset_mac_addr_filter(filter); | |
250 | ||
251 | netdev_for_each_mc_addr(ha, ndev) { | |
252 | if (!is_multicast_ether_addr(ha->addr)) | |
253 | continue; | |
254 | ||
255 | enetc_add_mac_addr_ht_filter(filter, ha->addr); | |
256 | } | |
257 | } | |
258 | ||
259 | if (!uprom || !mprom) | |
260 | /* update PF entries */ | |
261 | enetc_sync_mac_filters(pf); | |
262 | ||
263 | psipmr |= enetc_port_rd(hw, ENETC_PSIPMR) & | |
264 | ~(ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0)); | |
265 | enetc_port_wr(hw, ENETC_PSIPMR, psipmr); | |
266 | } | |
267 | ||
268 | static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx, | |
269 | u32 *hash) | |
270 | { | |
271 | enetc_port_wr(hw, ENETC_PSIVHFR0(si_idx), *hash); | |
272 | enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), *(hash + 1)); | |
273 | } | |
274 | ||
275 | static int enetc_vid_hash_idx(unsigned int vid) | |
276 | { | |
277 | int res = 0; | |
278 | int i; | |
279 | ||
280 | for (i = 0; i < 6; i++) | |
281 | res |= (hweight8(vid & (BIT(i) | BIT(i + 6))) & 0x1) << i; | |
282 | ||
283 | return res; | |
284 | } | |
285 | ||
286 | static void enetc_sync_vlan_ht_filter(struct enetc_pf *pf, bool rehash) | |
287 | { | |
288 | int i; | |
289 | ||
290 | if (rehash) { | |
291 | bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE); | |
292 | ||
293 | for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) { | |
294 | int hidx = enetc_vid_hash_idx(i); | |
295 | ||
296 | __set_bit(hidx, pf->vlan_ht_filter); | |
297 | } | |
298 | } | |
299 | ||
300 | enetc_set_vlan_ht_filter(&pf->si->hw, 0, (u32 *)pf->vlan_ht_filter); | |
301 | } | |
302 | ||
303 | static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid) | |
304 | { | |
305 | struct enetc_ndev_priv *priv = netdev_priv(ndev); | |
306 | struct enetc_pf *pf = enetc_si_priv(priv->si); | |
307 | int idx; | |
308 | ||
309 | if (enetc_si_vlan_promisc_is_on(pf, 0)) | |
310 | enetc_disable_si_vlan_promisc(pf, 0); | |
311 | ||
312 | __set_bit(vid, pf->active_vlans); | |
313 | ||
314 | idx = enetc_vid_hash_idx(vid); | |
315 | if (!__test_and_set_bit(idx, pf->vlan_ht_filter)) | |
316 | enetc_sync_vlan_ht_filter(pf, false); | |
317 | ||
318 | return 0; | |
319 | } | |
320 | ||
321 | static int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid) | |
322 | { | |
323 | struct enetc_ndev_priv *priv = netdev_priv(ndev); | |
324 | struct enetc_pf *pf = enetc_si_priv(priv->si); | |
325 | ||
326 | __clear_bit(vid, pf->active_vlans); | |
327 | enetc_sync_vlan_ht_filter(pf, true); | |
328 | ||
329 | if (!enetc_vlan_filter_is_on(pf)) | |
330 | enetc_enable_si_vlan_promisc(pf, 0); | |
331 | ||
332 | return 0; | |
333 | } | |
334 | ||
335 | static void enetc_set_loopback(struct net_device *ndev, bool en) | |
336 | { | |
337 | struct enetc_ndev_priv *priv = netdev_priv(ndev); | |
338 | struct enetc_hw *hw = &priv->si->hw; | |
339 | u32 reg; | |
340 | ||
341 | reg = enetc_port_rd(hw, ENETC_PM0_IF_MODE); | |
342 | if (reg & ENETC_PMO_IFM_RG) { | |
343 | /* RGMII mode */ | |
344 | reg = (reg & ~ENETC_PM0_IFM_RLP) | | |
345 | (en ? ENETC_PM0_IFM_RLP : 0); | |
346 | enetc_port_wr(hw, ENETC_PM0_IF_MODE, reg); | |
347 | } else { | |
348 | /* assume SGMII mode */ | |
349 | reg = enetc_port_rd(hw, ENETC_PM0_CMD_CFG); | |
350 | reg = (reg & ~ENETC_PM0_CMD_XGLP) | | |
351 | (en ? ENETC_PM0_CMD_XGLP : 0); | |
352 | reg = (reg & ~ENETC_PM0_CMD_PHY_TX_EN) | | |
353 | (en ? ENETC_PM0_CMD_PHY_TX_EN : 0); | |
354 | enetc_port_wr(hw, ENETC_PM0_CMD_CFG, reg); | |
355 | enetc_port_wr(hw, ENETC_PM1_CMD_CFG, reg); | |
356 | } | |
357 | } | |
358 | ||
359 | static int enetc_pf_set_vf_mac(struct net_device *ndev, int vf, u8 *mac) | |
360 | { | |
361 | struct enetc_ndev_priv *priv = netdev_priv(ndev); | |
362 | struct enetc_pf *pf = enetc_si_priv(priv->si); | |
beb74ac8 | 363 | struct enetc_vf_state *vf_state; |
d4fd0404 CM |
364 | |
365 | if (vf >= pf->total_vfs) | |
366 | return -EINVAL; | |
367 | ||
368 | if (!is_valid_ether_addr(mac)) | |
369 | return -EADDRNOTAVAIL; | |
370 | ||
beb74ac8 CM |
371 | vf_state = &pf->vf_state[vf]; |
372 | vf_state->flags |= ENETC_VF_FLAG_PF_SET_MAC; | |
d4fd0404 CM |
373 | enetc_pf_set_primary_mac_addr(&priv->si->hw, vf + 1, mac); |
374 | return 0; | |
375 | } | |
376 | ||
377 | static int enetc_pf_set_vf_vlan(struct net_device *ndev, int vf, u16 vlan, | |
378 | u8 qos, __be16 proto) | |
379 | { | |
380 | struct enetc_ndev_priv *priv = netdev_priv(ndev); | |
381 | struct enetc_pf *pf = enetc_si_priv(priv->si); | |
382 | ||
383 | if (priv->si->errata & ENETC_ERR_VLAN_ISOL) | |
384 | return -EOPNOTSUPP; | |
385 | ||
386 | if (vf >= pf->total_vfs) | |
387 | return -EINVAL; | |
388 | ||
389 | if (proto != htons(ETH_P_8021Q)) | |
390 | /* only C-tags supported for now */ | |
391 | return -EPROTONOSUPPORT; | |
392 | ||
393 | enetc_set_isol_vlan(&priv->si->hw, vf + 1, vlan, qos); | |
394 | return 0; | |
395 | } | |
396 | ||
397 | static int enetc_pf_set_vf_spoofchk(struct net_device *ndev, int vf, bool en) | |
398 | { | |
399 | struct enetc_ndev_priv *priv = netdev_priv(ndev); | |
400 | struct enetc_pf *pf = enetc_si_priv(priv->si); | |
401 | u32 cfgr; | |
402 | ||
403 | if (vf >= pf->total_vfs) | |
404 | return -EINVAL; | |
405 | ||
406 | cfgr = enetc_port_rd(&priv->si->hw, ENETC_PSICFGR0(vf + 1)); | |
407 | cfgr = (cfgr & ~ENETC_PSICFGR0_ASE) | (en ? ENETC_PSICFGR0_ASE : 0); | |
408 | enetc_port_wr(&priv->si->hw, ENETC_PSICFGR0(vf + 1), cfgr); | |
409 | ||
410 | return 0; | |
411 | } | |
412 | ||
413 | static void enetc_port_setup_primary_mac_address(struct enetc_si *si) | |
414 | { | |
415 | unsigned char mac_addr[MAX_ADDR_LEN]; | |
416 | struct enetc_pf *pf = enetc_si_priv(si); | |
417 | struct enetc_hw *hw = &si->hw; | |
418 | int i; | |
419 | ||
420 | /* check MAC addresses for PF and all VFs, if any is 0 set it ro rand */ | |
421 | for (i = 0; i < pf->total_vfs + 1; i++) { | |
422 | enetc_pf_get_primary_mac_addr(hw, i, mac_addr); | |
423 | if (!is_zero_ether_addr(mac_addr)) | |
424 | continue; | |
425 | eth_random_addr(mac_addr); | |
426 | dev_info(&si->pdev->dev, "no MAC address specified for SI%d, using %pM\n", | |
427 | i, mac_addr); | |
428 | enetc_pf_set_primary_mac_addr(hw, i, mac_addr); | |
429 | } | |
430 | } | |
431 | ||
d382563f CM |
432 | static void enetc_port_assign_rfs_entries(struct enetc_si *si) |
433 | { | |
434 | struct enetc_pf *pf = enetc_si_priv(si); | |
435 | struct enetc_hw *hw = &si->hw; | |
436 | int num_entries, vf_entries, i; | |
437 | u32 val; | |
438 | ||
439 | /* split RFS entries between functions */ | |
440 | val = enetc_port_rd(hw, ENETC_PRFSCAPR); | |
441 | num_entries = ENETC_PRFSCAPR_GET_NUM_RFS(val); | |
442 | vf_entries = num_entries / (pf->total_vfs + 1); | |
443 | ||
444 | for (i = 0; i < pf->total_vfs; i++) | |
445 | enetc_port_wr(hw, ENETC_PSIRFSCFGR(i + 1), vf_entries); | |
446 | enetc_port_wr(hw, ENETC_PSIRFSCFGR(0), | |
447 | num_entries - vf_entries * pf->total_vfs); | |
448 | ||
449 | /* enable RFS on port */ | |
450 | enetc_port_wr(hw, ENETC_PRFSMR, ENETC_PRFSMR_RFSE); | |
451 | } | |
452 | ||
d4fd0404 CM |
453 | static void enetc_port_si_configure(struct enetc_si *si) |
454 | { | |
455 | struct enetc_pf *pf = enetc_si_priv(si); | |
456 | struct enetc_hw *hw = &si->hw; | |
457 | int num_rings, i; | |
458 | u32 val; | |
459 | ||
460 | val = enetc_port_rd(hw, ENETC_PCAPR0); | |
461 | num_rings = min(ENETC_PCAPR0_RXBDR(val), ENETC_PCAPR0_TXBDR(val)); | |
462 | ||
463 | val = ENETC_PSICFGR0_SET_TXBDR(ENETC_PF_NUM_RINGS); | |
464 | val |= ENETC_PSICFGR0_SET_RXBDR(ENETC_PF_NUM_RINGS); | |
465 | ||
466 | if (unlikely(num_rings < ENETC_PF_NUM_RINGS)) { | |
467 | val = ENETC_PSICFGR0_SET_TXBDR(num_rings); | |
468 | val |= ENETC_PSICFGR0_SET_RXBDR(num_rings); | |
469 | ||
470 | dev_warn(&si->pdev->dev, "Found %d rings, expected %d!\n", | |
471 | num_rings, ENETC_PF_NUM_RINGS); | |
472 | ||
473 | num_rings = 0; | |
474 | } | |
475 | ||
476 | /* Add default one-time settings for SI0 (PF) */ | |
477 | val |= ENETC_PSICFGR0_SIVC(ENETC_VLAN_TYPE_C | ENETC_VLAN_TYPE_S); | |
478 | ||
479 | enetc_port_wr(hw, ENETC_PSICFGR0(0), val); | |
480 | ||
481 | if (num_rings) | |
482 | num_rings -= ENETC_PF_NUM_RINGS; | |
483 | ||
484 | /* Configure the SIs for each available VF */ | |
485 | val = ENETC_PSICFGR0_SIVC(ENETC_VLAN_TYPE_C | ENETC_VLAN_TYPE_S); | |
486 | val |= ENETC_PSICFGR0_VTE | ENETC_PSICFGR0_SIVIE; | |
487 | ||
488 | if (num_rings) { | |
489 | num_rings /= pf->total_vfs; | |
490 | val |= ENETC_PSICFGR0_SET_TXBDR(num_rings); | |
491 | val |= ENETC_PSICFGR0_SET_RXBDR(num_rings); | |
492 | } | |
493 | ||
494 | for (i = 0; i < pf->total_vfs; i++) | |
495 | enetc_port_wr(hw, ENETC_PSICFGR0(i + 1), val); | |
496 | ||
497 | /* Port level VLAN settings */ | |
498 | val = ENETC_PVCLCTR_OVTPIDL(ENETC_VLAN_TYPE_C | ENETC_VLAN_TYPE_S); | |
499 | enetc_port_wr(hw, ENETC_PVCLCTR, val); | |
500 | /* use outer tag for VLAN filtering */ | |
501 | enetc_port_wr(hw, ENETC_PSIVLANFMR, ENETC_PSIVLANFMR_VS); | |
502 | } | |
503 | ||
504 | static void enetc_configure_port_mac(struct enetc_hw *hw) | |
505 | { | |
506 | enetc_port_wr(hw, ENETC_PM0_MAXFRM, | |
507 | ENETC_SET_MAXFRM(ENETC_RX_MAXFRM_SIZE)); | |
508 | ||
509 | enetc_port_wr(hw, ENETC_PTCMSDUR(0), ENETC_MAC_MAXFRM_SIZE); | |
510 | enetc_port_wr(hw, ENETC_PTXMBAR, 2 * ENETC_MAC_MAXFRM_SIZE); | |
511 | ||
512 | enetc_port_wr(hw, ENETC_PM0_CMD_CFG, ENETC_PM0_CMD_PHY_TX_EN | | |
513 | ENETC_PM0_CMD_TXP | ENETC_PM0_PROMISC | | |
514 | ENETC_PM0_TX_EN | ENETC_PM0_RX_EN); | |
515 | ||
516 | enetc_port_wr(hw, ENETC_PM1_CMD_CFG, ENETC_PM0_CMD_PHY_TX_EN | | |
517 | ENETC_PM0_CMD_TXP | ENETC_PM0_PROMISC | | |
518 | ENETC_PM0_TX_EN | ENETC_PM0_RX_EN); | |
519 | /* set auto-speed for RGMII */ | |
520 | if (enetc_port_rd(hw, ENETC_PM0_IF_MODE) & ENETC_PMO_IFM_RG) | |
521 | enetc_port_wr(hw, ENETC_PM0_IF_MODE, ENETC_PM0_IFM_RGAUTO); | |
522 | if (enetc_global_rd(hw, ENETC_G_EPFBLPR(1)) == ENETC_G_EPFBLPR1_XGMII) | |
523 | enetc_port_wr(hw, ENETC_PM0_IF_MODE, ENETC_PM0_IFM_XGMII); | |
524 | } | |
525 | ||
526 | static void enetc_configure_port_pmac(struct enetc_hw *hw) | |
527 | { | |
528 | u32 temp; | |
529 | ||
530 | /* Set pMAC step lock */ | |
531 | temp = enetc_port_rd(hw, ENETC_PFPMR); | |
532 | enetc_port_wr(hw, ENETC_PFPMR, | |
533 | temp | ENETC_PFPMR_PMACE | ENETC_PFPMR_MWLM); | |
534 | ||
535 | temp = enetc_port_rd(hw, ENETC_MMCSR); | |
536 | enetc_port_wr(hw, ENETC_MMCSR, temp | ENETC_MMCSR_ME); | |
537 | } | |
538 | ||
539 | static void enetc_configure_port(struct enetc_pf *pf) | |
540 | { | |
d382563f | 541 | u8 hash_key[ENETC_RSSHASH_KEY_SIZE]; |
d4fd0404 CM |
542 | struct enetc_hw *hw = &pf->si->hw; |
543 | ||
544 | enetc_configure_port_pmac(hw); | |
545 | ||
546 | enetc_configure_port_mac(hw); | |
547 | ||
548 | enetc_port_si_configure(pf->si); | |
549 | ||
d382563f CM |
550 | /* set up hash key */ |
551 | get_random_bytes(hash_key, ENETC_RSSHASH_KEY_SIZE); | |
552 | enetc_set_rss_key(hw, hash_key); | |
553 | ||
554 | /* split up RFS entries */ | |
555 | enetc_port_assign_rfs_entries(pf->si); | |
556 | ||
d4fd0404 CM |
557 | /* fix-up primary MAC addresses, if not set already */ |
558 | enetc_port_setup_primary_mac_address(pf->si); | |
559 | ||
560 | /* enforce VLAN promisc mode for all SIs */ | |
561 | pf->vlan_promisc_simap = ENETC_VLAN_PROMISC_MAP_ALL; | |
562 | enetc_set_vlan_promisc(hw, pf->vlan_promisc_simap); | |
563 | ||
564 | enetc_port_wr(hw, ENETC_PSIPMR, 0); | |
565 | ||
566 | /* enable port */ | |
567 | enetc_port_wr(hw, ENETC_PMR, ENETC_PMR_EN); | |
568 | } | |
569 | ||
beb74ac8 CM |
570 | /* Messaging */ |
571 | static u16 enetc_msg_pf_set_vf_primary_mac_addr(struct enetc_pf *pf, | |
572 | int vf_id) | |
573 | { | |
574 | struct enetc_vf_state *vf_state = &pf->vf_state[vf_id]; | |
575 | struct enetc_msg_swbd *msg = &pf->rxmsg[vf_id]; | |
576 | struct enetc_msg_cmd_set_primary_mac *cmd; | |
577 | struct device *dev = &pf->si->pdev->dev; | |
578 | u16 cmd_id; | |
579 | char *addr; | |
580 | ||
581 | cmd = (struct enetc_msg_cmd_set_primary_mac *)msg->vaddr; | |
582 | cmd_id = cmd->header.id; | |
583 | if (cmd_id != ENETC_MSG_CMD_MNG_ADD) | |
584 | return ENETC_MSG_CMD_STATUS_FAIL; | |
585 | ||
586 | addr = cmd->mac.sa_data; | |
587 | if (vf_state->flags & ENETC_VF_FLAG_PF_SET_MAC) | |
588 | dev_warn(dev, "Attempt to override PF set mac addr for VF%d\n", | |
589 | vf_id); | |
590 | else | |
591 | enetc_pf_set_primary_mac_addr(&pf->si->hw, vf_id + 1, addr); | |
592 | ||
593 | return ENETC_MSG_CMD_STATUS_OK; | |
594 | } | |
595 | ||
596 | void enetc_msg_handle_rxmsg(struct enetc_pf *pf, int vf_id, u16 *status) | |
597 | { | |
598 | struct enetc_msg_swbd *msg = &pf->rxmsg[vf_id]; | |
599 | struct device *dev = &pf->si->pdev->dev; | |
600 | struct enetc_msg_cmd_header *cmd_hdr; | |
601 | u16 cmd_type; | |
602 | ||
603 | *status = ENETC_MSG_CMD_STATUS_OK; | |
604 | cmd_hdr = (struct enetc_msg_cmd_header *)msg->vaddr; | |
605 | cmd_type = cmd_hdr->type; | |
606 | ||
607 | switch (cmd_type) { | |
608 | case ENETC_MSG_CMD_MNG_MAC: | |
609 | *status = enetc_msg_pf_set_vf_primary_mac_addr(pf, vf_id); | |
610 | break; | |
611 | default: | |
612 | dev_err(dev, "command not supported (cmd_type: 0x%x)\n", | |
613 | cmd_type); | |
614 | } | |
615 | } | |
616 | ||
d4fd0404 CM |
617 | #ifdef CONFIG_PCI_IOV |
618 | static int enetc_sriov_configure(struct pci_dev *pdev, int num_vfs) | |
619 | { | |
620 | struct enetc_si *si = pci_get_drvdata(pdev); | |
621 | struct enetc_pf *pf = enetc_si_priv(si); | |
622 | int err; | |
623 | ||
624 | if (!num_vfs) { | |
beb74ac8 CM |
625 | enetc_msg_psi_free(pf); |
626 | kfree(pf->vf_state); | |
d4fd0404 CM |
627 | pf->num_vfs = 0; |
628 | pci_disable_sriov(pdev); | |
629 | } else { | |
630 | pf->num_vfs = num_vfs; | |
631 | ||
beb74ac8 CM |
632 | pf->vf_state = kcalloc(num_vfs, sizeof(struct enetc_vf_state), |
633 | GFP_KERNEL); | |
634 | if (!pf->vf_state) { | |
635 | pf->num_vfs = 0; | |
636 | return -ENOMEM; | |
637 | } | |
638 | ||
639 | err = enetc_msg_psi_init(pf); | |
640 | if (err) { | |
641 | dev_err(&pdev->dev, "enetc_msg_psi_init (%d)\n", err); | |
642 | goto err_msg_psi; | |
643 | } | |
644 | ||
d4fd0404 CM |
645 | err = pci_enable_sriov(pdev, num_vfs); |
646 | if (err) { | |
647 | dev_err(&pdev->dev, "pci_enable_sriov err %d\n", err); | |
648 | goto err_en_sriov; | |
649 | } | |
650 | } | |
651 | ||
652 | return num_vfs; | |
653 | ||
654 | err_en_sriov: | |
beb74ac8 CM |
655 | enetc_msg_psi_free(pf); |
656 | err_msg_psi: | |
657 | kfree(pf->vf_state); | |
d4fd0404 CM |
658 | pf->num_vfs = 0; |
659 | ||
660 | return err; | |
661 | } | |
662 | #else | |
663 | #define enetc_sriov_configure(pdev, num_vfs) (void)0 | |
664 | #endif | |
665 | ||
666 | static int enetc_pf_set_features(struct net_device *ndev, | |
667 | netdev_features_t features) | |
668 | { | |
669 | netdev_features_t changed = ndev->features ^ features; | |
670 | struct enetc_ndev_priv *priv = netdev_priv(ndev); | |
671 | ||
672 | if (changed & NETIF_F_HW_VLAN_CTAG_RX) | |
673 | enetc_enable_rxvlan(&priv->si->hw, 0, | |
674 | !!(features & NETIF_F_HW_VLAN_CTAG_RX)); | |
675 | ||
676 | if (changed & NETIF_F_HW_VLAN_CTAG_TX) | |
677 | enetc_enable_txvlan(&priv->si->hw, 0, | |
678 | !!(features & NETIF_F_HW_VLAN_CTAG_TX)); | |
679 | ||
680 | if (changed & NETIF_F_LOOPBACK) | |
681 | enetc_set_loopback(ndev, !!(features & NETIF_F_LOOPBACK)); | |
682 | ||
d382563f | 683 | return enetc_set_features(ndev, features); |
d4fd0404 CM |
684 | } |
685 | ||
686 | static const struct net_device_ops enetc_ndev_ops = { | |
687 | .ndo_open = enetc_open, | |
688 | .ndo_stop = enetc_close, | |
689 | .ndo_start_xmit = enetc_xmit, | |
690 | .ndo_get_stats = enetc_get_stats, | |
691 | .ndo_set_mac_address = enetc_pf_set_mac_addr, | |
692 | .ndo_set_rx_mode = enetc_pf_set_rx_mode, | |
693 | .ndo_vlan_rx_add_vid = enetc_vlan_rx_add_vid, | |
694 | .ndo_vlan_rx_kill_vid = enetc_vlan_rx_del_vid, | |
695 | .ndo_set_vf_mac = enetc_pf_set_vf_mac, | |
696 | .ndo_set_vf_vlan = enetc_pf_set_vf_vlan, | |
697 | .ndo_set_vf_spoofchk = enetc_pf_set_vf_spoofchk, | |
698 | .ndo_set_features = enetc_pf_set_features, | |
d3982312 | 699 | .ndo_do_ioctl = enetc_ioctl, |
cbe9e835 | 700 | .ndo_setup_tc = enetc_setup_tc, |
d4fd0404 CM |
701 | }; |
702 | ||
703 | static void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev, | |
704 | const struct net_device_ops *ndev_ops) | |
705 | { | |
706 | struct enetc_ndev_priv *priv = netdev_priv(ndev); | |
707 | ||
708 | SET_NETDEV_DEV(ndev, &si->pdev->dev); | |
709 | priv->ndev = ndev; | |
710 | priv->si = si; | |
711 | priv->dev = &si->pdev->dev; | |
712 | si->ndev = ndev; | |
713 | ||
714 | priv->msg_enable = (NETIF_MSG_WOL << 1) - 1; | |
715 | ndev->netdev_ops = ndev_ops; | |
716 | enetc_set_ethtool_ops(ndev); | |
717 | ndev->watchdog_timeo = 5 * HZ; | |
718 | ndev->max_mtu = ENETC_MAX_MTU; | |
719 | ||
5d91eebc | 720 | ndev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM | NETIF_F_HW_CSUM | |
d4fd0404 CM |
721 | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | |
722 | NETIF_F_LOOPBACK; | |
723 | ndev->features = NETIF_F_HIGHDMA | NETIF_F_SG | | |
724 | NETIF_F_RXCSUM | NETIF_F_HW_CSUM | | |
725 | NETIF_F_HW_VLAN_CTAG_TX | | |
726 | NETIF_F_HW_VLAN_CTAG_RX | | |
727 | NETIF_F_HW_VLAN_CTAG_FILTER; | |
728 | ||
d382563f CM |
729 | if (si->num_rss) |
730 | ndev->hw_features |= NETIF_F_RXHASH; | |
731 | ||
d4fd0404 CM |
732 | if (si->errata & ENETC_ERR_TXCSUM) { |
733 | ndev->hw_features &= ~NETIF_F_HW_CSUM; | |
734 | ndev->features &= ~NETIF_F_HW_CSUM; | |
735 | } | |
736 | ||
737 | ndev->priv_flags |= IFF_UNICAST_FLT; | |
738 | ||
2e47cb41 PL |
739 | if (si->hw_features & ENETC_SI_F_QBV) |
740 | priv->active_offloads |= ENETC_F_QBV; | |
741 | ||
d4fd0404 CM |
742 | /* pick up primary MAC address from SI */ |
743 | enetc_get_primary_mac_addr(&si->hw, ndev->dev_addr); | |
744 | } | |
745 | ||
6517798d CM |
746 | static int enetc_mdio_probe(struct enetc_pf *pf) |
747 | { | |
748 | struct device *dev = &pf->si->pdev->dev; | |
749 | struct enetc_mdio_priv *mdio_priv; | |
750 | struct device_node *np; | |
751 | struct mii_bus *bus; | |
752 | int err; | |
753 | ||
754 | bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv)); | |
755 | if (!bus) | |
756 | return -ENOMEM; | |
757 | ||
758 | bus->name = "Freescale ENETC MDIO Bus"; | |
759 | bus->read = enetc_mdio_read; | |
760 | bus->write = enetc_mdio_write; | |
761 | bus->parent = dev; | |
762 | mdio_priv = bus->priv; | |
763 | mdio_priv->hw = &pf->si->hw; | |
764 | mdio_priv->mdio_base = ENETC_EMDIO_BASE; | |
765 | snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev)); | |
766 | ||
767 | np = of_get_child_by_name(dev->of_node, "mdio"); | |
768 | if (!np) { | |
769 | dev_err(dev, "MDIO node missing\n"); | |
770 | return -EINVAL; | |
771 | } | |
772 | ||
773 | err = of_mdiobus_register(bus, np); | |
774 | if (err) { | |
775 | of_node_put(np); | |
776 | dev_err(dev, "cannot register MDIO bus\n"); | |
777 | return err; | |
778 | } | |
779 | ||
780 | of_node_put(np); | |
781 | pf->mdio = bus; | |
782 | ||
783 | return 0; | |
784 | } | |
785 | ||
786 | static void enetc_mdio_remove(struct enetc_pf *pf) | |
787 | { | |
788 | if (pf->mdio) | |
789 | mdiobus_unregister(pf->mdio); | |
790 | } | |
791 | ||
d4fd0404 CM |
792 | static int enetc_of_get_phy(struct enetc_ndev_priv *priv) |
793 | { | |
ebfcb23d | 794 | struct enetc_pf *pf = enetc_si_priv(priv->si); |
d4fd0404 | 795 | struct device_node *np = priv->dev->of_node; |
231ece36 | 796 | struct device_node *mdio_np; |
d4fd0404 CM |
797 | int err; |
798 | ||
d4fd0404 CM |
799 | priv->phy_node = of_parse_phandle(np, "phy-handle", 0); |
800 | if (!priv->phy_node) { | |
801 | if (!of_phy_is_fixed_link(np)) { | |
802 | dev_err(priv->dev, "PHY not specified\n"); | |
803 | return -ENODEV; | |
804 | } | |
805 | ||
806 | err = of_phy_register_fixed_link(np); | |
807 | if (err < 0) { | |
808 | dev_err(priv->dev, "fixed link registration failed\n"); | |
809 | return err; | |
810 | } | |
811 | ||
812 | priv->phy_node = of_node_get(np); | |
813 | } | |
814 | ||
231ece36 CM |
815 | mdio_np = of_get_child_by_name(np, "mdio"); |
816 | if (mdio_np) { | |
817 | of_node_put(mdio_np); | |
ebfcb23d CM |
818 | err = enetc_mdio_probe(pf); |
819 | if (err) { | |
820 | of_node_put(priv->phy_node); | |
821 | return err; | |
822 | } | |
823 | } | |
824 | ||
0c65b2b9 AL |
825 | err = of_get_phy_mode(np, &priv->if_mode); |
826 | if (err) { | |
d4fd0404 CM |
827 | dev_err(priv->dev, "missing phy type\n"); |
828 | of_node_put(priv->phy_node); | |
829 | if (of_phy_is_fixed_link(np)) | |
830 | of_phy_deregister_fixed_link(np); | |
ebfcb23d CM |
831 | else |
832 | enetc_mdio_remove(pf); | |
d4fd0404 CM |
833 | |
834 | return -EINVAL; | |
835 | } | |
836 | ||
837 | return 0; | |
838 | } | |
839 | ||
840 | static void enetc_of_put_phy(struct enetc_ndev_priv *priv) | |
841 | { | |
842 | struct device_node *np = priv->dev->of_node; | |
843 | ||
844 | if (np && of_phy_is_fixed_link(np)) | |
845 | of_phy_deregister_fixed_link(np); | |
846 | if (priv->phy_node) | |
847 | of_node_put(priv->phy_node); | |
848 | } | |
849 | ||
850 | static int enetc_pf_probe(struct pci_dev *pdev, | |
851 | const struct pci_device_id *ent) | |
852 | { | |
853 | struct enetc_ndev_priv *priv; | |
854 | struct net_device *ndev; | |
855 | struct enetc_si *si; | |
856 | struct enetc_pf *pf; | |
857 | int err; | |
858 | ||
859 | if (pdev->dev.of_node && !of_device_is_available(pdev->dev.of_node)) { | |
860 | dev_info(&pdev->dev, "device is disabled, skipping\n"); | |
861 | return -ENODEV; | |
862 | } | |
863 | ||
864 | err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(*pf)); | |
865 | if (err) { | |
866 | dev_err(&pdev->dev, "PCI probing failed\n"); | |
867 | return err; | |
868 | } | |
869 | ||
870 | si = pci_get_drvdata(pdev); | |
871 | if (!si->hw.port || !si->hw.global) { | |
872 | err = -ENODEV; | |
873 | dev_err(&pdev->dev, "could not map PF space, probing a VF?\n"); | |
874 | goto err_map_pf_space; | |
875 | } | |
876 | ||
877 | pf = enetc_si_priv(si); | |
878 | pf->si = si; | |
879 | pf->total_vfs = pci_sriov_get_totalvfs(pdev); | |
880 | ||
881 | enetc_configure_port(pf); | |
882 | ||
883 | enetc_get_si_caps(si); | |
884 | ||
885 | ndev = alloc_etherdev_mq(sizeof(*priv), ENETC_MAX_NUM_TXQS); | |
886 | if (!ndev) { | |
887 | err = -ENOMEM; | |
888 | dev_err(&pdev->dev, "netdev creation failed\n"); | |
889 | goto err_alloc_netdev; | |
890 | } | |
891 | ||
892 | enetc_pf_netdev_setup(si, ndev, &enetc_ndev_ops); | |
893 | ||
894 | priv = netdev_priv(ndev); | |
895 | ||
896 | enetc_init_si_rings_params(priv); | |
897 | ||
898 | err = enetc_alloc_si_resources(priv); | |
899 | if (err) { | |
900 | dev_err(&pdev->dev, "SI resource alloc failed\n"); | |
901 | goto err_alloc_si_res; | |
902 | } | |
903 | ||
904 | err = enetc_alloc_msix(priv); | |
905 | if (err) { | |
906 | dev_err(&pdev->dev, "MSIX alloc failed\n"); | |
907 | goto err_alloc_msix; | |
908 | } | |
909 | ||
910 | err = enetc_of_get_phy(priv); | |
911 | if (err) | |
912 | dev_warn(&pdev->dev, "Fallback to PHY-less operation\n"); | |
913 | ||
914 | err = register_netdev(ndev); | |
915 | if (err) | |
916 | goto err_reg_netdev; | |
917 | ||
918 | netif_carrier_off(ndev); | |
919 | ||
d4fd0404 CM |
920 | return 0; |
921 | ||
922 | err_reg_netdev: | |
923 | enetc_of_put_phy(priv); | |
924 | enetc_free_msix(priv); | |
925 | err_alloc_msix: | |
926 | enetc_free_si_resources(priv); | |
927 | err_alloc_si_res: | |
928 | si->ndev = NULL; | |
929 | free_netdev(ndev); | |
930 | err_alloc_netdev: | |
931 | err_map_pf_space: | |
932 | enetc_pci_remove(pdev); | |
933 | ||
934 | return err; | |
935 | } | |
936 | ||
937 | static void enetc_pf_remove(struct pci_dev *pdev) | |
938 | { | |
939 | struct enetc_si *si = pci_get_drvdata(pdev); | |
940 | struct enetc_pf *pf = enetc_si_priv(si); | |
941 | struct enetc_ndev_priv *priv; | |
942 | ||
943 | if (pf->num_vfs) | |
944 | enetc_sriov_configure(pdev, 0); | |
945 | ||
946 | priv = netdev_priv(si->ndev); | |
d4fd0404 CM |
947 | unregister_netdev(si->ndev); |
948 | ||
ebfcb23d | 949 | enetc_mdio_remove(pf); |
d4fd0404 CM |
950 | enetc_of_put_phy(priv); |
951 | ||
952 | enetc_free_msix(priv); | |
953 | ||
954 | enetc_free_si_resources(priv); | |
955 | ||
956 | free_netdev(si->ndev); | |
957 | ||
958 | enetc_pci_remove(pdev); | |
959 | } | |
960 | ||
961 | static const struct pci_device_id enetc_pf_id_table[] = { | |
962 | { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PF) }, | |
963 | { 0, } /* End of table. */ | |
964 | }; | |
965 | MODULE_DEVICE_TABLE(pci, enetc_pf_id_table); | |
966 | ||
967 | static struct pci_driver enetc_pf_driver = { | |
968 | .name = KBUILD_MODNAME, | |
969 | .id_table = enetc_pf_id_table, | |
970 | .probe = enetc_pf_probe, | |
971 | .remove = enetc_pf_remove, | |
972 | #ifdef CONFIG_PCI_IOV | |
973 | .sriov_configure = enetc_sriov_configure, | |
974 | #endif | |
975 | }; | |
976 | module_pci_driver(enetc_pf_driver); | |
977 | ||
978 | MODULE_DESCRIPTION(ENETC_DRV_NAME_STR); | |
979 | MODULE_LICENSE("Dual BSD/GPL"); |