Skip to content

Commit a3caa99

Browse files
committed
libipw: initiate cfg80211 API conversion (v2)
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>
1 parent 9f13084 commit a3caa99

File tree

4 files changed

+161
-36
lines changed

4 files changed

+161
-36
lines changed

drivers/net/wireless/ipw2x00/ipw2100.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6029,7 +6029,7 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
60296029
struct ipw2100_priv *priv;
60306030
struct net_device *dev;
60316031

6032-
dev = alloc_ieee80211(sizeof(struct ipw2100_priv));
6032+
dev = alloc_ieee80211(sizeof(struct ipw2100_priv), 0);
60336033
if (!dev)
60346034
return NULL;
60356035
priv = libipw_priv(dev);
@@ -6342,7 +6342,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
63426342
sysfs_remove_group(&pci_dev->dev.kobj,
63436343
&ipw2100_attribute_group);
63446344

6345-
free_ieee80211(dev);
6345+
free_ieee80211(dev, 0);
63466346
pci_set_drvdata(pci_dev, NULL);
63476347
}
63486348

@@ -6400,7 +6400,7 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev)
64006400
if (dev->base_addr)
64016401
iounmap((void __iomem *)dev->base_addr);
64026402

6403-
free_ieee80211(dev);
6403+
free_ieee80211(dev, 0);
64046404
}
64056405

64066406
pci_release_regions(pci_dev);

drivers/net/wireless/ipw2x00/ipw2200.c

Lines changed: 117 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,25 @@ static int antenna = CFG_SYS_ANTENNA_BOTH;
108108
static int rtap_iface = 0; /* def: 0 -- do not create rtap interface */
109109
#endif
110110

111+
static struct ieee80211_rate ipw2200_rates[] = {
112+
{ .bitrate = 10 },
113+
{ .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
114+
{ .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
115+
{ .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
116+
{ .bitrate = 60 },
117+
{ .bitrate = 90 },
118+
{ .bitrate = 120 },
119+
{ .bitrate = 180 },
120+
{ .bitrate = 240 },
121+
{ .bitrate = 360 },
122+
{ .bitrate = 480 },
123+
{ .bitrate = 540 }
124+
};
125+
126+
#define ipw2200_a_rates (ipw2200_rates + 4)
127+
#define ipw2200_num_a_rates 8
128+
#define ipw2200_bg_rates (ipw2200_rates + 0)
129+
#define ipw2200_num_bg_rates 12
111130

112131
#ifdef CONFIG_IPW2200_QOS
113132
static int qos_enable = 0;
@@ -8659,24 +8678,6 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option)
86598678
*
86608679
*/
86618680

8662-
static int ipw_wx_get_name(struct net_device *dev,
8663-
struct iw_request_info *info,
8664-
union iwreq_data *wrqu, char *extra)
8665-
{
8666-
struct ipw_priv *priv = libipw_priv(dev);
8667-
mutex_lock(&priv->mutex);
8668-
if (priv->status & STATUS_RF_KILL_MASK)
8669-
strcpy(wrqu->name, "radio off");
8670-
else if (!(priv->status & STATUS_ASSOCIATED))
8671-
strcpy(wrqu->name, "unassociated");
8672-
else
8673-
snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11%c",
8674-
ipw_modes[priv->assoc_request.ieee_mode]);
8675-
IPW_DEBUG_WX("Name: %s\n", wrqu->name);
8676-
mutex_unlock(&priv->mutex);
8677-
return 0;
8678-
}
8679-
86808681
static int ipw_set_channel(struct ipw_priv *priv, u8 channel)
86818682
{
86828683
if (channel == 0) {
@@ -9976,7 +9977,7 @@ static int ipw_wx_sw_reset(struct net_device *dev,
99769977
/* Rebase the WE IOCTLs to zero for the handler array */
99779978
#define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT]
99789979
static iw_handler ipw_wx_handlers[] = {
9979-
IW_IOCTL(SIOCGIWNAME) = ipw_wx_get_name,
9980+
IW_IOCTL(SIOCGIWNAME) = (iw_handler) cfg80211_wext_giwname,
99809981
IW_IOCTL(SIOCSIWFREQ) = ipw_wx_set_freq,
99819982
IW_IOCTL(SIOCGIWFREQ) = ipw_wx_get_freq,
99829983
IW_IOCTL(SIOCSIWMODE) = ipw_wx_set_mode,
@@ -11421,16 +11422,100 @@ static void ipw_bg_down(struct work_struct *work)
1142111422
/* Called by register_netdev() */
1142211423
static int ipw_net_init(struct net_device *dev)
1142311424
{
11425+
int i, rc = 0;
1142411426
struct ipw_priv *priv = libipw_priv(dev);
11427+
const struct libipw_geo *geo = libipw_get_geo(priv->ieee);
11428+
struct wireless_dev *wdev = &priv->ieee->wdev;
1142511429
mutex_lock(&priv->mutex);
1142611430

1142711431
if (ipw_up(priv)) {
11428-
mutex_unlock(&priv->mutex);
11429-
return -EIO;
11432+
rc = -EIO;
11433+
goto out;
1143011434
}
1143111435

11436+
memcpy(wdev->wiphy->perm_addr, priv->mac_addr, ETH_ALEN);
11437+
11438+
/* fill-out priv->ieee->bg_band */
11439+
if (geo->bg_channels) {
11440+
struct ieee80211_supported_band *bg_band = &priv->ieee->bg_band;
11441+
11442+
bg_band->band = IEEE80211_BAND_2GHZ;
11443+
bg_band->n_channels = geo->bg_channels;
11444+
bg_band->channels =
11445+
kzalloc(geo->bg_channels *
11446+
sizeof(struct ieee80211_channel), GFP_KERNEL);
11447+
/* translate geo->bg to bg_band.channels */
11448+
for (i = 0; i < geo->bg_channels; i++) {
11449+
bg_band->channels[i].band = IEEE80211_BAND_2GHZ;
11450+
bg_band->channels[i].center_freq = geo->bg[i].freq;
11451+
bg_band->channels[i].hw_value = geo->bg[i].channel;
11452+
bg_band->channels[i].max_power = geo->bg[i].max_power;
11453+
if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY)
11454+
bg_band->channels[i].flags |=
11455+
IEEE80211_CHAN_PASSIVE_SCAN;
11456+
if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS)
11457+
bg_band->channels[i].flags |=
11458+
IEEE80211_CHAN_NO_IBSS;
11459+
if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT)
11460+
bg_band->channels[i].flags |=
11461+
IEEE80211_CHAN_RADAR;
11462+
/* No equivalent for LIBIPW_CH_80211H_RULES,
11463+
LIBIPW_CH_UNIFORM_SPREADING, or
11464+
LIBIPW_CH_B_ONLY... */
11465+
}
11466+
/* point at bitrate info */
11467+
bg_band->bitrates = ipw2200_bg_rates;
11468+
bg_band->n_bitrates = ipw2200_num_bg_rates;
11469+
11470+
wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = bg_band;
11471+
}
11472+
11473+
/* fill-out priv->ieee->a_band */
11474+
if (geo->a_channels) {
11475+
struct ieee80211_supported_band *a_band = &priv->ieee->a_band;
11476+
11477+
a_band->band = IEEE80211_BAND_5GHZ;
11478+
a_band->n_channels = geo->a_channels;
11479+
a_band->channels =
11480+
kzalloc(geo->a_channels *
11481+
sizeof(struct ieee80211_channel), GFP_KERNEL);
11482+
/* translate geo->bg to a_band.channels */
11483+
for (i = 0; i < geo->a_channels; i++) {
11484+
a_band->channels[i].band = IEEE80211_BAND_2GHZ;
11485+
a_band->channels[i].center_freq = geo->a[i].freq;
11486+
a_band->channels[i].hw_value = geo->a[i].channel;
11487+
a_band->channels[i].max_power = geo->a[i].max_power;
11488+
if (geo->a[i].flags & LIBIPW_CH_PASSIVE_ONLY)
11489+
a_band->channels[i].flags |=
11490+
IEEE80211_CHAN_PASSIVE_SCAN;
11491+
if (geo->a[i].flags & LIBIPW_CH_NO_IBSS)
11492+
a_band->channels[i].flags |=
11493+
IEEE80211_CHAN_NO_IBSS;
11494+
if (geo->a[i].flags & LIBIPW_CH_RADAR_DETECT)
11495+
a_band->channels[i].flags |=
11496+
IEEE80211_CHAN_RADAR;
11497+
/* No equivalent for LIBIPW_CH_80211H_RULES,
11498+
LIBIPW_CH_UNIFORM_SPREADING, or
11499+
LIBIPW_CH_B_ONLY... */
11500+
}
11501+
/* point at bitrate info */
11502+
a_band->bitrates = ipw2200_a_rates;
11503+
a_band->n_bitrates = ipw2200_num_a_rates;
11504+
11505+
wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = a_band;
11506+
}
11507+
11508+
set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev);
11509+
11510+
/* With that information in place, we can now register the wiphy... */
11511+
if (wiphy_register(wdev->wiphy)) {
11512+
rc = -EIO;
11513+
goto out;
11514+
}
11515+
11516+
out:
1143211517
mutex_unlock(&priv->mutex);
11433-
return 0;
11518+
return rc;
1143411519
}
1143511520

1143611521
/* PCI driver stuff */
@@ -11561,7 +11646,7 @@ static int ipw_prom_alloc(struct ipw_priv *priv)
1156111646
if (priv->prom_net_dev)
1156211647
return -EPERM;
1156311648

11564-
priv->prom_net_dev = alloc_ieee80211(sizeof(struct ipw_prom_priv));
11649+
priv->prom_net_dev = alloc_ieee80211(sizeof(struct ipw_prom_priv), 1);
1156511650
if (priv->prom_net_dev == NULL)
1156611651
return -ENOMEM;
1156711652

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

1158111666
rc = register_netdev(priv->prom_net_dev);
1158211667
if (rc) {
11583-
free_ieee80211(priv->prom_net_dev);
11668+
free_ieee80211(priv->prom_net_dev, 1);
1158411669
priv->prom_net_dev = NULL;
1158511670
return rc;
1158611671
}
@@ -11594,7 +11679,7 @@ static void ipw_prom_free(struct ipw_priv *priv)
1159411679
return;
1159511680

1159611681
unregister_netdev(priv->prom_net_dev);
11597-
free_ieee80211(priv->prom_net_dev);
11682+
free_ieee80211(priv->prom_net_dev, 1);
1159811683

1159911684
priv->prom_net_dev = NULL;
1160011685
}
@@ -11622,7 +11707,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
1162211707
struct ipw_priv *priv;
1162311708
int i;
1162411709

11625-
net_dev = alloc_ieee80211(sizeof(struct ipw_priv));
11710+
net_dev = alloc_ieee80211(sizeof(struct ipw_priv), 0);
1162611711
if (net_dev == NULL) {
1162711712
err = -ENOMEM;
1162811713
goto out;
@@ -11770,7 +11855,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
1177011855
pci_disable_device(pdev);
1177111856
pci_set_drvdata(pdev, NULL);
1177211857
out_free_ieee80211:
11773-
free_ieee80211(priv->net_dev);
11858+
free_ieee80211(priv->net_dev, 0);
1177411859
out:
1177511860
return err;
1177611861
}
@@ -11837,7 +11922,11 @@ static void __devexit ipw_pci_remove(struct pci_dev *pdev)
1183711922
pci_release_regions(pdev);
1183811923
pci_disable_device(pdev);
1183911924
pci_set_drvdata(pdev, NULL);
11840-
free_ieee80211(priv->net_dev);
11925+
/* wiphy_unregister needs to be here, before free_ieee80211 */
11926+
wiphy_unregister(priv->ieee->wdev.wiphy);
11927+
kfree(priv->ieee->a_band.channels);
11928+
kfree(priv->ieee->bg_band.channels);
11929+
free_ieee80211(priv->net_dev, 0);
1184111930
free_firmware();
1184211931
}
1184311932

drivers/net/wireless/ipw2x00/libipw.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <linux/ieee80211.h>
3232

3333
#include <net/lib80211.h>
34+
#include <net/cfg80211.h>
3435

3536
#define LIBIPW_VERSION "git-1.1.13"
3637

@@ -783,12 +784,15 @@ struct libipw_geo {
783784

784785
struct libipw_device {
785786
struct net_device *dev;
787+
struct wireless_dev wdev;
786788
struct libipw_security sec;
787789

788790
/* Bookkeeping structures */
789791
struct libipw_stats ieee_stats;
790792

791793
struct libipw_geo geo;
794+
struct ieee80211_supported_band bg_band;
795+
struct ieee80211_supported_band a_band;
792796

793797
/* Probe / Beacon management */
794798
struct list_head network_free_list;
@@ -1014,8 +1018,8 @@ static inline int libipw_is_cck_rate(u8 rate)
10141018
}
10151019

10161020
/* ieee80211.c */
1017-
extern void free_ieee80211(struct net_device *dev);
1018-
extern struct net_device *alloc_ieee80211(int sizeof_priv);
1021+
extern void free_ieee80211(struct net_device *dev, int monitor);
1022+
extern struct net_device *alloc_ieee80211(int sizeof_priv, int monitor);
10191023
extern int libipw_change_mtu(struct net_device *dev, int new_mtu);
10201024

10211025
extern void libipw_networks_age(struct libipw_device *ieee,

drivers/net/wireless/ipw2x00/libipw_module.c

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION);
6262
MODULE_AUTHOR(DRV_COPYRIGHT);
6363
MODULE_LICENSE("GPL");
6464

65+
struct cfg80211_ops libipw_config_ops = { };
66+
void *libipw_wiphy_privid = &libipw_wiphy_privid;
67+
6568
static int libipw_networks_allocate(struct libipw_device *ieee)
6669
{
6770
if (ieee->networks)
@@ -140,7 +143,7 @@ int libipw_change_mtu(struct net_device *dev, int new_mtu)
140143
}
141144
EXPORT_SYMBOL(libipw_change_mtu);
142145

143-
struct net_device *alloc_ieee80211(int sizeof_priv)
146+
struct net_device *alloc_ieee80211(int sizeof_priv, int monitor)
144147
{
145148
struct libipw_device *ieee;
146149
struct net_device *dev;
@@ -157,10 +160,31 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
157160

158161
ieee->dev = dev;
159162

163+
if (!monitor) {
164+
ieee->wdev.wiphy = wiphy_new(&libipw_config_ops, 0);
165+
if (!ieee->wdev.wiphy) {
166+
LIBIPW_ERROR("Unable to allocate wiphy.\n");
167+
goto failed_free_netdev;
168+
}
169+
170+
ieee->dev->ieee80211_ptr = &ieee->wdev;
171+
ieee->wdev.iftype = NL80211_IFTYPE_STATION;
172+
173+
/* Fill-out wiphy structure bits we know... Not enough info
174+
here to call set_wiphy_dev or set MAC address or channel info
175+
-- have to do that in ->ndo_init... */
176+
ieee->wdev.wiphy->privid = libipw_wiphy_privid;
177+
178+
ieee->wdev.wiphy->max_scan_ssids = 1;
179+
ieee->wdev.wiphy->max_scan_ie_len = 0;
180+
ieee->wdev.wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
181+
| BIT(NL80211_IFTYPE_ADHOC);
182+
}
183+
160184
err = libipw_networks_allocate(ieee);
161185
if (err) {
162186
LIBIPW_ERROR("Unable to allocate beacon storage: %d\n", err);
163-
goto failed_free_netdev;
187+
goto failed_free_wiphy;
164188
}
165189
libipw_networks_initialize(ieee);
166190

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

194218
return dev;
195219

220+
failed_free_wiphy:
221+
if (!monitor)
222+
wiphy_free(ieee->wdev.wiphy);
196223
failed_free_netdev:
197224
free_netdev(dev);
198225
failed:
199226
return NULL;
200227
}
201228

202-
void free_ieee80211(struct net_device *dev)
229+
void free_ieee80211(struct net_device *dev, int monitor)
203230
{
204231
struct libipw_device *ieee = netdev_priv(dev);
205232

206233
lib80211_crypt_info_free(&ieee->crypt_info);
207234

208235
libipw_networks_free(ieee);
236+
237+
/* free cfg80211 resources */
238+
if (!monitor)
239+
wiphy_free(ieee->wdev.wiphy);
240+
209241
free_netdev(dev);
210242
}
211243

0 commit comments

Comments
 (0)