cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

netdev.c (13198B)


      1// SPDX-License-Identifier: ISC
      2/*
      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, &quota);
     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, &quota);
    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't
    237	 * 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	strlcpy(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	init_dummy_netdev(&wil->napi_ndev);
    457	if (wil->use_enhanced_dma_hw) {
    458		netif_napi_add(&wil->napi_ndev, &wil->napi_rx,
    459			       wil6210_netdev_poll_rx_edma,
    460			       NAPI_POLL_WEIGHT);
    461		netif_napi_add_tx(&wil->napi_ndev,
    462				  &wil->napi_tx, wil6210_netdev_poll_tx_edma);
    463	} else {
    464		netif_napi_add(&wil->napi_ndev, &wil->napi_rx,
    465			       wil6210_netdev_poll_rx,
    466			       NAPI_POLL_WEIGHT);
    467		netif_napi_add_tx(&wil->napi_ndev,
    468				  &wil->napi_tx, wil6210_netdev_poll_tx);
    469	}
    470
    471	wil_update_net_queues_bh(wil, vif, NULL, true);
    472
    473	rtnl_lock();
    474	wiphy_lock(wiphy);
    475	rc = wil_vif_add(wil, vif);
    476	wiphy_unlock(wiphy);
    477	rtnl_unlock();
    478	if (rc < 0)
    479		goto out_wiphy;
    480
    481	return 0;
    482
    483out_wiphy:
    484	wiphy_unregister(wiphy);
    485	return rc;
    486}
    487
    488void wil_vif_remove(struct wil6210_priv *wil, u8 mid)
    489{
    490	struct wil6210_vif *vif;
    491	struct net_device *ndev;
    492	bool any_active = wil_has_active_ifaces(wil, true, false);
    493
    494	ASSERT_RTNL();
    495	if (mid >= GET_MAX_VIFS(wil)) {
    496		wil_err(wil, "invalid MID: %d\n", mid);
    497		return;
    498	}
    499
    500	vif = wil->vifs[mid];
    501	if (!vif) {
    502		wil_err(wil, "MID %d not registered\n", mid);
    503		return;
    504	}
    505
    506	mutex_lock(&wil->mutex);
    507	wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING);
    508	mutex_unlock(&wil->mutex);
    509
    510	ndev = vif_to_ndev(vif);
    511	/* during unregister_netdevice cfg80211_leave may perform operations
    512	 * such as stop AP, disconnect, so we only clear the VIF afterwards
    513	 */
    514	cfg80211_unregister_netdevice(ndev);
    515
    516	if (any_active && vif->mid != 0)
    517		wmi_port_delete(wil, vif->mid);
    518
    519	/* make sure no one is accessing the VIF before removing */
    520	mutex_lock(&wil->vif_mutex);
    521	wil->vifs[mid] = NULL;
    522	/* ensure NAPI code will see the NULL VIF */
    523	wmb();
    524	if (test_bit(wil_status_napi_en, wil->status)) {
    525		napi_synchronize(&wil->napi_rx);
    526		napi_synchronize(&wil->napi_tx);
    527	}
    528	mutex_unlock(&wil->vif_mutex);
    529
    530	flush_work(&wil->wmi_event_worker);
    531	del_timer_sync(&vif->connect_timer);
    532	cancel_work_sync(&vif->disconnect_worker);
    533	wil_probe_client_flush(vif);
    534	cancel_work_sync(&vif->probe_client_worker);
    535	cancel_work_sync(&vif->enable_tx_key_worker);
    536	/* for VIFs, ndev will be freed by destructor after RTNL is unlocked.
    537	 * the main interface will be freed in wil_if_free, we need to keep it
    538	 * a bit longer so logging macros will work.
    539	 */
    540}
    541
    542void wil_if_remove(struct wil6210_priv *wil)
    543{
    544	struct net_device *ndev = wil->main_ndev;
    545	struct wireless_dev *wdev = ndev->ieee80211_ptr;
    546	struct wiphy *wiphy = wdev->wiphy;
    547
    548	wil_dbg_misc(wil, "if_remove\n");
    549
    550	rtnl_lock();
    551	wiphy_lock(wiphy);
    552	wil_vif_remove(wil, 0);
    553	wiphy_unlock(wiphy);
    554	rtnl_unlock();
    555
    556	netif_napi_del(&wil->napi_tx);
    557	netif_napi_del(&wil->napi_rx);
    558
    559	wiphy_unregister(wiphy);
    560}