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