diff options
author | David S. Miller <davem@davemloft.net> | 2009-11-24 18:01:29 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-11-24 18:01:29 -0500 |
commit | 4ba3eb034fb6fd1990ccc5a6d71d5abcda37b905 (patch) | |
tree | 0789ba36d96dba330416a1e6a9a68e891a78802a /drivers/net/wireless/ipw2x00 | |
parent | 35700212b45ea9f98fa682cfc1bc1a67c9ccc34b (diff) | |
parent | 18b6c9a2213d3b6e0212e8b225abf95f7564206a (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.c | 130 | ||||
-rw-r--r-- | drivers/net/wireless/ipw2x00/ipw2200.c | 153 | ||||
-rw-r--r-- | drivers/net/wireless/ipw2x00/libipw.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/ipw2x00/libipw_module.c | 38 |
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 | |||
301 | static 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 | |||
310 | static const long ipw2100_rates_11b[] = { | ||
311 | 1000000, | ||
312 | 2000000, | ||
313 | 5500000, | ||
314 | 11000000 | ||
315 | }; | ||
316 | |||
317 | static 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 */ |
300 | static void ipw2100_tx_send_commands(struct ipw2100_priv *priv); | 327 | static void ipw2100_tx_send_commands(struct ipw2100_priv *priv); |
301 | static void ipw2100_tx_send_data(struct ipw2100_priv *priv); | 328 | static 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() */ | ||
1818 | static 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 | |||
1824 | static void ipw2100_down(struct ipw2100_priv *priv) | 1848 | static 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() */ | ||
1903 | static 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 | |||
1878 | static void ipw2100_reset_adapter(struct work_struct *work) | 1960 | static 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) | |||
6601 | module_init(ipw2100_init); | 6687 | module_init(ipw2100_init); |
6602 | module_exit(ipw2100_exit); | 6688 | module_exit(ipw2100_exit); |
6603 | 6689 | ||
6604 | #define WEXT_USECHANNELS 1 | ||
6605 | |||
6606 | static 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 | |||
6615 | static 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 | |||
6624 | static int ipw2100_wx_get_name(struct net_device *dev, | 6690 | static 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; | |||
109 | static int rtap_iface = 0; /* def: 0 -- do not create rtap interface */ | 109 | static int rtap_iface = 0; /* def: 0 -- do not create rtap interface */ |
110 | #endif | 110 | #endif |
111 | 111 | ||
112 | static 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 |
114 | static int qos_enable = 0; | 133 | static int qos_enable = 0; |
@@ -1739,10 +1758,13 @@ static DEVICE_ATTR(direct_dword, S_IWUSR | S_IRUGO, | |||
1739 | 1758 | ||
1740 | static int rf_kill_active(struct ipw_priv *priv) | 1759 | static 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 | ||
8663 | static 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 | |||
8681 | static int ipw_set_channel(struct ipw_priv *priv, u8 channel) | 8686 | static 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] |
9979 | static iw_handler ipw_wx_handlers[] = { | 9984 | static 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() */ |
11423 | static int ipw_net_init(struct net_device *dev) | 11428 | static 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 | |||
11521 | out: | ||
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 | ||
784 | struct libipw_device { | 785 | struct 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 */ |
1017 | extern void free_ieee80211(struct net_device *dev); | 1021 | extern void free_ieee80211(struct net_device *dev, int monitor); |
1018 | extern struct net_device *alloc_ieee80211(int sizeof_priv); | 1022 | extern struct net_device *alloc_ieee80211(int sizeof_priv, int monitor); |
1019 | extern int libipw_change_mtu(struct net_device *dev, int new_mtu); | 1023 | extern int libipw_change_mtu(struct net_device *dev, int new_mtu); |
1020 | 1024 | ||
1021 | extern void libipw_networks_age(struct libipw_device *ieee, | 1025 | extern 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); | |||
62 | MODULE_AUTHOR(DRV_COPYRIGHT); | 62 | MODULE_AUTHOR(DRV_COPYRIGHT); |
63 | MODULE_LICENSE("GPL"); | 63 | MODULE_LICENSE("GPL"); |
64 | 64 | ||
65 | struct cfg80211_ops libipw_config_ops = { }; | ||
66 | void *libipw_wiphy_privid = &libipw_wiphy_privid; | ||
67 | |||
65 | static int libipw_networks_allocate(struct libipw_device *ieee) | 68 | static 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 | } |
141 | EXPORT_SYMBOL(libipw_change_mtu); | 144 | EXPORT_SYMBOL(libipw_change_mtu); |
142 | 145 | ||
143 | struct net_device *alloc_ieee80211(int sizeof_priv) | 146 | struct 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 | ||
220 | failed_free_wiphy: | ||
221 | if (!monitor) | ||
222 | wiphy_free(ieee->wdev.wiphy); | ||
196 | failed_free_netdev: | 223 | failed_free_netdev: |
197 | free_netdev(dev); | 224 | free_netdev(dev); |
198 | failed: | 225 | failed: |
199 | return NULL; | 226 | return NULL; |
200 | } | 227 | } |
201 | 228 | ||
202 | void free_ieee80211(struct net_device *dev) | 229 | void 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 | ||