1 /* 2 * Copyright (c) 2012-2017 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 #include "wil6210.h" 19 #include "txrx.h" 20 21 static int wil_open(struct net_device *ndev) 22 { 23 struct wil6210_priv *wil = ndev_to_wil(ndev); 24 25 wil_dbg_misc(wil, "open\n"); 26 27 if (debug_fw || 28 test_bit(WMI_FW_CAPABILITY_WMI_ONLY, wil->fw_capabilities)) { 29 wil_err(wil, "while in debug_fw or wmi_only mode\n"); 30 return -EINVAL; 31 } 32 33 return wil_up(wil); 34 } 35 36 static int wil_stop(struct net_device *ndev) 37 { 38 struct wil6210_priv *wil = ndev_to_wil(ndev); 39 40 wil_dbg_misc(wil, "stop\n"); 41 42 return wil_down(wil); 43 } 44 45 static int wil_do_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) 46 { 47 struct wil6210_priv *wil = ndev_to_wil(ndev); 48 49 return wil_ioctl(wil, ifr->ifr_data, cmd); 50 } 51 52 static const struct net_device_ops wil_netdev_ops = { 53 .ndo_open = wil_open, 54 .ndo_stop = wil_stop, 55 .ndo_start_xmit = wil_start_xmit, 56 .ndo_set_mac_address = eth_mac_addr, 57 .ndo_validate_addr = eth_validate_addr, 58 .ndo_do_ioctl = wil_do_ioctl, 59 }; 60 61 static int wil6210_netdev_poll_rx(struct napi_struct *napi, int budget) 62 { 63 struct wil6210_priv *wil = container_of(napi, struct wil6210_priv, 64 napi_rx); 65 int quota = budget; 66 int done; 67 68 wil_rx_handle(wil, "a); 69 done = budget - quota; 70 71 if (done < budget) { 72 napi_complete_done(napi, done); 73 wil6210_unmask_irq_rx(wil); 74 wil_dbg_txrx(wil, "NAPI RX complete\n"); 75 } 76 77 wil_dbg_txrx(wil, "NAPI RX poll(%d) done %d\n", budget, done); 78 79 return done; 80 } 81 82 static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget) 83 { 84 struct wil6210_priv *wil = container_of(napi, struct wil6210_priv, 85 napi_tx); 86 int tx_done = 0; 87 uint i; 88 89 /* always process ALL Tx complete, regardless budget - it is fast */ 90 for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { 91 struct vring *vring = &wil->vring_tx[i]; 92 struct vring_tx_data *txdata = &wil->vring_tx_data[i]; 93 94 if (!vring->va || !txdata->enabled) 95 continue; 96 97 tx_done += wil_tx_complete(wil, i); 98 } 99 100 if (tx_done < budget) { 101 napi_complete(napi); 102 wil6210_unmask_irq_tx(wil); 103 wil_dbg_txrx(wil, "NAPI TX complete\n"); 104 } 105 106 wil_dbg_txrx(wil, "NAPI TX poll(%d) done %d\n", budget, tx_done); 107 108 return min(tx_done, budget); 109 } 110 111 static void wil_dev_setup(struct net_device *dev) 112 { 113 ether_setup(dev); 114 dev->max_mtu = mtu_max; 115 dev->tx_queue_len = WIL_TX_Q_LEN_DEFAULT; 116 } 117 118 void *wil_if_alloc(struct device *dev) 119 { 120 struct net_device *ndev; 121 struct wireless_dev *wdev; 122 struct wil6210_priv *wil; 123 struct ieee80211_channel *ch; 124 int rc = 0; 125 126 wdev = wil_cfg80211_init(dev); 127 if (IS_ERR(wdev)) { 128 dev_err(dev, "wil_cfg80211_init failed\n"); 129 return wdev; 130 } 131 132 wil = wdev_to_wil(wdev); 133 wil->wdev = wdev; 134 wil->radio_wdev = wdev; 135 136 wil_dbg_misc(wil, "if_alloc\n"); 137 138 rc = wil_priv_init(wil); 139 if (rc) { 140 dev_err(dev, "wil_priv_init failed\n"); 141 goto out_wdev; 142 } 143 144 wdev->iftype = NL80211_IFTYPE_STATION; /* TODO */ 145 /* default monitor channel */ 146 ch = wdev->wiphy->bands[NL80211_BAND_60GHZ]->channels; 147 cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT); 148 149 ndev = alloc_netdev(0, "wlan%d", NET_NAME_UNKNOWN, wil_dev_setup); 150 if (!ndev) { 151 dev_err(dev, "alloc_netdev_mqs failed\n"); 152 rc = -ENOMEM; 153 goto out_priv; 154 } 155 156 ndev->netdev_ops = &wil_netdev_ops; 157 wil_set_ethtoolops(ndev); 158 ndev->ieee80211_ptr = wdev; 159 ndev->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM | 160 NETIF_F_SG | NETIF_F_GRO | 161 NETIF_F_TSO | NETIF_F_TSO6 | 162 NETIF_F_RXHASH; 163 164 ndev->features |= ndev->hw_features; 165 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); 166 wdev->netdev = ndev; 167 168 return wil; 169 170 out_priv: 171 wil_priv_deinit(wil); 172 173 out_wdev: 174 wil_wdev_free(wil); 175 176 return ERR_PTR(rc); 177 } 178 179 void wil_if_free(struct wil6210_priv *wil) 180 { 181 struct net_device *ndev = wil_to_ndev(wil); 182 183 wil_dbg_misc(wil, "if_free\n"); 184 185 if (!ndev) 186 return; 187 188 wil_priv_deinit(wil); 189 190 wil_to_ndev(wil) = NULL; 191 free_netdev(ndev); 192 193 wil_wdev_free(wil); 194 } 195 196 int wil_if_add(struct wil6210_priv *wil) 197 { 198 struct wireless_dev *wdev = wil_to_wdev(wil); 199 struct wiphy *wiphy = wdev->wiphy; 200 struct net_device *ndev = wil_to_ndev(wil); 201 int rc; 202 203 wil_dbg_misc(wil, "entered"); 204 205 strlcpy(wiphy->fw_version, wil->fw_version, sizeof(wiphy->fw_version)); 206 207 rc = wiphy_register(wiphy); 208 if (rc < 0) { 209 wil_err(wil, "failed to register wiphy, err %d\n", rc); 210 return rc; 211 } 212 213 netif_napi_add(ndev, &wil->napi_rx, wil6210_netdev_poll_rx, 214 WIL6210_NAPI_BUDGET); 215 netif_tx_napi_add(ndev, &wil->napi_tx, wil6210_netdev_poll_tx, 216 WIL6210_NAPI_BUDGET); 217 218 wil_update_net_queues_bh(wil, NULL, true); 219 220 rc = register_netdev(ndev); 221 if (rc < 0) { 222 dev_err(&ndev->dev, "Failed to register netdev: %d\n", rc); 223 goto out_wiphy; 224 } 225 226 return 0; 227 228 out_wiphy: 229 wiphy_unregister(wdev->wiphy); 230 return rc; 231 } 232 233 void wil_if_remove(struct wil6210_priv *wil) 234 { 235 struct net_device *ndev = wil_to_ndev(wil); 236 struct wireless_dev *wdev = wil_to_wdev(wil); 237 238 wil_dbg_misc(wil, "if_remove\n"); 239 240 unregister_netdev(ndev); 241 wiphy_unregister(wdev->wiphy); 242 } 243