Search Linux Wireless

Re: [RFC] libertas: first stab at cfg80211 support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 2009-09-28 at 13:21 +0200, Holger Schurig wrote:
> Signed-off-by: Holger Schurig <hs4233@xxxxxxxxxxxxxxxxxxxx>
> 
> ---
> 
> This patch currently just create a wdev, so you can do "iw list".
> 
> I'd like to get comments if the position where I create/destroy
> the wdev makes sense.

Yeah, that's probably more or less it.  The mesh bits are interesting,
because they aren't really mac80211 mesh, they are "special" mesh.
Perhaps we eventually want to port that over to cfg80211, but there are
special semantics with the mesh stuff that might be a problem (notably,
all encryption and rate settings are shared with the wlanX interface).

Because of that, the mesh interface is really just a shadow interface of
the normal wlanX interface, but during some calls we need to know
whether the call was done on the mesh iface or the wlanX iface, and of
course they each have different rx/tx queues.  Otherwise they share the
same private struct and whatnot.  That's what the "ml_priv" bits are
for.  I'd dearly love to find some other way of doing this though, since
the ml_priv stuff is really fragile.

Dan


> Index: linux-wl/drivers/net/wireless/Kconfig
> ===================================================================
> --- linux-wl.orig/drivers/net/wireless/Kconfig	2009-09-28 12:06:02.000000000 +0200
> +++ linux-wl/drivers/net/wireless/Kconfig	2009-09-28 12:06:30.000000000 +0200
> @@ -138,6 +138,7 @@ config LIBERTAS
>  	depends on WLAN_80211
>  	select WIRELESS_EXT
>  	select LIB80211
> +	select CFG80211
>  	select FW_LOADER
>  	---help---
>  	  A library for Marvell Libertas 8xxx devices.
> Index: linux-wl/drivers/net/wireless/libertas/Makefile
> ===================================================================
> --- linux-wl.orig/drivers/net/wireless/libertas/Makefile	2009-09-28 12:06:02.000000000 +0200
> +++ linux-wl/drivers/net/wireless/libertas/Makefile	2009-09-28 12:06:30.000000000 +0200
> @@ -1,5 +1,5 @@
>  libertas-objs := main.o wext.o rx.o tx.o cmd.o cmdresp.o scan.o 11d.o	\
> -		 debugfs.o persistcfg.o ethtool.o assoc.o
> +		 debugfs.o persistcfg.o ethtool.o assoc.o cfg.o
>  
>  usb8xxx-objs += if_usb.o
>  libertas_cs-objs += if_cs.o
> Index: linux-wl/drivers/net/wireless/libertas/dev.h
> ===================================================================
> --- linux-wl.orig/drivers/net/wireless/libertas/dev.h	2009-09-28 12:06:02.000000000 +0200
> +++ linux-wl/drivers/net/wireless/libertas/dev.h	2009-09-28 12:06:30.000000000 +0200
> @@ -100,6 +100,7 @@ struct lbs_mesh_stats {
>  
>  /** Private structure for the MV device */
>  struct lbs_private {
> +	struct wireless_dev *wdev;
>  	int mesh_open;
>  	int mesh_fw_ver;
>  	int infra_open;
> Index: linux-wl/drivers/net/wireless/libertas/cfg.h
> ===================================================================
> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ linux-wl/drivers/net/wireless/libertas/cfg.h	2009-09-28 12:07:23.000000000 +0200
> @@ -0,0 +1,9 @@
> +#ifndef __LBS_CFG80211_H__
> +#define __LBS_CFG80211_H__
> +
> +#include "dev.h"
> +
> +struct wireless_dev *lbs_wdev_alloc(int sizeof_priv, struct device *dev);
> +void lbs_wdev_free(struct lbs_private *lbs);
> +
> +#endif
> Index: linux-wl/drivers/net/wireless/libertas/cfg.c
> ===================================================================
> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ linux-wl/drivers/net/wireless/libertas/cfg.c	2009-09-28 12:09:06.000000000 +0200
> @@ -0,0 +1,160 @@
> +/*
> + * Implement cfg80211 ("iw") support.
> + *
> + * Copyright (C) 2009 M&N Solutions GmbH, 61191 Rosbach, Germany
> + * Holger Schurig <hs4233@xxxxxxxxxxxxxxxxxxxx>
> + *
> + * Based on cfg80211.h:
> + *   Copyright (C) 2009 Intel Corporation <ilw@xxxxxxxxxxxxxxx>
> + *   Samuel Ortiz <samuel.ortiz@xxxxxxxxx>
> + *   Zhu Yi <yi.zhu@xxxxxxxxx>
> + */
> +
> +#include <net/cfg80211.h>
> +
> +#include "cfg.h"
> +
> +
> +#define CHAN2G(_channel, _freq, _flags) {                       \
> +	.band                   = IEEE80211_BAND_2GHZ,          \
> +	.center_freq            = (_freq),                      \
> +	.hw_value               = (_channel),                   \
> +	.flags                  = (_flags),                     \
> +	.max_antenna_gain       = 0,                            \
> +	.max_power              = 30,                           \
> +}
> +
> +static struct ieee80211_channel lbs_2ghz_channels[] = {
> +	CHAN2G(1, 2412, 0),
> +	CHAN2G(2, 2417, 0),
> +	CHAN2G(3, 2422, 0),
> +	CHAN2G(4, 2427, 0),
> +	CHAN2G(5, 2432, 0),
> +	CHAN2G(6, 2437, 0),
> +	CHAN2G(7, 2442, 0),
> +	CHAN2G(8, 2447, 0),
> +	CHAN2G(9, 2452, 0),
> +	CHAN2G(10, 2457, 0),
> +	CHAN2G(11, 2462, 0),
> +	CHAN2G(12, 2467, 0),
> +	CHAN2G(13, 2472, 0),
> +	CHAN2G(14, 2484, 0),
> +};
> +
> +#define RATETAB_ENT(_rate, _rateid, _flags) \
> +	{                                                               \
> +		.bitrate        = (_rate),                              \
> +		.hw_value       = (_rateid),                            \
> +		.flags          = (_flags),                             \
> +	}
> +
> +
> +static struct ieee80211_rate lbs_rates[] = {
> +	RATETAB_ENT(10,  0x1,   0),
> +	RATETAB_ENT(20,  0x2,   0),
> +	RATETAB_ENT(55,  0x4,   0),
> +	RATETAB_ENT(110, 0x8,   0),
> +	RATETAB_ENT(60,  0x10,  0),
> +	RATETAB_ENT(90,  0x20,  0),
> +	RATETAB_ENT(120, 0x40,  0),
> +	RATETAB_ENT(180, 0x80,  0),
> +	RATETAB_ENT(240, 0x100, 0),
> +	RATETAB_ENT(360, 0x200, 0),
> +	RATETAB_ENT(480, 0x400, 0),
> +	RATETAB_ENT(540, 0x800, 0),
> +};
> +
> +static struct ieee80211_supported_band lbs_band_2ghz = {
> +	.channels = lbs_2ghz_channels,
> +	.n_channels = ARRAY_SIZE(lbs_2ghz_channels),
> +	.bitrates = lbs_rates,
> +	.n_bitrates = ARRAY_SIZE(lbs_rates),
> +};
> +
> +
> +static const u32 cipher_suites[] = {
> +	WLAN_CIPHER_SUITE_WEP40,
> +	WLAN_CIPHER_SUITE_WEP104,
> +	WLAN_CIPHER_SUITE_TKIP,
> +	WLAN_CIPHER_SUITE_CCMP,
> +};
> +
> +
> +
> +static struct cfg80211_ops lbs_cfg80211_ops = {
> +/* TODO
> +	.change_virtual_intf = iwm_cfg80211_change_iface,
> +	.add_key = iwm_cfg80211_add_key,
> +	.get_key = iwm_cfg80211_get_key,
> +	.del_key = iwm_cfg80211_del_key,
> +	.set_default_key = iwm_cfg80211_set_default_key,
> +	.get_station = iwm_cfg80211_get_station,
> +	.scan = iwm_cfg80211_scan,
> +	.set_wiphy_params = iwm_cfg80211_set_wiphy_params,
> +	.connect = iwm_cfg80211_connect,
> +	.disconnect = iwm_cfg80211_disconnect,
> +	.join_ibss = iwm_cfg80211_join_ibss,
> +	.leave_ibss = iwm_cfg80211_leave_ibss,
> +	.set_tx_power = iwm_cfg80211_set_txpower,
> +	.get_tx_power = iwm_cfg80211_get_txpower,
> +	.set_power_mgmt = iwm_cfg80211_set_power_mgmt,
> +*/
> +};
> +
> +struct wireless_dev *lbs_wdev_alloc(int sizeof_priv, struct device *dev)
> +{
> +	int ret = 0;
> +	struct wireless_dev *wdev;
> +
> +	wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
> +	if (!wdev) {
> +		dev_err(dev, "Couldn't allocate wireless device\n");
> +		return ERR_PTR(-ENOMEM);
> +	}
> +
> +	wdev->wiphy = wiphy_new(&lbs_cfg80211_ops,
> +		sizeof(struct lbs_private) + sizeof_priv);
> +	if (!wdev->wiphy) {
> +		dev_err(dev, "Couldn't allocate wiphy device\n");
> +		ret = -ENOMEM;
> +		goto out_err_new;
> +	}
> +
> +	set_wiphy_dev(wdev->wiphy, dev);
> +	wdev->wiphy->max_scan_ssids = 1; /* TODO */
> +	wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
> +		BIT(NL80211_IFTYPE_ADHOC);
> +	wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &lbs_band_2ghz;
> +	wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
> +	wdev->wiphy->cipher_suites = cipher_suites;
> +	wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
> +
> +	ret = wiphy_register(wdev->wiphy);
> +	if (ret < 0) {
> +		dev_err(dev, "Couldn't register wiphy device\n");
> +		goto out_err_register;
> +	}
> +
> +	return wdev;
> +
> + out_err_register:
> +	wiphy_free(wdev->wiphy);
> +
> + out_err_new:
> +	kfree(wdev);
> +
> +	return ERR_PTR(ret);
> +}
> +
> +
> +void lbs_wdev_free(struct lbs_private *lbs)
> +{
> +	struct wireless_dev *wdev = lbs->wdev;
> +
> +	if (!wdev)
> +		return;
> +
> +	wiphy_unregister(wdev->wiphy);
> +	wiphy_free(wdev->wiphy);
> +	kfree(wdev);
> +}
> Index: linux-wl/drivers/net/wireless/libertas/main.c
> ===================================================================
> --- linux-wl.orig/drivers/net/wireless/libertas/main.c	2009-09-28 12:06:02.000000000 +0200
> +++ linux-wl/drivers/net/wireless/libertas/main.c	2009-09-28 12:11:22.000000000 +0200
> @@ -14,11 +14,13 @@
>  #include <linux/stddef.h>
>  #include <linux/ieee80211.h>
>  #include <net/iw_handler.h>
> +#include <net/cfg80211.h>
>  
>  #include "host.h"
>  #include "decl.h"
>  #include "dev.h"
>  #include "wext.h"
> +#include "cfg.h"
>  #include "debugfs.h"
>  #include "scan.h"
>  #include "assoc.h"
> @@ -1168,31 +1170,42 @@ static const struct net_device_ops lbs_n
>   */
>  struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
>  {
> -	struct net_device *dev = NULL;
> +	struct net_device *dev;
> +	struct wireless_dev *wdev;
>  	struct lbs_private *priv = NULL;
>  
>  	lbs_deb_enter(LBS_DEB_MAIN);
>  
>  	/* Allocate an Ethernet device and register it */
> -	dev = alloc_etherdev(sizeof(struct lbs_private));
> -	if (!dev) {
> +	wdev = lbs_wdev_alloc(sizeof(struct lbs_private), dmdev);
> +	if (IS_ERR(wdev)) {
>  		lbs_pr_err("init wlanX device failed\n");
>  		goto done;
>  	}
> -	priv = netdev_priv(dev);
> -	dev->ml_priv = priv;
> +	/* TODO? */
> +	wdev->iftype = NL80211_IFTYPE_STATION;
> +	priv = wdev_priv(wdev);
> +	priv->wdev = wdev;
>  
>  	if (lbs_init_adapter(priv)) {
>  		lbs_pr_err("failed to initialize adapter structure.\n");
> -		goto err_init_adapter;
> +		goto err_wdev;
> +	}
> +
> +	//TODO? dev = alloc_netdev_mq(0, "wlan%d", ether_setup, IWM_TX_QUEUES);
> +	dev = alloc_netdev(0, "wlan%d", ether_setup);
> +	if (!dev) {
> +		dev_err(dmdev, "no memory for network device instance\n");
> +		goto err_adapter;
>  	}
>  
> +	dev->netdev_ops = &lbs_netdev_ops;
> +	dev->ieee80211_ptr = wdev;
> +	dev->ml_priv = priv;
> +	SET_NETDEV_DEV(dev, dmdev);
> +	wdev->netdev = dev;
>  	priv->dev = dev;
> -	priv->card = card;
> -	priv->mesh_open = 0;
> -	priv->infra_open = 0;
>  
> -	/* Setup the OS Interface to our functions */
>   	dev->netdev_ops = &lbs_netdev_ops;
>  	dev->watchdog_timeo = 5 * HZ;
>  	dev->ethtool_ops = &lbs_ethtool_ops;
> @@ -1201,7 +1214,14 @@ struct lbs_private *lbs_add_card(void *c
>  #endif
>  	dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
>  
> -	SET_NETDEV_DEV(dev, dmdev);
> +
> +	// TODO: kzalloc + iwm_init_default_profile(iwm, iwm->umac_profile); ??
> +
> +
> +	priv->card = card;
> +	priv->mesh_open = 0;
> +	priv->infra_open = 0;
> +
>  
>  	priv->rtap_net_dev = NULL;
>  	strcpy(dev->name, "wlan%d");
> @@ -1211,7 +1231,7 @@ struct lbs_private *lbs_add_card(void *c
>  	priv->main_thread = kthread_run(lbs_thread, dev, "lbs_main");
>  	if (IS_ERR(priv->main_thread)) {
>  		lbs_deb_thread("Error creating main thread.\n");
> -		goto err_init_adapter;
> +		goto err_ndev;
>  	}
>  
>  	priv->work_thread = create_singlethread_workqueue("lbs_worker");
> @@ -1228,9 +1248,15 @@ struct lbs_private *lbs_add_card(void *c
>  
>  	goto done;
>  
> -err_init_adapter:
> -	lbs_free_adapter(priv);
> + err_ndev:
>  	free_netdev(dev);
> +
> + err_adapter:
> +	lbs_free_adapter(priv);
> +
> + err_wdev:
> +	lbs_wdev_free(priv);
> +
>  	priv = NULL;
>  
>  done:
> @@ -1277,6 +1303,7 @@ void lbs_remove_card(struct lbs_private 
>  	kthread_stop(priv->main_thread);
>  
>  	lbs_free_adapter(priv);
> +	lbs_wdev_free(priv);
>  
>  	priv->dev = NULL;
>  	free_netdev(dev);
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux