Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git...
[cascardo/linux.git] / drivers / net / wireless / ath / wil6210 / netdev.c
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
21 static 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
28 static 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
35 static 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
43 static 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
64 static 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
92 void *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         ndev->features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
132         SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
133         wdev->netdev = ndev;
134
135         netif_napi_add(ndev, &wil->napi_rx, wil6210_netdev_poll_rx,
136                        WIL6210_NAPI_BUDGET);
137         netif_napi_add(ndev, &wil->napi_tx, wil6210_netdev_poll_tx,
138                        WIL6210_NAPI_BUDGET);
139
140         wil_link_off(wil);
141
142         return wil;
143
144  out_priv:
145         wil_priv_deinit(wil);
146
147  out_wdev:
148         wil_wdev_free(wil);
149
150         return ERR_PTR(rc);
151 }
152
153 void wil_if_free(struct wil6210_priv *wil)
154 {
155         struct net_device *ndev = wil_to_ndev(wil);
156         if (!ndev)
157                 return;
158
159         free_netdev(ndev);
160         wil_priv_deinit(wil);
161         wil_wdev_free(wil);
162 }
163
164 int wil_if_add(struct wil6210_priv *wil)
165 {
166         struct net_device *ndev = wil_to_ndev(wil);
167         int rc;
168
169         rc = register_netdev(ndev);
170         if (rc < 0) {
171                 dev_err(&ndev->dev, "Failed to register netdev: %d\n", rc);
172                 return rc;
173         }
174
175         wil_link_off(wil);
176
177         return 0;
178 }
179
180 void wil_if_remove(struct wil6210_priv *wil)
181 {
182         struct net_device *ndev = wil_to_ndev(wil);
183
184         unregister_netdev(ndev);
185 }