include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / drivers / net / wireless / hostap / hostap_info.c
index cf9e089..d737091 100644 (file)
@@ -1,5 +1,11 @@
 /* Host AP driver Info Frame processing (part of hostap.o module) */
 
+#include <linux/if_arp.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#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 +166,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;
 
@@ -195,8 +201,8 @@ static void prism2_host_roaming(local_info_t *local)
            local->preferred_ap[2] || local->preferred_ap[3] ||
            local->preferred_ap[4] || local->preferred_ap[5]) {
                /* Try to find preferred AP */
-               PDEBUG(DEBUG_EXTRA, "%s: Preferred AP BSSID " MACSTR "\n",
-                      dev->name, MAC2STR(local->preferred_ap));
+               PDEBUG(DEBUG_EXTRA, "%s: Preferred AP BSSID %pM\n",
+                      dev->name, local->preferred_ap);
                for (i = 0; i < local->last_scan_results_count; i++) {
                        entry = &local->last_scan_results[i];
                        if (memcmp(local->preferred_ap, entry->bssid, 6) == 0)
@@ -213,8 +219,9 @@ static void prism2_host_roaming(local_info_t *local)
        req.channel = selected->chid;
        spin_unlock_irqrestore(&local->lock, flags);
 
-       PDEBUG(DEBUG_EXTRA, "%s: JoinRequest: BSSID=" MACSTR " channel=%d\n",
-              dev->name, MAC2STR(req.bssid), le16_to_cpu(req.channel));
+       PDEBUG(DEBUG_EXTRA, "%s: JoinRequest: BSSID=%pM"
+              " channel=%d\n",
+              dev->name, req.bssid, le16_to_cpu(req.channel));
        if (local->func->set_rid(dev, HFA384X_RID_JOINREQUEST, &req,
                                 sizeof(req))) {
                printk(KERN_DEBUG "%s: JoinRequest failed\n", dev->name);
@@ -244,9 +251,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 +268,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;
@@ -289,7 +304,7 @@ static void prism2_info_hostscanresults(local_info_t *local,
        int i, result_size, copy_len, new_count;
        struct hfa384x_hostscan_result *results, *prev;
        unsigned long flags;
-       u16 *pos;
+       __le16 *pos;
        u8 *ptr;
 
        wake_up_interruptible(&local->hostscan_wq);
@@ -300,7 +315,7 @@ static void prism2_info_hostscanresults(local_info_t *local,
                return;
        }
 
-       pos = (u16 *) buf;
+       pos = (__le16 *) buf;
        copy_len = result_size = le16_to_cpu(*pos);
        if (result_size == 0) {
                printk(KERN_DEBUG "%s: invalid result_size (0) in "
@@ -316,11 +331,10 @@ static void prism2_info_hostscanresults(local_info_t *local,
        ptr = (u8 *) pos;
 
        new_count = left / result_size;
-       results = kmalloc(new_count * sizeof(struct hfa384x_hostscan_result),
+       results = kcalloc(new_count, sizeof(struct hfa384x_hostscan_result),
                          GFP_ATOMIC);
        if (results == NULL)
                return;
-       memset(results, 0, new_count * sizeof(struct hfa384x_hostscan_result));
 
        for (i = 0; i < new_count; i++) {
                memcpy(&results[i], ptr, copy_len);
@@ -335,9 +349,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);
 
@@ -360,7 +374,7 @@ void hostap_info_process(local_info_t *local, struct sk_buff *skb)
        buf = skb->data + sizeof(*info);
        left = skb->len - sizeof(*info);
 
-       switch (info->type) {
+       switch (le16_to_cpu(info->type)) {
        case HFA384X_INFO_COMMTALLIES:
                prism2_info_commtallies(local, buf, left);
                break;
@@ -382,7 +396,8 @@ void hostap_info_process(local_info_t *local, struct sk_buff *skb)
 #ifndef PRISM2_NO_DEBUG
        default:
                PDEBUG(DEBUG_EXTRA, "%s: INFO - len=%d type=0x%04x\n",
-                      local->dev->name, info->len, info->type);
+                      local->dev->name, le16_to_cpu(info->len),
+                      le16_to_cpu(info->type));
                PDEBUG(DEBUG_EXTRA, "Unknown info frame:");
                for (i = 0; i < (left < 100 ? left : 100); i++)
                        PDEBUG2(DEBUG_EXTRA, " %02x", buf[i]);
@@ -410,9 +425,9 @@ static void handle_info_queue_linkstatus(local_info_t *local)
                printk(KERN_DEBUG "%s: could not read CURRENTBSSID after "
                       "LinkStatus event\n", local->dev->name);
        } else {
-               PDEBUG(DEBUG_EXTRA, "%s: LinkStatus: BSSID=" MACSTR "\n",
+               PDEBUG(DEBUG_EXTRA, "%s: LinkStatus: BSSID=%pM\n",
                       local->dev->name,
-                      MAC2STR((unsigned char *) local->bssid));
+                      (unsigned char *) local->bssid);
                if (local->wds_type & HOSTAP_WDS_AP_CLIENT)
                        hostap_add_sta(local->ap, local->bssid);
        }
@@ -445,14 +460,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 +497,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 */
 }