Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1/*
  2 * Copyright (c) 2012 Qualcomm Atheros, Inc.
  3 *
  4 * Permission to use, copy, modify, and/or distribute this software for any
  5 * purpose with or without fee is hereby granted, provided that the above
  6 * copyright notice and this permission notice appear in all copies.
  7 *
  8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 15 */
 16
 17#include <linux/etherdevice.h>
 18
 19#include "wil6210.h"
 20
 21static int wil_open(struct net_device *ndev)
 22{
 23	struct wil6210_priv *wil = ndev_to_wil(ndev);
 24
 25	return wil_up(wil);
 26}
 27
 28static int wil_stop(struct net_device *ndev)
 29{
 30	struct wil6210_priv *wil = ndev_to_wil(ndev);
 31
 32	return wil_down(wil);
 33}
 34
 35static const struct net_device_ops wil_netdev_ops = {
 36	.ndo_open		= wil_open,
 37	.ndo_stop		= wil_stop,
 38	.ndo_start_xmit		= wil_start_xmit,
 39	.ndo_set_mac_address	= eth_mac_addr,
 40	.ndo_validate_addr	= eth_validate_addr,
 41};
 42
 43static int wil6210_netdev_poll_rx(struct napi_struct *napi, int budget)
 44{
 45	struct wil6210_priv *wil = container_of(napi, struct wil6210_priv,
 46						napi_rx);
 47	int quota = budget;
 48	int done;
 49
 50	wil_rx_handle(wil, &quota);
 51	done = budget - quota;
 52
 53	if (done <= 1) { /* burst ends - only one packet processed */
 54		napi_complete(napi);
 55		wil6210_unmask_irq_rx(wil);
 56		wil_dbg_txrx(wil, "NAPI RX complete\n");
 57	}
 58
 59	wil_dbg_txrx(wil, "NAPI RX poll(%d) done %d\n", budget, done);
 60
 61	return done;
 62}
 63
 64static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget)
 65{
 66	struct wil6210_priv *wil = container_of(napi, struct wil6210_priv,
 67						napi_tx);
 68	int tx_done = 0;
 69	uint i;
 70
 71	/* always process ALL Tx complete, regardless budget - it is fast */
 72	for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
 73		struct vring *vring = &wil->vring_tx[i];
 74
 75		if (!vring->va)
 76			continue;
 77
 78		tx_done += wil_tx_complete(wil, i);
 79	}
 80
 81	if (tx_done <= 1) { /* burst ends - only one packet processed */
 82		napi_complete(napi);
 83		wil6210_unmask_irq_tx(wil);
 84		wil_dbg_txrx(wil, "NAPI TX complete\n");
 85	}
 86
 87	wil_dbg_txrx(wil, "NAPI TX poll(%d) done %d\n", budget, tx_done);
 88
 89	return min(tx_done, budget);
 90}
 91
 92void *wil_if_alloc(struct device *dev, void __iomem *csr)
 93{
 94	struct net_device *ndev;
 95	struct wireless_dev *wdev;
 96	struct wil6210_priv *wil;
 97	struct ieee80211_channel *ch;
 98	int rc = 0;
 99
100	wdev = wil_cfg80211_init(dev);
101	if (IS_ERR(wdev)) {
102		dev_err(dev, "wil_cfg80211_init failed\n");
103		return wdev;
104	}
105
106	wil = wdev_to_wil(wdev);
107	wil->csr = csr;
108	wil->wdev = wdev;
109
110	rc = wil_priv_init(wil);
111	if (rc) {
112		dev_err(dev, "wil_priv_init failed\n");
113		goto out_wdev;
114	}
115
116	wdev->iftype = NL80211_IFTYPE_STATION; /* TODO */
117	/* default monitor channel */
118	ch = wdev->wiphy->bands[IEEE80211_BAND_60GHZ]->channels;
119	cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT);
120
121	ndev = alloc_netdev(0, "wlan%d", ether_setup);
122	if (!ndev) {
123		dev_err(dev, "alloc_netdev_mqs failed\n");
124		rc = -ENOMEM;
125		goto out_priv;
126	}
127
128	ndev->netdev_ops = &wil_netdev_ops;
129	ndev->ieee80211_ptr = wdev;
130	ndev->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM |
131			    NETIF_F_SG | NETIF_F_GRO;
132	ndev->features |= ndev->hw_features;
133	SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
134	wdev->netdev = ndev;
135
136	netif_napi_add(ndev, &wil->napi_rx, wil6210_netdev_poll_rx,
137		       WIL6210_NAPI_BUDGET);
138	netif_napi_add(ndev, &wil->napi_tx, wil6210_netdev_poll_tx,
139		       WIL6210_NAPI_BUDGET);
140
141	wil_link_off(wil);
142
143	return wil;
144
145 out_priv:
146	wil_priv_deinit(wil);
147
148 out_wdev:
149	wil_wdev_free(wil);
150
151	return ERR_PTR(rc);
152}
153
154void wil_if_free(struct wil6210_priv *wil)
155{
156	struct net_device *ndev = wil_to_ndev(wil);
157	if (!ndev)
158		return;
159
160	free_netdev(ndev);
161	wil_priv_deinit(wil);
162	wil_wdev_free(wil);
163}
164
165int wil_if_add(struct wil6210_priv *wil)
166{
167	struct net_device *ndev = wil_to_ndev(wil);
168	int rc;
169
170	rc = register_netdev(ndev);
171	if (rc < 0) {
172		dev_err(&ndev->dev, "Failed to register netdev: %d\n", rc);
173		return rc;
174	}
175
176	wil_link_off(wil);
177
178	return 0;
179}
180
181void wil_if_remove(struct wil6210_priv *wil)
182{
183	struct net_device *ndev = wil_to_ndev(wil);
184
185	unregister_netdev(ndev);
186}