]> err.no Git - linux-2.6/blobdiff - drivers/net/wireless/hostap/hostap_info.c
WorkStruct: make allyesconfig
[linux-2.6] / drivers / net / wireless / hostap / hostap_info.c
index cf9e0898b57fd15c6a1a354dffa32c138e7c5f75..5fd2b1ad7f5eac6da3a81dcf466f14c65dbbf87a 100644 (file)
@@ -1,5 +1,8 @@
 /* Host AP driver Info Frame processing (part of hostap.o module) */
 
+#include "hostap_wlan.h"
+#include "hostap.h"
+#include "hostap_ap.h"
 
 /* Called only as a tasklet (software IRQ) */
 static void prism2_info_commtallies16(local_info_t *local, unsigned char *buf,
@@ -160,7 +163,7 @@ static void prism2_host_roaming(local_info_t *local)
 {
        struct hfa384x_join_request req;
        struct net_device *dev = local->dev;
-       struct hfa384x_scan_result *selected, *entry;
+       struct hfa384x_hostscan_result *selected, *entry;
        int i;
        unsigned long flags;
 
@@ -244,9 +247,10 @@ static void prism2_info_scanresults(local_info_t *local, unsigned char *buf,
                                    int left)
 {
        u16 *pos;
-       int new_count;
+       int new_count, i;
        unsigned long flags;
-       struct hfa384x_scan_result *results, *prev;
+       struct hfa384x_scan_result *res;
+       struct hfa384x_hostscan_result *results, *prev;
 
        if (left < 4) {
                printk(KERN_DEBUG "%s: invalid scanresult info frame "
@@ -260,11 +264,18 @@ static void prism2_info_scanresults(local_info_t *local, unsigned char *buf,
        left -= 4;
 
        new_count = left / sizeof(struct hfa384x_scan_result);
-       results = kmalloc(new_count * sizeof(struct hfa384x_scan_result),
+       results = kmalloc(new_count * sizeof(struct hfa384x_hostscan_result),
                          GFP_ATOMIC);
        if (results == NULL)
                return;
-       memcpy(results, pos, new_count * sizeof(struct hfa384x_scan_result));
+
+       /* Convert to hostscan result format. */
+       res = (struct hfa384x_scan_result *) pos;
+       for (i = 0; i < new_count; i++) {
+               memcpy(&results[i], &res[i],
+                      sizeof(struct hfa384x_scan_result));
+               results[i].atim = 0;
+       }
 
        spin_lock_irqsave(&local->lock, flags);
        local->last_scan_type = PRISM2_SCAN;
@@ -335,9 +346,9 @@ static void prism2_info_hostscanresults(local_info_t *local,
 
        spin_lock_irqsave(&local->lock, flags);
        local->last_scan_type = PRISM2_HOSTSCAN;
-       prev = local->last_hostscan_results;
-       local->last_hostscan_results = results;
-       local->last_hostscan_results_count = new_count;
+       prev = local->last_scan_results;
+       local->last_scan_results = results;
+       local->last_scan_results_count = new_count;
        spin_unlock_irqrestore(&local->lock, flags);
        kfree(prev);
 
@@ -445,14 +456,27 @@ static void handle_info_queue_scanresults(local_info_t *local)
 {
        if (local->host_roaming == 1 && local->iw_mode == IW_MODE_INFRA)
                prism2_host_roaming(local);
+
+       if (local->host_roaming == 2 && local->iw_mode == IW_MODE_INFRA &&
+           memcmp(local->preferred_ap, "\x00\x00\x00\x00\x00\x00",
+                  ETH_ALEN) != 0) {
+               /*
+                * Firmware seems to be getting into odd state in host_roaming
+                * mode 2 when hostscan is used without join command, so try
+                * to fix this by re-joining the current AP. This does not
+                * actually trigger a new association if the current AP is
+                * still in the scan results.
+                */
+               prism2_host_roaming(local);
+       }
 }
 
 
 /* Called only as scheduled task after receiving info frames (used to avoid
  * pending too much time in HW IRQ handler). */
-static void handle_info_queue(void *data)
+static void handle_info_queue(struct work_struct *work)
 {
-       local_info_t *local = (local_info_t *) data;
+       local_info_t *local = container_of(work, local_info_t, info_queue);
 
        if (test_and_clear_bit(PRISM2_INFO_PENDING_LINKSTATUS,
                               &local->pending_info))
@@ -469,7 +493,7 @@ void hostap_info_init(local_info_t *local)
 {
        skb_queue_head_init(&local->info_list);
 #ifndef PRISM2_NO_STATION_MODES
-       INIT_WORK(&local->info_queue, handle_info_queue, local);
+       INIT_WORK(&local->info_queue, handle_info_queue);
 #endif /* PRISM2_NO_STATION_MODES */
 }