568 lines · c
1// SPDX-License-Identifier: ISC2/*3 * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.4 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.5 */6 7#include <linux/etherdevice.h>8#include <linux/rtnetlink.h>9#include "wil6210.h"10#include "txrx.h"11 12bool wil_has_other_active_ifaces(struct wil6210_priv *wil,13 struct net_device *ndev, bool up, bool ok)14{15 int i;16 struct wil6210_vif *vif;17 struct net_device *ndev_i;18 19 for (i = 0; i < GET_MAX_VIFS(wil); i++) {20 vif = wil->vifs[i];21 if (vif) {22 ndev_i = vif_to_ndev(vif);23 if (ndev_i != ndev)24 if ((up && (ndev_i->flags & IFF_UP)) ||25 (ok && netif_carrier_ok(ndev_i)))26 return true;27 }28 }29 30 return false;31}32 33bool wil_has_active_ifaces(struct wil6210_priv *wil, bool up, bool ok)34{35 /* use NULL ndev argument to check all interfaces */36 return wil_has_other_active_ifaces(wil, NULL, up, ok);37}38 39static int wil_open(struct net_device *ndev)40{41 struct wil6210_priv *wil = ndev_to_wil(ndev);42 int rc = 0;43 44 wil_dbg_misc(wil, "open\n");45 46 if (debug_fw ||47 test_bit(WMI_FW_CAPABILITY_WMI_ONLY, wil->fw_capabilities)) {48 wil_err(wil, "while in debug_fw or wmi_only mode\n");49 return -EINVAL;50 }51 52 if (!wil_has_other_active_ifaces(wil, ndev, true, false)) {53 wil_dbg_misc(wil, "open, first iface\n");54 rc = wil_pm_runtime_get(wil);55 if (rc < 0)56 return rc;57 58 rc = wil_up(wil);59 if (rc)60 wil_pm_runtime_put(wil);61 }62 63 return rc;64}65 66static int wil_stop(struct net_device *ndev)67{68 struct wil6210_priv *wil = ndev_to_wil(ndev);69 int rc = 0;70 71 wil_dbg_misc(wil, "stop\n");72 73 if (!wil_has_other_active_ifaces(wil, ndev, true, false)) {74 wil_dbg_misc(wil, "stop, last iface\n");75 rc = wil_down(wil);76 if (!rc)77 wil_pm_runtime_put(wil);78 }79 80 return rc;81}82 83static const struct net_device_ops wil_netdev_ops = {84 .ndo_open = wil_open,85 .ndo_stop = wil_stop,86 .ndo_start_xmit = wil_start_xmit,87 .ndo_set_mac_address = eth_mac_addr,88 .ndo_validate_addr = eth_validate_addr,89};90 91static int wil6210_netdev_poll_rx(struct napi_struct *napi, int budget)92{93 struct wil6210_priv *wil = container_of(napi, struct wil6210_priv,94 napi_rx);95 int quota = budget;96 int done;97 98 wil_rx_handle(wil, "a);99 done = budget - quota;100 101 if (done < budget) {102 napi_complete_done(napi, done);103 wil6210_unmask_irq_rx(wil);104 wil_dbg_txrx(wil, "NAPI RX complete\n");105 }106 107 wil_dbg_txrx(wil, "NAPI RX poll(%d) done %d\n", budget, done);108 109 return done;110}111 112static int wil6210_netdev_poll_rx_edma(struct napi_struct *napi, int budget)113{114 struct wil6210_priv *wil = container_of(napi, struct wil6210_priv,115 napi_rx);116 int quota = budget;117 int done;118 119 wil_rx_handle_edma(wil, "a);120 done = budget - quota;121 122 if (done < budget) {123 napi_complete_done(napi, done);124 wil6210_unmask_irq_rx_edma(wil);125 wil_dbg_txrx(wil, "NAPI RX complete\n");126 }127 128 wil_dbg_txrx(wil, "NAPI RX poll(%d) done %d\n", budget, done);129 130 return done;131}132 133static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget)134{135 struct wil6210_priv *wil = container_of(napi, struct wil6210_priv,136 napi_tx);137 int tx_done = 0;138 uint i;139 140 /* always process ALL Tx complete, regardless budget - it is fast */141 for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {142 struct wil_ring *ring = &wil->ring_tx[i];143 struct wil_ring_tx_data *txdata = &wil->ring_tx_data[i];144 struct wil6210_vif *vif;145 146 if (!ring->va || !txdata->enabled ||147 txdata->mid >= GET_MAX_VIFS(wil))148 continue;149 150 vif = wil->vifs[txdata->mid];151 if (unlikely(!vif)) {152 wil_dbg_txrx(wil, "Invalid MID %d\n", txdata->mid);153 continue;154 }155 156 tx_done += wil_tx_complete(vif, i);157 }158 159 if (tx_done < budget) {160 napi_complete(napi);161 wil6210_unmask_irq_tx(wil);162 wil_dbg_txrx(wil, "NAPI TX complete\n");163 }164 165 wil_dbg_txrx(wil, "NAPI TX poll(%d) done %d\n", budget, tx_done);166 167 return min(tx_done, budget);168}169 170static int wil6210_netdev_poll_tx_edma(struct napi_struct *napi, int budget)171{172 struct wil6210_priv *wil = container_of(napi, struct wil6210_priv,173 napi_tx);174 int tx_done;175 /* There is only one status TX ring */176 struct wil_status_ring *sring = &wil->srings[wil->tx_sring_idx];177 178 if (!sring->va)179 return 0;180 181 tx_done = wil_tx_sring_handler(wil, sring);182 183 if (tx_done < budget) {184 napi_complete(napi);185 wil6210_unmask_irq_tx_edma(wil);186 wil_dbg_txrx(wil, "NAPI TX complete\n");187 }188 189 wil_dbg_txrx(wil, "NAPI TX poll(%d) done %d\n", budget, tx_done);190 191 return min(tx_done, budget);192}193 194static void wil_dev_setup(struct net_device *dev)195{196 ether_setup(dev);197 dev->max_mtu = mtu_max;198 dev->tx_queue_len = WIL_TX_Q_LEN_DEFAULT;199}200 201static void wil_vif_deinit(struct wil6210_vif *vif)202{203 del_timer_sync(&vif->scan_timer);204 del_timer_sync(&vif->p2p.discovery_timer);205 cancel_work_sync(&vif->disconnect_worker);206 cancel_work_sync(&vif->p2p.discovery_expired_work);207 cancel_work_sync(&vif->p2p.delayed_listen_work);208 wil_probe_client_flush(vif);209 cancel_work_sync(&vif->probe_client_worker);210 cancel_work_sync(&vif->enable_tx_key_worker);211}212 213void wil_vif_free(struct wil6210_vif *vif)214{215 struct net_device *ndev = vif_to_ndev(vif);216 217 wil_vif_deinit(vif);218 free_netdev(ndev);219}220 221static void wil_ndev_destructor(struct net_device *ndev)222{223 struct wil6210_vif *vif = ndev_to_vif(ndev);224 225 wil_vif_deinit(vif);226}227 228static void wil_connect_timer_fn(struct timer_list *t)229{230 struct wil6210_vif *vif = from_timer(vif, t, connect_timer);231 struct wil6210_priv *wil = vif_to_wil(vif);232 bool q;233 234 wil_err(wil, "Connect timeout detected, disconnect station\n");235 236 /* reschedule to thread context - disconnect won't237 * run from atomic context.238 * queue on wmi_wq to prevent race with connect event.239 */240 q = queue_work(wil->wmi_wq, &vif->disconnect_worker);241 wil_dbg_wmi(wil, "queue_work of disconnect_worker -> %d\n", q);242}243 244static void wil_scan_timer_fn(struct timer_list *t)245{246 struct wil6210_vif *vif = from_timer(vif, t, scan_timer);247 struct wil6210_priv *wil = vif_to_wil(vif);248 249 clear_bit(wil_status_fwready, wil->status);250 wil_err(wil, "Scan timeout detected, start fw error recovery\n");251 wil_fw_error_recovery(wil);252}253 254static void wil_p2p_discovery_timer_fn(struct timer_list *t)255{256 struct wil6210_vif *vif = from_timer(vif, t, p2p.discovery_timer);257 struct wil6210_priv *wil = vif_to_wil(vif);258 259 wil_dbg_misc(wil, "p2p_discovery_timer_fn\n");260 261 schedule_work(&vif->p2p.discovery_expired_work);262}263 264static void wil_vif_init(struct wil6210_vif *vif)265{266 vif->bcast_ring = -1;267 268 mutex_init(&vif->probe_client_mutex);269 270 timer_setup(&vif->connect_timer, wil_connect_timer_fn, 0);271 timer_setup(&vif->scan_timer, wil_scan_timer_fn, 0);272 timer_setup(&vif->p2p.discovery_timer, wil_p2p_discovery_timer_fn, 0);273 274 INIT_WORK(&vif->probe_client_worker, wil_probe_client_worker);275 INIT_WORK(&vif->disconnect_worker, wil_disconnect_worker);276 INIT_WORK(&vif->p2p.discovery_expired_work, wil_p2p_listen_expired);277 INIT_WORK(&vif->p2p.delayed_listen_work, wil_p2p_delayed_listen_work);278 INIT_WORK(&vif->enable_tx_key_worker, wil_enable_tx_key_worker);279 280 INIT_LIST_HEAD(&vif->probe_client_pending);281 282 vif->net_queue_stopped = 1;283}284 285static u8 wil_vif_find_free_mid(struct wil6210_priv *wil)286{287 u8 i;288 289 for (i = 0; i < GET_MAX_VIFS(wil); i++) {290 if (!wil->vifs[i])291 return i;292 }293 294 return U8_MAX;295}296 297struct wil6210_vif *298wil_vif_alloc(struct wil6210_priv *wil, const char *name,299 unsigned char name_assign_type, enum nl80211_iftype iftype)300{301 struct net_device *ndev;302 struct wireless_dev *wdev;303 struct wil6210_vif *vif;304 u8 mid;305 306 mid = wil_vif_find_free_mid(wil);307 if (mid == U8_MAX) {308 wil_err(wil, "no available virtual interface\n");309 return ERR_PTR(-EINVAL);310 }311 312 ndev = alloc_netdev(sizeof(*vif), name, name_assign_type,313 wil_dev_setup);314 if (!ndev) {315 dev_err(wil_to_dev(wil), "alloc_netdev failed\n");316 return ERR_PTR(-ENOMEM);317 }318 if (mid == 0) {319 wil->main_ndev = ndev;320 } else {321 ndev->priv_destructor = wil_ndev_destructor;322 ndev->needs_free_netdev = true;323 }324 325 vif = ndev_to_vif(ndev);326 vif->ndev = ndev;327 vif->wil = wil;328 vif->mid = mid;329 wil_vif_init(vif);330 331 wdev = &vif->wdev;332 wdev->wiphy = wil->wiphy;333 wdev->iftype = iftype;334 335 ndev->netdev_ops = &wil_netdev_ops;336 wil_set_ethtoolops(ndev);337 ndev->ieee80211_ptr = wdev;338 ndev->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM |339 NETIF_F_SG | NETIF_F_GRO |340 NETIF_F_TSO | NETIF_F_TSO6;341 342 ndev->features |= ndev->hw_features;343 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));344 wdev->netdev = ndev;345 return vif;346}347 348void *wil_if_alloc(struct device *dev)349{350 struct wil6210_priv *wil;351 struct wil6210_vif *vif;352 int rc = 0;353 354 wil = wil_cfg80211_init(dev);355 if (IS_ERR(wil)) {356 dev_err(dev, "wil_cfg80211_init failed\n");357 return wil;358 }359 360 rc = wil_priv_init(wil);361 if (rc) {362 dev_err(dev, "wil_priv_init failed\n");363 goto out_cfg;364 }365 366 wil_dbg_misc(wil, "if_alloc\n");367 368 vif = wil_vif_alloc(wil, "wlan%d", NET_NAME_UNKNOWN,369 NL80211_IFTYPE_STATION);370 if (IS_ERR(vif)) {371 dev_err(dev, "wil_vif_alloc failed\n");372 rc = -ENOMEM;373 goto out_priv;374 }375 376 wil->radio_wdev = vif_to_wdev(vif);377 378 return wil;379 380out_priv:381 wil_priv_deinit(wil);382 383out_cfg:384 wil_cfg80211_deinit(wil);385 386 return ERR_PTR(rc);387}388 389void wil_if_free(struct wil6210_priv *wil)390{391 struct net_device *ndev = wil->main_ndev;392 393 wil_dbg_misc(wil, "if_free\n");394 395 if (!ndev)396 return;397 398 wil_priv_deinit(wil);399 400 wil->main_ndev = NULL;401 wil_ndev_destructor(ndev);402 free_netdev(ndev);403 404 wil_cfg80211_deinit(wil);405}406 407int wil_vif_add(struct wil6210_priv *wil, struct wil6210_vif *vif)408{409 struct net_device *ndev = vif_to_ndev(vif);410 struct wireless_dev *wdev = vif_to_wdev(vif);411 bool any_active = wil_has_active_ifaces(wil, true, false);412 int rc;413 414 ASSERT_RTNL();415 416 if (wil->vifs[vif->mid]) {417 dev_err(&ndev->dev, "VIF with mid %d already in use\n",418 vif->mid);419 return -EEXIST;420 }421 if (any_active && vif->mid != 0) {422 rc = wmi_port_allocate(wil, vif->mid, ndev->dev_addr,423 wdev->iftype);424 if (rc)425 return rc;426 }427 rc = cfg80211_register_netdevice(ndev);428 if (rc < 0) {429 dev_err(&ndev->dev, "Failed to register netdev: %d\n", rc);430 if (any_active && vif->mid != 0)431 wmi_port_delete(wil, vif->mid);432 return rc;433 }434 435 wil->vifs[vif->mid] = vif;436 return 0;437}438 439int wil_if_add(struct wil6210_priv *wil)440{441 struct wiphy *wiphy = wil->wiphy;442 struct net_device *ndev = wil->main_ndev;443 struct wil6210_vif *vif = ndev_to_vif(ndev);444 int rc;445 446 wil_dbg_misc(wil, "entered");447 448 strscpy(wiphy->fw_version, wil->fw_version, sizeof(wiphy->fw_version));449 450 rc = wiphy_register(wiphy);451 if (rc < 0) {452 wil_err(wil, "failed to register wiphy, err %d\n", rc);453 return rc;454 }455 456 wil->napi_ndev = alloc_netdev_dummy(0);457 if (!wil->napi_ndev) {458 wil_err(wil, "failed to allocate dummy netdev");459 rc = -ENOMEM;460 goto out_wiphy;461 }462 if (wil->use_enhanced_dma_hw) {463 netif_napi_add(wil->napi_ndev, &wil->napi_rx,464 wil6210_netdev_poll_rx_edma);465 netif_napi_add_tx(wil->napi_ndev,466 &wil->napi_tx, wil6210_netdev_poll_tx_edma);467 } else {468 netif_napi_add(wil->napi_ndev, &wil->napi_rx,469 wil6210_netdev_poll_rx);470 netif_napi_add_tx(wil->napi_ndev,471 &wil->napi_tx, wil6210_netdev_poll_tx);472 }473 474 wil_update_net_queues_bh(wil, vif, NULL, true);475 476 rtnl_lock();477 wiphy_lock(wiphy);478 rc = wil_vif_add(wil, vif);479 wiphy_unlock(wiphy);480 rtnl_unlock();481 if (rc < 0)482 goto free_dummy;483 484 return 0;485 486free_dummy:487 free_netdev(wil->napi_ndev);488out_wiphy:489 wiphy_unregister(wiphy);490 return rc;491}492 493void wil_vif_remove(struct wil6210_priv *wil, u8 mid)494{495 struct wil6210_vif *vif;496 struct net_device *ndev;497 bool any_active = wil_has_active_ifaces(wil, true, false);498 499 ASSERT_RTNL();500 if (mid >= GET_MAX_VIFS(wil)) {501 wil_err(wil, "invalid MID: %d\n", mid);502 return;503 }504 505 vif = wil->vifs[mid];506 if (!vif) {507 wil_err(wil, "MID %d not registered\n", mid);508 return;509 }510 511 mutex_lock(&wil->mutex);512 wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING);513 mutex_unlock(&wil->mutex);514 515 ndev = vif_to_ndev(vif);516 /* during unregister_netdevice cfg80211_leave may perform operations517 * such as stop AP, disconnect, so we only clear the VIF afterwards518 */519 cfg80211_unregister_netdevice(ndev);520 521 if (any_active && vif->mid != 0)522 wmi_port_delete(wil, vif->mid);523 524 /* make sure no one is accessing the VIF before removing */525 mutex_lock(&wil->vif_mutex);526 wil->vifs[mid] = NULL;527 /* ensure NAPI code will see the NULL VIF */528 wmb();529 if (test_bit(wil_status_napi_en, wil->status)) {530 napi_synchronize(&wil->napi_rx);531 napi_synchronize(&wil->napi_tx);532 }533 mutex_unlock(&wil->vif_mutex);534 535 flush_work(&wil->wmi_event_worker);536 del_timer_sync(&vif->connect_timer);537 cancel_work_sync(&vif->disconnect_worker);538 wil_probe_client_flush(vif);539 cancel_work_sync(&vif->probe_client_worker);540 cancel_work_sync(&vif->enable_tx_key_worker);541 /* for VIFs, ndev will be freed by destructor after RTNL is unlocked.542 * the main interface will be freed in wil_if_free, we need to keep it543 * a bit longer so logging macros will work.544 */545}546 547void wil_if_remove(struct wil6210_priv *wil)548{549 struct net_device *ndev = wil->main_ndev;550 struct wireless_dev *wdev = ndev->ieee80211_ptr;551 struct wiphy *wiphy = wdev->wiphy;552 553 wil_dbg_misc(wil, "if_remove\n");554 555 rtnl_lock();556 wiphy_lock(wiphy);557 wil_vif_remove(wil, 0);558 wiphy_unlock(wiphy);559 rtnl_unlock();560 561 netif_napi_del(&wil->napi_tx);562 netif_napi_del(&wil->napi_rx);563 564 free_netdev(wil->napi_ndev);565 566 wiphy_unregister(wiphy);567}568