diff options
author | James Ketrenos <jketreno@linux.intel.com> | 2005-08-24 23:33:31 -0400 |
---|---|---|
committer | James Ketrenos <jketreno@linux.intel.com> | 2005-11-07 18:50:01 -0500 |
commit | 823283549da144ff49e65c6e4a670b7784203e0b (patch) | |
tree | 84ea52f5016b5af30ba029616bfcd3f77e40e2a0 /drivers/net/wireless/ipw2100.c | |
parent | b095c3819805f87d73d41641a53e4c070360d783 (diff) |
Catch ipw2100 up to equivelancy with v1.1.1
* Added WE-18 support. This allows the use of -Dext with wpa_supplicant
> 0.4.x (thanks to Hong Liu)
* Fixed #339 problem with iwconfig set/get txpower (thanks to Hong Liu)
* Fixed #598 problem when with error messages when module loaded with
'disable=1' (thanks to Hong Liu)
* Fixed #640 problem with 'iwlist retry' now showing min/max retry
* Fixed compatibility with wpa_supplicant and the new -Dipw interface
(that included a fix for 64-bit compatibility)
* Added CFG_CRC_CHECK which allows passing through packets with bad
CRCs while in monitor mode.
Signed-off-by: James Ketrenos <jketreno@linux.intel.com>
Diffstat (limited to 'drivers/net/wireless/ipw2100.c')
-rw-r--r-- | drivers/net/wireless/ipw2100.c | 577 |
1 files changed, 444 insertions, 133 deletions
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 449c1c085fb9..e7c222119da6 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c | |||
@@ -167,12 +167,12 @@ that only one external action is invoked at a time. | |||
167 | 167 | ||
168 | #include "ipw2100.h" | 168 | #include "ipw2100.h" |
169 | 169 | ||
170 | #define IPW2100_VERSION "1.1.0" | 170 | #define IPW2100_VERSION "1.1.1" |
171 | 171 | ||
172 | #define DRV_NAME "ipw2100" | 172 | #define DRV_NAME "ipw2100" |
173 | #define DRV_VERSION IPW2100_VERSION | 173 | #define DRV_VERSION IPW2100_VERSION |
174 | #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2100 Network Driver" | 174 | #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2100 Network Driver" |
175 | #define DRV_COPYRIGHT "Copyright(c) 2003-2004 Intel Corporation" | 175 | #define DRV_COPYRIGHT "Copyright(c) 2003-2005 Intel Corporation" |
176 | 176 | ||
177 | /* Debugging stuff */ | 177 | /* Debugging stuff */ |
178 | #ifdef CONFIG_IPW_DEBUG | 178 | #ifdef CONFIG_IPW_DEBUG |
@@ -779,7 +779,7 @@ static int ipw2100_hw_send_command(struct ipw2100_priv *priv, | |||
779 | 779 | ||
780 | if (err == 0) { | 780 | if (err == 0) { |
781 | IPW_DEBUG_INFO("Command completion failed out after %dms.\n", | 781 | IPW_DEBUG_INFO("Command completion failed out after %dms.\n", |
782 | HOST_COMPLETE_TIMEOUT / (HZ / 100)); | 782 | 1000 * (HOST_COMPLETE_TIMEOUT / HZ)); |
783 | priv->fatal_error = IPW2100_ERR_MSG_TIMEOUT; | 783 | priv->fatal_error = IPW2100_ERR_MSG_TIMEOUT; |
784 | priv->status &= ~STATUS_CMD_ACTIVE; | 784 | priv->status &= ~STATUS_CMD_ACTIVE; |
785 | schedule_reset(priv); | 785 | schedule_reset(priv); |
@@ -1986,7 +1986,7 @@ static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid, | |||
1986 | IPW_DEBUG_HC("SSID: '%s'\n", escape_essid(essid, ssid_len)); | 1986 | IPW_DEBUG_HC("SSID: '%s'\n", escape_essid(essid, ssid_len)); |
1987 | 1987 | ||
1988 | if (ssid_len) | 1988 | if (ssid_len) |
1989 | memcpy((char *)cmd.host_command_parameters, essid, ssid_len); | 1989 | memcpy(cmd.host_command_parameters, essid, ssid_len); |
1990 | 1990 | ||
1991 | if (!batch_mode) { | 1991 | if (!batch_mode) { |
1992 | err = ipw2100_disable_adapter(priv); | 1992 | err = ipw2100_disable_adapter(priv); |
@@ -2369,13 +2369,15 @@ static inline void isr_rx(struct ipw2100_priv *priv, int i, | |||
2369 | IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); | 2369 | IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); |
2370 | return; | 2370 | return; |
2371 | } | 2371 | } |
2372 | 2372 | #ifdef CONFIG_IPW2100_MONITOR | |
2373 | if (unlikely(priv->ieee->iw_mode == IW_MODE_MONITOR && | 2373 | if (unlikely(priv->ieee->iw_mode == IW_MODE_MONITOR && |
2374 | priv->config & CFG_CRC_CHECK && | ||
2374 | status->flags & IPW_STATUS_FLAG_CRC_ERROR)) { | 2375 | status->flags & IPW_STATUS_FLAG_CRC_ERROR)) { |
2375 | IPW_DEBUG_RX("CRC error in packet. Dropping.\n"); | 2376 | IPW_DEBUG_RX("CRC error in packet. Dropping.\n"); |
2376 | priv->ieee->stats.rx_errors++; | 2377 | priv->ieee->stats.rx_errors++; |
2377 | return; | 2378 | return; |
2378 | } | 2379 | } |
2380 | #endif | ||
2379 | 2381 | ||
2380 | if (unlikely(priv->ieee->iw_mode != IW_MODE_MONITOR && | 2382 | if (unlikely(priv->ieee->iw_mode != IW_MODE_MONITOR && |
2381 | !(priv->status & STATUS_ASSOCIATED))) { | 2383 | !(priv->status & STATUS_ASSOCIATED))) { |
@@ -2744,7 +2746,6 @@ static inline int __ipw2100_tx_process(struct ipw2100_priv *priv) | |||
2744 | priv->net_dev->name, txq->oldest, packet->index); | 2746 | priv->net_dev->name, txq->oldest, packet->index); |
2745 | 2747 | ||
2746 | /* DATA packet; we have to unmap and free the SKB */ | 2748 | /* DATA packet; we have to unmap and free the SKB */ |
2747 | priv->ieee->stats.tx_packets++; | ||
2748 | for (i = 0; i < frag_num; i++) { | 2749 | for (i = 0; i < frag_num; i++) { |
2749 | tbd = &txq->drv[(packet->index + 1 + i) % txq->entries]; | 2750 | tbd = &txq->drv[(packet->index + 1 + i) % txq->entries]; |
2750 | 2751 | ||
@@ -2757,8 +2758,6 @@ static inline int __ipw2100_tx_process(struct ipw2100_priv *priv) | |||
2757 | tbd->buf_length, PCI_DMA_TODEVICE); | 2758 | tbd->buf_length, PCI_DMA_TODEVICE); |
2758 | } | 2759 | } |
2759 | 2760 | ||
2760 | priv->ieee->stats.tx_bytes += | ||
2761 | packet->info.d_struct.txb->payload_size; | ||
2762 | ieee80211_txb_free(packet->info.d_struct.txb); | 2761 | ieee80211_txb_free(packet->info.d_struct.txb); |
2763 | packet->info.d_struct.txb = NULL; | 2762 | packet->info.d_struct.txb = NULL; |
2764 | 2763 | ||
@@ -2767,13 +2766,8 @@ static inline int __ipw2100_tx_process(struct ipw2100_priv *priv) | |||
2767 | 2766 | ||
2768 | /* We have a free slot in the Tx queue, so wake up the | 2767 | /* We have a free slot in the Tx queue, so wake up the |
2769 | * transmit layer if it is stopped. */ | 2768 | * transmit layer if it is stopped. */ |
2770 | if (priv->status & STATUS_ASSOCIATED && | 2769 | if (priv->status & STATUS_ASSOCIATED) |
2771 | netif_queue_stopped(priv->net_dev)) { | ||
2772 | IPW_DEBUG_INFO(KERN_INFO | ||
2773 | "%s: Waking net queue.\n", | ||
2774 | priv->net_dev->name); | ||
2775 | netif_wake_queue(priv->net_dev); | 2770 | netif_wake_queue(priv->net_dev); |
2776 | } | ||
2777 | 2771 | ||
2778 | /* A packet was processed by the hardware, so update the | 2772 | /* A packet was processed by the hardware, so update the |
2779 | * watchdog */ | 2773 | * watchdog */ |
@@ -3791,6 +3785,9 @@ static ssize_t show_ordinals(struct device *d, struct device_attribute *attr, | |||
3791 | u32 val_len; | 3785 | u32 val_len; |
3792 | static int loop = 0; | 3786 | static int loop = 0; |
3793 | 3787 | ||
3788 | if (priv->status & STATUS_RF_KILL_MASK) | ||
3789 | return 0; | ||
3790 | |||
3794 | if (loop >= sizeof(ord_data) / sizeof(*ord_data)) | 3791 | if (loop >= sizeof(ord_data) / sizeof(*ord_data)) |
3795 | loop = 0; | 3792 | loop = 0; |
3796 | 3793 | ||
@@ -3947,6 +3944,9 @@ static ssize_t show_bssinfo(struct device *d, struct device_attribute *attr, | |||
3947 | int length; | 3944 | int length; |
3948 | int ret; | 3945 | int ret; |
3949 | 3946 | ||
3947 | if (priv->status & STATUS_RF_KILL_MASK) | ||
3948 | return 0; | ||
3949 | |||
3950 | memset(essid, 0, sizeof(essid)); | 3950 | memset(essid, 0, sizeof(essid)); |
3951 | memset(bssid, 0, sizeof(bssid)); | 3951 | memset(bssid, 0, sizeof(bssid)); |
3952 | 3952 | ||
@@ -3986,8 +3986,8 @@ static ssize_t show_debug_level(struct device_driver *d, char *buf) | |||
3986 | return sprintf(buf, "0x%08X\n", ipw2100_debug_level); | 3986 | return sprintf(buf, "0x%08X\n", ipw2100_debug_level); |
3987 | } | 3987 | } |
3988 | 3988 | ||
3989 | static ssize_t store_debug_level(struct device_driver *d, const char *buf, | 3989 | static ssize_t store_debug_level(struct device_driver *d, |
3990 | size_t count) | 3990 | const char *buf, size_t count) |
3991 | { | 3991 | { |
3992 | char *p = (char *)buf; | 3992 | char *p = (char *)buf; |
3993 | u32 val; | 3993 | u32 val; |
@@ -4943,7 +4943,7 @@ static int ipw2100_set_mandatory_bssid(struct ipw2100_priv *priv, u8 * bssid, | |||
4943 | #endif | 4943 | #endif |
4944 | /* if BSSID is empty then we disable mandatory bssid mode */ | 4944 | /* if BSSID is empty then we disable mandatory bssid mode */ |
4945 | if (bssid != NULL) | 4945 | if (bssid != NULL) |
4946 | memcpy((u8 *) cmd.host_command_parameters, bssid, ETH_ALEN); | 4946 | memcpy(cmd.host_command_parameters, bssid, ETH_ALEN); |
4947 | 4947 | ||
4948 | if (!batch_mode) { | 4948 | if (!batch_mode) { |
4949 | err = ipw2100_disable_adapter(priv); | 4949 | err = ipw2100_disable_adapter(priv); |
@@ -4959,7 +4959,6 @@ static int ipw2100_set_mandatory_bssid(struct ipw2100_priv *priv, u8 * bssid, | |||
4959 | return err; | 4959 | return err; |
4960 | } | 4960 | } |
4961 | 4961 | ||
4962 | #ifdef CONFIG_IEEE80211_WPA | ||
4963 | static int ipw2100_disassociate_bssid(struct ipw2100_priv *priv) | 4962 | static int ipw2100_disassociate_bssid(struct ipw2100_priv *priv) |
4964 | { | 4963 | { |
4965 | struct host_command cmd = { | 4964 | struct host_command cmd = { |
@@ -4983,34 +4982,6 @@ static int ipw2100_disassociate_bssid(struct ipw2100_priv *priv) | |||
4983 | 4982 | ||
4984 | return err; | 4983 | return err; |
4985 | } | 4984 | } |
4986 | #endif | ||
4987 | |||
4988 | /* | ||
4989 | * Pseudo code for setting up wpa_frame: | ||
4990 | */ | ||
4991 | #if 0 | ||
4992 | void x(struct ieee80211_assoc_frame *wpa_assoc) | ||
4993 | { | ||
4994 | struct ipw2100_wpa_assoc_frame frame; | ||
4995 | frame->fixed_ie_mask = IPW_WPA_CAPABILTIES | | ||
4996 | IPW_WPA_LISTENINTERVAL | IPW_WPA_AP_ADDRESS; | ||
4997 | frame->capab_info = wpa_assoc->capab_info; | ||
4998 | frame->lisen_interval = wpa_assoc->listent_interval; | ||
4999 | memcpy(frame->current_ap, wpa_assoc->current_ap, ETH_ALEN); | ||
5000 | |||
5001 | /* UNKNOWN -- I'm not postivive about this part; don't have any WPA | ||
5002 | * setup here to test it with. | ||
5003 | * | ||
5004 | * Walk the IEs in the wpa_assoc and figure out the total size of all | ||
5005 | * that data. Stick that into frame->var_ie_len. Then memcpy() all of | ||
5006 | * the IEs from wpa_frame into frame. | ||
5007 | */ | ||
5008 | frame->var_ie_len = calculate_ie_len(wpa_assoc); | ||
5009 | memcpy(frame->var_ie, wpa_assoc->variable, frame->var_ie_len); | ||
5010 | |||
5011 | ipw2100_set_wpa_ie(priv, &frame, 0); | ||
5012 | } | ||
5013 | #endif | ||
5014 | 4985 | ||
5015 | static int ipw2100_set_wpa_ie(struct ipw2100_priv *, | 4986 | static int ipw2100_set_wpa_ie(struct ipw2100_priv *, |
5016 | struct ipw2100_wpa_assoc_frame *, int) | 4987 | struct ipw2100_wpa_assoc_frame *, int) |
@@ -5750,11 +5721,10 @@ static struct net_device_stats *ipw2100_stats(struct net_device *dev) | |||
5750 | return &priv->ieee->stats; | 5721 | return &priv->ieee->stats; |
5751 | } | 5722 | } |
5752 | 5723 | ||
5753 | /* Support for wpa_supplicant. Will be replaced with WEXT once | 5724 | #if WIRELESS_EXT < 18 |
5754 | * they get WPA support. */ | 5725 | /* Support for wpa_supplicant before WE-18, deprecated. */ |
5755 | #ifdef CONFIG_IEEE80211_WPA | ||
5756 | 5726 | ||
5757 | /* following definitions must match definitions in driver_ipw2100.c */ | 5727 | /* following definitions must match definitions in driver_ipw.c */ |
5758 | 5728 | ||
5759 | #define IPW2100_IOCTL_WPA_SUPPLICANT SIOCIWFIRSTPRIV+30 | 5729 | #define IPW2100_IOCTL_WPA_SUPPLICANT SIOCIWFIRSTPRIV+30 |
5760 | 5730 | ||
@@ -5792,11 +5762,12 @@ struct ipw2100_param { | |||
5792 | } wpa_param; | 5762 | } wpa_param; |
5793 | struct { | 5763 | struct { |
5794 | u32 len; | 5764 | u32 len; |
5795 | u8 *data; | 5765 | u8 reserved[32]; |
5766 | u8 data[0]; | ||
5796 | } wpa_ie; | 5767 | } wpa_ie; |
5797 | struct { | 5768 | struct { |
5798 | int command; | 5769 | u32 command; |
5799 | int reason_code; | 5770 | u32 reason_code; |
5800 | } mlme; | 5771 | } mlme; |
5801 | struct { | 5772 | struct { |
5802 | u8 alg[IPW2100_CRYPT_ALG_NAME_LEN]; | 5773 | u8 alg[IPW2100_CRYPT_ALG_NAME_LEN]; |
@@ -5811,37 +5782,21 @@ struct ipw2100_param { | |||
5811 | } u; | 5782 | } u; |
5812 | }; | 5783 | }; |
5813 | 5784 | ||
5814 | /* end of driver_ipw2100.c code */ | 5785 | /* end of driver_ipw.c code */ |
5786 | #endif /* WIRELESS_EXT < 18 */ | ||
5815 | 5787 | ||
5816 | static int ipw2100_wpa_enable(struct ipw2100_priv *priv, int value) | 5788 | static int ipw2100_wpa_enable(struct ipw2100_priv *priv, int value) |
5817 | { | 5789 | { |
5818 | 5790 | /* This is called when wpa_supplicant loads and closes the driver | |
5819 | struct ieee80211_device *ieee = priv->ieee; | 5791 | * interface. */ |
5820 | struct ieee80211_security sec = { | 5792 | priv->ieee->wpa_enabled = value; |
5821 | .flags = SEC_LEVEL | SEC_ENABLED, | 5793 | return 0; |
5822 | }; | ||
5823 | int ret = 0; | ||
5824 | |||
5825 | ieee->wpa_enabled = value; | ||
5826 | |||
5827 | if (value) { | ||
5828 | sec.level = SEC_LEVEL_3; | ||
5829 | sec.enabled = 1; | ||
5830 | } else { | ||
5831 | sec.level = SEC_LEVEL_0; | ||
5832 | sec.enabled = 0; | ||
5833 | } | ||
5834 | |||
5835 | if (ieee->set_security) | ||
5836 | ieee->set_security(ieee->dev, &sec); | ||
5837 | else | ||
5838 | ret = -EOPNOTSUPP; | ||
5839 | |||
5840 | return ret; | ||
5841 | } | 5794 | } |
5842 | 5795 | ||
5843 | #define AUTH_ALG_OPEN_SYSTEM 0x1 | 5796 | #if WIRELESS_EXT < 18 |
5844 | #define AUTH_ALG_SHARED_KEY 0x2 | 5797 | #define IW_AUTH_ALG_OPEN_SYSTEM 0x1 |
5798 | #define IW_AUTH_ALG_SHARED_KEY 0x2 | ||
5799 | #endif | ||
5845 | 5800 | ||
5846 | static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value) | 5801 | static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value) |
5847 | { | 5802 | { |
@@ -5852,13 +5807,14 @@ static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value) | |||
5852 | }; | 5807 | }; |
5853 | int ret = 0; | 5808 | int ret = 0; |
5854 | 5809 | ||
5855 | if (value & AUTH_ALG_SHARED_KEY) { | 5810 | if (value & IW_AUTH_ALG_SHARED_KEY) { |
5856 | sec.auth_mode = WLAN_AUTH_SHARED_KEY; | 5811 | sec.auth_mode = WLAN_AUTH_SHARED_KEY; |
5857 | ieee->open_wep = 0; | 5812 | ieee->open_wep = 0; |
5858 | } else { | 5813 | } else if (value & IW_AUTH_ALG_OPEN_SYSTEM) { |
5859 | sec.auth_mode = WLAN_AUTH_OPEN; | 5814 | sec.auth_mode = WLAN_AUTH_OPEN; |
5860 | ieee->open_wep = 1; | 5815 | ieee->open_wep = 1; |
5861 | } | 5816 | } else |
5817 | return -EINVAL; | ||
5862 | 5818 | ||
5863 | if (ieee->set_security) | 5819 | if (ieee->set_security) |
5864 | ieee->set_security(ieee->dev, &sec); | 5820 | ieee->set_security(ieee->dev, &sec); |
@@ -5868,10 +5824,29 @@ static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value) | |||
5868 | return ret; | 5824 | return ret; |
5869 | } | 5825 | } |
5870 | 5826 | ||
5871 | static int ipw2100_wpa_set_param(struct net_device *dev, u8 name, u32 value) | 5827 | void ipw2100_wpa_assoc_frame(struct ipw2100_priv *priv, |
5828 | char *wpa_ie, int wpa_ie_len) | ||
5872 | { | 5829 | { |
5873 | 5830 | ||
5831 | struct ipw2100_wpa_assoc_frame frame; | ||
5832 | |||
5833 | frame.fixed_ie_mask = 0; | ||
5834 | |||
5835 | /* copy WPA IE */ | ||
5836 | memcpy(frame.var_ie, wpa_ie, wpa_ie_len); | ||
5837 | frame.var_ie_len = wpa_ie_len; | ||
5838 | |||
5839 | /* make sure WPA is enabled */ | ||
5840 | ipw2100_wpa_enable(priv, 1); | ||
5841 | ipw2100_set_wpa_ie(priv, &frame, 0); | ||
5842 | } | ||
5843 | |||
5844 | #if WIRELESS_EXT < 18 | ||
5845 | static int ipw2100_wpa_set_param(struct net_device *dev, u8 name, u32 value) | ||
5846 | { | ||
5874 | struct ipw2100_priv *priv = ieee80211_priv(dev); | 5847 | struct ipw2100_priv *priv = ieee80211_priv(dev); |
5848 | struct ieee80211_crypt_data *crypt; | ||
5849 | unsigned long flags; | ||
5875 | int ret = 0; | 5850 | int ret = 0; |
5876 | 5851 | ||
5877 | switch (name) { | 5852 | switch (name) { |
@@ -5880,7 +5855,22 @@ static int ipw2100_wpa_set_param(struct net_device *dev, u8 name, u32 value) | |||
5880 | break; | 5855 | break; |
5881 | 5856 | ||
5882 | case IPW2100_PARAM_TKIP_COUNTERMEASURES: | 5857 | case IPW2100_PARAM_TKIP_COUNTERMEASURES: |
5883 | priv->ieee->tkip_countermeasures = value; | 5858 | crypt = priv->ieee->crypt[priv->ieee->tx_keyidx]; |
5859 | if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags) { | ||
5860 | IPW_DEBUG_WARNING("Can't set TKIP countermeasures: " | ||
5861 | "crypt not set!\n"); | ||
5862 | break; | ||
5863 | } | ||
5864 | |||
5865 | flags = crypt->ops->get_flags(crypt->priv); | ||
5866 | |||
5867 | if (value) | ||
5868 | flags |= IEEE80211_CRYPTO_TKIP_COUNTERMEASURES; | ||
5869 | else | ||
5870 | flags &= ~IEEE80211_CRYPTO_TKIP_COUNTERMEASURES; | ||
5871 | |||
5872 | crypt->ops->set_flags(flags, crypt->priv); | ||
5873 | |||
5884 | break; | 5874 | break; |
5885 | 5875 | ||
5886 | case IPW2100_PARAM_DROP_UNENCRYPTED: | 5876 | case IPW2100_PARAM_DROP_UNENCRYPTED: |
@@ -5932,23 +5922,6 @@ static int ipw2100_wpa_mlme(struct net_device *dev, int command, int reason) | |||
5932 | return ret; | 5922 | return ret; |
5933 | } | 5923 | } |
5934 | 5924 | ||
5935 | void ipw2100_wpa_assoc_frame(struct ipw2100_priv *priv, | ||
5936 | char *wpa_ie, int wpa_ie_len) | ||
5937 | { | ||
5938 | |||
5939 | struct ipw2100_wpa_assoc_frame frame; | ||
5940 | |||
5941 | frame.fixed_ie_mask = 0; | ||
5942 | |||
5943 | /* copy WPA IE */ | ||
5944 | memcpy(frame.var_ie, wpa_ie, wpa_ie_len); | ||
5945 | frame.var_ie_len = wpa_ie_len; | ||
5946 | |||
5947 | /* make sure WPA is enabled */ | ||
5948 | ipw2100_wpa_enable(priv, 1); | ||
5949 | ipw2100_set_wpa_ie(priv, &frame, 0); | ||
5950 | } | ||
5951 | |||
5952 | static int ipw2100_wpa_set_wpa_ie(struct net_device *dev, | 5925 | static int ipw2100_wpa_set_wpa_ie(struct net_device *dev, |
5953 | struct ipw2100_param *param, int plen) | 5926 | struct ipw2100_param *param, int plen) |
5954 | { | 5927 | { |
@@ -5992,7 +5965,6 @@ static int ipw2100_wpa_set_encryption(struct net_device *dev, | |||
5992 | struct ipw2100_param *param, | 5965 | struct ipw2100_param *param, |
5993 | int param_len) | 5966 | int param_len) |
5994 | { | 5967 | { |
5995 | |||
5996 | int ret = 0; | 5968 | int ret = 0; |
5997 | struct ipw2100_priv *priv = ieee80211_priv(dev); | 5969 | struct ipw2100_priv *priv = ieee80211_priv(dev); |
5998 | struct ieee80211_device *ieee = priv->ieee; | 5970 | struct ieee80211_device *ieee = priv->ieee; |
@@ -6101,8 +6073,8 @@ static int ipw2100_wpa_set_encryption(struct net_device *dev, | |||
6101 | if (ops->name != NULL) { | 6073 | if (ops->name != NULL) { |
6102 | 6074 | ||
6103 | if (strcmp(ops->name, "WEP") == 0) { | 6075 | if (strcmp(ops->name, "WEP") == 0) { |
6104 | memcpy(sec.keys[param->u.crypt.idx], param->u.crypt.key, | 6076 | memcpy(sec.keys[param->u.crypt.idx], |
6105 | param->u.crypt.key_len); | 6077 | param->u.crypt.key, param->u.crypt.key_len); |
6106 | sec.key_sizes[param->u.crypt.idx] = | 6078 | sec.key_sizes[param->u.crypt.idx] = |
6107 | param->u.crypt.key_len; | 6079 | param->u.crypt.key_len; |
6108 | sec.flags |= (1 << param->u.crypt.idx); | 6080 | sec.flags |= (1 << param->u.crypt.idx); |
@@ -6190,11 +6162,9 @@ static int ipw2100_wpa_supplicant(struct net_device *dev, struct iw_point *p) | |||
6190 | kfree(param); | 6162 | kfree(param); |
6191 | return ret; | 6163 | return ret; |
6192 | } | 6164 | } |
6193 | #endif /* CONFIG_IEEE80211_WPA */ | ||
6194 | 6165 | ||
6195 | static int ipw2100_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | 6166 | static int ipw2100_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) |
6196 | { | 6167 | { |
6197 | #ifdef CONFIG_IEEE80211_WPA | ||
6198 | struct iwreq *wrq = (struct iwreq *)rq; | 6168 | struct iwreq *wrq = (struct iwreq *)rq; |
6199 | int ret = -1; | 6169 | int ret = -1; |
6200 | switch (cmd) { | 6170 | switch (cmd) { |
@@ -6206,10 +6176,9 @@ static int ipw2100_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | |||
6206 | return -EOPNOTSUPP; | 6176 | return -EOPNOTSUPP; |
6207 | } | 6177 | } |
6208 | 6178 | ||
6209 | #endif /* CONFIG_IEEE80211_WPA */ | ||
6210 | |||
6211 | return -EOPNOTSUPP; | 6179 | return -EOPNOTSUPP; |
6212 | } | 6180 | } |
6181 | #endif /* WIRELESS_EXT < 18 */ | ||
6213 | 6182 | ||
6214 | static void ipw_ethtool_get_drvinfo(struct net_device *dev, | 6183 | static void ipw_ethtool_get_drvinfo(struct net_device *dev, |
6215 | struct ethtool_drvinfo *info) | 6184 | struct ethtool_drvinfo *info) |
@@ -6333,10 +6302,15 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, | |||
6333 | priv->ieee->hard_start_xmit = ipw2100_tx; | 6302 | priv->ieee->hard_start_xmit = ipw2100_tx; |
6334 | priv->ieee->set_security = shim__set_security; | 6303 | priv->ieee->set_security = shim__set_security; |
6335 | 6304 | ||
6305 | priv->ieee->perfect_rssi = -20; | ||
6306 | priv->ieee->worst_rssi = -85; | ||
6307 | |||
6336 | dev->open = ipw2100_open; | 6308 | dev->open = ipw2100_open; |
6337 | dev->stop = ipw2100_close; | 6309 | dev->stop = ipw2100_close; |
6338 | dev->init = ipw2100_net_init; | 6310 | dev->init = ipw2100_net_init; |
6311 | #if WIRELESS_EXT < 18 | ||
6339 | dev->do_ioctl = ipw2100_ioctl; | 6312 | dev->do_ioctl = ipw2100_ioctl; |
6313 | #endif | ||
6340 | dev->get_stats = ipw2100_stats; | 6314 | dev->get_stats = ipw2100_stats; |
6341 | dev->ethtool_ops = &ipw2100_ethtool_ops; | 6315 | dev->ethtool_ops = &ipw2100_ethtool_ops; |
6342 | dev->tx_timeout = ipw2100_tx_timeout; | 6316 | dev->tx_timeout = ipw2100_tx_timeout; |
@@ -6362,13 +6336,13 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, | |||
6362 | /* If power management is turned on, default to AUTO mode */ | 6336 | /* If power management is turned on, default to AUTO mode */ |
6363 | priv->power_mode = IPW_POWER_AUTO; | 6337 | priv->power_mode = IPW_POWER_AUTO; |
6364 | 6338 | ||
6365 | #ifdef CONFIG_IEEE80211_WPA | 6339 | #ifdef CONFIG_IPW2100_MONITOR |
6340 | priv->config |= CFG_CRC_CHECK; | ||
6341 | #endif | ||
6366 | priv->ieee->wpa_enabled = 0; | 6342 | priv->ieee->wpa_enabled = 0; |
6367 | priv->ieee->tkip_countermeasures = 0; | ||
6368 | priv->ieee->drop_unencrypted = 0; | 6343 | priv->ieee->drop_unencrypted = 0; |
6369 | priv->ieee->privacy_invoked = 0; | 6344 | priv->ieee->privacy_invoked = 0; |
6370 | priv->ieee->ieee802_1x = 1; | 6345 | priv->ieee->ieee802_1x = 1; |
6371 | #endif /* CONFIG_IEEE80211_WPA */ | ||
6372 | 6346 | ||
6373 | /* Set module parameters */ | 6347 | /* Set module parameters */ |
6374 | switch (mode) { | 6348 | switch (mode) { |
@@ -6429,7 +6403,7 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, | |||
6429 | INIT_LIST_HEAD(&priv->fw_pend_list); | 6403 | INIT_LIST_HEAD(&priv->fw_pend_list); |
6430 | INIT_STAT(&priv->fw_pend_stat); | 6404 | INIT_STAT(&priv->fw_pend_stat); |
6431 | 6405 | ||
6432 | #ifdef CONFIG_SOFTWARE_SUSPEND2 | 6406 | #ifdef PF_SYNCTHREAD |
6433 | priv->workqueue = create_workqueue(DRV_NAME, 0); | 6407 | priv->workqueue = create_workqueue(DRV_NAME, 0); |
6434 | #else | 6408 | #else |
6435 | priv->workqueue = create_workqueue(DRV_NAME); | 6409 | priv->workqueue = create_workqueue(DRV_NAME); |
@@ -6591,7 +6565,6 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, | |||
6591 | 6565 | ||
6592 | /* perform this after register_netdev so that dev->name is set */ | 6566 | /* perform this after register_netdev so that dev->name is set */ |
6593 | sysfs_create_group(&pci_dev->dev.kobj, &ipw2100_attribute_group); | 6567 | sysfs_create_group(&pci_dev->dev.kobj, &ipw2100_attribute_group); |
6594 | netif_carrier_off(dev); | ||
6595 | 6568 | ||
6596 | /* If the RF Kill switch is disabled, go ahead and complete the | 6569 | /* If the RF Kill switch is disabled, go ahead and complete the |
6597 | * startup sequence */ | 6570 | * startup sequence */ |
@@ -6860,10 +6833,6 @@ static int __init ipw2100_init(void) | |||
6860 | printk(KERN_INFO DRV_NAME ": %s, %s\n", DRV_DESCRIPTION, DRV_VERSION); | 6833 | printk(KERN_INFO DRV_NAME ": %s, %s\n", DRV_DESCRIPTION, DRV_VERSION); |
6861 | printk(KERN_INFO DRV_NAME ": %s\n", DRV_COPYRIGHT); | 6834 | printk(KERN_INFO DRV_NAME ": %s\n", DRV_COPYRIGHT); |
6862 | 6835 | ||
6863 | #ifdef CONFIG_IEEE80211_NOWEP | ||
6864 | IPW_DEBUG_INFO(DRV_NAME ": Compiled with WEP disabled.\n"); | ||
6865 | #endif | ||
6866 | |||
6867 | ret = pci_module_init(&ipw2100_pci_driver); | 6836 | ret = pci_module_init(&ipw2100_pci_driver); |
6868 | 6837 | ||
6869 | #ifdef CONFIG_IPW_DEBUG | 6838 | #ifdef CONFIG_IPW_DEBUG |
@@ -6963,9 +6932,10 @@ static int ipw2100_wx_set_freq(struct net_device *dev, | |||
6963 | } | 6932 | } |
6964 | } | 6933 | } |
6965 | 6934 | ||
6966 | if (fwrq->e > 0 || fwrq->m > 1000) | 6935 | if (fwrq->e > 0 || fwrq->m > 1000) { |
6967 | return -EOPNOTSUPP; | 6936 | err = -EOPNOTSUPP; |
6968 | else { /* Set the channel */ | 6937 | goto done; |
6938 | } else { /* Set the channel */ | ||
6969 | IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m); | 6939 | IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m); |
6970 | err = ipw2100_set_channel(priv, fwrq->m, 0); | 6940 | err = ipw2100_set_channel(priv, fwrq->m, 0); |
6971 | } | 6941 | } |
@@ -7256,7 +7226,7 @@ static int ipw2100_wx_get_wap(struct net_device *dev, | |||
7256 | * configured BSSID then return that; otherwise return ANY */ | 7226 | * configured BSSID then return that; otherwise return ANY */ |
7257 | if (priv->config & CFG_STATIC_BSSID || priv->status & STATUS_ASSOCIATED) { | 7227 | if (priv->config & CFG_STATIC_BSSID || priv->status & STATUS_ASSOCIATED) { |
7258 | wrqu->ap_addr.sa_family = ARPHRD_ETHER; | 7228 | wrqu->ap_addr.sa_family = ARPHRD_ETHER; |
7259 | memcpy(wrqu->ap_addr.sa_data, &priv->bssid, ETH_ALEN); | 7229 | memcpy(wrqu->ap_addr.sa_data, priv->bssid, ETH_ALEN); |
7260 | } else | 7230 | } else |
7261 | memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN); | 7231 | memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN); |
7262 | 7232 | ||
@@ -7711,13 +7681,13 @@ static int ipw2100_wx_get_retry(struct net_device *dev, | |||
7711 | return -EINVAL; | 7681 | return -EINVAL; |
7712 | 7682 | ||
7713 | if (wrqu->retry.flags & IW_RETRY_MAX) { | 7683 | if (wrqu->retry.flags & IW_RETRY_MAX) { |
7714 | wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MAX; | 7684 | wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX; |
7715 | wrqu->retry.value = priv->long_retry_limit; | 7685 | wrqu->retry.value = priv->long_retry_limit; |
7716 | } else { | 7686 | } else { |
7717 | wrqu->retry.flags = | 7687 | wrqu->retry.flags = |
7718 | (priv->short_retry_limit != | 7688 | (priv->short_retry_limit != |
7719 | priv->long_retry_limit) ? | 7689 | priv->long_retry_limit) ? |
7720 | IW_RETRY_LIMIT & IW_RETRY_MIN : IW_RETRY_LIMIT; | 7690 | IW_RETRY_LIMIT | IW_RETRY_MIN : IW_RETRY_LIMIT; |
7721 | 7691 | ||
7722 | wrqu->retry.value = priv->short_retry_limit; | 7692 | wrqu->retry.value = priv->short_retry_limit; |
7723 | } | 7693 | } |
@@ -7847,9 +7817,9 @@ static int ipw2100_wx_get_power(struct net_device *dev, | |||
7847 | 7817 | ||
7848 | struct ipw2100_priv *priv = ieee80211_priv(dev); | 7818 | struct ipw2100_priv *priv = ieee80211_priv(dev); |
7849 | 7819 | ||
7850 | if (!(priv->power_mode & IPW_POWER_ENABLED)) { | 7820 | if (!(priv->power_mode & IPW_POWER_ENABLED)) |
7851 | wrqu->power.disabled = 1; | 7821 | wrqu->power.disabled = 1; |
7852 | } else { | 7822 | else { |
7853 | wrqu->power.disabled = 0; | 7823 | wrqu->power.disabled = 0; |
7854 | wrqu->power.flags = 0; | 7824 | wrqu->power.flags = 0; |
7855 | } | 7825 | } |
@@ -7859,6 +7829,273 @@ static int ipw2100_wx_get_power(struct net_device *dev, | |||
7859 | return 0; | 7829 | return 0; |
7860 | } | 7830 | } |
7861 | 7831 | ||
7832 | #if WIRELESS_EXT > 17 | ||
7833 | /* | ||
7834 | * WE-18 WPA support | ||
7835 | */ | ||
7836 | |||
7837 | /* SIOCSIWGENIE */ | ||
7838 | static int ipw2100_wx_set_genie(struct net_device *dev, | ||
7839 | struct iw_request_info *info, | ||
7840 | union iwreq_data *wrqu, char *extra) | ||
7841 | { | ||
7842 | |||
7843 | struct ipw2100_priv *priv = ieee80211_priv(dev); | ||
7844 | struct ieee80211_device *ieee = priv->ieee; | ||
7845 | u8 *buf; | ||
7846 | |||
7847 | if (!ieee->wpa_enabled) | ||
7848 | return -EOPNOTSUPP; | ||
7849 | |||
7850 | if (wrqu->data.length > MAX_WPA_IE_LEN || | ||
7851 | (wrqu->data.length && extra == NULL)) | ||
7852 | return -EINVAL; | ||
7853 | |||
7854 | if (wrqu->data.length) { | ||
7855 | buf = kmalloc(wrqu->data.length, GFP_KERNEL); | ||
7856 | if (buf == NULL) | ||
7857 | return -ENOMEM; | ||
7858 | |||
7859 | memcpy(buf, extra, wrqu->data.length); | ||
7860 | kfree(ieee->wpa_ie); | ||
7861 | ieee->wpa_ie = buf; | ||
7862 | ieee->wpa_ie_len = wrqu->data.length; | ||
7863 | } else { | ||
7864 | kfree(ieee->wpa_ie); | ||
7865 | ieee->wpa_ie = NULL; | ||
7866 | ieee->wpa_ie_len = 0; | ||
7867 | } | ||
7868 | |||
7869 | ipw2100_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len); | ||
7870 | |||
7871 | return 0; | ||
7872 | } | ||
7873 | |||
7874 | /* SIOCGIWGENIE */ | ||
7875 | static int ipw2100_wx_get_genie(struct net_device *dev, | ||
7876 | struct iw_request_info *info, | ||
7877 | union iwreq_data *wrqu, char *extra) | ||
7878 | { | ||
7879 | struct ipw2100_priv *priv = ieee80211_priv(dev); | ||
7880 | struct ieee80211_device *ieee = priv->ieee; | ||
7881 | |||
7882 | if (ieee->wpa_ie_len == 0 || ieee->wpa_ie == NULL) { | ||
7883 | wrqu->data.length = 0; | ||
7884 | return 0; | ||
7885 | } | ||
7886 | |||
7887 | if (wrqu->data.length < ieee->wpa_ie_len) | ||
7888 | return -E2BIG; | ||
7889 | |||
7890 | wrqu->data.length = ieee->wpa_ie_len; | ||
7891 | memcpy(extra, ieee->wpa_ie, ieee->wpa_ie_len); | ||
7892 | |||
7893 | return 0; | ||
7894 | } | ||
7895 | |||
7896 | /* SIOCSIWAUTH */ | ||
7897 | static int ipw2100_wx_set_auth(struct net_device *dev, | ||
7898 | struct iw_request_info *info, | ||
7899 | union iwreq_data *wrqu, char *extra) | ||
7900 | { | ||
7901 | struct ipw2100_priv *priv = ieee80211_priv(dev); | ||
7902 | struct ieee80211_device *ieee = priv->ieee; | ||
7903 | struct iw_param *param = &wrqu->param; | ||
7904 | struct ieee80211_crypt_data *crypt; | ||
7905 | unsigned long flags; | ||
7906 | int ret = 0; | ||
7907 | |||
7908 | switch (param->flags & IW_AUTH_INDEX) { | ||
7909 | case IW_AUTH_WPA_VERSION: | ||
7910 | case IW_AUTH_CIPHER_PAIRWISE: | ||
7911 | case IW_AUTH_CIPHER_GROUP: | ||
7912 | case IW_AUTH_KEY_MGMT: | ||
7913 | /* | ||
7914 | * ipw2200 does not use these parameters | ||
7915 | */ | ||
7916 | break; | ||
7917 | |||
7918 | case IW_AUTH_TKIP_COUNTERMEASURES: | ||
7919 | crypt = priv->ieee->crypt[priv->ieee->tx_keyidx]; | ||
7920 | if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags) { | ||
7921 | IPW_DEBUG_WARNING("Can't set TKIP countermeasures: " | ||
7922 | "crypt not set!\n"); | ||
7923 | break; | ||
7924 | } | ||
7925 | |||
7926 | flags = crypt->ops->get_flags(crypt->priv); | ||
7927 | |||
7928 | if (param->value) | ||
7929 | flags |= IEEE80211_CRYPTO_TKIP_COUNTERMEASURES; | ||
7930 | else | ||
7931 | flags &= ~IEEE80211_CRYPTO_TKIP_COUNTERMEASURES; | ||
7932 | |||
7933 | crypt->ops->set_flags(flags, crypt->priv); | ||
7934 | |||
7935 | break; | ||
7936 | |||
7937 | case IW_AUTH_DROP_UNENCRYPTED:{ | ||
7938 | /* HACK: | ||
7939 | * | ||
7940 | * wpa_supplicant calls set_wpa_enabled when the driver | ||
7941 | * is loaded and unloaded, regardless of if WPA is being | ||
7942 | * used. No other calls are made which can be used to | ||
7943 | * determine if encryption will be used or not prior to | ||
7944 | * association being expected. If encryption is not being | ||
7945 | * used, drop_unencrypted is set to false, else true -- we | ||
7946 | * can use this to determine if the CAP_PRIVACY_ON bit should | ||
7947 | * be set. | ||
7948 | */ | ||
7949 | struct ieee80211_security sec = { | ||
7950 | .flags = SEC_ENABLED, | ||
7951 | .enabled = param->value, | ||
7952 | }; | ||
7953 | priv->ieee->drop_unencrypted = param->value; | ||
7954 | /* We only change SEC_LEVEL for open mode. Others | ||
7955 | * are set by ipw_wpa_set_encryption. | ||
7956 | */ | ||
7957 | if (!param->value) { | ||
7958 | sec.flags |= SEC_LEVEL; | ||
7959 | sec.level = SEC_LEVEL_0; | ||
7960 | } else { | ||
7961 | sec.flags |= SEC_LEVEL; | ||
7962 | sec.level = SEC_LEVEL_1; | ||
7963 | } | ||
7964 | if (priv->ieee->set_security) | ||
7965 | priv->ieee->set_security(priv->ieee->dev, &sec); | ||
7966 | break; | ||
7967 | } | ||
7968 | |||
7969 | case IW_AUTH_80211_AUTH_ALG: | ||
7970 | ret = ipw2100_wpa_set_auth_algs(priv, param->value); | ||
7971 | break; | ||
7972 | |||
7973 | case IW_AUTH_WPA_ENABLED: | ||
7974 | ret = ipw2100_wpa_enable(priv, param->value); | ||
7975 | break; | ||
7976 | |||
7977 | case IW_AUTH_RX_UNENCRYPTED_EAPOL: | ||
7978 | ieee->ieee802_1x = param->value; | ||
7979 | break; | ||
7980 | |||
7981 | //case IW_AUTH_ROAMING_CONTROL: | ||
7982 | case IW_AUTH_PRIVACY_INVOKED: | ||
7983 | ieee->privacy_invoked = param->value; | ||
7984 | break; | ||
7985 | |||
7986 | default: | ||
7987 | return -EOPNOTSUPP; | ||
7988 | } | ||
7989 | return ret; | ||
7990 | } | ||
7991 | |||
7992 | /* SIOCGIWAUTH */ | ||
7993 | static int ipw2100_wx_get_auth(struct net_device *dev, | ||
7994 | struct iw_request_info *info, | ||
7995 | union iwreq_data *wrqu, char *extra) | ||
7996 | { | ||
7997 | struct ipw2100_priv *priv = ieee80211_priv(dev); | ||
7998 | struct ieee80211_device *ieee = priv->ieee; | ||
7999 | struct ieee80211_crypt_data *crypt; | ||
8000 | struct iw_param *param = &wrqu->param; | ||
8001 | int ret = 0; | ||
8002 | |||
8003 | switch (param->flags & IW_AUTH_INDEX) { | ||
8004 | case IW_AUTH_WPA_VERSION: | ||
8005 | case IW_AUTH_CIPHER_PAIRWISE: | ||
8006 | case IW_AUTH_CIPHER_GROUP: | ||
8007 | case IW_AUTH_KEY_MGMT: | ||
8008 | /* | ||
8009 | * wpa_supplicant will control these internally | ||
8010 | */ | ||
8011 | ret = -EOPNOTSUPP; | ||
8012 | break; | ||
8013 | |||
8014 | case IW_AUTH_TKIP_COUNTERMEASURES: | ||
8015 | crypt = priv->ieee->crypt[priv->ieee->tx_keyidx]; | ||
8016 | if (!crypt || !crypt->ops->get_flags) { | ||
8017 | IPW_DEBUG_WARNING("Can't get TKIP countermeasures: " | ||
8018 | "crypt not set!\n"); | ||
8019 | break; | ||
8020 | } | ||
8021 | |||
8022 | param->value = (crypt->ops->get_flags(crypt->priv) & | ||
8023 | IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) ? 1 : 0; | ||
8024 | |||
8025 | break; | ||
8026 | |||
8027 | case IW_AUTH_DROP_UNENCRYPTED: | ||
8028 | param->value = ieee->drop_unencrypted; | ||
8029 | break; | ||
8030 | |||
8031 | case IW_AUTH_80211_AUTH_ALG: | ||
8032 | param->value = priv->sec.auth_mode; | ||
8033 | break; | ||
8034 | |||
8035 | case IW_AUTH_WPA_ENABLED: | ||
8036 | param->value = ieee->wpa_enabled; | ||
8037 | break; | ||
8038 | |||
8039 | case IW_AUTH_RX_UNENCRYPTED_EAPOL: | ||
8040 | param->value = ieee->ieee802_1x; | ||
8041 | break; | ||
8042 | |||
8043 | case IW_AUTH_ROAMING_CONTROL: | ||
8044 | case IW_AUTH_PRIVACY_INVOKED: | ||
8045 | param->value = ieee->privacy_invoked; | ||
8046 | break; | ||
8047 | |||
8048 | default: | ||
8049 | return -EOPNOTSUPP; | ||
8050 | } | ||
8051 | return 0; | ||
8052 | } | ||
8053 | |||
8054 | /* SIOCSIWENCODEEXT */ | ||
8055 | static int ipw2100_wx_set_encodeext(struct net_device *dev, | ||
8056 | struct iw_request_info *info, | ||
8057 | union iwreq_data *wrqu, char *extra) | ||
8058 | { | ||
8059 | struct ipw2100_priv *priv = ieee80211_priv(dev); | ||
8060 | return ieee80211_wx_set_encodeext(priv->ieee, info, wrqu, extra); | ||
8061 | } | ||
8062 | |||
8063 | /* SIOCGIWENCODEEXT */ | ||
8064 | static int ipw2100_wx_get_encodeext(struct net_device *dev, | ||
8065 | struct iw_request_info *info, | ||
8066 | union iwreq_data *wrqu, char *extra) | ||
8067 | { | ||
8068 | struct ipw2100_priv *priv = ieee80211_priv(dev); | ||
8069 | return ieee80211_wx_get_encodeext(priv->ieee, info, wrqu, extra); | ||
8070 | } | ||
8071 | |||
8072 | /* SIOCSIWMLME */ | ||
8073 | static int ipw2100_wx_set_mlme(struct net_device *dev, | ||
8074 | struct iw_request_info *info, | ||
8075 | union iwreq_data *wrqu, char *extra) | ||
8076 | { | ||
8077 | struct ipw2100_priv *priv = ieee80211_priv(dev); | ||
8078 | struct iw_mlme *mlme = (struct iw_mlme *)extra; | ||
8079 | u16 reason; | ||
8080 | |||
8081 | reason = cpu_to_le16(mlme->reason_code); | ||
8082 | |||
8083 | switch (mlme->cmd) { | ||
8084 | case IW_MLME_DEAUTH: | ||
8085 | // silently ignore | ||
8086 | break; | ||
8087 | |||
8088 | case IW_MLME_DISASSOC: | ||
8089 | ipw2100_disassociate_bssid(priv); | ||
8090 | break; | ||
8091 | |||
8092 | default: | ||
8093 | return -EOPNOTSUPP; | ||
8094 | } | ||
8095 | return 0; | ||
8096 | } | ||
8097 | #endif /* WIRELESS_EXT > 17 */ | ||
8098 | |||
7862 | /* | 8099 | /* |
7863 | * | 8100 | * |
7864 | * IWPRIV handlers | 8101 | * IWPRIV handlers |
@@ -8019,6 +8256,54 @@ static int ipw2100_wx_get_preamble(struct net_device *dev, | |||
8019 | return 0; | 8256 | return 0; |
8020 | } | 8257 | } |
8021 | 8258 | ||
8259 | #ifdef CONFIG_IPW2100_MONITOR | ||
8260 | static int ipw2100_wx_set_crc_check(struct net_device *dev, | ||
8261 | struct iw_request_info *info, | ||
8262 | union iwreq_data *wrqu, char *extra) | ||
8263 | { | ||
8264 | struct ipw2100_priv *priv = ieee80211_priv(dev); | ||
8265 | int err, mode = *(int *)extra; | ||
8266 | |||
8267 | down(&priv->action_sem); | ||
8268 | if (!(priv->status & STATUS_INITIALIZED)) { | ||
8269 | err = -EIO; | ||
8270 | goto done; | ||
8271 | } | ||
8272 | |||
8273 | if (mode == 1) | ||
8274 | priv->config |= CFG_CRC_CHECK; | ||
8275 | else if (mode == 0) | ||
8276 | priv->config &= ~CFG_CRC_CHECK; | ||
8277 | else { | ||
8278 | err = -EINVAL; | ||
8279 | goto done; | ||
8280 | } | ||
8281 | err = 0; | ||
8282 | |||
8283 | done: | ||
8284 | up(&priv->action_sem); | ||
8285 | return err; | ||
8286 | } | ||
8287 | |||
8288 | static int ipw2100_wx_get_crc_check(struct net_device *dev, | ||
8289 | struct iw_request_info *info, | ||
8290 | union iwreq_data *wrqu, char *extra) | ||
8291 | { | ||
8292 | /* | ||
8293 | * This can be called at any time. No action lock required | ||
8294 | */ | ||
8295 | |||
8296 | struct ipw2100_priv *priv = ieee80211_priv(dev); | ||
8297 | |||
8298 | if (priv->config & CFG_CRC_CHECK) | ||
8299 | snprintf(wrqu->name, IFNAMSIZ, "CRC checked (1)"); | ||
8300 | else | ||
8301 | snprintf(wrqu->name, IFNAMSIZ, "CRC ignored (0)"); | ||
8302 | |||
8303 | return 0; | ||
8304 | } | ||
8305 | #endif /* CONFIG_IPW2100_MONITOR */ | ||
8306 | |||
8022 | static iw_handler ipw2100_wx_handlers[] = { | 8307 | static iw_handler ipw2100_wx_handlers[] = { |
8023 | NULL, /* SIOCSIWCOMMIT */ | 8308 | NULL, /* SIOCSIWCOMMIT */ |
8024 | ipw2100_wx_get_name, /* SIOCGIWNAME */ | 8309 | ipw2100_wx_get_name, /* SIOCGIWNAME */ |
@@ -8042,7 +8327,11 @@ static iw_handler ipw2100_wx_handlers[] = { | |||
8042 | NULL, /* SIOCWIWTHRSPY */ | 8327 | NULL, /* SIOCWIWTHRSPY */ |
8043 | ipw2100_wx_set_wap, /* SIOCSIWAP */ | 8328 | ipw2100_wx_set_wap, /* SIOCSIWAP */ |
8044 | ipw2100_wx_get_wap, /* SIOCGIWAP */ | 8329 | ipw2100_wx_get_wap, /* SIOCGIWAP */ |
8330 | #if WIRELESS_EXT > 17 | ||
8331 | ipw2100_wx_set_mlme, /* SIOCSIWMLME */ | ||
8332 | #else | ||
8045 | NULL, /* -- hole -- */ | 8333 | NULL, /* -- hole -- */ |
8334 | #endif | ||
8046 | NULL, /* SIOCGIWAPLIST -- deprecated */ | 8335 | NULL, /* SIOCGIWAPLIST -- deprecated */ |
8047 | ipw2100_wx_set_scan, /* SIOCSIWSCAN */ | 8336 | ipw2100_wx_set_scan, /* SIOCSIWSCAN */ |
8048 | ipw2100_wx_get_scan, /* SIOCGIWSCAN */ | 8337 | ipw2100_wx_get_scan, /* SIOCGIWSCAN */ |
@@ -8066,6 +8355,17 @@ static iw_handler ipw2100_wx_handlers[] = { | |||
8066 | ipw2100_wx_get_encode, /* SIOCGIWENCODE */ | 8355 | ipw2100_wx_get_encode, /* SIOCGIWENCODE */ |
8067 | ipw2100_wx_set_power, /* SIOCSIWPOWER */ | 8356 | ipw2100_wx_set_power, /* SIOCSIWPOWER */ |
8068 | ipw2100_wx_get_power, /* SIOCGIWPOWER */ | 8357 | ipw2100_wx_get_power, /* SIOCGIWPOWER */ |
8358 | #if WIRELESS_EXT > 17 | ||
8359 | NULL, /* -- hole -- */ | ||
8360 | NULL, /* -- hole -- */ | ||
8361 | ipw2100_wx_set_genie, /* SIOCSIWGENIE */ | ||
8362 | ipw2100_wx_get_genie, /* SIOCGIWGENIE */ | ||
8363 | ipw2100_wx_set_auth, /* SIOCSIWAUTH */ | ||
8364 | ipw2100_wx_get_auth, /* SIOCGIWAUTH */ | ||
8365 | ipw2100_wx_set_encodeext, /* SIOCSIWENCODEEXT */ | ||
8366 | ipw2100_wx_get_encodeext, /* SIOCGIWENCODEEXT */ | ||
8367 | NULL, /* SIOCSIWPMKSA */ | ||
8368 | #endif | ||
8069 | }; | 8369 | }; |
8070 | 8370 | ||
8071 | #define IPW2100_PRIV_SET_MONITOR SIOCIWFIRSTPRIV | 8371 | #define IPW2100_PRIV_SET_MONITOR SIOCIWFIRSTPRIV |
@@ -8074,6 +8374,8 @@ static iw_handler ipw2100_wx_handlers[] = { | |||
8074 | #define IPW2100_PRIV_GET_POWER SIOCIWFIRSTPRIV+3 | 8374 | #define IPW2100_PRIV_GET_POWER SIOCIWFIRSTPRIV+3 |
8075 | #define IPW2100_PRIV_SET_LONGPREAMBLE SIOCIWFIRSTPRIV+4 | 8375 | #define IPW2100_PRIV_SET_LONGPREAMBLE SIOCIWFIRSTPRIV+4 |
8076 | #define IPW2100_PRIV_GET_LONGPREAMBLE SIOCIWFIRSTPRIV+5 | 8376 | #define IPW2100_PRIV_GET_LONGPREAMBLE SIOCIWFIRSTPRIV+5 |
8377 | #define IPW2100_PRIV_SET_CRC_CHECK SIOCIWFIRSTPRIV+6 | ||
8378 | #define IPW2100_PRIV_GET_CRC_CHECK SIOCIWFIRSTPRIV+7 | ||
8077 | 8379 | ||
8078 | static const struct iw_priv_args ipw2100_private_args[] = { | 8380 | static const struct iw_priv_args ipw2100_private_args[] = { |
8079 | 8381 | ||
@@ -8099,6 +8401,14 @@ static const struct iw_priv_args ipw2100_private_args[] = { | |||
8099 | { | 8401 | { |
8100 | IPW2100_PRIV_GET_LONGPREAMBLE, | 8402 | IPW2100_PRIV_GET_LONGPREAMBLE, |
8101 | 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "get_preamble"}, | 8403 | 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "get_preamble"}, |
8404 | #ifdef CONFIG_IPW2100_MONITOR | ||
8405 | { | ||
8406 | IPW2100_PRIV_SET_CRC_CHECK, | ||
8407 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_crc_check"}, | ||
8408 | { | ||
8409 | IPW2100_PRIV_GET_CRC_CHECK, | ||
8410 | 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "get_crc_check"}, | ||
8411 | #endif /* CONFIG_IPW2100_MONITOR */ | ||
8102 | }; | 8412 | }; |
8103 | 8413 | ||
8104 | static iw_handler ipw2100_private_handler[] = { | 8414 | static iw_handler ipw2100_private_handler[] = { |
@@ -8113,6 +8423,13 @@ static iw_handler ipw2100_private_handler[] = { | |||
8113 | ipw2100_wx_get_powermode, | 8423 | ipw2100_wx_get_powermode, |
8114 | ipw2100_wx_set_preamble, | 8424 | ipw2100_wx_set_preamble, |
8115 | ipw2100_wx_get_preamble, | 8425 | ipw2100_wx_get_preamble, |
8426 | #ifdef CONFIG_IPW2100_MONITOR | ||
8427 | ipw2100_wx_set_crc_check, | ||
8428 | ipw2100_wx_get_crc_check, | ||
8429 | #else /* CONFIG_IPW2100_MONITOR */ | ||
8430 | NULL, | ||
8431 | NULL, | ||
8432 | #endif /* CONFIG_IPW2100_MONITOR */ | ||
8116 | }; | 8433 | }; |
8117 | 8434 | ||
8118 | static struct iw_handler_def ipw2100_wx_handler_def = { | 8435 | static struct iw_handler_def ipw2100_wx_handler_def = { |
@@ -8292,17 +8609,11 @@ static void ipw2100_wx_event_work(struct ipw2100_priv *priv) | |||
8292 | /* We now have the BSSID, so can finish setting to the full | 8609 | /* We now have the BSSID, so can finish setting to the full |
8293 | * associated state */ | 8610 | * associated state */ |
8294 | memcpy(wrqu.ap_addr.sa_data, priv->bssid, ETH_ALEN); | 8611 | memcpy(wrqu.ap_addr.sa_data, priv->bssid, ETH_ALEN); |
8295 | memcpy(&priv->ieee->bssid, priv->bssid, ETH_ALEN); | 8612 | memcpy(priv->ieee->bssid, priv->bssid, ETH_ALEN); |
8296 | priv->status &= ~STATUS_ASSOCIATING; | 8613 | priv->status &= ~STATUS_ASSOCIATING; |
8297 | priv->status |= STATUS_ASSOCIATED; | 8614 | priv->status |= STATUS_ASSOCIATED; |
8298 | netif_carrier_on(priv->net_dev); | 8615 | netif_carrier_on(priv->net_dev); |
8299 | if (netif_queue_stopped(priv->net_dev)) { | 8616 | netif_wake_queue(priv->net_dev); |
8300 | IPW_DEBUG_INFO("Waking net queue.\n"); | ||
8301 | netif_wake_queue(priv->net_dev); | ||
8302 | } else { | ||
8303 | IPW_DEBUG_INFO("Starting net queue.\n"); | ||
8304 | netif_start_queue(priv->net_dev); | ||
8305 | } | ||
8306 | } | 8617 | } |
8307 | 8618 | ||
8308 | if (!(priv->status & STATUS_ASSOCIATED)) { | 8619 | if (!(priv->status & STATUS_ASSOCIATED)) { |