Skip to content

Commit

Permalink
libipw: initiate cfg80211 API conversion (v2)
Browse files Browse the repository at this point in the history
Initiate the conversion of libipw to the new cfg80211 configuration API.

For now, leave CONFIG_IPW2200_PROMISCUOUS stuff alone.  Eventually
migrate it to cfg80211 when the add/del/change_virtual_intf methods
are implemented.

(v2: Fix unconditional wiphy_unregister in libipw which was causing
     problems for ipw2100, somewhat based on prior attempted fix
     by Zhu Yi <yi.zhu@intel.com>.  Previously both original version of
     this patch and Zhu Yi's fix attempt were reverted due to
     discovery of regressions. -- JWL)

Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
John W. Linville committed Nov 23, 2009
1 parent 9f13084 commit a3caa99
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 36 deletions.
6 changes: 3 additions & 3 deletions drivers/net/wireless/ipw2x00/ipw2100.c
Original file line number Diff line number Diff line change
Expand Up @@ -6029,7 +6029,7 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
struct ipw2100_priv *priv;
struct net_device *dev;

dev = alloc_ieee80211(sizeof(struct ipw2100_priv));
dev = alloc_ieee80211(sizeof(struct ipw2100_priv), 0);
if (!dev)
return NULL;
priv = libipw_priv(dev);
Expand Down Expand Up @@ -6342,7 +6342,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
sysfs_remove_group(&pci_dev->dev.kobj,
&ipw2100_attribute_group);

free_ieee80211(dev);
free_ieee80211(dev, 0);
pci_set_drvdata(pci_dev, NULL);
}

Expand Down Expand Up @@ -6400,7 +6400,7 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev)
if (dev->base_addr)
iounmap((void __iomem *)dev->base_addr);

free_ieee80211(dev);
free_ieee80211(dev, 0);
}

pci_release_regions(pci_dev);
Expand Down
145 changes: 117 additions & 28 deletions drivers/net/wireless/ipw2x00/ipw2200.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,25 @@ static int antenna = CFG_SYS_ANTENNA_BOTH;
static int rtap_iface = 0; /* def: 0 -- do not create rtap interface */
#endif

static struct ieee80211_rate ipw2200_rates[] = {
{ .bitrate = 10 },
{ .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
{ .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
{ .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
{ .bitrate = 60 },
{ .bitrate = 90 },
{ .bitrate = 120 },
{ .bitrate = 180 },
{ .bitrate = 240 },
{ .bitrate = 360 },
{ .bitrate = 480 },
{ .bitrate = 540 }
};

#define ipw2200_a_rates (ipw2200_rates + 4)
#define ipw2200_num_a_rates 8
#define ipw2200_bg_rates (ipw2200_rates + 0)
#define ipw2200_num_bg_rates 12

#ifdef CONFIG_IPW2200_QOS
static int qos_enable = 0;
Expand Down Expand Up @@ -8659,24 +8678,6 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option)
*
*/

static int ipw_wx_get_name(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct ipw_priv *priv = libipw_priv(dev);
mutex_lock(&priv->mutex);
if (priv->status & STATUS_RF_KILL_MASK)
strcpy(wrqu->name, "radio off");
else if (!(priv->status & STATUS_ASSOCIATED))
strcpy(wrqu->name, "unassociated");
else
snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11%c",
ipw_modes[priv->assoc_request.ieee_mode]);
IPW_DEBUG_WX("Name: %s\n", wrqu->name);
mutex_unlock(&priv->mutex);
return 0;
}

static int ipw_set_channel(struct ipw_priv *priv, u8 channel)
{
if (channel == 0) {
Expand Down Expand Up @@ -9976,7 +9977,7 @@ static int ipw_wx_sw_reset(struct net_device *dev,
/* Rebase the WE IOCTLs to zero for the handler array */
#define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT]
static iw_handler ipw_wx_handlers[] = {
IW_IOCTL(SIOCGIWNAME) = ipw_wx_get_name,
IW_IOCTL(SIOCGIWNAME) = (iw_handler) cfg80211_wext_giwname,
IW_IOCTL(SIOCSIWFREQ) = ipw_wx_set_freq,
IW_IOCTL(SIOCGIWFREQ) = ipw_wx_get_freq,
IW_IOCTL(SIOCSIWMODE) = ipw_wx_set_mode,
Expand Down Expand Up @@ -11421,16 +11422,100 @@ static void ipw_bg_down(struct work_struct *work)
/* Called by register_netdev() */
static int ipw_net_init(struct net_device *dev)
{
int i, rc = 0;
struct ipw_priv *priv = libipw_priv(dev);
const struct libipw_geo *geo = libipw_get_geo(priv->ieee);
struct wireless_dev *wdev = &priv->ieee->wdev;
mutex_lock(&priv->mutex);

if (ipw_up(priv)) {
mutex_unlock(&priv->mutex);
return -EIO;
rc = -EIO;
goto out;
}

memcpy(wdev->wiphy->perm_addr, priv->mac_addr, ETH_ALEN);

/* fill-out priv->ieee->bg_band */
if (geo->bg_channels) {
struct ieee80211_supported_band *bg_band = &priv->ieee->bg_band;

bg_band->band = IEEE80211_BAND_2GHZ;
bg_band->n_channels = geo->bg_channels;
bg_band->channels =
kzalloc(geo->bg_channels *
sizeof(struct ieee80211_channel), GFP_KERNEL);
/* translate geo->bg to bg_band.channels */
for (i = 0; i < geo->bg_channels; i++) {
bg_band->channels[i].band = IEEE80211_BAND_2GHZ;
bg_band->channels[i].center_freq = geo->bg[i].freq;
bg_band->channels[i].hw_value = geo->bg[i].channel;
bg_band->channels[i].max_power = geo->bg[i].max_power;
if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY)
bg_band->channels[i].flags |=
IEEE80211_CHAN_PASSIVE_SCAN;
if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS)
bg_band->channels[i].flags |=
IEEE80211_CHAN_NO_IBSS;
if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT)
bg_band->channels[i].flags |=
IEEE80211_CHAN_RADAR;
/* No equivalent for LIBIPW_CH_80211H_RULES,
LIBIPW_CH_UNIFORM_SPREADING, or
LIBIPW_CH_B_ONLY... */
}
/* point at bitrate info */
bg_band->bitrates = ipw2200_bg_rates;
bg_band->n_bitrates = ipw2200_num_bg_rates;

wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = bg_band;
}

/* fill-out priv->ieee->a_band */
if (geo->a_channels) {
struct ieee80211_supported_band *a_band = &priv->ieee->a_band;

a_band->band = IEEE80211_BAND_5GHZ;
a_band->n_channels = geo->a_channels;
a_band->channels =
kzalloc(geo->a_channels *
sizeof(struct ieee80211_channel), GFP_KERNEL);
/* translate geo->bg to a_band.channels */
for (i = 0; i < geo->a_channels; i++) {
a_band->channels[i].band = IEEE80211_BAND_2GHZ;
a_band->channels[i].center_freq = geo->a[i].freq;
a_band->channels[i].hw_value = geo->a[i].channel;
a_band->channels[i].max_power = geo->a[i].max_power;
if (geo->a[i].flags & LIBIPW_CH_PASSIVE_ONLY)
a_band->channels[i].flags |=
IEEE80211_CHAN_PASSIVE_SCAN;
if (geo->a[i].flags & LIBIPW_CH_NO_IBSS)
a_band->channels[i].flags |=
IEEE80211_CHAN_NO_IBSS;
if (geo->a[i].flags & LIBIPW_CH_RADAR_DETECT)
a_band->channels[i].flags |=
IEEE80211_CHAN_RADAR;
/* No equivalent for LIBIPW_CH_80211H_RULES,
LIBIPW_CH_UNIFORM_SPREADING, or
LIBIPW_CH_B_ONLY... */
}
/* point at bitrate info */
a_band->bitrates = ipw2200_a_rates;
a_band->n_bitrates = ipw2200_num_a_rates;

wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = a_band;
}

set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev);

/* With that information in place, we can now register the wiphy... */
if (wiphy_register(wdev->wiphy)) {
rc = -EIO;
goto out;
}

out:
mutex_unlock(&priv->mutex);
return 0;
return rc;
}

/* PCI driver stuff */
Expand Down Expand Up @@ -11561,7 +11646,7 @@ static int ipw_prom_alloc(struct ipw_priv *priv)
if (priv->prom_net_dev)
return -EPERM;

priv->prom_net_dev = alloc_ieee80211(sizeof(struct ipw_prom_priv));
priv->prom_net_dev = alloc_ieee80211(sizeof(struct ipw_prom_priv), 1);
if (priv->prom_net_dev == NULL)
return -ENOMEM;

Expand All @@ -11580,7 +11665,7 @@ static int ipw_prom_alloc(struct ipw_priv *priv)

rc = register_netdev(priv->prom_net_dev);
if (rc) {
free_ieee80211(priv->prom_net_dev);
free_ieee80211(priv->prom_net_dev, 1);
priv->prom_net_dev = NULL;
return rc;
}
Expand All @@ -11594,7 +11679,7 @@ static void ipw_prom_free(struct ipw_priv *priv)
return;

unregister_netdev(priv->prom_net_dev);
free_ieee80211(priv->prom_net_dev);
free_ieee80211(priv->prom_net_dev, 1);

priv->prom_net_dev = NULL;
}
Expand Down Expand Up @@ -11622,7 +11707,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
struct ipw_priv *priv;
int i;

net_dev = alloc_ieee80211(sizeof(struct ipw_priv));
net_dev = alloc_ieee80211(sizeof(struct ipw_priv), 0);
if (net_dev == NULL) {
err = -ENOMEM;
goto out;
Expand Down Expand Up @@ -11770,7 +11855,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
out_free_ieee80211:
free_ieee80211(priv->net_dev);
free_ieee80211(priv->net_dev, 0);
out:
return err;
}
Expand Down Expand Up @@ -11837,7 +11922,11 @@ static void __devexit ipw_pci_remove(struct pci_dev *pdev)
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
free_ieee80211(priv->net_dev);
/* wiphy_unregister needs to be here, before free_ieee80211 */
wiphy_unregister(priv->ieee->wdev.wiphy);
kfree(priv->ieee->a_band.channels);
kfree(priv->ieee->bg_band.channels);
free_ieee80211(priv->net_dev, 0);
free_firmware();
}

Expand Down
8 changes: 6 additions & 2 deletions drivers/net/wireless/ipw2x00/libipw.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <linux/ieee80211.h>

#include <net/lib80211.h>
#include <net/cfg80211.h>

#define LIBIPW_VERSION "git-1.1.13"

Expand Down Expand Up @@ -783,12 +784,15 @@ struct libipw_geo {

struct libipw_device {
struct net_device *dev;
struct wireless_dev wdev;
struct libipw_security sec;

/* Bookkeeping structures */
struct libipw_stats ieee_stats;

struct libipw_geo geo;
struct ieee80211_supported_band bg_band;
struct ieee80211_supported_band a_band;

/* Probe / Beacon management */
struct list_head network_free_list;
Expand Down Expand Up @@ -1014,8 +1018,8 @@ static inline int libipw_is_cck_rate(u8 rate)
}

/* ieee80211.c */
extern void free_ieee80211(struct net_device *dev);
extern struct net_device *alloc_ieee80211(int sizeof_priv);
extern void free_ieee80211(struct net_device *dev, int monitor);
extern struct net_device *alloc_ieee80211(int sizeof_priv, int monitor);
extern int libipw_change_mtu(struct net_device *dev, int new_mtu);

extern void libipw_networks_age(struct libipw_device *ieee,
Expand Down
38 changes: 35 additions & 3 deletions drivers/net/wireless/ipw2x00/libipw_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_AUTHOR(DRV_COPYRIGHT);
MODULE_LICENSE("GPL");

struct cfg80211_ops libipw_config_ops = { };
void *libipw_wiphy_privid = &libipw_wiphy_privid;

static int libipw_networks_allocate(struct libipw_device *ieee)
{
if (ieee->networks)
Expand Down Expand Up @@ -140,7 +143,7 @@ int libipw_change_mtu(struct net_device *dev, int new_mtu)
}
EXPORT_SYMBOL(libipw_change_mtu);

struct net_device *alloc_ieee80211(int sizeof_priv)
struct net_device *alloc_ieee80211(int sizeof_priv, int monitor)
{
struct libipw_device *ieee;
struct net_device *dev;
Expand All @@ -157,10 +160,31 @@ struct net_device *alloc_ieee80211(int sizeof_priv)

ieee->dev = dev;

if (!monitor) {
ieee->wdev.wiphy = wiphy_new(&libipw_config_ops, 0);
if (!ieee->wdev.wiphy) {
LIBIPW_ERROR("Unable to allocate wiphy.\n");
goto failed_free_netdev;
}

ieee->dev->ieee80211_ptr = &ieee->wdev;
ieee->wdev.iftype = NL80211_IFTYPE_STATION;

/* Fill-out wiphy structure bits we know... Not enough info
here to call set_wiphy_dev or set MAC address or channel info
-- have to do that in ->ndo_init... */
ieee->wdev.wiphy->privid = libipw_wiphy_privid;

ieee->wdev.wiphy->max_scan_ssids = 1;
ieee->wdev.wiphy->max_scan_ie_len = 0;
ieee->wdev.wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
| BIT(NL80211_IFTYPE_ADHOC);
}

err = libipw_networks_allocate(ieee);
if (err) {
LIBIPW_ERROR("Unable to allocate beacon storage: %d\n", err);
goto failed_free_netdev;
goto failed_free_wiphy;
}
libipw_networks_initialize(ieee);

Expand Down Expand Up @@ -193,19 +217,27 @@ struct net_device *alloc_ieee80211(int sizeof_priv)

return dev;

failed_free_wiphy:
if (!monitor)
wiphy_free(ieee->wdev.wiphy);
failed_free_netdev:
free_netdev(dev);
failed:
return NULL;
}

void free_ieee80211(struct net_device *dev)
void free_ieee80211(struct net_device *dev, int monitor)
{
struct libipw_device *ieee = netdev_priv(dev);

lib80211_crypt_info_free(&ieee->crypt_info);

libipw_networks_free(ieee);

/* free cfg80211 resources */
if (!monitor)
wiphy_free(ieee->wdev.wiphy);

free_netdev(dev);
}

Expand Down

0 comments on commit a3caa99

Please sign in to comment.