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