diff options
Diffstat (limited to 'drivers/net/wireless/ipw2200.c')
| -rw-r--r-- | drivers/net/wireless/ipw2200.c | 849 |
1 files changed, 730 insertions, 119 deletions
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index bca89cff85a6..39f82f219749 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c | |||
| @@ -33,7 +33,44 @@ | |||
| 33 | #include "ipw2200.h" | 33 | #include "ipw2200.h" |
| 34 | #include <linux/version.h> | 34 | #include <linux/version.h> |
| 35 | 35 | ||
| 36 | #define IPW2200_VERSION "git-1.1.1" | 36 | |
| 37 | #ifndef KBUILD_EXTMOD | ||
| 38 | #define VK "k" | ||
| 39 | #else | ||
| 40 | #define VK | ||
| 41 | #endif | ||
| 42 | |||
| 43 | #ifdef CONFIG_IPW2200_DEBUG | ||
| 44 | #define VD "d" | ||
| 45 | #else | ||
| 46 | #define VD | ||
| 47 | #endif | ||
| 48 | |||
| 49 | #ifdef CONFIG_IPW2200_MONITOR | ||
| 50 | #define VM "m" | ||
| 51 | #else | ||
| 52 | #define VM | ||
| 53 | #endif | ||
| 54 | |||
| 55 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 56 | #define VP "p" | ||
| 57 | #else | ||
| 58 | #define VP | ||
| 59 | #endif | ||
| 60 | |||
| 61 | #ifdef CONFIG_IPW2200_RADIOTAP | ||
| 62 | #define VR "r" | ||
| 63 | #else | ||
| 64 | #define VR | ||
| 65 | #endif | ||
| 66 | |||
| 67 | #ifdef CONFIG_IPW2200_QOS | ||
| 68 | #define VQ "q" | ||
| 69 | #else | ||
| 70 | #define VQ | ||
| 71 | #endif | ||
| 72 | |||
| 73 | #define IPW2200_VERSION "1.1.2" VK VD VM VP VR VQ | ||
| 37 | #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" | 74 | #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" |
| 38 | #define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation" | 75 | #define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation" |
| 39 | #define DRV_VERSION IPW2200_VERSION | 76 | #define DRV_VERSION IPW2200_VERSION |
| @@ -46,7 +83,9 @@ MODULE_AUTHOR(DRV_COPYRIGHT); | |||
| 46 | MODULE_LICENSE("GPL"); | 83 | MODULE_LICENSE("GPL"); |
| 47 | 84 | ||
| 48 | static int cmdlog = 0; | 85 | static int cmdlog = 0; |
| 86 | #ifdef CONFIG_IPW2200_DEBUG | ||
| 49 | static int debug = 0; | 87 | static int debug = 0; |
| 88 | #endif | ||
| 50 | static int channel = 0; | 89 | static int channel = 0; |
| 51 | static int mode = 0; | 90 | static int mode = 0; |
| 52 | 91 | ||
| @@ -61,8 +100,14 @@ static int roaming = 1; | |||
| 61 | static const char ipw_modes[] = { | 100 | static const char ipw_modes[] = { |
| 62 | 'a', 'b', 'g', '?' | 101 | 'a', 'b', 'g', '?' |
| 63 | }; | 102 | }; |
| 103 | static int antenna = CFG_SYS_ANTENNA_BOTH; | ||
| 64 | 104 | ||
| 65 | #ifdef CONFIG_IPW_QOS | 105 | #ifdef CONFIG_IPW2200_PROMISCUOUS |
| 106 | static int rtap_iface = 0; /* def: 0 -- do not create rtap interface */ | ||
| 107 | #endif | ||
| 108 | |||
| 109 | |||
| 110 | #ifdef CONFIG_IPW2200_QOS | ||
| 66 | static int qos_enable = 0; | 111 | static int qos_enable = 0; |
| 67 | static int qos_burst_enable = 0; | 112 | static int qos_burst_enable = 0; |
| 68 | static int qos_no_ack_mask = 0; | 113 | static int qos_no_ack_mask = 0; |
| @@ -126,7 +171,7 @@ static int ipw_send_qos_params_command(struct ipw_priv *priv, struct ieee80211_q | |||
| 126 | *qos_param); | 171 | *qos_param); |
| 127 | static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos_information_element | 172 | static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos_information_element |
| 128 | *qos_param); | 173 | *qos_param); |
| 129 | #endif /* CONFIG_IPW_QOS */ | 174 | #endif /* CONFIG_IPW2200_QOS */ |
| 130 | 175 | ||
| 131 | static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev); | 176 | static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev); |
| 132 | static void ipw_remove_current_network(struct ipw_priv *priv); | 177 | static void ipw_remove_current_network(struct ipw_priv *priv); |
| @@ -1269,6 +1314,105 @@ static ssize_t show_cmd_log(struct device *d, | |||
| 1269 | 1314 | ||
| 1270 | static DEVICE_ATTR(cmd_log, S_IRUGO, show_cmd_log, NULL); | 1315 | static DEVICE_ATTR(cmd_log, S_IRUGO, show_cmd_log, NULL); |
| 1271 | 1316 | ||
| 1317 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 1318 | static void ipw_prom_free(struct ipw_priv *priv); | ||
| 1319 | static int ipw_prom_alloc(struct ipw_priv *priv); | ||
| 1320 | static ssize_t store_rtap_iface(struct device *d, | ||
| 1321 | struct device_attribute *attr, | ||
| 1322 | const char *buf, size_t count) | ||
| 1323 | { | ||
| 1324 | struct ipw_priv *priv = dev_get_drvdata(d); | ||
| 1325 | int rc = 0; | ||
| 1326 | |||
| 1327 | if (count < 1) | ||
| 1328 | return -EINVAL; | ||
| 1329 | |||
| 1330 | switch (buf[0]) { | ||
| 1331 | case '0': | ||
| 1332 | if (!rtap_iface) | ||
| 1333 | return count; | ||
| 1334 | |||
| 1335 | if (netif_running(priv->prom_net_dev)) { | ||
| 1336 | IPW_WARNING("Interface is up. Cannot unregister.\n"); | ||
| 1337 | return count; | ||
| 1338 | } | ||
| 1339 | |||
| 1340 | ipw_prom_free(priv); | ||
| 1341 | rtap_iface = 0; | ||
| 1342 | break; | ||
| 1343 | |||
| 1344 | case '1': | ||
| 1345 | if (rtap_iface) | ||
| 1346 | return count; | ||
| 1347 | |||
| 1348 | rc = ipw_prom_alloc(priv); | ||
| 1349 | if (!rc) | ||
| 1350 | rtap_iface = 1; | ||
| 1351 | break; | ||
| 1352 | |||
| 1353 | default: | ||
| 1354 | return -EINVAL; | ||
| 1355 | } | ||
| 1356 | |||
| 1357 | if (rc) { | ||
| 1358 | IPW_ERROR("Failed to register promiscuous network " | ||
| 1359 | "device (error %d).\n", rc); | ||
| 1360 | } | ||
| 1361 | |||
| 1362 | return count; | ||
| 1363 | } | ||
| 1364 | |||
| 1365 | static ssize_t show_rtap_iface(struct device *d, | ||
| 1366 | struct device_attribute *attr, | ||
| 1367 | char *buf) | ||
| 1368 | { | ||
| 1369 | struct ipw_priv *priv = dev_get_drvdata(d); | ||
| 1370 | if (rtap_iface) | ||
| 1371 | return sprintf(buf, "%s", priv->prom_net_dev->name); | ||
| 1372 | else { | ||
| 1373 | buf[0] = '-'; | ||
| 1374 | buf[1] = '1'; | ||
| 1375 | buf[2] = '\0'; | ||
| 1376 | return 3; | ||
| 1377 | } | ||
| 1378 | } | ||
| 1379 | |||
| 1380 | static DEVICE_ATTR(rtap_iface, S_IWUSR | S_IRUSR, show_rtap_iface, | ||
| 1381 | store_rtap_iface); | ||
| 1382 | |||
| 1383 | static ssize_t store_rtap_filter(struct device *d, | ||
| 1384 | struct device_attribute *attr, | ||
| 1385 | const char *buf, size_t count) | ||
| 1386 | { | ||
| 1387 | struct ipw_priv *priv = dev_get_drvdata(d); | ||
| 1388 | |||
| 1389 | if (!priv->prom_priv) { | ||
| 1390 | IPW_ERROR("Attempting to set filter without " | ||
| 1391 | "rtap_iface enabled.\n"); | ||
| 1392 | return -EPERM; | ||
| 1393 | } | ||
| 1394 | |||
| 1395 | priv->prom_priv->filter = simple_strtol(buf, NULL, 0); | ||
| 1396 | |||
| 1397 | IPW_DEBUG_INFO("Setting rtap filter to " BIT_FMT16 "\n", | ||
| 1398 | BIT_ARG16(priv->prom_priv->filter)); | ||
| 1399 | |||
| 1400 | return count; | ||
| 1401 | } | ||
| 1402 | |||
| 1403 | static ssize_t show_rtap_filter(struct device *d, | ||
| 1404 | struct device_attribute *attr, | ||
| 1405 | char *buf) | ||
| 1406 | { | ||
| 1407 | struct ipw_priv *priv = dev_get_drvdata(d); | ||
| 1408 | return sprintf(buf, "0x%04X", | ||
| 1409 | priv->prom_priv ? priv->prom_priv->filter : 0); | ||
| 1410 | } | ||
| 1411 | |||
| 1412 | static DEVICE_ATTR(rtap_filter, S_IWUSR | S_IRUSR, show_rtap_filter, | ||
| 1413 | store_rtap_filter); | ||
| 1414 | #endif | ||
| 1415 | |||
| 1272 | static ssize_t show_scan_age(struct device *d, struct device_attribute *attr, | 1416 | static ssize_t show_scan_age(struct device *d, struct device_attribute *attr, |
| 1273 | char *buf) | 1417 | char *buf) |
| 1274 | { | 1418 | { |
| @@ -2025,16 +2169,11 @@ static int ipw_send_host_complete(struct ipw_priv *priv) | |||
| 2025 | return ipw_send_cmd_simple(priv, IPW_CMD_HOST_COMPLETE); | 2169 | return ipw_send_cmd_simple(priv, IPW_CMD_HOST_COMPLETE); |
| 2026 | } | 2170 | } |
| 2027 | 2171 | ||
| 2028 | static int ipw_send_system_config(struct ipw_priv *priv, | 2172 | static int ipw_send_system_config(struct ipw_priv *priv) |
| 2029 | struct ipw_sys_config *config) | ||
| 2030 | { | 2173 | { |
| 2031 | if (!priv || !config) { | 2174 | return ipw_send_cmd_pdu(priv, IPW_CMD_SYSTEM_CONFIG, |
| 2032 | IPW_ERROR("Invalid args\n"); | 2175 | sizeof(priv->sys_config), |
| 2033 | return -1; | 2176 | &priv->sys_config); |
| 2034 | } | ||
| 2035 | |||
| 2036 | return ipw_send_cmd_pdu(priv, IPW_CMD_SYSTEM_CONFIG, sizeof(*config), | ||
| 2037 | config); | ||
| 2038 | } | 2177 | } |
| 2039 | 2178 | ||
| 2040 | static int ipw_send_ssid(struct ipw_priv *priv, u8 * ssid, int len) | 2179 | static int ipw_send_ssid(struct ipw_priv *priv, u8 * ssid, int len) |
| @@ -3104,10 +3243,10 @@ static int ipw_reset_nic(struct ipw_priv *priv) | |||
| 3104 | 3243 | ||
| 3105 | 3244 | ||
| 3106 | struct ipw_fw { | 3245 | struct ipw_fw { |
| 3107 | u32 ver; | 3246 | __le32 ver; |
| 3108 | u32 boot_size; | 3247 | __le32 boot_size; |
| 3109 | u32 ucode_size; | 3248 | __le32 ucode_size; |
| 3110 | u32 fw_size; | 3249 | __le32 fw_size; |
| 3111 | u8 data[0]; | 3250 | u8 data[0]; |
| 3112 | }; | 3251 | }; |
| 3113 | 3252 | ||
| @@ -3131,8 +3270,8 @@ static int ipw_get_fw(struct ipw_priv *priv, | |||
| 3131 | 3270 | ||
| 3132 | fw = (void *)(*raw)->data; | 3271 | fw = (void *)(*raw)->data; |
| 3133 | 3272 | ||
| 3134 | if ((*raw)->size < sizeof(*fw) + | 3273 | if ((*raw)->size < sizeof(*fw) + le32_to_cpu(fw->boot_size) + |
| 3135 | fw->boot_size + fw->ucode_size + fw->fw_size) { | 3274 | le32_to_cpu(fw->ucode_size) + le32_to_cpu(fw->fw_size)) { |
| 3136 | IPW_ERROR("%s is too small or corrupt (%zd)\n", | 3275 | IPW_ERROR("%s is too small or corrupt (%zd)\n", |
| 3137 | name, (*raw)->size); | 3276 | name, (*raw)->size); |
| 3138 | return -EINVAL; | 3277 | return -EINVAL; |
| @@ -3237,8 +3376,9 @@ static int ipw_load(struct ipw_priv *priv) | |||
| 3237 | 3376 | ||
| 3238 | fw = (void *)raw->data; | 3377 | fw = (void *)raw->data; |
| 3239 | boot_img = &fw->data[0]; | 3378 | boot_img = &fw->data[0]; |
| 3240 | ucode_img = &fw->data[fw->boot_size]; | 3379 | ucode_img = &fw->data[le32_to_cpu(fw->boot_size)]; |
| 3241 | fw_img = &fw->data[fw->boot_size + fw->ucode_size]; | 3380 | fw_img = &fw->data[le32_to_cpu(fw->boot_size) + |
| 3381 | le32_to_cpu(fw->ucode_size)]; | ||
| 3242 | 3382 | ||
| 3243 | if (rc < 0) | 3383 | if (rc < 0) |
| 3244 | goto error; | 3384 | goto error; |
| @@ -3272,7 +3412,7 @@ static int ipw_load(struct ipw_priv *priv) | |||
| 3272 | IPW_NIC_SRAM_UPPER_BOUND - IPW_NIC_SRAM_LOWER_BOUND); | 3412 | IPW_NIC_SRAM_UPPER_BOUND - IPW_NIC_SRAM_LOWER_BOUND); |
| 3273 | 3413 | ||
| 3274 | /* DMA the initial boot firmware into the device */ | 3414 | /* DMA the initial boot firmware into the device */ |
| 3275 | rc = ipw_load_firmware(priv, boot_img, fw->boot_size); | 3415 | rc = ipw_load_firmware(priv, boot_img, le32_to_cpu(fw->boot_size)); |
| 3276 | if (rc < 0) { | 3416 | if (rc < 0) { |
| 3277 | IPW_ERROR("Unable to load boot firmware: %d\n", rc); | 3417 | IPW_ERROR("Unable to load boot firmware: %d\n", rc); |
| 3278 | goto error; | 3418 | goto error; |
| @@ -3294,7 +3434,7 @@ static int ipw_load(struct ipw_priv *priv) | |||
| 3294 | ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE); | 3434 | ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE); |
| 3295 | 3435 | ||
| 3296 | /* DMA the ucode into the device */ | 3436 | /* DMA the ucode into the device */ |
| 3297 | rc = ipw_load_ucode(priv, ucode_img, fw->ucode_size); | 3437 | rc = ipw_load_ucode(priv, ucode_img, le32_to_cpu(fw->ucode_size)); |
| 3298 | if (rc < 0) { | 3438 | if (rc < 0) { |
| 3299 | IPW_ERROR("Unable to load ucode: %d\n", rc); | 3439 | IPW_ERROR("Unable to load ucode: %d\n", rc); |
| 3300 | goto error; | 3440 | goto error; |
| @@ -3304,7 +3444,7 @@ static int ipw_load(struct ipw_priv *priv) | |||
| 3304 | ipw_stop_nic(priv); | 3444 | ipw_stop_nic(priv); |
| 3305 | 3445 | ||
| 3306 | /* DMA bss firmware into the device */ | 3446 | /* DMA bss firmware into the device */ |
| 3307 | rc = ipw_load_firmware(priv, fw_img, fw->fw_size); | 3447 | rc = ipw_load_firmware(priv, fw_img, le32_to_cpu(fw->fw_size)); |
| 3308 | if (rc < 0) { | 3448 | if (rc < 0) { |
| 3309 | IPW_ERROR("Unable to load firmware: %d\n", rc); | 3449 | IPW_ERROR("Unable to load firmware: %d\n", rc); |
| 3310 | goto error; | 3450 | goto error; |
| @@ -3700,7 +3840,17 @@ static void ipw_bg_disassociate(void *data) | |||
| 3700 | static void ipw_system_config(void *data) | 3840 | static void ipw_system_config(void *data) |
| 3701 | { | 3841 | { |
| 3702 | struct ipw_priv *priv = data; | 3842 | struct ipw_priv *priv = data; |
| 3703 | ipw_send_system_config(priv, &priv->sys_config); | 3843 | |
| 3844 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 3845 | if (priv->prom_net_dev && netif_running(priv->prom_net_dev)) { | ||
| 3846 | priv->sys_config.accept_all_data_frames = 1; | ||
| 3847 | priv->sys_config.accept_non_directed_frames = 1; | ||
| 3848 | priv->sys_config.accept_all_mgmt_bcpr = 1; | ||
| 3849 | priv->sys_config.accept_all_mgmt_frames = 1; | ||
| 3850 | } | ||
| 3851 | #endif | ||
| 3852 | |||
| 3853 | ipw_send_system_config(priv); | ||
| 3704 | } | 3854 | } |
| 3705 | 3855 | ||
| 3706 | struct ipw_status_code { | 3856 | struct ipw_status_code { |
| @@ -3771,6 +3921,13 @@ static void inline average_init(struct average *avg) | |||
| 3771 | memset(avg, 0, sizeof(*avg)); | 3921 | memset(avg, 0, sizeof(*avg)); |
| 3772 | } | 3922 | } |
| 3773 | 3923 | ||
| 3924 | #define DEPTH_RSSI 8 | ||
| 3925 | #define DEPTH_NOISE 16 | ||
| 3926 | static s16 exponential_average(s16 prev_avg, s16 val, u8 depth) | ||
| 3927 | { | ||
| 3928 | return ((depth-1)*prev_avg + val)/depth; | ||
| 3929 | } | ||
| 3930 | |||
| 3774 | static void average_add(struct average *avg, s16 val) | 3931 | static void average_add(struct average *avg, s16 val) |
| 3775 | { | 3932 | { |
| 3776 | avg->sum -= avg->entries[avg->pos]; | 3933 | avg->sum -= avg->entries[avg->pos]; |
| @@ -3800,8 +3957,8 @@ static void ipw_reset_stats(struct ipw_priv *priv) | |||
| 3800 | priv->quality = 0; | 3957 | priv->quality = 0; |
| 3801 | 3958 | ||
| 3802 | average_init(&priv->average_missed_beacons); | 3959 | average_init(&priv->average_missed_beacons); |
| 3803 | average_init(&priv->average_rssi); | 3960 | priv->exp_avg_rssi = -60; |
| 3804 | average_init(&priv->average_noise); | 3961 | priv->exp_avg_noise = -85 + 0x100; |
| 3805 | 3962 | ||
| 3806 | priv->last_rate = 0; | 3963 | priv->last_rate = 0; |
| 3807 | priv->last_missed_beacons = 0; | 3964 | priv->last_missed_beacons = 0; |
| @@ -4008,7 +4165,7 @@ static void ipw_gather_stats(struct ipw_priv *priv) | |||
| 4008 | IPW_DEBUG_STATS("Tx quality : %3d%% (%u errors, %u packets)\n", | 4165 | IPW_DEBUG_STATS("Tx quality : %3d%% (%u errors, %u packets)\n", |
| 4009 | tx_quality, tx_failures_delta, tx_packets_delta); | 4166 | tx_quality, tx_failures_delta, tx_packets_delta); |
| 4010 | 4167 | ||
| 4011 | rssi = average_value(&priv->average_rssi); | 4168 | rssi = priv->exp_avg_rssi; |
| 4012 | signal_quality = | 4169 | signal_quality = |
| 4013 | (100 * | 4170 | (100 * |
| 4014 | (priv->ieee->perfect_rssi - priv->ieee->worst_rssi) * | 4171 | (priv->ieee->perfect_rssi - priv->ieee->worst_rssi) * |
| @@ -4185,7 +4342,7 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
| 4185 | queue_work(priv->workqueue, | 4342 | queue_work(priv->workqueue, |
| 4186 | &priv->system_config); | 4343 | &priv->system_config); |
| 4187 | 4344 | ||
| 4188 | #ifdef CONFIG_IPW_QOS | 4345 | #ifdef CONFIG_IPW2200_QOS |
| 4189 | #define IPW_GET_PACKET_STYPE(x) WLAN_FC_GET_STYPE( \ | 4346 | #define IPW_GET_PACKET_STYPE(x) WLAN_FC_GET_STYPE( \ |
| 4190 | le16_to_cpu(((struct ieee80211_hdr *)(x))->frame_ctl)) | 4347 | le16_to_cpu(((struct ieee80211_hdr *)(x))->frame_ctl)) |
| 4191 | if ((priv->status & STATUS_AUTH) && | 4348 | if ((priv->status & STATUS_AUTH) && |
| @@ -4482,6 +4639,24 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
| 4482 | && priv->status & STATUS_ASSOCIATED) | 4639 | && priv->status & STATUS_ASSOCIATED) |
| 4483 | queue_delayed_work(priv->workqueue, | 4640 | queue_delayed_work(priv->workqueue, |
| 4484 | &priv->request_scan, HZ); | 4641 | &priv->request_scan, HZ); |
| 4642 | |||
| 4643 | /* Send an empty event to user space. | ||
| 4644 | * We don't send the received data on the event because | ||
| 4645 | * it would require us to do complex transcoding, and | ||
| 4646 | * we want to minimise the work done in the irq handler | ||
| 4647 | * Use a request to extract the data. | ||
| 4648 | * Also, we generate this even for any scan, regardless | ||
| 4649 | * on how the scan was initiated. User space can just | ||
| 4650 | * sync on periodic scan to get fresh data... | ||
| 4651 | * Jean II */ | ||
| 4652 | if (x->status == SCAN_COMPLETED_STATUS_COMPLETE) { | ||
| 4653 | union iwreq_data wrqu; | ||
| 4654 | |||
| 4655 | wrqu.data.length = 0; | ||
| 4656 | wrqu.data.flags = 0; | ||
| 4657 | wireless_send_event(priv->net_dev, SIOCGIWSCAN, | ||
| 4658 | &wrqu, NULL); | ||
| 4659 | } | ||
| 4485 | break; | 4660 | break; |
| 4486 | } | 4661 | } |
| 4487 | 4662 | ||
| @@ -4577,11 +4752,10 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
| 4577 | 4752 | ||
| 4578 | case HOST_NOTIFICATION_NOISE_STATS:{ | 4753 | case HOST_NOTIFICATION_NOISE_STATS:{ |
| 4579 | if (notif->size == sizeof(u32)) { | 4754 | if (notif->size == sizeof(u32)) { |
| 4580 | priv->last_noise = | 4755 | priv->exp_avg_noise = |
| 4581 | (u8) (le32_to_cpu(notif->u.noise.value) & | 4756 | exponential_average(priv->exp_avg_noise, |
| 4582 | 0xff); | 4757 | (u8) (le32_to_cpu(notif->u.noise.value) & 0xff), |
| 4583 | average_add(&priv->average_noise, | 4758 | DEPTH_NOISE); |
| 4584 | priv->last_noise); | ||
| 4585 | break; | 4759 | break; |
| 4586 | } | 4760 | } |
| 4587 | 4761 | ||
| @@ -6170,8 +6344,6 @@ static void ipw_wpa_assoc_frame(struct ipw_priv *priv, char *wpa_ie, | |||
| 6170 | { | 6344 | { |
| 6171 | /* make sure WPA is enabled */ | 6345 | /* make sure WPA is enabled */ |
| 6172 | ipw_wpa_enable(priv, 1); | 6346 | ipw_wpa_enable(priv, 1); |
| 6173 | |||
| 6174 | ipw_disassociate(priv); | ||
| 6175 | } | 6347 | } |
| 6176 | 6348 | ||
| 6177 | static int ipw_set_rsn_capa(struct ipw_priv *priv, | 6349 | static int ipw_set_rsn_capa(struct ipw_priv *priv, |
| @@ -6365,6 +6537,7 @@ static int ipw_wx_set_auth(struct net_device *dev, | |||
| 6365 | 6537 | ||
| 6366 | case IW_AUTH_WPA_ENABLED: | 6538 | case IW_AUTH_WPA_ENABLED: |
| 6367 | ret = ipw_wpa_enable(priv, param->value); | 6539 | ret = ipw_wpa_enable(priv, param->value); |
| 6540 | ipw_disassociate(priv); | ||
| 6368 | break; | 6541 | break; |
| 6369 | 6542 | ||
| 6370 | case IW_AUTH_RX_UNENCRYPTED_EAPOL: | 6543 | case IW_AUTH_RX_UNENCRYPTED_EAPOL: |
| @@ -6506,7 +6679,7 @@ static int ipw_wx_set_mlme(struct net_device *dev, | |||
| 6506 | return 0; | 6679 | return 0; |
| 6507 | } | 6680 | } |
| 6508 | 6681 | ||
| 6509 | #ifdef CONFIG_IPW_QOS | 6682 | #ifdef CONFIG_IPW2200_QOS |
| 6510 | 6683 | ||
| 6511 | /* QoS */ | 6684 | /* QoS */ |
| 6512 | /* | 6685 | /* |
| @@ -6853,61 +7026,55 @@ static int ipw_get_tx_queue_number(struct ipw_priv *priv, u16 priority) | |||
| 6853 | return from_priority_to_tx_queue[priority] - 1; | 7026 | return from_priority_to_tx_queue[priority] - 1; |
| 6854 | } | 7027 | } |
| 6855 | 7028 | ||
| 6856 | /* | 7029 | static int ipw_is_qos_active(struct net_device *dev, |
| 6857 | * add QoS parameter to the TX command | 7030 | struct sk_buff *skb) |
| 6858 | */ | ||
| 6859 | static int ipw_qos_set_tx_queue_command(struct ipw_priv *priv, | ||
| 6860 | u16 priority, | ||
| 6861 | struct tfd_data *tfd, u8 unicast) | ||
| 6862 | { | 7031 | { |
| 6863 | int ret = 0; | 7032 | struct ipw_priv *priv = ieee80211_priv(dev); |
| 6864 | int tx_queue_id = 0; | ||
| 6865 | struct ieee80211_qos_data *qos_data = NULL; | 7033 | struct ieee80211_qos_data *qos_data = NULL; |
| 6866 | int active, supported; | 7034 | int active, supported; |
| 6867 | unsigned long flags; | 7035 | u8 *daddr = skb->data + ETH_ALEN; |
| 7036 | int unicast = !is_multicast_ether_addr(daddr); | ||
| 6868 | 7037 | ||
| 6869 | if (!(priv->status & STATUS_ASSOCIATED)) | 7038 | if (!(priv->status & STATUS_ASSOCIATED)) |
| 6870 | return 0; | 7039 | return 0; |
| 6871 | 7040 | ||
| 6872 | qos_data = &priv->assoc_network->qos_data; | 7041 | qos_data = &priv->assoc_network->qos_data; |
| 6873 | 7042 | ||
| 6874 | spin_lock_irqsave(&priv->ieee->lock, flags); | ||
| 6875 | |||
| 6876 | if (priv->ieee->iw_mode == IW_MODE_ADHOC) { | 7043 | if (priv->ieee->iw_mode == IW_MODE_ADHOC) { |
| 6877 | if (unicast == 0) | 7044 | if (unicast == 0) |
| 6878 | qos_data->active = 0; | 7045 | qos_data->active = 0; |
| 6879 | else | 7046 | else |
| 6880 | qos_data->active = qos_data->supported; | 7047 | qos_data->active = qos_data->supported; |
| 6881 | } | 7048 | } |
| 6882 | |||
| 6883 | active = qos_data->active; | 7049 | active = qos_data->active; |
| 6884 | supported = qos_data->supported; | 7050 | supported = qos_data->supported; |
| 6885 | |||
| 6886 | spin_unlock_irqrestore(&priv->ieee->lock, flags); | ||
| 6887 | |||
| 6888 | IPW_DEBUG_QOS("QoS %d network is QoS active %d supported %d " | 7051 | IPW_DEBUG_QOS("QoS %d network is QoS active %d supported %d " |
| 6889 | "unicast %d\n", | 7052 | "unicast %d\n", |
| 6890 | priv->qos_data.qos_enable, active, supported, unicast); | 7053 | priv->qos_data.qos_enable, active, supported, unicast); |
| 6891 | if (active && priv->qos_data.qos_enable) { | 7054 | if (active && priv->qos_data.qos_enable) |
| 6892 | ret = from_priority_to_tx_queue[priority]; | 7055 | return 1; |
| 6893 | tx_queue_id = ret - 1; | ||
| 6894 | IPW_DEBUG_QOS("QoS packet priority is %d \n", priority); | ||
| 6895 | if (priority <= 7) { | ||
| 6896 | tfd->tx_flags_ext |= DCT_FLAG_EXT_QOS_ENABLED; | ||
| 6897 | tfd->tfd.tfd_26.mchdr.qos_ctrl = priority; | ||
| 6898 | tfd->tfd.tfd_26.mchdr.frame_ctl |= | ||
| 6899 | IEEE80211_STYPE_QOS_DATA; | ||
| 6900 | |||
| 6901 | if (priv->qos_data.qos_no_ack_mask & | ||
| 6902 | (1UL << tx_queue_id)) { | ||
| 6903 | tfd->tx_flags &= ~DCT_FLAG_ACK_REQD; | ||
| 6904 | tfd->tfd.tfd_26.mchdr.qos_ctrl |= | ||
| 6905 | CTRL_QOS_NO_ACK; | ||
| 6906 | } | ||
| 6907 | } | ||
| 6908 | } | ||
| 6909 | 7056 | ||
| 6910 | return ret; | 7057 | return 0; |
| 7058 | |||
| 7059 | } | ||
| 7060 | /* | ||
| 7061 | * add QoS parameter to the TX command | ||
| 7062 | */ | ||
| 7063 | static int ipw_qos_set_tx_queue_command(struct ipw_priv *priv, | ||
| 7064 | u16 priority, | ||
| 7065 | struct tfd_data *tfd) | ||
| 7066 | { | ||
| 7067 | int tx_queue_id = 0; | ||
| 7068 | |||
| 7069 | |||
| 7070 | tx_queue_id = from_priority_to_tx_queue[priority] - 1; | ||
| 7071 | tfd->tx_flags_ext |= DCT_FLAG_EXT_QOS_ENABLED; | ||
| 7072 | |||
| 7073 | if (priv->qos_data.qos_no_ack_mask & (1UL << tx_queue_id)) { | ||
| 7074 | tfd->tx_flags &= ~DCT_FLAG_ACK_REQD; | ||
| 7075 | tfd->tfd.tfd_26.mchdr.qos_ctrl |= CTRL_QOS_NO_ACK; | ||
| 7076 | } | ||
| 7077 | return 0; | ||
| 6911 | } | 7078 | } |
| 6912 | 7079 | ||
| 6913 | /* | 7080 | /* |
| @@ -6977,7 +7144,7 @@ static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos | |||
| 6977 | qos_param); | 7144 | qos_param); |
| 6978 | } | 7145 | } |
| 6979 | 7146 | ||
| 6980 | #endif /* CONFIG_IPW_QOS */ | 7147 | #endif /* CONFIG_IPW2200_QOS */ |
| 6981 | 7148 | ||
| 6982 | static int ipw_associate_network(struct ipw_priv *priv, | 7149 | static int ipw_associate_network(struct ipw_priv *priv, |
| 6983 | struct ieee80211_network *network, | 7150 | struct ieee80211_network *network, |
| @@ -7116,7 +7283,7 @@ static int ipw_associate_network(struct ipw_priv *priv, | |||
| 7116 | else | 7283 | else |
| 7117 | priv->sys_config.answer_broadcast_ssid_probe = 0; | 7284 | priv->sys_config.answer_broadcast_ssid_probe = 0; |
| 7118 | 7285 | ||
| 7119 | err = ipw_send_system_config(priv, &priv->sys_config); | 7286 | err = ipw_send_system_config(priv); |
| 7120 | if (err) { | 7287 | if (err) { |
| 7121 | IPW_DEBUG_HC("Attempt to send sys config command failed.\n"); | 7288 | IPW_DEBUG_HC("Attempt to send sys config command failed.\n"); |
| 7122 | return err; | 7289 | return err; |
| @@ -7141,7 +7308,7 @@ static int ipw_associate_network(struct ipw_priv *priv, | |||
| 7141 | 7308 | ||
| 7142 | priv->assoc_network = network; | 7309 | priv->assoc_network = network; |
| 7143 | 7310 | ||
| 7144 | #ifdef CONFIG_IPW_QOS | 7311 | #ifdef CONFIG_IPW2200_QOS |
| 7145 | ipw_qos_association(priv, network); | 7312 | ipw_qos_association(priv, network); |
| 7146 | #endif | 7313 | #endif |
| 7147 | 7314 | ||
| @@ -7415,7 +7582,7 @@ static void ipw_handle_data_packet(struct ipw_priv *priv, | |||
| 7415 | } | 7582 | } |
| 7416 | } | 7583 | } |
| 7417 | 7584 | ||
| 7418 | #ifdef CONFIG_IEEE80211_RADIOTAP | 7585 | #ifdef CONFIG_IPW2200_RADIOTAP |
| 7419 | static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, | 7586 | static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, |
| 7420 | struct ipw_rx_mem_buffer *rxb, | 7587 | struct ipw_rx_mem_buffer *rxb, |
| 7421 | struct ieee80211_rx_stats *stats) | 7588 | struct ieee80211_rx_stats *stats) |
| @@ -7432,15 +7599,7 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, | |||
| 7432 | /* Magic struct that slots into the radiotap header -- no reason | 7599 | /* Magic struct that slots into the radiotap header -- no reason |
| 7433 | * to build this manually element by element, we can write it much | 7600 | * to build this manually element by element, we can write it much |
| 7434 | * more efficiently than we can parse it. ORDER MATTERS HERE */ | 7601 | * more efficiently than we can parse it. ORDER MATTERS HERE */ |
| 7435 | struct ipw_rt_hdr { | 7602 | struct ipw_rt_hdr *ipw_rt; |
| 7436 | struct ieee80211_radiotap_header rt_hdr; | ||
| 7437 | u8 rt_flags; /* radiotap packet flags */ | ||
| 7438 | u8 rt_rate; /* rate in 500kb/s */ | ||
| 7439 | u16 rt_channel; /* channel in mhz */ | ||
| 7440 | u16 rt_chbitmask; /* channel bitfield */ | ||
| 7441 | s8 rt_dbmsignal; /* signal in dbM, kluged to signed */ | ||
| 7442 | u8 rt_antenna; /* antenna number */ | ||
| 7443 | } *ipw_rt; | ||
| 7444 | 7603 | ||
| 7445 | short len = le16_to_cpu(pkt->u.frame.length); | 7604 | short len = le16_to_cpu(pkt->u.frame.length); |
| 7446 | 7605 | ||
| @@ -7494,9 +7653,11 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, | |||
| 7494 | /* Big bitfield of all the fields we provide in radiotap */ | 7653 | /* Big bitfield of all the fields we provide in radiotap */ |
| 7495 | ipw_rt->rt_hdr.it_present = | 7654 | ipw_rt->rt_hdr.it_present = |
| 7496 | ((1 << IEEE80211_RADIOTAP_FLAGS) | | 7655 | ((1 << IEEE80211_RADIOTAP_FLAGS) | |
| 7656 | (1 << IEEE80211_RADIOTAP_TSFT) | | ||
| 7497 | (1 << IEEE80211_RADIOTAP_RATE) | | 7657 | (1 << IEEE80211_RADIOTAP_RATE) | |
| 7498 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | 7658 | (1 << IEEE80211_RADIOTAP_CHANNEL) | |
| 7499 | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | | 7659 | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | |
| 7660 | (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | | ||
| 7500 | (1 << IEEE80211_RADIOTAP_ANTENNA)); | 7661 | (1 << IEEE80211_RADIOTAP_ANTENNA)); |
| 7501 | 7662 | ||
| 7502 | /* Zero the flags, we'll add to them as we go */ | 7663 | /* Zero the flags, we'll add to them as we go */ |
| @@ -7582,6 +7743,217 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, | |||
| 7582 | } | 7743 | } |
| 7583 | #endif | 7744 | #endif |
| 7584 | 7745 | ||
| 7746 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 7747 | #define ieee80211_is_probe_response(fc) \ | ||
| 7748 | ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT && \ | ||
| 7749 | (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP ) | ||
| 7750 | |||
| 7751 | #define ieee80211_is_management(fc) \ | ||
| 7752 | ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) | ||
| 7753 | |||
| 7754 | #define ieee80211_is_control(fc) \ | ||
| 7755 | ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) | ||
| 7756 | |||
| 7757 | #define ieee80211_is_data(fc) \ | ||
| 7758 | ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) | ||
| 7759 | |||
| 7760 | #define ieee80211_is_assoc_request(fc) \ | ||
| 7761 | ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ) | ||
| 7762 | |||
| 7763 | #define ieee80211_is_reassoc_request(fc) \ | ||
| 7764 | ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_REQ) | ||
| 7765 | |||
| 7766 | static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, | ||
| 7767 | struct ipw_rx_mem_buffer *rxb, | ||
| 7768 | struct ieee80211_rx_stats *stats) | ||
| 7769 | { | ||
| 7770 | struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data; | ||
| 7771 | struct ipw_rx_frame *frame = &pkt->u.frame; | ||
| 7772 | struct ipw_rt_hdr *ipw_rt; | ||
| 7773 | |||
| 7774 | /* First cache any information we need before we overwrite | ||
| 7775 | * the information provided in the skb from the hardware */ | ||
| 7776 | struct ieee80211_hdr *hdr; | ||
| 7777 | u16 channel = frame->received_channel; | ||
| 7778 | u8 phy_flags = frame->antennaAndPhy; | ||
| 7779 | s8 signal = frame->rssi_dbm - IPW_RSSI_TO_DBM; | ||
| 7780 | s8 noise = frame->noise; | ||
| 7781 | u8 rate = frame->rate; | ||
| 7782 | short len = le16_to_cpu(pkt->u.frame.length); | ||
| 7783 | u64 tsf = 0; | ||
| 7784 | struct sk_buff *skb; | ||
| 7785 | int hdr_only = 0; | ||
| 7786 | u16 filter = priv->prom_priv->filter; | ||
| 7787 | |||
| 7788 | /* If the filter is set to not include Rx frames then return */ | ||
| 7789 | if (filter & IPW_PROM_NO_RX) | ||
| 7790 | return; | ||
| 7791 | |||
| 7792 | /* We received data from the HW, so stop the watchdog */ | ||
| 7793 | priv->prom_net_dev->trans_start = jiffies; | ||
| 7794 | |||
| 7795 | if (unlikely((len + IPW_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) { | ||
| 7796 | priv->prom_priv->ieee->stats.rx_errors++; | ||
| 7797 | IPW_DEBUG_DROP("Corruption detected! Oh no!\n"); | ||
| 7798 | return; | ||
| 7799 | } | ||
| 7800 | |||
| 7801 | /* We only process data packets if the interface is open */ | ||
| 7802 | if (unlikely(!netif_running(priv->prom_net_dev))) { | ||
| 7803 | priv->prom_priv->ieee->stats.rx_dropped++; | ||
| 7804 | IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); | ||
| 7805 | return; | ||
| 7806 | } | ||
| 7807 | |||
| 7808 | /* Libpcap 0.9.3+ can handle variable length radiotap, so we'll use | ||
| 7809 | * that now */ | ||
| 7810 | if (len > IPW_RX_BUF_SIZE - sizeof(struct ipw_rt_hdr)) { | ||
| 7811 | /* FIXME: Should alloc bigger skb instead */ | ||
| 7812 | priv->prom_priv->ieee->stats.rx_dropped++; | ||
| 7813 | IPW_DEBUG_DROP("Dropping too large packet in monitor\n"); | ||
| 7814 | return; | ||
| 7815 | } | ||
| 7816 | |||
| 7817 | hdr = (void *)rxb->skb->data + IPW_RX_FRAME_SIZE; | ||
| 7818 | if (ieee80211_is_management(hdr->frame_ctl)) { | ||
| 7819 | if (filter & IPW_PROM_NO_MGMT) | ||
| 7820 | return; | ||
| 7821 | if (filter & IPW_PROM_MGMT_HEADER_ONLY) | ||
| 7822 | hdr_only = 1; | ||
| 7823 | } else if (ieee80211_is_control(hdr->frame_ctl)) { | ||
| 7824 | if (filter & IPW_PROM_NO_CTL) | ||
| 7825 | return; | ||
| 7826 | if (filter & IPW_PROM_CTL_HEADER_ONLY) | ||
| 7827 | hdr_only = 1; | ||
| 7828 | } else if (ieee80211_is_data(hdr->frame_ctl)) { | ||
| 7829 | if (filter & IPW_PROM_NO_DATA) | ||
| 7830 | return; | ||
| 7831 | if (filter & IPW_PROM_DATA_HEADER_ONLY) | ||
| 7832 | hdr_only = 1; | ||
| 7833 | } | ||
| 7834 | |||
| 7835 | /* Copy the SKB since this is for the promiscuous side */ | ||
| 7836 | skb = skb_copy(rxb->skb, GFP_ATOMIC); | ||
| 7837 | if (skb == NULL) { | ||
| 7838 | IPW_ERROR("skb_clone failed for promiscuous copy.\n"); | ||
| 7839 | return; | ||
| 7840 | } | ||
| 7841 | |||
| 7842 | /* copy the frame data to write after where the radiotap header goes */ | ||
| 7843 | ipw_rt = (void *)skb->data; | ||
| 7844 | |||
| 7845 | if (hdr_only) | ||
| 7846 | len = ieee80211_get_hdrlen(hdr->frame_ctl); | ||
| 7847 | |||
| 7848 | memcpy(ipw_rt->payload, hdr, len); | ||
| 7849 | |||
| 7850 | /* Zero the radiotap static buffer ... We only need to zero the bytes | ||
| 7851 | * NOT part of our real header, saves a little time. | ||
| 7852 | * | ||
| 7853 | * No longer necessary since we fill in all our data. Purge before | ||
| 7854 | * merging patch officially. | ||
| 7855 | * memset(rxb->skb->data + sizeof(struct ipw_rt_hdr), 0, | ||
| 7856 | * IEEE80211_RADIOTAP_HDRLEN - sizeof(struct ipw_rt_hdr)); | ||
| 7857 | */ | ||
| 7858 | |||
| 7859 | ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; | ||
| 7860 | ipw_rt->rt_hdr.it_pad = 0; /* always good to zero */ | ||
| 7861 | ipw_rt->rt_hdr.it_len = sizeof(*ipw_rt); /* total header+data */ | ||
| 7862 | |||
| 7863 | /* Set the size of the skb to the size of the frame */ | ||
| 7864 | skb_put(skb, ipw_rt->rt_hdr.it_len + len); | ||
| 7865 | |||
| 7866 | /* Big bitfield of all the fields we provide in radiotap */ | ||
| 7867 | ipw_rt->rt_hdr.it_present = | ||
| 7868 | ((1 << IEEE80211_RADIOTAP_FLAGS) | | ||
| 7869 | (1 << IEEE80211_RADIOTAP_TSFT) | | ||
| 7870 | (1 << IEEE80211_RADIOTAP_RATE) | | ||
| 7871 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | ||
| 7872 | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | | ||
| 7873 | (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | | ||
| 7874 | (1 << IEEE80211_RADIOTAP_ANTENNA)); | ||
| 7875 | |||
| 7876 | /* Zero the flags, we'll add to them as we go */ | ||
| 7877 | ipw_rt->rt_flags = 0; | ||
| 7878 | |||
| 7879 | ipw_rt->rt_tsf = tsf; | ||
| 7880 | |||
| 7881 | /* Convert to DBM */ | ||
| 7882 | ipw_rt->rt_dbmsignal = signal; | ||
| 7883 | ipw_rt->rt_dbmnoise = noise; | ||
| 7884 | |||
| 7885 | /* Convert the channel data and set the flags */ | ||
| 7886 | ipw_rt->rt_channel = cpu_to_le16(ieee80211chan2mhz(channel)); | ||
| 7887 | if (channel > 14) { /* 802.11a */ | ||
| 7888 | ipw_rt->rt_chbitmask = | ||
| 7889 | cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ)); | ||
| 7890 | } else if (phy_flags & (1 << 5)) { /* 802.11b */ | ||
| 7891 | ipw_rt->rt_chbitmask = | ||
| 7892 | cpu_to_le16((IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ)); | ||
| 7893 | } else { /* 802.11g */ | ||
| 7894 | ipw_rt->rt_chbitmask = | ||
| 7895 | (IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ); | ||
| 7896 | } | ||
| 7897 | |||
| 7898 | /* set the rate in multiples of 500k/s */ | ||
| 7899 | switch (rate) { | ||
| 7900 | case IPW_TX_RATE_1MB: | ||
| 7901 | ipw_rt->rt_rate = 2; | ||
| 7902 | break; | ||
| 7903 | case IPW_TX_RATE_2MB: | ||
| 7904 | ipw_rt->rt_rate = 4; | ||
| 7905 | break; | ||
| 7906 | case IPW_TX_RATE_5MB: | ||
| 7907 | ipw_rt->rt_rate = 10; | ||
| 7908 | break; | ||
| 7909 | case IPW_TX_RATE_6MB: | ||
| 7910 | ipw_rt->rt_rate = 12; | ||
| 7911 | break; | ||
| 7912 | case IPW_TX_RATE_9MB: | ||
| 7913 | ipw_rt->rt_rate = 18; | ||
| 7914 | break; | ||
| 7915 | case IPW_TX_RATE_11MB: | ||
| 7916 | ipw_rt->rt_rate = 22; | ||
| 7917 | break; | ||
| 7918 | case IPW_TX_RATE_12MB: | ||
| 7919 | ipw_rt->rt_rate = 24; | ||
| 7920 | break; | ||
| 7921 | case IPW_TX_RATE_18MB: | ||
| 7922 | ipw_rt->rt_rate = 36; | ||
| 7923 | break; | ||
| 7924 | case IPW_TX_RATE_24MB: | ||
| 7925 | ipw_rt->rt_rate = 48; | ||
| 7926 | break; | ||
| 7927 | case IPW_TX_RATE_36MB: | ||
| 7928 | ipw_rt->rt_rate = 72; | ||
| 7929 | break; | ||
| 7930 | case IPW_TX_RATE_48MB: | ||
| 7931 | ipw_rt->rt_rate = 96; | ||
| 7932 | break; | ||
| 7933 | case IPW_TX_RATE_54MB: | ||
| 7934 | ipw_rt->rt_rate = 108; | ||
| 7935 | break; | ||
| 7936 | default: | ||
| 7937 | ipw_rt->rt_rate = 0; | ||
| 7938 | break; | ||
| 7939 | } | ||
| 7940 | |||
| 7941 | /* antenna number */ | ||
| 7942 | ipw_rt->rt_antenna = (phy_flags & 3); | ||
| 7943 | |||
| 7944 | /* set the preamble flag if we have it */ | ||
| 7945 | if (phy_flags & (1 << 6)) | ||
| 7946 | ipw_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; | ||
| 7947 | |||
| 7948 | IPW_DEBUG_RX("Rx packet of %d bytes.\n", skb->len); | ||
| 7949 | |||
| 7950 | if (!ieee80211_rx(priv->prom_priv->ieee, skb, stats)) { | ||
| 7951 | priv->prom_priv->ieee->stats.rx_errors++; | ||
| 7952 | dev_kfree_skb_any(skb); | ||
| 7953 | } | ||
| 7954 | } | ||
| 7955 | #endif | ||
| 7956 | |||
| 7585 | static int is_network_packet(struct ipw_priv *priv, | 7957 | static int is_network_packet(struct ipw_priv *priv, |
| 7586 | struct ieee80211_hdr_4addr *header) | 7958 | struct ieee80211_hdr_4addr *header) |
| 7587 | { | 7959 | { |
| @@ -7808,15 +8180,21 @@ static void ipw_rx(struct ipw_priv *priv) | |||
| 7808 | 8180 | ||
| 7809 | priv->rx_packets++; | 8181 | priv->rx_packets++; |
| 7810 | 8182 | ||
| 8183 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 8184 | if (priv->prom_net_dev && netif_running(priv->prom_net_dev)) | ||
| 8185 | ipw_handle_promiscuous_rx(priv, rxb, &stats); | ||
| 8186 | #endif | ||
| 8187 | |||
| 7811 | #ifdef CONFIG_IPW2200_MONITOR | 8188 | #ifdef CONFIG_IPW2200_MONITOR |
| 7812 | if (priv->ieee->iw_mode == IW_MODE_MONITOR) { | 8189 | if (priv->ieee->iw_mode == IW_MODE_MONITOR) { |
| 7813 | #ifdef CONFIG_IEEE80211_RADIOTAP | 8190 | #ifdef CONFIG_IPW2200_RADIOTAP |
| 7814 | ipw_handle_data_packet_monitor(priv, | 8191 | |
| 7815 | rxb, | 8192 | ipw_handle_data_packet_monitor(priv, |
| 7816 | &stats); | 8193 | rxb, |
| 8194 | &stats); | ||
| 7817 | #else | 8195 | #else |
| 7818 | ipw_handle_data_packet(priv, rxb, | 8196 | ipw_handle_data_packet(priv, rxb, |
| 7819 | &stats); | 8197 | &stats); |
| 7820 | #endif | 8198 | #endif |
| 7821 | break; | 8199 | break; |
| 7822 | } | 8200 | } |
| @@ -7837,9 +8215,9 @@ static void ipw_rx(struct ipw_priv *priv) | |||
| 7837 | if (network_packet && priv->assoc_network) { | 8215 | if (network_packet && priv->assoc_network) { |
| 7838 | priv->assoc_network->stats.rssi = | 8216 | priv->assoc_network->stats.rssi = |
| 7839 | stats.rssi; | 8217 | stats.rssi; |
| 7840 | average_add(&priv->average_rssi, | 8218 | priv->exp_avg_rssi = |
| 7841 | stats.rssi); | 8219 | exponential_average(priv->exp_avg_rssi, |
| 7842 | priv->last_rx_rssi = stats.rssi; | 8220 | stats.rssi, DEPTH_RSSI); |
| 7843 | } | 8221 | } |
| 7844 | 8222 | ||
| 7845 | IPW_DEBUG_RX("Frame: len=%u\n", | 8223 | IPW_DEBUG_RX("Frame: len=%u\n", |
| @@ -7982,10 +8360,10 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option) | |||
| 7982 | IPW_DEBUG_INFO("Bind to static channel %d\n", channel); | 8360 | IPW_DEBUG_INFO("Bind to static channel %d\n", channel); |
| 7983 | /* TODO: Validate that provided channel is in range */ | 8361 | /* TODO: Validate that provided channel is in range */ |
| 7984 | } | 8362 | } |
| 7985 | #ifdef CONFIG_IPW_QOS | 8363 | #ifdef CONFIG_IPW2200_QOS |
| 7986 | ipw_qos_init(priv, qos_enable, qos_burst_enable, | 8364 | ipw_qos_init(priv, qos_enable, qos_burst_enable, |
| 7987 | burst_duration_CCK, burst_duration_OFDM); | 8365 | burst_duration_CCK, burst_duration_OFDM); |
| 7988 | #endif /* CONFIG_IPW_QOS */ | 8366 | #endif /* CONFIG_IPW2200_QOS */ |
| 7989 | 8367 | ||
| 7990 | switch (mode) { | 8368 | switch (mode) { |
| 7991 | case 1: | 8369 | case 1: |
| @@ -7996,7 +8374,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option) | |||
| 7996 | #ifdef CONFIG_IPW2200_MONITOR | 8374 | #ifdef CONFIG_IPW2200_MONITOR |
| 7997 | case 2: | 8375 | case 2: |
| 7998 | priv->ieee->iw_mode = IW_MODE_MONITOR; | 8376 | priv->ieee->iw_mode = IW_MODE_MONITOR; |
| 7999 | #ifdef CONFIG_IEEE80211_RADIOTAP | 8377 | #ifdef CONFIG_IPW2200_RADIOTAP |
| 8000 | priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP; | 8378 | priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP; |
| 8001 | #else | 8379 | #else |
| 8002 | priv->net_dev->type = ARPHRD_IEEE80211; | 8380 | priv->net_dev->type = ARPHRD_IEEE80211; |
| @@ -8251,7 +8629,7 @@ static int ipw_wx_set_mode(struct net_device *dev, | |||
| 8251 | priv->net_dev->type = ARPHRD_ETHER; | 8629 | priv->net_dev->type = ARPHRD_ETHER; |
| 8252 | 8630 | ||
| 8253 | if (wrqu->mode == IW_MODE_MONITOR) | 8631 | if (wrqu->mode == IW_MODE_MONITOR) |
| 8254 | #ifdef CONFIG_IEEE80211_RADIOTAP | 8632 | #ifdef CONFIG_IPW2200_RADIOTAP |
| 8255 | priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP; | 8633 | priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP; |
| 8256 | #else | 8634 | #else |
| 8257 | priv->net_dev->type = ARPHRD_IEEE80211; | 8635 | priv->net_dev->type = ARPHRD_IEEE80211; |
| @@ -8379,7 +8757,8 @@ static int ipw_wx_get_range(struct net_device *dev, | |||
| 8379 | /* Event capability (kernel + driver) */ | 8757 | /* Event capability (kernel + driver) */ |
| 8380 | range->event_capa[0] = (IW_EVENT_CAPA_K_0 | | 8758 | range->event_capa[0] = (IW_EVENT_CAPA_K_0 | |
| 8381 | IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) | | 8759 | IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) | |
| 8382 | IW_EVENT_CAPA_MASK(SIOCGIWAP)); | 8760 | IW_EVENT_CAPA_MASK(SIOCGIWAP) | |
| 8761 | IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); | ||
| 8383 | range->event_capa[1] = IW_EVENT_CAPA_K_1; | 8762 | range->event_capa[1] = IW_EVENT_CAPA_K_1; |
| 8384 | 8763 | ||
| 8385 | range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | | 8764 | range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | |
| @@ -8734,6 +9113,7 @@ static int ipw_wx_get_rate(struct net_device *dev, | |||
| 8734 | struct ipw_priv *priv = ieee80211_priv(dev); | 9113 | struct ipw_priv *priv = ieee80211_priv(dev); |
| 8735 | mutex_lock(&priv->mutex); | 9114 | mutex_lock(&priv->mutex); |
| 8736 | wrqu->bitrate.value = priv->last_rate; | 9115 | wrqu->bitrate.value = priv->last_rate; |
| 9116 | wrqu->bitrate.fixed = (priv->config & CFG_FIXED_RATE) ? 1 : 0; | ||
| 8737 | mutex_unlock(&priv->mutex); | 9117 | mutex_unlock(&priv->mutex); |
| 8738 | IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value); | 9118 | IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value); |
| 8739 | return 0; | 9119 | return 0; |
| @@ -9351,7 +9731,7 @@ static int ipw_wx_set_monitor(struct net_device *dev, | |||
| 9351 | IPW_DEBUG_WX("SET MONITOR: %d %d\n", enable, parms[1]); | 9731 | IPW_DEBUG_WX("SET MONITOR: %d %d\n", enable, parms[1]); |
| 9352 | if (enable) { | 9732 | if (enable) { |
| 9353 | if (priv->ieee->iw_mode != IW_MODE_MONITOR) { | 9733 | if (priv->ieee->iw_mode != IW_MODE_MONITOR) { |
| 9354 | #ifdef CONFIG_IEEE80211_RADIOTAP | 9734 | #ifdef CONFIG_IPW2200_RADIOTAP |
| 9355 | priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP; | 9735 | priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP; |
| 9356 | #else | 9736 | #else |
| 9357 | priv->net_dev->type = ARPHRD_IEEE80211; | 9737 | priv->net_dev->type = ARPHRD_IEEE80211; |
| @@ -9579,8 +9959,8 @@ static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev) | |||
| 9579 | } | 9959 | } |
| 9580 | 9960 | ||
| 9581 | wstats->qual.qual = priv->quality; | 9961 | wstats->qual.qual = priv->quality; |
| 9582 | wstats->qual.level = average_value(&priv->average_rssi); | 9962 | wstats->qual.level = priv->exp_avg_rssi; |
| 9583 | wstats->qual.noise = average_value(&priv->average_noise); | 9963 | wstats->qual.noise = priv->exp_avg_noise; |
| 9584 | wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | | 9964 | wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | |
| 9585 | IW_QUAL_NOISE_UPDATED | IW_QUAL_DBM; | 9965 | IW_QUAL_NOISE_UPDATED | IW_QUAL_DBM; |
| 9586 | 9966 | ||
| @@ -9608,7 +9988,9 @@ static void init_sys_config(struct ipw_sys_config *sys_config) | |||
| 9608 | sys_config->disable_unicast_decryption = 1; | 9988 | sys_config->disable_unicast_decryption = 1; |
| 9609 | sys_config->exclude_multicast_unencrypted = 0; | 9989 | sys_config->exclude_multicast_unencrypted = 0; |
| 9610 | sys_config->disable_multicast_decryption = 1; | 9990 | sys_config->disable_multicast_decryption = 1; |
| 9611 | sys_config->antenna_diversity = CFG_SYS_ANTENNA_SLOW_DIV; | 9991 | if (antenna < CFG_SYS_ANTENNA_BOTH || antenna > CFG_SYS_ANTENNA_B) |
| 9992 | antenna = CFG_SYS_ANTENNA_BOTH; | ||
| 9993 | sys_config->antenna_diversity = antenna; | ||
| 9612 | sys_config->pass_crc_to_host = 0; /* TODO: See if 1 gives us FCS */ | 9994 | sys_config->pass_crc_to_host = 0; /* TODO: See if 1 gives us FCS */ |
| 9613 | sys_config->dot11g_auto_detection = 0; | 9995 | sys_config->dot11g_auto_detection = 0; |
| 9614 | sys_config->enable_cts_to_self = 0; | 9996 | sys_config->enable_cts_to_self = 0; |
| @@ -9647,11 +10029,11 @@ we need to heavily modify the ieee80211_skb_to_txb. | |||
| 9647 | static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, | 10029 | static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, |
| 9648 | int pri) | 10030 | int pri) |
| 9649 | { | 10031 | { |
| 9650 | struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *) | 10032 | struct ieee80211_hdr_3addrqos *hdr = (struct ieee80211_hdr_3addrqos *) |
| 9651 | txb->fragments[0]->data; | 10033 | txb->fragments[0]->data; |
| 9652 | int i = 0; | 10034 | int i = 0; |
| 9653 | struct tfd_frame *tfd; | 10035 | struct tfd_frame *tfd; |
| 9654 | #ifdef CONFIG_IPW_QOS | 10036 | #ifdef CONFIG_IPW2200_QOS |
| 9655 | int tx_id = ipw_get_tx_queue_number(priv, pri); | 10037 | int tx_id = ipw_get_tx_queue_number(priv, pri); |
| 9656 | struct clx2_tx_queue *txq = &priv->txq[tx_id]; | 10038 | struct clx2_tx_queue *txq = &priv->txq[tx_id]; |
| 9657 | #else | 10039 | #else |
| @@ -9662,9 +10044,9 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, | |||
| 9662 | u16 remaining_bytes; | 10044 | u16 remaining_bytes; |
| 9663 | int fc; | 10045 | int fc; |
| 9664 | 10046 | ||
| 10047 | hdr_len = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); | ||
| 9665 | switch (priv->ieee->iw_mode) { | 10048 | switch (priv->ieee->iw_mode) { |
| 9666 | case IW_MODE_ADHOC: | 10049 | case IW_MODE_ADHOC: |
| 9667 | hdr_len = IEEE80211_3ADDR_LEN; | ||
| 9668 | unicast = !is_multicast_ether_addr(hdr->addr1); | 10050 | unicast = !is_multicast_ether_addr(hdr->addr1); |
| 9669 | id = ipw_find_station(priv, hdr->addr1); | 10051 | id = ipw_find_station(priv, hdr->addr1); |
| 9670 | if (id == IPW_INVALID_STATION) { | 10052 | if (id == IPW_INVALID_STATION) { |
| @@ -9681,7 +10063,6 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, | |||
| 9681 | case IW_MODE_INFRA: | 10063 | case IW_MODE_INFRA: |
| 9682 | default: | 10064 | default: |
| 9683 | unicast = !is_multicast_ether_addr(hdr->addr3); | 10065 | unicast = !is_multicast_ether_addr(hdr->addr3); |
| 9684 | hdr_len = IEEE80211_3ADDR_LEN; | ||
| 9685 | id = 0; | 10066 | id = 0; |
| 9686 | break; | 10067 | break; |
| 9687 | } | 10068 | } |
| @@ -9759,9 +10140,10 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, | |||
| 9759 | /* No hardware encryption */ | 10140 | /* No hardware encryption */ |
| 9760 | tfd->u.data.tx_flags |= DCT_FLAG_NO_WEP; | 10141 | tfd->u.data.tx_flags |= DCT_FLAG_NO_WEP; |
| 9761 | 10142 | ||
| 9762 | #ifdef CONFIG_IPW_QOS | 10143 | #ifdef CONFIG_IPW2200_QOS |
| 9763 | ipw_qos_set_tx_queue_command(priv, pri, &(tfd->u.data), unicast); | 10144 | if (fc & IEEE80211_STYPE_QOS_DATA) |
| 9764 | #endif /* CONFIG_IPW_QOS */ | 10145 | ipw_qos_set_tx_queue_command(priv, pri, &(tfd->u.data)); |
| 10146 | #endif /* CONFIG_IPW2200_QOS */ | ||
| 9765 | 10147 | ||
| 9766 | /* payload */ | 10148 | /* payload */ |
| 9767 | tfd->u.data.num_chunks = cpu_to_le32(min((u8) (NUM_TFD_CHUNKS - 2), | 10149 | tfd->u.data.num_chunks = cpu_to_le32(min((u8) (NUM_TFD_CHUNKS - 2), |
| @@ -9841,12 +10223,12 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, | |||
| 9841 | static int ipw_net_is_queue_full(struct net_device *dev, int pri) | 10223 | static int ipw_net_is_queue_full(struct net_device *dev, int pri) |
| 9842 | { | 10224 | { |
| 9843 | struct ipw_priv *priv = ieee80211_priv(dev); | 10225 | struct ipw_priv *priv = ieee80211_priv(dev); |
| 9844 | #ifdef CONFIG_IPW_QOS | 10226 | #ifdef CONFIG_IPW2200_QOS |
| 9845 | int tx_id = ipw_get_tx_queue_number(priv, pri); | 10227 | int tx_id = ipw_get_tx_queue_number(priv, pri); |
| 9846 | struct clx2_tx_queue *txq = &priv->txq[tx_id]; | 10228 | struct clx2_tx_queue *txq = &priv->txq[tx_id]; |
| 9847 | #else | 10229 | #else |
| 9848 | struct clx2_tx_queue *txq = &priv->txq[0]; | 10230 | struct clx2_tx_queue *txq = &priv->txq[0]; |
| 9849 | #endif /* CONFIG_IPW_QOS */ | 10231 | #endif /* CONFIG_IPW2200_QOS */ |
| 9850 | 10232 | ||
| 9851 | if (ipw_queue_space(&txq->q) < txq->q.high_mark) | 10233 | if (ipw_queue_space(&txq->q) < txq->q.high_mark) |
| 9852 | return 1; | 10234 | return 1; |
| @@ -9854,6 +10236,88 @@ static int ipw_net_is_queue_full(struct net_device *dev, int pri) | |||
| 9854 | return 0; | 10236 | return 0; |
| 9855 | } | 10237 | } |
| 9856 | 10238 | ||
| 10239 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 10240 | static void ipw_handle_promiscuous_tx(struct ipw_priv *priv, | ||
| 10241 | struct ieee80211_txb *txb) | ||
| 10242 | { | ||
| 10243 | struct ieee80211_rx_stats dummystats; | ||
| 10244 | struct ieee80211_hdr *hdr; | ||
| 10245 | u8 n; | ||
| 10246 | u16 filter = priv->prom_priv->filter; | ||
| 10247 | int hdr_only = 0; | ||
| 10248 | |||
| 10249 | if (filter & IPW_PROM_NO_TX) | ||
| 10250 | return; | ||
| 10251 | |||
| 10252 | memset(&dummystats, 0, sizeof(dummystats)); | ||
| 10253 | |||
| 10254 | /* Filtering of fragment chains is done agains the first fragment */ | ||
| 10255 | hdr = (void *)txb->fragments[0]->data; | ||
| 10256 | if (ieee80211_is_management(hdr->frame_ctl)) { | ||
| 10257 | if (filter & IPW_PROM_NO_MGMT) | ||
| 10258 | return; | ||
| 10259 | if (filter & IPW_PROM_MGMT_HEADER_ONLY) | ||
| 10260 | hdr_only = 1; | ||
| 10261 | } else if (ieee80211_is_control(hdr->frame_ctl)) { | ||
| 10262 | if (filter & IPW_PROM_NO_CTL) | ||
| 10263 | return; | ||
| 10264 | if (filter & IPW_PROM_CTL_HEADER_ONLY) | ||
| 10265 | hdr_only = 1; | ||
| 10266 | } else if (ieee80211_is_data(hdr->frame_ctl)) { | ||
| 10267 | if (filter & IPW_PROM_NO_DATA) | ||
| 10268 | return; | ||
| 10269 | if (filter & IPW_PROM_DATA_HEADER_ONLY) | ||
| 10270 | hdr_only = 1; | ||
| 10271 | } | ||
| 10272 | |||
| 10273 | for(n=0; n<txb->nr_frags; ++n) { | ||
| 10274 | struct sk_buff *src = txb->fragments[n]; | ||
| 10275 | struct sk_buff *dst; | ||
| 10276 | struct ieee80211_radiotap_header *rt_hdr; | ||
| 10277 | int len; | ||
| 10278 | |||
| 10279 | if (hdr_only) { | ||
| 10280 | hdr = (void *)src->data; | ||
| 10281 | len = ieee80211_get_hdrlen(hdr->frame_ctl); | ||
| 10282 | } else | ||
| 10283 | len = src->len; | ||
| 10284 | |||
| 10285 | dst = alloc_skb( | ||
| 10286 | len + IEEE80211_RADIOTAP_HDRLEN, GFP_ATOMIC); | ||
| 10287 | if (!dst) continue; | ||
| 10288 | |||
| 10289 | rt_hdr = (void *)skb_put(dst, sizeof(*rt_hdr)); | ||
| 10290 | |||
| 10291 | rt_hdr->it_version = PKTHDR_RADIOTAP_VERSION; | ||
| 10292 | rt_hdr->it_pad = 0; | ||
| 10293 | rt_hdr->it_present = 0; /* after all, it's just an idea */ | ||
| 10294 | rt_hdr->it_present |= (1 << IEEE80211_RADIOTAP_CHANNEL); | ||
| 10295 | |||
| 10296 | *(u16*)skb_put(dst, sizeof(u16)) = cpu_to_le16( | ||
| 10297 | ieee80211chan2mhz(priv->channel)); | ||
| 10298 | if (priv->channel > 14) /* 802.11a */ | ||
| 10299 | *(u16*)skb_put(dst, sizeof(u16)) = | ||
| 10300 | cpu_to_le16(IEEE80211_CHAN_OFDM | | ||
| 10301 | IEEE80211_CHAN_5GHZ); | ||
| 10302 | else if (priv->ieee->mode == IEEE_B) /* 802.11b */ | ||
| 10303 | *(u16*)skb_put(dst, sizeof(u16)) = | ||
| 10304 | cpu_to_le16(IEEE80211_CHAN_CCK | | ||
| 10305 | IEEE80211_CHAN_2GHZ); | ||
| 10306 | else /* 802.11g */ | ||
| 10307 | *(u16*)skb_put(dst, sizeof(u16)) = | ||
| 10308 | cpu_to_le16(IEEE80211_CHAN_OFDM | | ||
| 10309 | IEEE80211_CHAN_2GHZ); | ||
| 10310 | |||
| 10311 | rt_hdr->it_len = dst->len; | ||
| 10312 | |||
| 10313 | memcpy(skb_put(dst, len), src->data, len); | ||
| 10314 | |||
| 10315 | if (!ieee80211_rx(priv->prom_priv->ieee, dst, &dummystats)) | ||
| 10316 | dev_kfree_skb_any(dst); | ||
| 10317 | } | ||
| 10318 | } | ||
| 10319 | #endif | ||
| 10320 | |||
| 9857 | static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb, | 10321 | static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb, |
| 9858 | struct net_device *dev, int pri) | 10322 | struct net_device *dev, int pri) |
| 9859 | { | 10323 | { |
| @@ -9871,6 +10335,11 @@ static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb, | |||
| 9871 | goto fail_unlock; | 10335 | goto fail_unlock; |
| 9872 | } | 10336 | } |
| 9873 | 10337 | ||
| 10338 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 10339 | if (rtap_iface && netif_running(priv->prom_net_dev)) | ||
| 10340 | ipw_handle_promiscuous_tx(priv, txb); | ||
| 10341 | #endif | ||
| 10342 | |||
| 9874 | ret = ipw_tx_skb(priv, txb, pri); | 10343 | ret = ipw_tx_skb(priv, txb, pri); |
| 9875 | if (ret == NETDEV_TX_OK) | 10344 | if (ret == NETDEV_TX_OK) |
| 9876 | __ipw_led_activity_on(priv); | 10345 | __ipw_led_activity_on(priv); |
| @@ -10169,10 +10638,10 @@ static int ipw_setup_deferred_work(struct ipw_priv *priv) | |||
| 10169 | INIT_WORK(&priv->merge_networks, | 10638 | INIT_WORK(&priv->merge_networks, |
| 10170 | (void (*)(void *))ipw_merge_adhoc_network, priv); | 10639 | (void (*)(void *))ipw_merge_adhoc_network, priv); |
| 10171 | 10640 | ||
| 10172 | #ifdef CONFIG_IPW_QOS | 10641 | #ifdef CONFIG_IPW2200_QOS |
| 10173 | INIT_WORK(&priv->qos_activate, (void (*)(void *))ipw_bg_qos_activate, | 10642 | INIT_WORK(&priv->qos_activate, (void (*)(void *))ipw_bg_qos_activate, |
| 10174 | priv); | 10643 | priv); |
| 10175 | #endif /* CONFIG_IPW_QOS */ | 10644 | #endif /* CONFIG_IPW2200_QOS */ |
| 10176 | 10645 | ||
| 10177 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) | 10646 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) |
| 10178 | ipw_irq_tasklet, (unsigned long)priv); | 10647 | ipw_irq_tasklet, (unsigned long)priv); |
| @@ -10318,12 +10787,21 @@ static int ipw_config(struct ipw_priv *priv) | |||
| 10318 | |= CFG_BT_COEXISTENCE_OOB; | 10787 | |= CFG_BT_COEXISTENCE_OOB; |
| 10319 | } | 10788 | } |
| 10320 | 10789 | ||
| 10790 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 10791 | if (priv->prom_net_dev && netif_running(priv->prom_net_dev)) { | ||
| 10792 | priv->sys_config.accept_all_data_frames = 1; | ||
| 10793 | priv->sys_config.accept_non_directed_frames = 1; | ||
| 10794 | priv->sys_config.accept_all_mgmt_bcpr = 1; | ||
| 10795 | priv->sys_config.accept_all_mgmt_frames = 1; | ||
| 10796 | } | ||
| 10797 | #endif | ||
| 10798 | |||
| 10321 | if (priv->ieee->iw_mode == IW_MODE_ADHOC) | 10799 | if (priv->ieee->iw_mode == IW_MODE_ADHOC) |
| 10322 | priv->sys_config.answer_broadcast_ssid_probe = 1; | 10800 | priv->sys_config.answer_broadcast_ssid_probe = 1; |
| 10323 | else | 10801 | else |
| 10324 | priv->sys_config.answer_broadcast_ssid_probe = 0; | 10802 | priv->sys_config.answer_broadcast_ssid_probe = 0; |
| 10325 | 10803 | ||
| 10326 | if (ipw_send_system_config(priv, &priv->sys_config)) | 10804 | if (ipw_send_system_config(priv)) |
| 10327 | goto error; | 10805 | goto error; |
| 10328 | 10806 | ||
| 10329 | init_supported_rates(priv, &priv->rates); | 10807 | init_supported_rates(priv, &priv->rates); |
| @@ -10335,10 +10813,10 @@ static int ipw_config(struct ipw_priv *priv) | |||
| 10335 | if (ipw_send_rts_threshold(priv, priv->rts_threshold)) | 10813 | if (ipw_send_rts_threshold(priv, priv->rts_threshold)) |
| 10336 | goto error; | 10814 | goto error; |
| 10337 | } | 10815 | } |
| 10338 | #ifdef CONFIG_IPW_QOS | 10816 | #ifdef CONFIG_IPW2200_QOS |
| 10339 | IPW_DEBUG_QOS("QoS: call ipw_qos_activate\n"); | 10817 | IPW_DEBUG_QOS("QoS: call ipw_qos_activate\n"); |
| 10340 | ipw_qos_activate(priv, NULL); | 10818 | ipw_qos_activate(priv, NULL); |
| 10341 | #endif /* CONFIG_IPW_QOS */ | 10819 | #endif /* CONFIG_IPW2200_QOS */ |
| 10342 | 10820 | ||
| 10343 | if (ipw_set_random_seed(priv)) | 10821 | if (ipw_set_random_seed(priv)) |
| 10344 | goto error; | 10822 | goto error; |
| @@ -10639,6 +11117,7 @@ static int ipw_up(struct ipw_priv *priv) | |||
| 10639 | if (priv->cmdlog == NULL) { | 11117 | if (priv->cmdlog == NULL) { |
| 10640 | IPW_ERROR("Error allocating %d command log entries.\n", | 11118 | IPW_ERROR("Error allocating %d command log entries.\n", |
| 10641 | cmdlog); | 11119 | cmdlog); |
| 11120 | return -ENOMEM; | ||
| 10642 | } else { | 11121 | } else { |
| 10643 | memset(priv->cmdlog, 0, sizeof(*priv->cmdlog) * cmdlog); | 11122 | memset(priv->cmdlog, 0, sizeof(*priv->cmdlog) * cmdlog); |
| 10644 | priv->cmdlog_len = cmdlog; | 11123 | priv->cmdlog_len = cmdlog; |
| @@ -10860,6 +11339,10 @@ static struct attribute *ipw_sysfs_entries[] = { | |||
| 10860 | &dev_attr_led.attr, | 11339 | &dev_attr_led.attr, |
| 10861 | &dev_attr_speed_scan.attr, | 11340 | &dev_attr_speed_scan.attr, |
| 10862 | &dev_attr_net_stats.attr, | 11341 | &dev_attr_net_stats.attr, |
| 11342 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 11343 | &dev_attr_rtap_iface.attr, | ||
| 11344 | &dev_attr_rtap_filter.attr, | ||
| 11345 | #endif | ||
| 10863 | NULL | 11346 | NULL |
| 10864 | }; | 11347 | }; |
| 10865 | 11348 | ||
| @@ -10868,6 +11351,109 @@ static struct attribute_group ipw_attribute_group = { | |||
| 10868 | .attrs = ipw_sysfs_entries, | 11351 | .attrs = ipw_sysfs_entries, |
| 10869 | }; | 11352 | }; |
| 10870 | 11353 | ||
| 11354 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 11355 | static int ipw_prom_open(struct net_device *dev) | ||
| 11356 | { | ||
| 11357 | struct ipw_prom_priv *prom_priv = ieee80211_priv(dev); | ||
| 11358 | struct ipw_priv *priv = prom_priv->priv; | ||
| 11359 | |||
| 11360 | IPW_DEBUG_INFO("prom dev->open\n"); | ||
| 11361 | netif_carrier_off(dev); | ||
| 11362 | netif_stop_queue(dev); | ||
| 11363 | |||
| 11364 | if (priv->ieee->iw_mode != IW_MODE_MONITOR) { | ||
| 11365 | priv->sys_config.accept_all_data_frames = 1; | ||
| 11366 | priv->sys_config.accept_non_directed_frames = 1; | ||
| 11367 | priv->sys_config.accept_all_mgmt_bcpr = 1; | ||
| 11368 | priv->sys_config.accept_all_mgmt_frames = 1; | ||
| 11369 | |||
| 11370 | ipw_send_system_config(priv); | ||
| 11371 | } | ||
| 11372 | |||
| 11373 | return 0; | ||
| 11374 | } | ||
| 11375 | |||
| 11376 | static int ipw_prom_stop(struct net_device *dev) | ||
| 11377 | { | ||
| 11378 | struct ipw_prom_priv *prom_priv = ieee80211_priv(dev); | ||
| 11379 | struct ipw_priv *priv = prom_priv->priv; | ||
| 11380 | |||
| 11381 | IPW_DEBUG_INFO("prom dev->stop\n"); | ||
| 11382 | |||
| 11383 | if (priv->ieee->iw_mode != IW_MODE_MONITOR) { | ||
| 11384 | priv->sys_config.accept_all_data_frames = 0; | ||
| 11385 | priv->sys_config.accept_non_directed_frames = 0; | ||
| 11386 | priv->sys_config.accept_all_mgmt_bcpr = 0; | ||
| 11387 | priv->sys_config.accept_all_mgmt_frames = 0; | ||
| 11388 | |||
| 11389 | ipw_send_system_config(priv); | ||
| 11390 | } | ||
| 11391 | |||
| 11392 | return 0; | ||
| 11393 | } | ||
| 11394 | |||
| 11395 | static int ipw_prom_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | ||
| 11396 | { | ||
| 11397 | IPW_DEBUG_INFO("prom dev->xmit\n"); | ||
| 11398 | netif_stop_queue(dev); | ||
| 11399 | return -EOPNOTSUPP; | ||
| 11400 | } | ||
| 11401 | |||
| 11402 | static struct net_device_stats *ipw_prom_get_stats(struct net_device *dev) | ||
| 11403 | { | ||
| 11404 | struct ipw_prom_priv *prom_priv = ieee80211_priv(dev); | ||
| 11405 | return &prom_priv->ieee->stats; | ||
| 11406 | } | ||
| 11407 | |||
| 11408 | static int ipw_prom_alloc(struct ipw_priv *priv) | ||
| 11409 | { | ||
| 11410 | int rc = 0; | ||
| 11411 | |||
| 11412 | if (priv->prom_net_dev) | ||
| 11413 | return -EPERM; | ||
| 11414 | |||
| 11415 | priv->prom_net_dev = alloc_ieee80211(sizeof(struct ipw_prom_priv)); | ||
| 11416 | if (priv->prom_net_dev == NULL) | ||
| 11417 | return -ENOMEM; | ||
| 11418 | |||
| 11419 | priv->prom_priv = ieee80211_priv(priv->prom_net_dev); | ||
| 11420 | priv->prom_priv->ieee = netdev_priv(priv->prom_net_dev); | ||
| 11421 | priv->prom_priv->priv = priv; | ||
| 11422 | |||
| 11423 | strcpy(priv->prom_net_dev->name, "rtap%d"); | ||
| 11424 | |||
| 11425 | priv->prom_net_dev->type = ARPHRD_IEEE80211_RADIOTAP; | ||
| 11426 | priv->prom_net_dev->open = ipw_prom_open; | ||
| 11427 | priv->prom_net_dev->stop = ipw_prom_stop; | ||
| 11428 | priv->prom_net_dev->get_stats = ipw_prom_get_stats; | ||
| 11429 | priv->prom_net_dev->hard_start_xmit = ipw_prom_hard_start_xmit; | ||
| 11430 | |||
| 11431 | priv->prom_priv->ieee->iw_mode = IW_MODE_MONITOR; | ||
| 11432 | |||
| 11433 | rc = register_netdev(priv->prom_net_dev); | ||
| 11434 | if (rc) { | ||
| 11435 | free_ieee80211(priv->prom_net_dev); | ||
| 11436 | priv->prom_net_dev = NULL; | ||
| 11437 | return rc; | ||
| 11438 | } | ||
| 11439 | |||
| 11440 | return 0; | ||
| 11441 | } | ||
| 11442 | |||
| 11443 | static void ipw_prom_free(struct ipw_priv *priv) | ||
| 11444 | { | ||
| 11445 | if (!priv->prom_net_dev) | ||
| 11446 | return; | ||
| 11447 | |||
| 11448 | unregister_netdev(priv->prom_net_dev); | ||
| 11449 | free_ieee80211(priv->prom_net_dev); | ||
| 11450 | |||
| 11451 | priv->prom_net_dev = NULL; | ||
| 11452 | } | ||
| 11453 | |||
| 11454 | #endif | ||
| 11455 | |||
| 11456 | |||
| 10871 | static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 11457 | static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
| 10872 | { | 11458 | { |
| 10873 | int err = 0; | 11459 | int err = 0; |
| @@ -10959,11 +11545,12 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 10959 | priv->ieee->set_security = shim__set_security; | 11545 | priv->ieee->set_security = shim__set_security; |
| 10960 | priv->ieee->is_queue_full = ipw_net_is_queue_full; | 11546 | priv->ieee->is_queue_full = ipw_net_is_queue_full; |
| 10961 | 11547 | ||
| 10962 | #ifdef CONFIG_IPW_QOS | 11548 | #ifdef CONFIG_IPW2200_QOS |
| 11549 | priv->ieee->is_qos_active = ipw_is_qos_active; | ||
| 10963 | priv->ieee->handle_probe_response = ipw_handle_beacon; | 11550 | priv->ieee->handle_probe_response = ipw_handle_beacon; |
| 10964 | priv->ieee->handle_beacon = ipw_handle_probe_response; | 11551 | priv->ieee->handle_beacon = ipw_handle_probe_response; |
| 10965 | priv->ieee->handle_assoc_response = ipw_handle_assoc_response; | 11552 | priv->ieee->handle_assoc_response = ipw_handle_assoc_response; |
| 10966 | #endif /* CONFIG_IPW_QOS */ | 11553 | #endif /* CONFIG_IPW2200_QOS */ |
| 10967 | 11554 | ||
| 10968 | priv->ieee->perfect_rssi = -20; | 11555 | priv->ieee->perfect_rssi = -20; |
| 10969 | priv->ieee->worst_rssi = -85; | 11556 | priv->ieee->worst_rssi = -85; |
| @@ -10997,6 +11584,18 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 10997 | goto out_remove_sysfs; | 11584 | goto out_remove_sysfs; |
| 10998 | } | 11585 | } |
| 10999 | 11586 | ||
| 11587 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 11588 | if (rtap_iface) { | ||
| 11589 | err = ipw_prom_alloc(priv); | ||
| 11590 | if (err) { | ||
| 11591 | IPW_ERROR("Failed to register promiscuous network " | ||
| 11592 | "device (error %d).\n", err); | ||
| 11593 | unregister_netdev(priv->net_dev); | ||
| 11594 | goto out_remove_sysfs; | ||
| 11595 | } | ||
| 11596 | } | ||
| 11597 | #endif | ||
| 11598 | |||
| 11000 | printk(KERN_INFO DRV_NAME ": Detected geography %s (%d 802.11bg " | 11599 | printk(KERN_INFO DRV_NAME ": Detected geography %s (%d 802.11bg " |
| 11001 | "channels, %d 802.11a channels)\n", | 11600 | "channels, %d 802.11a channels)\n", |
| 11002 | priv->ieee->geo.name, priv->ieee->geo.bg_channels, | 11601 | priv->ieee->geo.name, priv->ieee->geo.bg_channels, |
| @@ -11076,6 +11675,10 @@ static void ipw_pci_remove(struct pci_dev *pdev) | |||
| 11076 | priv->error = NULL; | 11675 | priv->error = NULL; |
| 11077 | } | 11676 | } |
| 11078 | 11677 | ||
| 11678 | #ifdef CONFIG_IPW2200_PROMISCUOUS | ||
| 11679 | ipw_prom_free(priv); | ||
| 11680 | #endif | ||
| 11681 | |||
| 11079 | free_irq(pdev->irq, priv); | 11682 | free_irq(pdev->irq, priv); |
| 11080 | iounmap(priv->hw_base); | 11683 | iounmap(priv->hw_base); |
| 11081 | pci_release_regions(pdev); | 11684 | pci_release_regions(pdev); |
| @@ -11200,7 +11803,12 @@ MODULE_PARM_DESC(debug, "debug output mask"); | |||
| 11200 | module_param(channel, int, 0444); | 11803 | module_param(channel, int, 0444); |
| 11201 | MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])"); | 11804 | MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])"); |
| 11202 | 11805 | ||
| 11203 | #ifdef CONFIG_IPW_QOS | 11806 | #ifdef CONFIG_IPW2200_PROMISCUOUS |
| 11807 | module_param(rtap_iface, int, 0444); | ||
| 11808 | MODULE_PARM_DESC(rtap_iface, "create the rtap interface (1 - create, default 0)"); | ||
| 11809 | #endif | ||
| 11810 | |||
| 11811 | #ifdef CONFIG_IPW2200_QOS | ||
| 11204 | module_param(qos_enable, int, 0444); | 11812 | module_param(qos_enable, int, 0444); |
| 11205 | MODULE_PARM_DESC(qos_enable, "enable all QoS functionalitis"); | 11813 | MODULE_PARM_DESC(qos_enable, "enable all QoS functionalitis"); |
| 11206 | 11814 | ||
| @@ -11215,7 +11823,7 @@ MODULE_PARM_DESC(burst_duration_CCK, "set CCK burst value"); | |||
| 11215 | 11823 | ||
| 11216 | module_param(burst_duration_OFDM, int, 0444); | 11824 | module_param(burst_duration_OFDM, int, 0444); |
| 11217 | MODULE_PARM_DESC(burst_duration_OFDM, "set OFDM burst value"); | 11825 | MODULE_PARM_DESC(burst_duration_OFDM, "set OFDM burst value"); |
| 11218 | #endif /* CONFIG_IPW_QOS */ | 11826 | #endif /* CONFIG_IPW2200_QOS */ |
| 11219 | 11827 | ||
| 11220 | #ifdef CONFIG_IPW2200_MONITOR | 11828 | #ifdef CONFIG_IPW2200_MONITOR |
| 11221 | module_param(mode, int, 0444); | 11829 | module_param(mode, int, 0444); |
| @@ -11238,5 +11846,8 @@ MODULE_PARM_DESC(cmdlog, | |||
| 11238 | module_param(roaming, int, 0444); | 11846 | module_param(roaming, int, 0444); |
| 11239 | MODULE_PARM_DESC(roaming, "enable roaming support (default on)"); | 11847 | MODULE_PARM_DESC(roaming, "enable roaming support (default on)"); |
| 11240 | 11848 | ||
| 11849 | module_param(antenna, int, 0444); | ||
| 11850 | MODULE_PARM_DESC(antenna, "select antenna 1=Main, 3=Aux, default 0 [both], 2=slow_diversity (choose the one with lower background noise)"); | ||
| 11851 | |||
| 11241 | module_exit(ipw_exit); | 11852 | module_exit(ipw_exit); |
| 11242 | module_init(ipw_init); | 11853 | module_init(ipw_init); |
