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); |