aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ipw2x00
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-11-24 18:01:29 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-24 18:01:29 -0500
commit4ba3eb034fb6fd1990ccc5a6d71d5abcda37b905 (patch)
tree0789ba36d96dba330416a1e6a9a68e891a78802a /drivers/net/wireless/ipw2x00
parent35700212b45ea9f98fa682cfc1bc1a67c9ccc34b (diff)
parent18b6c9a2213d3b6e0212e8b225abf95f7564206a (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers/net/wireless/ipw2x00')
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2100.c130
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2200.c153
-rw-r--r--drivers/net/wireless/ipw2x00/libipw.h8
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_module.c38
4 files changed, 262 insertions, 67 deletions
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index b7408370cf82..6c836c892e43 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -296,6 +296,33 @@ static const char *command_types[] = {
296}; 296};
297#endif 297#endif
298 298
299#define WEXT_USECHANNELS 1
300
301static const long ipw2100_frequencies[] = {
302 2412, 2417, 2422, 2427,
303 2432, 2437, 2442, 2447,
304 2452, 2457, 2462, 2467,
305 2472, 2484
306};
307
308#define FREQ_COUNT ARRAY_SIZE(ipw2100_frequencies)
309
310static const long ipw2100_rates_11b[] = {
311 1000000,
312 2000000,
313 5500000,
314 11000000
315};
316
317static struct ieee80211_rate ipw2100_bg_rates[] = {
318 { .bitrate = 10 },
319 { .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
320 { .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
321 { .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
322};
323
324#define RATE_COUNT ARRAY_SIZE(ipw2100_rates_11b)
325
299/* Pre-decl until we get the code solid and then we can clean it up */ 326/* Pre-decl until we get the code solid and then we can clean it up */
300static void ipw2100_tx_send_commands(struct ipw2100_priv *priv); 327static void ipw2100_tx_send_commands(struct ipw2100_priv *priv);
301static void ipw2100_tx_send_data(struct ipw2100_priv *priv); 328static void ipw2100_tx_send_data(struct ipw2100_priv *priv);
@@ -1141,6 +1168,7 @@ static int rf_kill_active(struct ipw2100_priv *priv)
1141 int i; 1168 int i;
1142 1169
1143 if (!(priv->hw_features & HW_FEATURE_RFKILL)) { 1170 if (!(priv->hw_features & HW_FEATURE_RFKILL)) {
1171 wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, false);
1144 priv->status &= ~STATUS_RF_KILL_HW; 1172 priv->status &= ~STATUS_RF_KILL_HW;
1145 return 0; 1173 return 0;
1146 } 1174 }
@@ -1151,10 +1179,13 @@ static int rf_kill_active(struct ipw2100_priv *priv)
1151 value = (value << 1) | ((reg & IPW_BIT_GPIO_RF_KILL) ? 0 : 1); 1179 value = (value << 1) | ((reg & IPW_BIT_GPIO_RF_KILL) ? 0 : 1);
1152 } 1180 }
1153 1181
1154 if (value == 0) 1182 if (value == 0) {
1183 wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, true);
1155 priv->status |= STATUS_RF_KILL_HW; 1184 priv->status |= STATUS_RF_KILL_HW;
1156 else 1185 } else {
1186 wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, false);
1157 priv->status &= ~STATUS_RF_KILL_HW; 1187 priv->status &= ~STATUS_RF_KILL_HW;
1188 }
1158 1189
1159 return (value == 0); 1190 return (value == 0);
1160} 1191}
@@ -1814,13 +1845,6 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
1814 return rc; 1845 return rc;
1815} 1846}
1816 1847
1817/* Called by register_netdev() */
1818static int ipw2100_net_init(struct net_device *dev)
1819{
1820 struct ipw2100_priv *priv = libipw_priv(dev);
1821 return ipw2100_up(priv, 1);
1822}
1823
1824static void ipw2100_down(struct ipw2100_priv *priv) 1848static void ipw2100_down(struct ipw2100_priv *priv)
1825{ 1849{
1826 unsigned long flags; 1850 unsigned long flags;
@@ -1875,6 +1899,64 @@ static void ipw2100_down(struct ipw2100_priv *priv)
1875 netif_stop_queue(priv->net_dev); 1899 netif_stop_queue(priv->net_dev);
1876} 1900}
1877 1901
1902/* Called by register_netdev() */
1903static int ipw2100_net_init(struct net_device *dev)
1904{
1905 struct ipw2100_priv *priv = libipw_priv(dev);
1906 const struct libipw_geo *geo = libipw_get_geo(priv->ieee);
1907 struct wireless_dev *wdev = &priv->ieee->wdev;
1908 int ret;
1909 int i;
1910
1911 ret = ipw2100_up(priv, 1);
1912 if (ret)
1913 return ret;
1914
1915 memcpy(wdev->wiphy->perm_addr, priv->mac_addr, ETH_ALEN);
1916
1917 /* fill-out priv->ieee->bg_band */
1918 if (geo->bg_channels) {
1919 struct ieee80211_supported_band *bg_band = &priv->ieee->bg_band;
1920
1921 bg_band->band = IEEE80211_BAND_2GHZ;
1922 bg_band->n_channels = geo->bg_channels;
1923 bg_band->channels =
1924 kzalloc(geo->bg_channels *
1925 sizeof(struct ieee80211_channel), GFP_KERNEL);
1926 /* translate geo->bg to bg_band.channels */
1927 for (i = 0; i < geo->bg_channels; i++) {
1928 bg_band->channels[i].band = IEEE80211_BAND_2GHZ;
1929 bg_band->channels[i].center_freq = geo->bg[i].freq;
1930 bg_band->channels[i].hw_value = geo->bg[i].channel;
1931 bg_band->channels[i].max_power = geo->bg[i].max_power;
1932 if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY)
1933 bg_band->channels[i].flags |=
1934 IEEE80211_CHAN_PASSIVE_SCAN;
1935 if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS)
1936 bg_band->channels[i].flags |=
1937 IEEE80211_CHAN_NO_IBSS;
1938 if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT)
1939 bg_band->channels[i].flags |=
1940 IEEE80211_CHAN_RADAR;
1941 /* No equivalent for LIBIPW_CH_80211H_RULES,
1942 LIBIPW_CH_UNIFORM_SPREADING, or
1943 LIBIPW_CH_B_ONLY... */
1944 }
1945 /* point at bitrate info */
1946 bg_band->bitrates = ipw2100_bg_rates;
1947 bg_band->n_bitrates = RATE_COUNT;
1948
1949 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = bg_band;
1950 }
1951
1952 set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev);
1953 if (wiphy_register(wdev->wiphy)) {
1954 ipw2100_down(priv);
1955 return -EIO;
1956 }
1957 return 0;
1958}
1959
1878static void ipw2100_reset_adapter(struct work_struct *work) 1960static void ipw2100_reset_adapter(struct work_struct *work)
1879{ 1961{
1880 struct ipw2100_priv *priv = 1962 struct ipw2100_priv *priv =
@@ -2090,6 +2172,7 @@ static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status)
2090 priv->net_dev->name); 2172 priv->net_dev->name);
2091 2173
2092 /* RF_KILL is now enabled (else we wouldn't be here) */ 2174 /* RF_KILL is now enabled (else we wouldn't be here) */
2175 wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, true);
2093 priv->status |= STATUS_RF_KILL_HW; 2176 priv->status |= STATUS_RF_KILL_HW;
2094 2177
2095 /* Make sure the RF Kill check timer is running */ 2178 /* Make sure the RF Kill check timer is running */
@@ -6029,7 +6112,7 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
6029 struct ipw2100_priv *priv; 6112 struct ipw2100_priv *priv;
6030 struct net_device *dev; 6113 struct net_device *dev;
6031 6114
6032 dev = alloc_ieee80211(sizeof(struct ipw2100_priv)); 6115 dev = alloc_ieee80211(sizeof(struct ipw2100_priv), 0);
6033 if (!dev) 6116 if (!dev)
6034 return NULL; 6117 return NULL;
6035 priv = libipw_priv(dev); 6118 priv = libipw_priv(dev);
@@ -6342,7 +6425,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
6342 sysfs_remove_group(&pci_dev->dev.kobj, 6425 sysfs_remove_group(&pci_dev->dev.kobj,
6343 &ipw2100_attribute_group); 6426 &ipw2100_attribute_group);
6344 6427
6345 free_ieee80211(dev); 6428 free_ieee80211(dev, 0);
6346 pci_set_drvdata(pci_dev, NULL); 6429 pci_set_drvdata(pci_dev, NULL);
6347 } 6430 }
6348 6431
@@ -6400,7 +6483,10 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev)
6400 if (dev->base_addr) 6483 if (dev->base_addr)
6401 iounmap((void __iomem *)dev->base_addr); 6484 iounmap((void __iomem *)dev->base_addr);
6402 6485
6403 free_ieee80211(dev); 6486 /* wiphy_unregister needs to be here, before free_ieee80211 */
6487 wiphy_unregister(priv->ieee->wdev.wiphy);
6488 kfree(priv->ieee->bg_band.channels);
6489 free_ieee80211(dev, 0);
6404 } 6490 }
6405 6491
6406 pci_release_regions(pci_dev); 6492 pci_release_regions(pci_dev);
@@ -6601,26 +6687,6 @@ static void __exit ipw2100_exit(void)
6601module_init(ipw2100_init); 6687module_init(ipw2100_init);
6602module_exit(ipw2100_exit); 6688module_exit(ipw2100_exit);
6603 6689
6604#define WEXT_USECHANNELS 1
6605
6606static const long ipw2100_frequencies[] = {
6607 2412, 2417, 2422, 2427,
6608 2432, 2437, 2442, 2447,
6609 2452, 2457, 2462, 2467,
6610 2472, 2484
6611};
6612
6613#define FREQ_COUNT ARRAY_SIZE(ipw2100_frequencies)
6614
6615static const long ipw2100_rates_11b[] = {
6616 1000000,
6617 2000000,
6618 5500000,
6619 11000000
6620};
6621
6622#define RATE_COUNT ARRAY_SIZE(ipw2100_rates_11b)
6623
6624static int ipw2100_wx_get_name(struct net_device *dev, 6690static int ipw2100_wx_get_name(struct net_device *dev,
6625 struct iw_request_info *info, 6691 struct iw_request_info *info,
6626 union iwreq_data *wrqu, char *extra) 6692 union iwreq_data *wrqu, char *extra)
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index 9fe0e8078a88..c28984ae46ff 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -109,6 +109,25 @@ static int antenna = CFG_SYS_ANTENNA_BOTH;
109static int rtap_iface = 0; /* def: 0 -- do not create rtap interface */ 109static int rtap_iface = 0; /* def: 0 -- do not create rtap interface */
110#endif 110#endif
111 111
112static struct ieee80211_rate ipw2200_rates[] = {
113 { .bitrate = 10 },
114 { .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
115 { .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
116 { .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
117 { .bitrate = 60 },
118 { .bitrate = 90 },
119 { .bitrate = 120 },
120 { .bitrate = 180 },
121 { .bitrate = 240 },
122 { .bitrate = 360 },
123 { .bitrate = 480 },
124 { .bitrate = 540 }
125};
126
127#define ipw2200_a_rates (ipw2200_rates + 4)
128#define ipw2200_num_a_rates 8
129#define ipw2200_bg_rates (ipw2200_rates + 0)
130#define ipw2200_num_bg_rates 12
112 131
113#ifdef CONFIG_IPW2200_QOS 132#ifdef CONFIG_IPW2200_QOS
114static int qos_enable = 0; 133static int qos_enable = 0;
@@ -1739,10 +1758,13 @@ static DEVICE_ATTR(direct_dword, S_IWUSR | S_IRUGO,
1739 1758
1740static int rf_kill_active(struct ipw_priv *priv) 1759static int rf_kill_active(struct ipw_priv *priv)
1741{ 1760{
1742 if (0 == (ipw_read32(priv, 0x30) & 0x10000)) 1761 if (0 == (ipw_read32(priv, 0x30) & 0x10000)) {
1743 priv->status |= STATUS_RF_KILL_HW; 1762 priv->status |= STATUS_RF_KILL_HW;
1744 else 1763 wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, true);
1764 } else {
1745 priv->status &= ~STATUS_RF_KILL_HW; 1765 priv->status &= ~STATUS_RF_KILL_HW;
1766 wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, false);
1767 }
1746 1768
1747 return (priv->status & STATUS_RF_KILL_HW) ? 1 : 0; 1769 return (priv->status & STATUS_RF_KILL_HW) ? 1 : 0;
1748} 1770}
@@ -2025,6 +2047,7 @@ static void ipw_irq_tasklet(struct ipw_priv *priv)
2025 if (inta & IPW_INTA_BIT_RF_KILL_DONE) { 2047 if (inta & IPW_INTA_BIT_RF_KILL_DONE) {
2026 IPW_DEBUG_RF_KILL("RF_KILL_DONE\n"); 2048 IPW_DEBUG_RF_KILL("RF_KILL_DONE\n");
2027 priv->status |= STATUS_RF_KILL_HW; 2049 priv->status |= STATUS_RF_KILL_HW;
2050 wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, true);
2028 wake_up_interruptible(&priv->wait_command_queue); 2051 wake_up_interruptible(&priv->wait_command_queue);
2029 priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING); 2052 priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);
2030 cancel_delayed_work(&priv->request_scan); 2053 cancel_delayed_work(&priv->request_scan);
@@ -8660,24 +8683,6 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option)
8660 * 8683 *
8661 */ 8684 */
8662 8685
8663static int ipw_wx_get_name(struct net_device *dev,
8664 struct iw_request_info *info,
8665 union iwreq_data *wrqu, char *extra)
8666{
8667 struct ipw_priv *priv = libipw_priv(dev);
8668 mutex_lock(&priv->mutex);
8669 if (priv->status & STATUS_RF_KILL_MASK)
8670 strcpy(wrqu->name, "radio off");
8671 else if (!(priv->status & STATUS_ASSOCIATED))
8672 strcpy(wrqu->name, "unassociated");
8673 else
8674 snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11%c",
8675 ipw_modes[priv->assoc_request.ieee_mode]);
8676 IPW_DEBUG_WX("Name: %s\n", wrqu->name);
8677 mutex_unlock(&priv->mutex);
8678 return 0;
8679}
8680
8681static int ipw_set_channel(struct ipw_priv *priv, u8 channel) 8686static int ipw_set_channel(struct ipw_priv *priv, u8 channel)
8682{ 8687{
8683 if (channel == 0) { 8688 if (channel == 0) {
@@ -9977,7 +9982,7 @@ static int ipw_wx_sw_reset(struct net_device *dev,
9977/* Rebase the WE IOCTLs to zero for the handler array */ 9982/* Rebase the WE IOCTLs to zero for the handler array */
9978#define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT] 9983#define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT]
9979static iw_handler ipw_wx_handlers[] = { 9984static iw_handler ipw_wx_handlers[] = {
9980 IW_IOCTL(SIOCGIWNAME) = ipw_wx_get_name, 9985 IW_IOCTL(SIOCGIWNAME) = (iw_handler) cfg80211_wext_giwname,
9981 IW_IOCTL(SIOCSIWFREQ) = ipw_wx_set_freq, 9986 IW_IOCTL(SIOCSIWFREQ) = ipw_wx_set_freq,
9982 IW_IOCTL(SIOCGIWFREQ) = ipw_wx_get_freq, 9987 IW_IOCTL(SIOCGIWFREQ) = ipw_wx_get_freq,
9983 IW_IOCTL(SIOCSIWMODE) = ipw_wx_set_mode, 9988 IW_IOCTL(SIOCSIWMODE) = ipw_wx_set_mode,
@@ -11422,16 +11427,100 @@ static void ipw_bg_down(struct work_struct *work)
11422/* Called by register_netdev() */ 11427/* Called by register_netdev() */
11423static int ipw_net_init(struct net_device *dev) 11428static int ipw_net_init(struct net_device *dev)
11424{ 11429{
11430 int i, rc = 0;
11425 struct ipw_priv *priv = libipw_priv(dev); 11431 struct ipw_priv *priv = libipw_priv(dev);
11432 const struct libipw_geo *geo = libipw_get_geo(priv->ieee);
11433 struct wireless_dev *wdev = &priv->ieee->wdev;
11426 mutex_lock(&priv->mutex); 11434 mutex_lock(&priv->mutex);
11427 11435
11428 if (ipw_up(priv)) { 11436 if (ipw_up(priv)) {
11429 mutex_unlock(&priv->mutex); 11437 rc = -EIO;
11430 return -EIO; 11438 goto out;
11439 }
11440
11441 memcpy(wdev->wiphy->perm_addr, priv->mac_addr, ETH_ALEN);
11442
11443 /* fill-out priv->ieee->bg_band */
11444 if (geo->bg_channels) {
11445 struct ieee80211_supported_band *bg_band = &priv->ieee->bg_band;
11446
11447 bg_band->band = IEEE80211_BAND_2GHZ;
11448 bg_band->n_channels = geo->bg_channels;
11449 bg_band->channels =
11450 kzalloc(geo->bg_channels *
11451 sizeof(struct ieee80211_channel), GFP_KERNEL);
11452 /* translate geo->bg to bg_band.channels */
11453 for (i = 0; i < geo->bg_channels; i++) {
11454 bg_band->channels[i].band = IEEE80211_BAND_2GHZ;
11455 bg_band->channels[i].center_freq = geo->bg[i].freq;
11456 bg_band->channels[i].hw_value = geo->bg[i].channel;
11457 bg_band->channels[i].max_power = geo->bg[i].max_power;
11458 if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY)
11459 bg_band->channels[i].flags |=
11460 IEEE80211_CHAN_PASSIVE_SCAN;
11461 if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS)
11462 bg_band->channels[i].flags |=
11463 IEEE80211_CHAN_NO_IBSS;
11464 if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT)
11465 bg_band->channels[i].flags |=
11466 IEEE80211_CHAN_RADAR;
11467 /* No equivalent for LIBIPW_CH_80211H_RULES,
11468 LIBIPW_CH_UNIFORM_SPREADING, or
11469 LIBIPW_CH_B_ONLY... */
11470 }
11471 /* point at bitrate info */
11472 bg_band->bitrates = ipw2200_bg_rates;
11473 bg_band->n_bitrates = ipw2200_num_bg_rates;
11474
11475 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = bg_band;
11431 } 11476 }
11432 11477
11478 /* fill-out priv->ieee->a_band */
11479 if (geo->a_channels) {
11480 struct ieee80211_supported_band *a_band = &priv->ieee->a_band;
11481
11482 a_band->band = IEEE80211_BAND_5GHZ;
11483 a_band->n_channels = geo->a_channels;
11484 a_band->channels =
11485 kzalloc(geo->a_channels *
11486 sizeof(struct ieee80211_channel), GFP_KERNEL);
11487 /* translate geo->bg to a_band.channels */
11488 for (i = 0; i < geo->a_channels; i++) {
11489 a_band->channels[i].band = IEEE80211_BAND_2GHZ;
11490 a_band->channels[i].center_freq = geo->a[i].freq;
11491 a_band->channels[i].hw_value = geo->a[i].channel;
11492 a_band->channels[i].max_power = geo->a[i].max_power;
11493 if (geo->a[i].flags & LIBIPW_CH_PASSIVE_ONLY)
11494 a_band->channels[i].flags |=
11495 IEEE80211_CHAN_PASSIVE_SCAN;
11496 if (geo->a[i].flags & LIBIPW_CH_NO_IBSS)
11497 a_band->channels[i].flags |=
11498 IEEE80211_CHAN_NO_IBSS;
11499 if (geo->a[i].flags & LIBIPW_CH_RADAR_DETECT)
11500 a_band->channels[i].flags |=
11501 IEEE80211_CHAN_RADAR;
11502 /* No equivalent for LIBIPW_CH_80211H_RULES,
11503 LIBIPW_CH_UNIFORM_SPREADING, or
11504 LIBIPW_CH_B_ONLY... */
11505 }
11506 /* point at bitrate info */
11507 a_band->bitrates = ipw2200_a_rates;
11508 a_band->n_bitrates = ipw2200_num_a_rates;
11509
11510 wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = a_band;
11511 }
11512
11513 set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev);
11514
11515 /* With that information in place, we can now register the wiphy... */
11516 if (wiphy_register(wdev->wiphy)) {
11517 rc = -EIO;
11518 goto out;
11519 }
11520
11521out:
11433 mutex_unlock(&priv->mutex); 11522 mutex_unlock(&priv->mutex);
11434 return 0; 11523 return rc;
11435} 11524}
11436 11525
11437/* PCI driver stuff */ 11526/* PCI driver stuff */
@@ -11562,7 +11651,7 @@ static int ipw_prom_alloc(struct ipw_priv *priv)
11562 if (priv->prom_net_dev) 11651 if (priv->prom_net_dev)
11563 return -EPERM; 11652 return -EPERM;
11564 11653
11565 priv->prom_net_dev = alloc_ieee80211(sizeof(struct ipw_prom_priv)); 11654 priv->prom_net_dev = alloc_ieee80211(sizeof(struct ipw_prom_priv), 1);
11566 if (priv->prom_net_dev == NULL) 11655 if (priv->prom_net_dev == NULL)
11567 return -ENOMEM; 11656 return -ENOMEM;
11568 11657
@@ -11581,7 +11670,7 @@ static int ipw_prom_alloc(struct ipw_priv *priv)
11581 11670
11582 rc = register_netdev(priv->prom_net_dev); 11671 rc = register_netdev(priv->prom_net_dev);
11583 if (rc) { 11672 if (rc) {
11584 free_ieee80211(priv->prom_net_dev); 11673 free_ieee80211(priv->prom_net_dev, 1);
11585 priv->prom_net_dev = NULL; 11674 priv->prom_net_dev = NULL;
11586 return rc; 11675 return rc;
11587 } 11676 }
@@ -11595,7 +11684,7 @@ static void ipw_prom_free(struct ipw_priv *priv)
11595 return; 11684 return;
11596 11685
11597 unregister_netdev(priv->prom_net_dev); 11686 unregister_netdev(priv->prom_net_dev);
11598 free_ieee80211(priv->prom_net_dev); 11687 free_ieee80211(priv->prom_net_dev, 1);
11599 11688
11600 priv->prom_net_dev = NULL; 11689 priv->prom_net_dev = NULL;
11601} 11690}
@@ -11623,7 +11712,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
11623 struct ipw_priv *priv; 11712 struct ipw_priv *priv;
11624 int i; 11713 int i;
11625 11714
11626 net_dev = alloc_ieee80211(sizeof(struct ipw_priv)); 11715 net_dev = alloc_ieee80211(sizeof(struct ipw_priv), 0);
11627 if (net_dev == NULL) { 11716 if (net_dev == NULL) {
11628 err = -ENOMEM; 11717 err = -ENOMEM;
11629 goto out; 11718 goto out;
@@ -11771,7 +11860,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
11771 pci_disable_device(pdev); 11860 pci_disable_device(pdev);
11772 pci_set_drvdata(pdev, NULL); 11861 pci_set_drvdata(pdev, NULL);
11773 out_free_ieee80211: 11862 out_free_ieee80211:
11774 free_ieee80211(priv->net_dev); 11863 free_ieee80211(priv->net_dev, 0);
11775 out: 11864 out:
11776 return err; 11865 return err;
11777} 11866}
@@ -11838,7 +11927,11 @@ static void __devexit ipw_pci_remove(struct pci_dev *pdev)
11838 pci_release_regions(pdev); 11927 pci_release_regions(pdev);
11839 pci_disable_device(pdev); 11928 pci_disable_device(pdev);
11840 pci_set_drvdata(pdev, NULL); 11929 pci_set_drvdata(pdev, NULL);
11841 free_ieee80211(priv->net_dev); 11930 /* wiphy_unregister needs to be here, before free_ieee80211 */
11931 wiphy_unregister(priv->ieee->wdev.wiphy);
11932 kfree(priv->ieee->a_band.channels);
11933 kfree(priv->ieee->bg_band.channels);
11934 free_ieee80211(priv->net_dev, 0);
11842 free_firmware(); 11935 free_firmware();
11843} 11936}
11844 11937
diff --git a/drivers/net/wireless/ipw2x00/libipw.h b/drivers/net/wireless/ipw2x00/libipw.h
index 1e334ff6bd52..bf45391172f3 100644
--- a/drivers/net/wireless/ipw2x00/libipw.h
+++ b/drivers/net/wireless/ipw2x00/libipw.h
@@ -31,6 +31,7 @@
31#include <linux/ieee80211.h> 31#include <linux/ieee80211.h>
32 32
33#include <net/lib80211.h> 33#include <net/lib80211.h>
34#include <net/cfg80211.h>
34 35
35#define LIBIPW_VERSION "git-1.1.13" 36#define LIBIPW_VERSION "git-1.1.13"
36 37
@@ -783,12 +784,15 @@ struct libipw_geo {
783 784
784struct libipw_device { 785struct libipw_device {
785 struct net_device *dev; 786 struct net_device *dev;
787 struct wireless_dev wdev;
786 struct libipw_security sec; 788 struct libipw_security sec;
787 789
788 /* Bookkeeping structures */ 790 /* Bookkeeping structures */
789 struct libipw_stats ieee_stats; 791 struct libipw_stats ieee_stats;
790 792
791 struct libipw_geo geo; 793 struct libipw_geo geo;
794 struct ieee80211_supported_band bg_band;
795 struct ieee80211_supported_band a_band;
792 796
793 /* Probe / Beacon management */ 797 /* Probe / Beacon management */
794 struct list_head network_free_list; 798 struct list_head network_free_list;
@@ -1014,8 +1018,8 @@ static inline int libipw_is_cck_rate(u8 rate)
1014} 1018}
1015 1019
1016/* ieee80211.c */ 1020/* ieee80211.c */
1017extern void free_ieee80211(struct net_device *dev); 1021extern void free_ieee80211(struct net_device *dev, int monitor);
1018extern struct net_device *alloc_ieee80211(int sizeof_priv); 1022extern struct net_device *alloc_ieee80211(int sizeof_priv, int monitor);
1019extern int libipw_change_mtu(struct net_device *dev, int new_mtu); 1023extern int libipw_change_mtu(struct net_device *dev, int new_mtu);
1020 1024
1021extern void libipw_networks_age(struct libipw_device *ieee, 1025extern void libipw_networks_age(struct libipw_device *ieee,
diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c
index eb2b60834c17..e8a1ac5f8e11 100644
--- a/drivers/net/wireless/ipw2x00/libipw_module.c
+++ b/drivers/net/wireless/ipw2x00/libipw_module.c
@@ -62,6 +62,9 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION);
62MODULE_AUTHOR(DRV_COPYRIGHT); 62MODULE_AUTHOR(DRV_COPYRIGHT);
63MODULE_LICENSE("GPL"); 63MODULE_LICENSE("GPL");
64 64
65struct cfg80211_ops libipw_config_ops = { };
66void *libipw_wiphy_privid = &libipw_wiphy_privid;
67
65static int libipw_networks_allocate(struct libipw_device *ieee) 68static int libipw_networks_allocate(struct libipw_device *ieee)
66{ 69{
67 if (ieee->networks) 70 if (ieee->networks)
@@ -140,7 +143,7 @@ int libipw_change_mtu(struct net_device *dev, int new_mtu)
140} 143}
141EXPORT_SYMBOL(libipw_change_mtu); 144EXPORT_SYMBOL(libipw_change_mtu);
142 145
143struct net_device *alloc_ieee80211(int sizeof_priv) 146struct net_device *alloc_ieee80211(int sizeof_priv, int monitor)
144{ 147{
145 struct libipw_device *ieee; 148 struct libipw_device *ieee;
146 struct net_device *dev; 149 struct net_device *dev;
@@ -157,10 +160,31 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
157 160
158 ieee->dev = dev; 161 ieee->dev = dev;
159 162
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
160 err = libipw_networks_allocate(ieee); 184 err = libipw_networks_allocate(ieee);
161 if (err) { 185 if (err) {
162 LIBIPW_ERROR("Unable to allocate beacon storage: %d\n", err); 186 LIBIPW_ERROR("Unable to allocate beacon storage: %d\n", err);
163 goto failed_free_netdev; 187 goto failed_free_wiphy;
164 } 188 }
165 libipw_networks_initialize(ieee); 189 libipw_networks_initialize(ieee);
166 190
@@ -193,19 +217,27 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
193 217
194 return dev; 218 return dev;
195 219
220failed_free_wiphy:
221 if (!monitor)
222 wiphy_free(ieee->wdev.wiphy);
196failed_free_netdev: 223failed_free_netdev:
197 free_netdev(dev); 224 free_netdev(dev);
198failed: 225failed:
199 return NULL; 226 return NULL;
200} 227}
201 228
202void free_ieee80211(struct net_device *dev) 229void free_ieee80211(struct net_device *dev, int monitor)
203{ 230{
204 struct libipw_device *ieee = netdev_priv(dev); 231 struct libipw_device *ieee = netdev_priv(dev);
205 232
206 lib80211_crypt_info_free(&ieee->crypt_info); 233 lib80211_crypt_info_free(&ieee->crypt_info);
207 234
208 libipw_networks_free(ieee); 235 libipw_networks_free(ieee);
236
237 /* free cfg80211 resources */
238 if (!monitor)
239 wiphy_free(ieee->wdev.wiphy);
240
209 free_netdev(dev); 241 free_netdev(dev);
210} 242}
211 243