Linux Audio

Check our new training course

Linux kernel drivers training

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