1c0c77d9a14f01281ff57db1f97b1eaf507a90fe
[cascardo/linux.git] / drivers / net / wireless / ath / wil6210 / netdev.c
1 /*
2  * Copyright (c) 2012-2014 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 #include "txrx.h"
21
22 static int wil_open(struct net_device *ndev)
23 {
24         struct wil6210_priv *wil = ndev_to_wil(ndev);
25
26         wil_dbg_misc(wil, "%s()\n", __func__);
27
28         return wil_up(wil);
29 }
30
31 static int wil_stop(struct net_device *ndev)
32 {
33         struct wil6210_priv *wil = ndev_to_wil(ndev);
34
35         wil_dbg_misc(wil, "%s()\n", __func__);
36
37         return wil_down(wil);
38 }
39
40 static int wil_change_mtu(struct net_device *ndev, int new_mtu)
41 {
42         struct wil6210_priv *wil = ndev_to_wil(ndev);
43
44         if (new_mtu < 68 || new_mtu > (TX_BUF_LEN - ETH_HLEN)) {
45                 wil_err(wil, "invalid MTU %d\n", new_mtu);
46                 return -EINVAL;
47         }
48
49         wil_dbg_misc(wil, "change MTU %d -> %d\n", ndev->mtu, new_mtu);
50         ndev->mtu = new_mtu;
51
52         return 0;
53 }
54
55 static const struct net_device_ops wil_netdev_ops = {
56         .ndo_open               = wil_open,
57         .ndo_stop               = wil_stop,
58         .ndo_start_xmit         = wil_start_xmit,
59         .ndo_set_mac_address    = eth_mac_addr,
60         .ndo_validate_addr      = eth_validate_addr,
61         .ndo_change_mtu         = wil_change_mtu,
62 };
63
64 static int wil6210_netdev_poll_rx(struct napi_struct *napi, int budget)
65 {
66         struct wil6210_priv *wil = container_of(napi, struct wil6210_priv,
67                                                 napi_rx);
68         int quota = budget;
69         int done;
70
71         wil_rx_handle(wil, &quota);
72         done = budget - quota;
73
74         if (done <= 1) { /* burst ends - only one packet processed */
75                 napi_complete(napi);
76                 wil6210_unmask_irq_rx(wil);
77                 wil_dbg_txrx(wil, "NAPI RX complete\n");
78         }
79
80         wil_dbg_txrx(wil, "NAPI RX poll(%d) done %d\n", budget, done);
81
82         return done;
83 }
84
85 static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget)
86 {
87         struct wil6210_priv *wil = container_of(napi, struct wil6210_priv,
88                                                 napi_tx);
89         int tx_done = 0;
90         uint i;
91
92         /* always process ALL Tx complete, regardless budget - it is fast */
93         for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
94                 struct vring *vring = &wil->vring_tx[i];
95
96                 if (!vring->va)
97                         continue;
98
99                 tx_done += wil_tx_complete(wil, i);
100         }
101
102         if (tx_done <= 1) { /* burst ends - only one packet processed */
103                 napi_complete(napi);
104                 wil6210_unmask_irq_tx(wil);
105                 wil_dbg_txrx(wil, "NAPI TX complete\n");
106         }
107
108         wil_dbg_txrx(wil, "NAPI TX poll(%d) done %d\n", budget, tx_done);
109
110         return min(tx_done, budget);
111 }
112
113 void *wil_if_alloc(struct device *dev, void __iomem *csr)
114 {
115         struct net_device *ndev;
116         struct wireless_dev *wdev;
117         struct wil6210_priv *wil;
118         struct ieee80211_channel *ch;
119         int rc = 0;
120
121         wdev = wil_cfg80211_init(dev);
122         if (IS_ERR(wdev)) {
123                 dev_err(dev, "wil_cfg80211_init failed\n");
124                 return wdev;
125         }
126
127         wil = wdev_to_wil(wdev);
128         wil->csr = csr;
129         wil->wdev = wdev;
130
131         wil_dbg_misc(wil, "%s()\n", __func__);
132
133         rc = wil_priv_init(wil);
134         if (rc) {
135                 dev_err(dev, "wil_priv_init failed\n");
136                 goto out_wdev;
137         }
138
139         wdev->iftype = NL80211_IFTYPE_STATION; /* TODO */
140         /* default monitor channel */
141         ch = wdev->wiphy->bands[IEEE80211_BAND_60GHZ]->channels;
142         cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT);
143
144         ndev = alloc_netdev(0, "wlan%d", NET_NAME_UNKNOWN, ether_setup);
145         if (!ndev) {
146                 dev_err(dev, "alloc_netdev_mqs failed\n");
147                 rc = -ENOMEM;
148                 goto out_priv;
149         }
150
151         ndev->netdev_ops = &wil_netdev_ops;
152         ndev->ieee80211_ptr = wdev;
153         ndev->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM |
154                             NETIF_F_SG | NETIF_F_GRO;
155         ndev->features |= ndev->hw_features;
156         SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
157         wdev->netdev = ndev;
158
159         netif_napi_add(ndev, &wil->napi_rx, wil6210_netdev_poll_rx,
160                        WIL6210_NAPI_BUDGET);
161         netif_napi_add(ndev, &wil->napi_tx, wil6210_netdev_poll_tx,
162                        WIL6210_NAPI_BUDGET);
163
164         wil_link_off(wil);
165
166         return wil;
167
168  out_priv:
169         wil_priv_deinit(wil);
170
171  out_wdev:
172         wil_wdev_free(wil);
173
174         return ERR_PTR(rc);
175 }
176
177 void wil_if_free(struct wil6210_priv *wil)
178 {
179         struct net_device *ndev = wil_to_ndev(wil);
180
181         wil_dbg_misc(wil, "%s()\n", __func__);
182
183         if (!ndev)
184                 return;
185
186         wil_priv_deinit(wil);
187
188         wil_to_ndev(wil) = NULL;
189         free_netdev(ndev);
190
191         wil_wdev_free(wil);
192 }
193
194 int wil_if_add(struct wil6210_priv *wil)
195 {
196         struct net_device *ndev = wil_to_ndev(wil);
197         int rc;
198
199         wil_dbg_misc(wil, "%s()\n", __func__);
200
201         rc = register_netdev(ndev);
202         if (rc < 0) {
203                 dev_err(&ndev->dev, "Failed to register netdev: %d\n", rc);
204                 return rc;
205         }
206
207         wil_link_off(wil);
208
209         return 0;
210 }
211
212 void wil_if_remove(struct wil6210_priv *wil)
213 {
214         struct net_device *ndev = wil_to_ndev(wil);
215
216         wil_dbg_misc(wil, "%s()\n", __func__);
217
218         unregister_netdev(ndev);
219 }