diff options
Diffstat (limited to 'drivers/net/wireless/ath/wil6210/netdev.c')
| -rw-r--r-- | drivers/net/wireless/ath/wil6210/netdev.c | 157 | 
1 files changed, 157 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c new file mode 100644 index 00000000000..3068b5cb53a --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/netdev.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2012 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <linux/module.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/slab.h> + +#include "wil6210.h" + +static int wil_open(struct net_device *ndev) +{ +	struct wil6210_priv *wil = ndev_to_wil(ndev); + +	return wil_up(wil); +} + +static int wil_stop(struct net_device *ndev) +{ +	struct wil6210_priv *wil = ndev_to_wil(ndev); + +	return wil_down(wil); +} + +/* + * AC to queue mapping + * + * AC_VO -> queue 3 + * AC_VI -> queue 2 + * AC_BE -> queue 1 + * AC_BK -> queue 0 + */ +static u16 wil_select_queue(struct net_device *ndev, struct sk_buff *skb) +{ +	static const u16 wil_1d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; +	struct wil6210_priv *wil = ndev_to_wil(ndev); +	u16 rc; + +	skb->priority = cfg80211_classify8021d(skb); + +	rc = wil_1d_to_queue[skb->priority]; + +	wil_dbg_TXRX(wil, "%s() %d -> %d\n", __func__, (int)skb->priority, +		     (int)rc); + +	return rc; +} + +static const struct net_device_ops wil_netdev_ops = { +	.ndo_open		= wil_open, +	.ndo_stop		= wil_stop, +	.ndo_start_xmit		= wil_start_xmit, +	.ndo_select_queue	= wil_select_queue, +	.ndo_set_mac_address    = eth_mac_addr, +	.ndo_validate_addr      = eth_validate_addr, +}; + +void *wil_if_alloc(struct device *dev, void __iomem *csr) +{ +	struct net_device *ndev; +	struct wireless_dev *wdev; +	struct wil6210_priv *wil; +	struct ieee80211_channel *ch; +	int rc = 0; + +	wdev = wil_cfg80211_init(dev); +	if (IS_ERR(wdev)) { +		dev_err(dev, "wil_cfg80211_init failed\n"); +		return wdev; +	} + +	wil = wdev_to_wil(wdev); +	wil->csr = csr; +	wil->wdev = wdev; + +	rc = wil_priv_init(wil); +	if (rc) { +		dev_err(dev, "wil_priv_init failed\n"); +		goto out_wdev; +	} + +	wdev->iftype = NL80211_IFTYPE_STATION; /* TODO */ +	/* default monitor channel */ +	ch = wdev->wiphy->bands[IEEE80211_BAND_60GHZ]->channels; +	cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT); + +	ndev = alloc_netdev_mqs(0, "wlan%d", ether_setup, WIL6210_TX_QUEUES, 1); +	if (!ndev) { +		dev_err(dev, "alloc_netdev_mqs failed\n"); +		rc = -ENOMEM; +		goto out_priv; +	} + +	ndev->netdev_ops = &wil_netdev_ops; +	ndev->ieee80211_ptr = wdev; +	SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); +	wdev->netdev = ndev; + +	wil_link_off(wil); + +	return wil; + + out_priv: +	wil_priv_deinit(wil); + + out_wdev: +	wil_wdev_free(wil); + +	return ERR_PTR(rc); +} + +void wil_if_free(struct wil6210_priv *wil) +{ +	struct net_device *ndev = wil_to_ndev(wil); +	if (!ndev) +		return; + +	free_netdev(ndev); +	wil_priv_deinit(wil); +	wil_wdev_free(wil); +} + +int wil_if_add(struct wil6210_priv *wil) +{ +	struct net_device *ndev = wil_to_ndev(wil); +	int rc; + +	rc = register_netdev(ndev); +	if (rc < 0) { +		dev_err(&ndev->dev, "Failed to register netdev: %d\n", rc); +		return rc; +	} + +	wil_link_off(wil); + +	return 0; +} + +void wil_if_remove(struct wil6210_priv *wil) +{ +	struct net_device *ndev = wil_to_ndev(wil); + +	unregister_netdev(ndev); +}  |