linux/drivers/net/wireless/ath/wil6210/netdev.c
<<
>>
Prefs
   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        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
 153void 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
 164int 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
 180void wil_if_remove(struct wil6210_priv *wil)
 181{
 182        struct net_device *ndev = wil_to_ndev(wil);
 183
 184        unregister_netdev(ndev);
 185}
 186