1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */ |
3 | |
4 | #include <linux/kernel.h> |
5 | #include <linux/module.h> |
6 | #include <linux/if_ether.h> |
7 | #include <linux/nospec.h> |
8 | |
9 | #include "core.h" |
10 | #include "bus.h" |
11 | #include "trans.h" |
12 | #include "commands.h" |
13 | #include "cfg80211.h" |
14 | #include "event.h" |
15 | #include "util.h" |
16 | #include "switchdev.h" |
17 | |
18 | #define QTNF_PRIMARY_VIF_IDX 0 |
19 | |
20 | static bool slave_radar = true; |
21 | module_param(slave_radar, bool, 0644); |
22 | MODULE_PARM_DESC(slave_radar, "set 0 to disable radar detection in slave mode" ); |
23 | |
24 | static bool dfs_offload; |
25 | module_param(dfs_offload, bool, 0644); |
26 | MODULE_PARM_DESC(dfs_offload, "set 1 to enable DFS offload to firmware" ); |
27 | |
28 | static struct dentry *qtnf_debugfs_dir; |
29 | |
30 | bool qtnf_slave_radar_get(void) |
31 | { |
32 | return slave_radar; |
33 | } |
34 | |
35 | bool qtnf_dfs_offload_get(void) |
36 | { |
37 | return dfs_offload; |
38 | } |
39 | |
40 | struct qtnf_wmac *qtnf_core_get_mac(const struct qtnf_bus *bus, u8 macid) |
41 | { |
42 | struct qtnf_wmac *mac = NULL; |
43 | |
44 | if (macid >= QTNF_MAX_MAC) { |
45 | pr_err("invalid MAC index %u\n" , macid); |
46 | return NULL; |
47 | } |
48 | |
49 | macid = array_index_nospec(macid, QTNF_MAX_MAC); |
50 | mac = bus->mac[macid]; |
51 | |
52 | if (unlikely(!mac)) { |
53 | pr_err("MAC%u: not initialized\n" , macid); |
54 | return NULL; |
55 | } |
56 | |
57 | return mac; |
58 | } |
59 | |
60 | /* Netdev handler for open. |
61 | */ |
62 | static int qtnf_netdev_open(struct net_device *ndev) |
63 | { |
64 | netif_carrier_off(dev: ndev); |
65 | qtnf_netdev_updown(ndev, up: 1); |
66 | return 0; |
67 | } |
68 | |
69 | /* Netdev handler for close. |
70 | */ |
71 | static int qtnf_netdev_close(struct net_device *ndev) |
72 | { |
73 | netif_carrier_off(dev: ndev); |
74 | qtnf_virtual_intf_cleanup(ndev); |
75 | qtnf_netdev_updown(ndev, up: 0); |
76 | return 0; |
77 | } |
78 | |
79 | static void qtnf_packet_send_hi_pri(struct sk_buff *skb) |
80 | { |
81 | struct qtnf_vif *vif = qtnf_netdev_get_priv(dev: skb->dev); |
82 | |
83 | skb_queue_tail(list: &vif->high_pri_tx_queue, newsk: skb); |
84 | queue_work(wq: vif->mac->bus->hprio_workqueue, work: &vif->high_pri_tx_work); |
85 | } |
86 | |
87 | /* Netdev handler for data transmission. |
88 | */ |
89 | static netdev_tx_t |
90 | qtnf_netdev_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev) |
91 | { |
92 | struct qtnf_vif *vif; |
93 | struct qtnf_wmac *mac; |
94 | |
95 | vif = qtnf_netdev_get_priv(dev: ndev); |
96 | |
97 | if (unlikely(skb->dev != ndev)) { |
98 | pr_err_ratelimited("invalid skb->dev" ); |
99 | dev_kfree_skb_any(skb); |
100 | return 0; |
101 | } |
102 | |
103 | if (unlikely(vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED)) { |
104 | pr_err_ratelimited("%s: VIF not initialized\n" , ndev->name); |
105 | dev_kfree_skb_any(skb); |
106 | return 0; |
107 | } |
108 | |
109 | mac = vif->mac; |
110 | if (unlikely(!mac)) { |
111 | pr_err_ratelimited("%s: NULL mac pointer" , ndev->name); |
112 | dev_kfree_skb_any(skb); |
113 | return 0; |
114 | } |
115 | |
116 | if (!skb->len || (skb->len > ETH_FRAME_LEN)) { |
117 | pr_err_ratelimited("%s: invalid skb len %d\n" , ndev->name, |
118 | skb->len); |
119 | dev_kfree_skb_any(skb); |
120 | ndev->stats.tx_dropped++; |
121 | return 0; |
122 | } |
123 | |
124 | /* tx path is enabled: reset vif timeout */ |
125 | vif->cons_tx_timeout_cnt = 0; |
126 | |
127 | if (unlikely(skb->protocol == htons(ETH_P_PAE))) { |
128 | qtnf_packet_send_hi_pri(skb); |
129 | dev_sw_netstats_tx_add(dev: ndev, packets: 1, len: skb->len); |
130 | return NETDEV_TX_OK; |
131 | } |
132 | |
133 | return qtnf_bus_data_tx(bus: mac->bus, skb, macid: mac->macid, vifid: vif->vifid); |
134 | } |
135 | |
136 | /* Netdev handler for transmission timeout. |
137 | */ |
138 | static void qtnf_netdev_tx_timeout(struct net_device *ndev, unsigned int txqueue) |
139 | { |
140 | struct qtnf_vif *vif = qtnf_netdev_get_priv(dev: ndev); |
141 | struct qtnf_wmac *mac; |
142 | struct qtnf_bus *bus; |
143 | |
144 | if (unlikely(!vif || !vif->mac || !vif->mac->bus)) |
145 | return; |
146 | |
147 | mac = vif->mac; |
148 | bus = mac->bus; |
149 | |
150 | pr_warn("VIF%u.%u: Tx timeout- %lu\n" , mac->macid, vif->vifid, jiffies); |
151 | |
152 | qtnf_bus_data_tx_timeout(bus, ndev); |
153 | ndev->stats.tx_errors++; |
154 | |
155 | if (++vif->cons_tx_timeout_cnt > QTNF_TX_TIMEOUT_TRSHLD) { |
156 | pr_err("Tx timeout threshold exceeded !\n" ); |
157 | pr_err("schedule interface %s reset !\n" , netdev_name(ndev)); |
158 | queue_work(wq: bus->workqueue, work: &vif->reset_work); |
159 | } |
160 | } |
161 | |
162 | static int qtnf_netdev_set_mac_address(struct net_device *ndev, void *addr) |
163 | { |
164 | struct qtnf_vif *vif = qtnf_netdev_get_priv(dev: ndev); |
165 | struct sockaddr *sa = addr; |
166 | int ret; |
167 | unsigned char old_addr[ETH_ALEN]; |
168 | |
169 | memcpy(old_addr, sa->sa_data, sizeof(old_addr)); |
170 | |
171 | ret = eth_mac_addr(dev: ndev, p: sa); |
172 | if (ret) |
173 | return ret; |
174 | |
175 | qtnf_scan_done(mac: vif->mac, aborted: true); |
176 | |
177 | ret = qtnf_cmd_send_change_intf_type(vif, iftype: vif->wdev.iftype, |
178 | use4addr: vif->wdev.use_4addr, |
179 | mac_addr: sa->sa_data); |
180 | |
181 | if (ret) |
182 | eth_hw_addr_set(dev: ndev, addr: old_addr); |
183 | |
184 | return ret; |
185 | } |
186 | |
187 | static int qtnf_netdev_port_parent_id(struct net_device *ndev, |
188 | struct netdev_phys_item_id *ppid) |
189 | { |
190 | const struct qtnf_vif *vif = qtnf_netdev_get_priv(dev: ndev); |
191 | const struct qtnf_bus *bus = vif->mac->bus; |
192 | |
193 | ppid->id_len = sizeof(bus->hw_id); |
194 | memcpy(&ppid->id, bus->hw_id, ppid->id_len); |
195 | |
196 | return 0; |
197 | } |
198 | |
199 | static int qtnf_netdev_alloc_pcpu_stats(struct net_device *dev) |
200 | { |
201 | dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); |
202 | |
203 | return dev->tstats ? 0 : -ENOMEM; |
204 | } |
205 | |
206 | static void qtnf_netdev_free_pcpu_stats(struct net_device *dev) |
207 | { |
208 | free_percpu(pdata: dev->tstats); |
209 | } |
210 | |
211 | /* Network device ops handlers */ |
212 | const struct net_device_ops qtnf_netdev_ops = { |
213 | .ndo_init = qtnf_netdev_alloc_pcpu_stats, |
214 | .ndo_uninit = qtnf_netdev_free_pcpu_stats, |
215 | .ndo_open = qtnf_netdev_open, |
216 | .ndo_stop = qtnf_netdev_close, |
217 | .ndo_start_xmit = qtnf_netdev_hard_start_xmit, |
218 | .ndo_tx_timeout = qtnf_netdev_tx_timeout, |
219 | .ndo_get_stats64 = dev_get_tstats64, |
220 | .ndo_set_mac_address = qtnf_netdev_set_mac_address, |
221 | .ndo_get_port_parent_id = qtnf_netdev_port_parent_id, |
222 | }; |
223 | |
224 | static int qtnf_mac_init_single_band(struct wiphy *wiphy, |
225 | struct qtnf_wmac *mac, |
226 | enum nl80211_band band) |
227 | { |
228 | int ret; |
229 | |
230 | wiphy->bands[band] = kzalloc(size: sizeof(*wiphy->bands[band]), GFP_KERNEL); |
231 | if (!wiphy->bands[band]) |
232 | return -ENOMEM; |
233 | |
234 | wiphy->bands[band]->band = band; |
235 | |
236 | ret = qtnf_cmd_band_info_get(mac, band: wiphy->bands[band]); |
237 | if (ret) { |
238 | pr_err("MAC%u: band %u: failed to get chans info: %d\n" , |
239 | mac->macid, band, ret); |
240 | return ret; |
241 | } |
242 | |
243 | qtnf_band_init_rates(band: wiphy->bands[band]); |
244 | |
245 | return 0; |
246 | } |
247 | |
248 | static int qtnf_mac_init_bands(struct qtnf_wmac *mac) |
249 | { |
250 | struct wiphy *wiphy = priv_to_wiphy(priv: mac); |
251 | int ret = 0; |
252 | |
253 | if (mac->macinfo.bands_cap & QLINK_BAND_2GHZ) { |
254 | ret = qtnf_mac_init_single_band(wiphy, mac, band: NL80211_BAND_2GHZ); |
255 | if (ret) |
256 | goto out; |
257 | } |
258 | |
259 | if (mac->macinfo.bands_cap & QLINK_BAND_5GHZ) { |
260 | ret = qtnf_mac_init_single_band(wiphy, mac, band: NL80211_BAND_5GHZ); |
261 | if (ret) |
262 | goto out; |
263 | } |
264 | |
265 | if (mac->macinfo.bands_cap & QLINK_BAND_60GHZ) |
266 | ret = qtnf_mac_init_single_band(wiphy, mac, band: NL80211_BAND_60GHZ); |
267 | |
268 | out: |
269 | return ret; |
270 | } |
271 | |
272 | struct qtnf_vif *qtnf_mac_get_free_vif(struct qtnf_wmac *mac) |
273 | { |
274 | struct qtnf_vif *vif; |
275 | int i; |
276 | |
277 | for (i = 0; i < QTNF_MAX_INTF; i++) { |
278 | vif = &mac->iflist[i]; |
279 | if (vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED) |
280 | return vif; |
281 | } |
282 | |
283 | return NULL; |
284 | } |
285 | |
286 | struct qtnf_vif *qtnf_mac_get_base_vif(struct qtnf_wmac *mac) |
287 | { |
288 | struct qtnf_vif *vif; |
289 | |
290 | vif = &mac->iflist[QTNF_PRIMARY_VIF_IDX]; |
291 | |
292 | if (vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED) |
293 | return NULL; |
294 | |
295 | return vif; |
296 | } |
297 | |
298 | void qtnf_mac_iface_comb_free(struct qtnf_wmac *mac) |
299 | { |
300 | struct ieee80211_iface_combination *comb; |
301 | int i; |
302 | |
303 | if (mac->macinfo.if_comb) { |
304 | for (i = 0; i < mac->macinfo.n_if_comb; i++) { |
305 | comb = &mac->macinfo.if_comb[i]; |
306 | kfree(objp: comb->limits); |
307 | comb->limits = NULL; |
308 | } |
309 | |
310 | kfree(objp: mac->macinfo.if_comb); |
311 | mac->macinfo.if_comb = NULL; |
312 | } |
313 | } |
314 | |
315 | void qtnf_mac_ext_caps_free(struct qtnf_wmac *mac) |
316 | { |
317 | if (mac->macinfo.extended_capabilities_len) { |
318 | kfree(objp: mac->macinfo.extended_capabilities); |
319 | mac->macinfo.extended_capabilities = NULL; |
320 | |
321 | kfree(objp: mac->macinfo.extended_capabilities_mask); |
322 | mac->macinfo.extended_capabilities_mask = NULL; |
323 | |
324 | mac->macinfo.extended_capabilities_len = 0; |
325 | } |
326 | } |
327 | |
328 | static void qtnf_vif_reset_handler(struct work_struct *work) |
329 | { |
330 | struct qtnf_vif *vif = container_of(work, struct qtnf_vif, reset_work); |
331 | |
332 | rtnl_lock(); |
333 | |
334 | if (vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED) { |
335 | rtnl_unlock(); |
336 | return; |
337 | } |
338 | |
339 | /* stop tx completely */ |
340 | netif_tx_stop_all_queues(dev: vif->netdev); |
341 | if (netif_carrier_ok(dev: vif->netdev)) |
342 | netif_carrier_off(dev: vif->netdev); |
343 | |
344 | qtnf_cfg80211_vif_reset(vif); |
345 | |
346 | rtnl_unlock(); |
347 | } |
348 | |
349 | static void qtnf_mac_init_primary_intf(struct qtnf_wmac *mac) |
350 | { |
351 | struct qtnf_vif *vif = &mac->iflist[QTNF_PRIMARY_VIF_IDX]; |
352 | |
353 | vif->wdev.iftype = NL80211_IFTYPE_STATION; |
354 | vif->bss_priority = QTNF_DEF_BSS_PRIORITY; |
355 | vif->wdev.wiphy = priv_to_wiphy(priv: mac); |
356 | INIT_WORK(&vif->reset_work, qtnf_vif_reset_handler); |
357 | vif->cons_tx_timeout_cnt = 0; |
358 | } |
359 | |
360 | static void qtnf_mac_scan_finish(struct qtnf_wmac *mac, bool aborted) |
361 | { |
362 | struct cfg80211_scan_info info = { |
363 | .aborted = aborted, |
364 | }; |
365 | |
366 | mutex_lock(&mac->mac_lock); |
367 | |
368 | if (mac->scan_req) { |
369 | cfg80211_scan_done(request: mac->scan_req, info: &info); |
370 | mac->scan_req = NULL; |
371 | } |
372 | |
373 | mutex_unlock(lock: &mac->mac_lock); |
374 | } |
375 | |
376 | void qtnf_scan_done(struct qtnf_wmac *mac, bool aborted) |
377 | { |
378 | cancel_delayed_work_sync(dwork: &mac->scan_timeout); |
379 | qtnf_mac_scan_finish(mac, aborted); |
380 | } |
381 | |
382 | static void qtnf_mac_scan_timeout(struct work_struct *work) |
383 | { |
384 | struct qtnf_wmac *mac = |
385 | container_of(work, struct qtnf_wmac, scan_timeout.work); |
386 | |
387 | pr_warn("MAC%d: scan timed out\n" , mac->macid); |
388 | qtnf_mac_scan_finish(mac, aborted: true); |
389 | } |
390 | |
391 | static void qtnf_vif_send_data_high_pri(struct work_struct *work) |
392 | { |
393 | struct qtnf_vif *vif = |
394 | container_of(work, struct qtnf_vif, high_pri_tx_work); |
395 | struct sk_buff *skb; |
396 | |
397 | if (!vif->netdev || |
398 | vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED) |
399 | return; |
400 | |
401 | while ((skb = skb_dequeue(list: &vif->high_pri_tx_queue))) { |
402 | qtnf_cmd_send_frame(vif, cookie: 0, flags: QLINK_FRAME_TX_FLAG_8023, |
403 | freq: 0, buf: skb->data, len: skb->len); |
404 | dev_kfree_skb_any(skb); |
405 | } |
406 | } |
407 | |
408 | static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus, |
409 | unsigned int macid) |
410 | { |
411 | struct platform_device *pdev = NULL; |
412 | struct qtnf_wmac *mac; |
413 | struct qtnf_vif *vif; |
414 | struct wiphy *wiphy; |
415 | unsigned int i; |
416 | |
417 | if (bus->hw_info.num_mac > 1) { |
418 | pdev = platform_device_register_data(parent: bus->dev, |
419 | name: dev_name(dev: bus->dev), |
420 | id: macid, NULL, size: 0); |
421 | if (IS_ERR(ptr: pdev)) |
422 | return ERR_PTR(error: -EINVAL); |
423 | } |
424 | |
425 | wiphy = qtnf_wiphy_allocate(bus, pdev); |
426 | if (!wiphy) { |
427 | if (pdev) |
428 | platform_device_unregister(pdev); |
429 | return ERR_PTR(error: -ENOMEM); |
430 | } |
431 | |
432 | mac = wiphy_priv(wiphy); |
433 | |
434 | mac->macid = macid; |
435 | mac->pdev = pdev; |
436 | mac->bus = bus; |
437 | mutex_init(&mac->mac_lock); |
438 | INIT_DELAYED_WORK(&mac->scan_timeout, qtnf_mac_scan_timeout); |
439 | |
440 | for (i = 0; i < QTNF_MAX_INTF; i++) { |
441 | vif = &mac->iflist[i]; |
442 | |
443 | memset(vif, 0, sizeof(*vif)); |
444 | vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; |
445 | vif->mac = mac; |
446 | vif->vifid = i; |
447 | qtnf_sta_list_init(list: &vif->sta_list); |
448 | INIT_WORK(&vif->high_pri_tx_work, qtnf_vif_send_data_high_pri); |
449 | skb_queue_head_init(list: &vif->high_pri_tx_queue); |
450 | } |
451 | |
452 | qtnf_mac_init_primary_intf(mac); |
453 | bus->mac[macid] = mac; |
454 | |
455 | return mac; |
456 | } |
457 | |
458 | static const struct ethtool_ops qtnf_ethtool_ops = { |
459 | .get_drvinfo = cfg80211_get_drvinfo, |
460 | }; |
461 | |
462 | int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *vif, |
463 | const char *name, unsigned char name_assign_type) |
464 | { |
465 | struct wiphy *wiphy = priv_to_wiphy(priv: mac); |
466 | struct net_device *dev; |
467 | void *qdev_vif; |
468 | int ret; |
469 | |
470 | dev = alloc_netdev_mqs(sizeof_priv: sizeof(struct qtnf_vif *), name, |
471 | name_assign_type, setup: ether_setup, txqs: 1, rxqs: 1); |
472 | if (!dev) |
473 | return -ENOMEM; |
474 | |
475 | vif->netdev = dev; |
476 | |
477 | dev->netdev_ops = &qtnf_netdev_ops; |
478 | dev->needs_free_netdev = true; |
479 | dev_net_set(dev, net: wiphy_net(wiphy)); |
480 | dev->ieee80211_ptr = &vif->wdev; |
481 | eth_hw_addr_set(dev, addr: vif->mac_addr); |
482 | dev->flags |= IFF_BROADCAST | IFF_MULTICAST; |
483 | dev->watchdog_timeo = QTNF_DEF_WDOG_TIMEOUT; |
484 | dev->tx_queue_len = 100; |
485 | dev->ethtool_ops = &qtnf_ethtool_ops; |
486 | |
487 | if (qtnf_hwcap_is_set(info: &mac->bus->hw_info, bit: QLINK_HW_CAPAB_HW_BRIDGE)) |
488 | dev->needed_tailroom = sizeof(struct qtnf_frame_meta_info); |
489 | |
490 | qdev_vif = netdev_priv(dev); |
491 | *((void **)qdev_vif) = vif; |
492 | |
493 | SET_NETDEV_DEV(dev, wiphy_dev(wiphy)); |
494 | |
495 | ret = cfg80211_register_netdevice(dev); |
496 | if (ret) { |
497 | free_netdev(dev); |
498 | vif->netdev = NULL; |
499 | } |
500 | |
501 | return ret; |
502 | } |
503 | |
504 | static void qtnf_core_mac_detach(struct qtnf_bus *bus, unsigned int macid) |
505 | { |
506 | struct qtnf_wmac *mac; |
507 | struct wiphy *wiphy; |
508 | struct qtnf_vif *vif; |
509 | unsigned int i; |
510 | enum nl80211_band band; |
511 | |
512 | mac = bus->mac[macid]; |
513 | |
514 | if (!mac) |
515 | return; |
516 | |
517 | wiphy = priv_to_wiphy(priv: mac); |
518 | |
519 | for (i = 0; i < QTNF_MAX_INTF; i++) { |
520 | vif = &mac->iflist[i]; |
521 | rtnl_lock(); |
522 | if (vif->netdev && |
523 | vif->wdev.iftype != NL80211_IFTYPE_UNSPECIFIED) { |
524 | qtnf_virtual_intf_cleanup(ndev: vif->netdev); |
525 | qtnf_del_virtual_intf(wiphy, wdev: &vif->wdev); |
526 | } |
527 | rtnl_unlock(); |
528 | qtnf_sta_list_free(list: &vif->sta_list); |
529 | } |
530 | |
531 | if (mac->wiphy_registered) |
532 | wiphy_unregister(wiphy); |
533 | |
534 | for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; ++band) { |
535 | if (!wiphy->bands[band]) |
536 | continue; |
537 | |
538 | kfree(objp: (__force void *)wiphy->bands[band]->iftype_data); |
539 | wiphy->bands[band]->n_iftype_data = 0; |
540 | |
541 | kfree(objp: wiphy->bands[band]->channels); |
542 | wiphy->bands[band]->n_channels = 0; |
543 | |
544 | kfree(objp: wiphy->bands[band]); |
545 | wiphy->bands[band] = NULL; |
546 | } |
547 | |
548 | platform_device_unregister(mac->pdev); |
549 | qtnf_mac_iface_comb_free(mac); |
550 | qtnf_mac_ext_caps_free(mac); |
551 | kfree(objp: mac->macinfo.wowlan); |
552 | kfree(objp: mac->rd); |
553 | mac->rd = NULL; |
554 | wiphy_free(wiphy); |
555 | bus->mac[macid] = NULL; |
556 | } |
557 | |
558 | static int qtnf_core_mac_attach(struct qtnf_bus *bus, unsigned int macid) |
559 | { |
560 | struct qtnf_wmac *mac; |
561 | struct qtnf_vif *vif; |
562 | int ret; |
563 | |
564 | if (!(bus->hw_info.mac_bitmap & BIT(macid))) { |
565 | pr_info("MAC%u is not active in FW\n" , macid); |
566 | return 0; |
567 | } |
568 | |
569 | mac = qtnf_core_mac_alloc(bus, macid); |
570 | if (IS_ERR(ptr: mac)) { |
571 | pr_err("MAC%u allocation failed\n" , macid); |
572 | return PTR_ERR(ptr: mac); |
573 | } |
574 | |
575 | vif = qtnf_mac_get_base_vif(mac); |
576 | if (!vif) { |
577 | pr_err("MAC%u: primary VIF is not ready\n" , macid); |
578 | ret = -EFAULT; |
579 | goto error; |
580 | } |
581 | |
582 | ret = qtnf_cmd_send_add_intf(vif, iftype: vif->wdev.iftype, |
583 | use4addr: vif->wdev.use_4addr, mac_addr: vif->mac_addr); |
584 | if (ret) { |
585 | pr_err("MAC%u: failed to add VIF\n" , macid); |
586 | goto error; |
587 | } |
588 | |
589 | ret = qtnf_cmd_get_mac_info(mac); |
590 | if (ret) { |
591 | pr_err("MAC%u: failed to get MAC info\n" , macid); |
592 | goto error_del_vif; |
593 | } |
594 | |
595 | /* Use MAC address of the first active radio as a unique device ID */ |
596 | if (is_zero_ether_addr(addr: mac->bus->hw_id)) |
597 | ether_addr_copy(dst: mac->bus->hw_id, src: mac->macaddr); |
598 | |
599 | ret = qtnf_mac_init_bands(mac); |
600 | if (ret) { |
601 | pr_err("MAC%u: failed to init bands\n" , macid); |
602 | goto error_del_vif; |
603 | } |
604 | |
605 | ret = qtnf_wiphy_register(hw_info: &bus->hw_info, mac); |
606 | if (ret) { |
607 | pr_err("MAC%u: wiphy registration failed\n" , macid); |
608 | goto error_del_vif; |
609 | } |
610 | |
611 | mac->wiphy_registered = 1; |
612 | |
613 | rtnl_lock(); |
614 | wiphy_lock(wiphy: priv_to_wiphy(priv: mac)); |
615 | ret = qtnf_core_net_attach(mac, vif, name: "wlan%d" , NET_NAME_ENUM); |
616 | wiphy_unlock(wiphy: priv_to_wiphy(priv: mac)); |
617 | rtnl_unlock(); |
618 | |
619 | if (ret) { |
620 | pr_err("MAC%u: failed to attach netdev\n" , macid); |
621 | goto error_del_vif; |
622 | } |
623 | |
624 | if (qtnf_hwcap_is_set(info: &bus->hw_info, bit: QLINK_HW_CAPAB_HW_BRIDGE)) { |
625 | ret = qtnf_cmd_netdev_changeupper(vif, br_domain: vif->netdev->ifindex); |
626 | if (ret) |
627 | goto error; |
628 | } |
629 | |
630 | pr_debug("MAC%u initialized\n" , macid); |
631 | |
632 | return 0; |
633 | |
634 | error_del_vif: |
635 | qtnf_cmd_send_del_intf(vif); |
636 | vif->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; |
637 | error: |
638 | qtnf_core_mac_detach(bus, macid); |
639 | return ret; |
640 | } |
641 | |
642 | bool qtnf_netdev_is_qtn(const struct net_device *ndev) |
643 | { |
644 | return ndev->netdev_ops == &qtnf_netdev_ops; |
645 | } |
646 | |
647 | static int qtnf_check_br_ports(struct net_device *dev, |
648 | struct netdev_nested_priv *priv) |
649 | { |
650 | struct net_device *ndev = (struct net_device *)priv->data; |
651 | |
652 | if (dev != ndev && netdev_port_same_parent_id(a: dev, b: ndev)) |
653 | return -ENOTSUPP; |
654 | |
655 | return 0; |
656 | } |
657 | |
658 | static int qtnf_core_netdevice_event(struct notifier_block *nb, |
659 | unsigned long event, void *ptr) |
660 | { |
661 | struct net_device *ndev = netdev_notifier_info_to_dev(info: ptr); |
662 | const struct netdev_notifier_changeupper_info *info; |
663 | struct netdev_nested_priv priv = { |
664 | .data = (void *)ndev, |
665 | }; |
666 | struct net_device *brdev; |
667 | struct qtnf_vif *vif; |
668 | struct qtnf_bus *bus; |
669 | int br_domain; |
670 | int ret = 0; |
671 | |
672 | if (!qtnf_netdev_is_qtn(ndev)) |
673 | return NOTIFY_DONE; |
674 | |
675 | if (!net_eq(net1: dev_net(dev: ndev), net2: &init_net)) |
676 | return NOTIFY_OK; |
677 | |
678 | vif = qtnf_netdev_get_priv(dev: ndev); |
679 | bus = vif->mac->bus; |
680 | |
681 | switch (event) { |
682 | case NETDEV_CHANGEUPPER: |
683 | info = ptr; |
684 | brdev = info->upper_dev; |
685 | |
686 | if (!netif_is_bridge_master(dev: brdev)) |
687 | break; |
688 | |
689 | pr_debug("[VIF%u.%u] change bridge: %s %s\n" , |
690 | vif->mac->macid, vif->vifid, netdev_name(brdev), |
691 | info->linking ? "add" : "del" ); |
692 | |
693 | if (IS_ENABLED(CONFIG_NET_SWITCHDEV) && |
694 | qtnf_hwcap_is_set(info: &bus->hw_info, |
695 | bit: QLINK_HW_CAPAB_HW_BRIDGE)) { |
696 | if (info->linking) |
697 | br_domain = brdev->ifindex; |
698 | else |
699 | br_domain = ndev->ifindex; |
700 | |
701 | ret = qtnf_cmd_netdev_changeupper(vif, br_domain); |
702 | } else { |
703 | ret = netdev_walk_all_lower_dev(dev: brdev, |
704 | fn: qtnf_check_br_ports, |
705 | priv: &priv); |
706 | } |
707 | |
708 | break; |
709 | default: |
710 | break; |
711 | } |
712 | |
713 | return notifier_from_errno(err: ret); |
714 | } |
715 | |
716 | int qtnf_core_attach(struct qtnf_bus *bus) |
717 | { |
718 | unsigned int i; |
719 | int ret; |
720 | |
721 | qtnf_trans_init(bus); |
722 | qtnf_bus_data_rx_start(bus); |
723 | |
724 | bus->workqueue = alloc_ordered_workqueue("QTNF_BUS" , 0); |
725 | if (!bus->workqueue) { |
726 | pr_err("failed to alloc main workqueue\n" ); |
727 | ret = -ENOMEM; |
728 | goto error; |
729 | } |
730 | |
731 | bus->hprio_workqueue = alloc_workqueue(fmt: "QTNF_HPRI" , flags: WQ_HIGHPRI, max_active: 0); |
732 | if (!bus->hprio_workqueue) { |
733 | pr_err("failed to alloc high prio workqueue\n" ); |
734 | ret = -ENOMEM; |
735 | goto error; |
736 | } |
737 | |
738 | INIT_WORK(&bus->event_work, qtnf_event_work_handler); |
739 | |
740 | ret = qtnf_cmd_send_init_fw(bus); |
741 | if (ret) { |
742 | pr_err("failed to init FW: %d\n" , ret); |
743 | goto error; |
744 | } |
745 | |
746 | if (QLINK_VER_MAJOR(bus->hw_info.ql_proto_ver) != |
747 | QLINK_PROTO_VER_MAJOR) { |
748 | pr_err("qlink driver vs FW version mismatch: %u vs %u\n" , |
749 | QLINK_PROTO_VER_MAJOR, |
750 | QLINK_VER_MAJOR(bus->hw_info.ql_proto_ver)); |
751 | ret = -EPROTONOSUPPORT; |
752 | goto error; |
753 | } |
754 | |
755 | bus->fw_state = QTNF_FW_STATE_ACTIVE; |
756 | ret = qtnf_cmd_get_hw_info(bus); |
757 | if (ret) { |
758 | pr_err("failed to get HW info: %d\n" , ret); |
759 | goto error; |
760 | } |
761 | |
762 | if (qtnf_hwcap_is_set(info: &bus->hw_info, bit: QLINK_HW_CAPAB_HW_BRIDGE) && |
763 | bus->bus_ops->data_tx_use_meta_set) |
764 | bus->bus_ops->data_tx_use_meta_set(bus, true); |
765 | |
766 | if (bus->hw_info.num_mac > QTNF_MAX_MAC) { |
767 | pr_err("no support for number of MACs=%u\n" , |
768 | bus->hw_info.num_mac); |
769 | ret = -ERANGE; |
770 | goto error; |
771 | } |
772 | |
773 | for (i = 0; i < bus->hw_info.num_mac; i++) { |
774 | ret = qtnf_core_mac_attach(bus, macid: i); |
775 | |
776 | if (ret) { |
777 | pr_err("MAC%u: attach failed: %d\n" , i, ret); |
778 | goto error; |
779 | } |
780 | } |
781 | |
782 | bus->netdev_nb.notifier_call = qtnf_core_netdevice_event; |
783 | ret = register_netdevice_notifier(nb: &bus->netdev_nb); |
784 | if (ret) { |
785 | pr_err("failed to register netdev notifier: %d\n" , ret); |
786 | goto error; |
787 | } |
788 | |
789 | bus->fw_state = QTNF_FW_STATE_RUNNING; |
790 | return 0; |
791 | |
792 | error: |
793 | qtnf_core_detach(bus); |
794 | return ret; |
795 | } |
796 | EXPORT_SYMBOL_GPL(qtnf_core_attach); |
797 | |
798 | void qtnf_core_detach(struct qtnf_bus *bus) |
799 | { |
800 | unsigned int macid; |
801 | |
802 | unregister_netdevice_notifier(nb: &bus->netdev_nb); |
803 | qtnf_bus_data_rx_stop(bus); |
804 | |
805 | for (macid = 0; macid < QTNF_MAX_MAC; macid++) |
806 | qtnf_core_mac_detach(bus, macid); |
807 | |
808 | if (qtnf_fw_is_up(bus)) |
809 | qtnf_cmd_send_deinit_fw(bus); |
810 | |
811 | bus->fw_state = QTNF_FW_STATE_DETACHED; |
812 | |
813 | if (bus->workqueue) { |
814 | destroy_workqueue(wq: bus->workqueue); |
815 | bus->workqueue = NULL; |
816 | } |
817 | |
818 | if (bus->hprio_workqueue) { |
819 | destroy_workqueue(wq: bus->hprio_workqueue); |
820 | bus->hprio_workqueue = NULL; |
821 | } |
822 | |
823 | qtnf_trans_free(bus); |
824 | } |
825 | EXPORT_SYMBOL_GPL(qtnf_core_detach); |
826 | |
827 | static inline int qtnf_is_frame_meta_magic_valid(struct qtnf_frame_meta_info *m) |
828 | { |
829 | return m->magic_s == HBM_FRAME_META_MAGIC_PATTERN_S && |
830 | m->magic_e == HBM_FRAME_META_MAGIC_PATTERN_E; |
831 | } |
832 | |
833 | struct net_device *qtnf_classify_skb(struct qtnf_bus *bus, struct sk_buff *skb) |
834 | { |
835 | struct qtnf_frame_meta_info *meta; |
836 | struct net_device *ndev = NULL; |
837 | struct qtnf_wmac *mac; |
838 | struct qtnf_vif *vif; |
839 | |
840 | if (unlikely(bus->fw_state != QTNF_FW_STATE_RUNNING)) |
841 | return NULL; |
842 | |
843 | meta = (struct qtnf_frame_meta_info *) |
844 | (skb_tail_pointer(skb) - sizeof(*meta)); |
845 | |
846 | if (unlikely(!qtnf_is_frame_meta_magic_valid(meta))) { |
847 | pr_err_ratelimited("invalid magic 0x%x:0x%x\n" , |
848 | meta->magic_s, meta->magic_e); |
849 | goto out; |
850 | } |
851 | |
852 | if (unlikely(meta->macid >= QTNF_MAX_MAC)) { |
853 | pr_err_ratelimited("invalid mac(%u)\n" , meta->macid); |
854 | goto out; |
855 | } |
856 | |
857 | if (unlikely(meta->ifidx >= QTNF_MAX_INTF)) { |
858 | pr_err_ratelimited("invalid vif(%u)\n" , meta->ifidx); |
859 | goto out; |
860 | } |
861 | |
862 | mac = bus->mac[meta->macid]; |
863 | |
864 | if (unlikely(!mac)) { |
865 | pr_err_ratelimited("mac(%d) does not exist\n" , meta->macid); |
866 | goto out; |
867 | } |
868 | |
869 | vif = &mac->iflist[meta->ifidx]; |
870 | |
871 | if (unlikely(vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED)) { |
872 | pr_err_ratelimited("vif(%u) does not exists\n" , meta->ifidx); |
873 | goto out; |
874 | } |
875 | |
876 | ndev = vif->netdev; |
877 | |
878 | if (unlikely(!ndev)) { |
879 | pr_err_ratelimited("netdev for wlan%u.%u does not exists\n" , |
880 | meta->macid, meta->ifidx); |
881 | goto out; |
882 | } |
883 | |
884 | __skb_trim(skb, len: skb->len - sizeof(*meta)); |
885 | /* Firmware always handles packets that require flooding */ |
886 | qtnfmac_switch_mark_skb_flooded(skb); |
887 | |
888 | out: |
889 | return ndev; |
890 | } |
891 | EXPORT_SYMBOL_GPL(qtnf_classify_skb); |
892 | |
893 | void qtnf_wake_all_queues(struct net_device *ndev) |
894 | { |
895 | struct qtnf_vif *vif = qtnf_netdev_get_priv(dev: ndev); |
896 | struct qtnf_wmac *mac; |
897 | struct qtnf_bus *bus; |
898 | int macid; |
899 | int i; |
900 | |
901 | if (unlikely(!vif || !vif->mac || !vif->mac->bus)) |
902 | return; |
903 | |
904 | bus = vif->mac->bus; |
905 | |
906 | for (macid = 0; macid < QTNF_MAX_MAC; macid++) { |
907 | if (!(bus->hw_info.mac_bitmap & BIT(macid))) |
908 | continue; |
909 | |
910 | mac = bus->mac[macid]; |
911 | for (i = 0; i < QTNF_MAX_INTF; i++) { |
912 | vif = &mac->iflist[i]; |
913 | if (vif->netdev && netif_queue_stopped(dev: vif->netdev)) |
914 | netif_tx_wake_all_queues(dev: vif->netdev); |
915 | } |
916 | } |
917 | } |
918 | EXPORT_SYMBOL_GPL(qtnf_wake_all_queues); |
919 | |
920 | struct dentry *qtnf_get_debugfs_dir(void) |
921 | { |
922 | return qtnf_debugfs_dir; |
923 | } |
924 | EXPORT_SYMBOL_GPL(qtnf_get_debugfs_dir); |
925 | |
926 | static int __init qtnf_core_register(void) |
927 | { |
928 | qtnf_debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL); |
929 | |
930 | if (IS_ERR(ptr: qtnf_debugfs_dir)) |
931 | qtnf_debugfs_dir = NULL; |
932 | |
933 | return 0; |
934 | } |
935 | |
936 | static void __exit qtnf_core_exit(void) |
937 | { |
938 | debugfs_remove(dentry: qtnf_debugfs_dir); |
939 | } |
940 | |
941 | module_init(qtnf_core_register); |
942 | module_exit(qtnf_core_exit); |
943 | |
944 | MODULE_AUTHOR("Quantenna Communications" ); |
945 | MODULE_DESCRIPTION("Quantenna 802.11 wireless LAN FullMAC driver." ); |
946 | MODULE_LICENSE("GPL" ); |
947 | |