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 > mtu_max) { 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 int wil_do_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) 56 { 57 struct wil6210_priv *wil = ndev_to_wil(ndev); 58 59 int ret = wil_ioctl(wil, ifr->ifr_data, cmd); 60 61 wil_dbg_misc(wil, "ioctl(0x%04x) -> %d\n", cmd, ret); 62 63 return ret; 64 } 65 66 static const struct net_device_ops wil_netdev_ops = { 67 .ndo_open = wil_open, 68 .ndo_stop = wil_stop, 69 .ndo_start_xmit = wil_start_xmit, 70 .ndo_set_mac_address = eth_mac_addr, 71 .ndo_validate_addr = eth_validate_addr, 72 .ndo_change_mtu = wil_change_mtu, 73 .ndo_do_ioctl = wil_do_ioctl, 74 }; 75 76 static int wil6210_netdev_poll_rx(struct napi_struct *napi, int budget) 77 { 78 struct wil6210_priv *wil = container_of(napi, struct wil6210_priv, 79 napi_rx); 80 int quota = budget; 81 int done; 82 83 wil_rx_handle(wil, "a); 84 done = budget - quota; 85 86 if (done <= 1) { /* burst ends - only one packet processed */ 87 napi_complete(napi); 88 wil6210_unmask_irq_rx(wil); 89 wil_dbg_txrx(wil, "NAPI RX complete\n"); 90 } 91 92 wil_dbg_txrx(wil, "NAPI RX poll(%d) done %d\n", budget, done); 93 94 return done; 95 } 96 97 static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget) 98 { 99 struct wil6210_priv *wil = container_of(napi, struct wil6210_priv, 100 napi_tx); 101 int tx_done = 0; 102 uint i; 103 104 /* always process ALL Tx complete, regardless budget - it is fast */ 105 for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { 106 struct vring *vring = &wil->vring_tx[i]; 107 108 if (!vring->va) 109 continue; 110 111 tx_done += wil_tx_complete(wil, i); 112 } 113 114 if (tx_done <= 1) { /* burst ends - only one packet processed */ 115 napi_complete(napi); 116 wil6210_unmask_irq_tx(wil); 117 wil_dbg_txrx(wil, "NAPI TX complete\n"); 118 } 119 120 wil_dbg_txrx(wil, "NAPI TX poll(%d) done %d\n", budget, tx_done); 121 122 return min(tx_done, budget); 123 } 124 125 void *wil_if_alloc(struct device *dev, void __iomem *csr) 126 { 127 struct net_device *ndev; 128 struct wireless_dev *wdev; 129 struct wil6210_priv *wil; 130 struct ieee80211_channel *ch; 131 int rc = 0; 132 133 wdev = wil_cfg80211_init(dev); 134 if (IS_ERR(wdev)) { 135 dev_err(dev, "wil_cfg80211_init failed\n"); 136 return wdev; 137 } 138 139 wil = wdev_to_wil(wdev); 140 wil->csr = csr; 141 wil->wdev = wdev; 142 143 wil_dbg_misc(wil, "%s()\n", __func__); 144 145 rc = wil_priv_init(wil); 146 if (rc) { 147 dev_err(dev, "wil_priv_init failed\n"); 148 goto out_wdev; 149 } 150 151 wdev->iftype = NL80211_IFTYPE_STATION; /* TODO */ 152 /* default monitor channel */ 153 ch = wdev->wiphy->bands[IEEE80211_BAND_60GHZ]->channels; 154 cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT); 155 156 ndev = alloc_netdev(0, "wlan%d", NET_NAME_UNKNOWN, ether_setup); 157 if (!ndev) { 158 dev_err(dev, "alloc_netdev_mqs failed\n"); 159 rc = -ENOMEM; 160 goto out_priv; 161 } 162 163 ndev->netdev_ops = &wil_netdev_ops; 164 wil_set_ethtoolops(ndev); 165 ndev->ieee80211_ptr = wdev; 166 ndev->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM | 167 NETIF_F_SG | NETIF_F_GRO; 168 ndev->features |= ndev->hw_features; 169 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); 170 wdev->netdev = ndev; 171 172 netif_napi_add(ndev, &wil->napi_rx, wil6210_netdev_poll_rx, 173 WIL6210_NAPI_BUDGET); 174 netif_napi_add(ndev, &wil->napi_tx, wil6210_netdev_poll_tx, 175 WIL6210_NAPI_BUDGET); 176 177 wil_link_off(wil); 178 179 return wil; 180 181 out_priv: 182 wil_priv_deinit(wil); 183 184 out_wdev: 185 wil_wdev_free(wil); 186 187 return ERR_PTR(rc); 188 } 189 190 void wil_if_free(struct wil6210_priv *wil) 191 { 192 struct net_device *ndev = wil_to_ndev(wil); 193 194 wil_dbg_misc(wil, "%s()\n", __func__); 195 196 if (!ndev) 197 return; 198 199 wil_priv_deinit(wil); 200 201 wil_to_ndev(wil) = NULL; 202 free_netdev(ndev); 203 204 wil_wdev_free(wil); 205 } 206 207 int wil_if_add(struct wil6210_priv *wil) 208 { 209 struct net_device *ndev = wil_to_ndev(wil); 210 int rc; 211 212 wil_dbg_misc(wil, "%s()\n", __func__); 213 214 rc = register_netdev(ndev); 215 if (rc < 0) { 216 dev_err(&ndev->dev, "Failed to register netdev: %d\n", rc); 217 return rc; 218 } 219 220 wil_link_off(wil); 221 222 return 0; 223 } 224 225 void wil_if_remove(struct wil6210_priv *wil) 226 { 227 struct net_device *ndev = wil_to_ndev(wil); 228 229 wil_dbg_misc(wil, "%s()\n", __func__); 230 231 unregister_netdev(ndev); 232 } 233