]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/wireless/libertas/scan.c
libertas: convert 802_11_SCAN to a direct command
[linux-2.6-omap-h63xx.git] / drivers / net / wireless / libertas / scan.c
index 69f94c92b32d8986a5221658b180d09c94b0a6d7..9f9c7d9c8bd20c4e81800a4529c2a5a4c343b2bc 100644 (file)
@@ -20,6 +20,7 @@
 #include "dev.h"
 #include "scan.h"
 #include "join.h"
+#include "cmd.h"
 
 //! Approximate amount of data needed to pass a scan result back to iwlist
 #define MAX_SCAN_CELL_SIZE  (IW_EV_ADDR_LEN             \
 //! Memory needed to store a max number/size SSID TLV for a firmware scan
 #define SSID_TLV_MAX_SIZE  (1 * sizeof(struct mrvlietypes_ssidparamset))
 
-//! Maximum memory needed for a lbs_scan_cmd_config with all TLVs at max
-#define MAX_SCAN_CFG_ALLOC (sizeof(struct lbs_scan_cmd_config)  \
-                            + CHAN_TLV_MAX_SIZE                 \
-                            + SSID_TLV_MAX_SIZE)
+//! Maximum memory needed for a cmd_ds_802_11_scan with all TLVs at max
+#define MAX_SCAN_CFG_ALLOC (sizeof(struct cmd_ds_802_11_scan)  \
+                            + CHAN_TLV_MAX_SIZE + SSID_TLV_MAX_SIZE)
 
 //! The maximum number of channels the firmware can scan per command
 #define MRVDRV_MAX_CHANNELS_PER_SCAN   14
@@ -64,8 +64,8 @@
 static const u8 zeromac[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 static const u8 bcastmac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
 
-
-
+static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
+                             struct cmd_header *resp);
 
 /*********************************************************************/
 /*                                                                   */
@@ -73,6 +73,23 @@ static const u8 bcastmac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
 /*                                                                   */
 /*********************************************************************/
 
+/**
+ *  @brief Unsets the MSB on basic rates
+ *
+ * Scan through an array and unset the MSB for basic data rates.
+ *
+ *  @param rates     buffer of data rates
+ *  @param len       size of buffer
+ */
+static void lbs_unset_basic_rate_flags(u8 *rates, size_t len)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               rates[i] &= 0x7f;
+}
+
+
 static inline void clear_bss_descriptor (struct bss_descriptor * bss)
 {
        /* Don't blow away ->list, just BSS data */
@@ -475,24 +492,22 @@ static int lbs_scan_add_rates_tlv(u8 *tlv)
  * Generate the CMD_802_11_SCAN command with the proper tlv
  * for a bunch of channels.
  */
-static int lbs_do_scan(struct lbs_private *priv,
-       u8 bsstype,
-       struct chanscanparamset *chan_list,
-       int chan_count,
-       const struct lbs_ioctl_user_scan_cfg *user_cfg)
+static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype,
+                      struct chanscanparamset *chan_list, int chan_count,
+                      const struct lbs_ioctl_user_scan_cfg *user_cfg)
 {
        int ret = -ENOMEM;
-       struct lbs_scan_cmd_config *scan_cmd;
-       u8 *tlv;    /* pointer into our current, growing TLV storage area */
+       struct cmd_ds_802_11_scan *scan_cmd;
+       uint8_t *tlv;   /* pointer into our current, growing TLV storage area */
 
-       lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, "
-               "chan_count %d",
-               bsstype, chan_list[0].channumber, chan_count);
+       lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, chan_count %d",
+                          bsstype, chan_list[0].channumber, chan_count);
 
        /* create the fixed part for scan command */
        scan_cmd = kzalloc(MAX_SCAN_CFG_ALLOC, GFP_KERNEL);
        if (scan_cmd == NULL)
                goto out;
+
        tlv = scan_cmd->tlvbuffer;
        if (user_cfg)
                memcpy(scan_cmd->bssid, user_cfg->bssid, ETH_ALEN);
@@ -506,13 +521,16 @@ static int lbs_do_scan(struct lbs_private *priv,
        tlv += lbs_scan_add_rates_tlv(tlv);
 
        /* This is the final data we are about to send */
-       scan_cmd->tlvbufferlen = tlv - scan_cmd->tlvbuffer;
-       lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd, 1+6);
+       scan_cmd->hdr.size = cpu_to_le16(tlv - (uint8_t *)scan_cmd);
+       lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd,
+                   sizeof(*scan_cmd));
        lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TLV", scan_cmd->tlvbuffer,
-               scan_cmd->tlvbufferlen);
+                   tlv - scan_cmd->tlvbuffer);
+
+       ret = __lbs_cmd(priv, CMD_802_11_SCAN, &scan_cmd->hdr,
+                       le16_to_cpu(scan_cmd->hdr.size),
+                       lbs_ret_80211_scan, 0);
 
-       ret = lbs_prepare_and_send_command(priv, CMD_802_11_SCAN, 0,
-               CMD_OPTION_WAITFORRSP, 0, scan_cmd);
 out:
        kfree(scan_cmd);
        lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
@@ -595,13 +613,13 @@ int lbs_scan_networks(struct lbs_private *priv,
        }
 
        /* Prepare to continue an interrupted scan */
-       lbs_deb_scan("chan_count %d, last_scanned_channel %d\n",
-                    chan_count, priv->last_scanned_channel);
+       lbs_deb_scan("chan_count %d, scan_channel %d\n",
+                    chan_count, priv->scan_channel);
        curr_chans = chan_list;
        /* advance channel list by already-scanned-channels */
-       if (priv->last_scanned_channel > 0) {
-               curr_chans += priv->last_scanned_channel;
-               chan_count -= priv->last_scanned_channel;
+       if (priv->scan_channel > 0) {
+               curr_chans += priv->scan_channel;
+               chan_count -= priv->scan_channel;
        }
 
        /* Send scan command(s)
@@ -627,10 +645,10 @@ int lbs_scan_networks(struct lbs_private *priv,
                    !full_scan &&
                    !priv->surpriseremoved) {
                        /* -1 marks just that we're currently scanning */
-                       if (priv->last_scanned_channel < 0)
-                               priv->last_scanned_channel = to_scan;
+                       if (priv->scan_channel < 0)
+                               priv->scan_channel = to_scan;
                        else
-                               priv->last_scanned_channel += to_scan;
+                               priv->scan_channel += to_scan;
                        cancel_delayed_work(&priv->scan_work);
                        queue_delayed_work(priv->work_thread, &priv->scan_work,
                                msecs_to_jiffies(300));
@@ -654,7 +672,7 @@ int lbs_scan_networks(struct lbs_private *priv,
 #endif
 
 out2:
-       priv->last_scanned_channel = 0;
+       priv->scan_channel = 0;
 
 out:
        if (priv->connect_status == LBS_CONNECTED) {
@@ -1376,7 +1394,7 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
                queue_delayed_work(priv->work_thread, &priv->scan_work,
                        msecs_to_jiffies(50));
        /* set marker that currently a scan is taking place */
-       priv->last_scanned_channel = -1;
+       priv->scan_channel = -1;
 
        if (priv->surpriseremoved)
                return -EIO;
@@ -1410,7 +1428,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
        lbs_deb_enter(LBS_DEB_SCAN);
 
        /* iwlist should wait until the current scan is finished */
-       if (priv->last_scanned_channel)
+       if (priv->scan_channel)
                return -EAGAIN;
 
        /* Update RSSI if current BSS is a locally created ad-hoc BSS */
@@ -1467,44 +1485,6 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
 /*********************************************************************/
 
 
-/**
- *  @brief Prepare a scan command to be sent to the firmware
- *
- *  Called via lbs_prepare_and_send_command(priv, CMD_802_11_SCAN, ...)
- *  from cmd.c
- *
- *  Sends a fixed length data part (specifying the BSS type and BSSID filters)
- *  as well as a variable number/length of TLVs to the firmware.
- *
- *  @param priv       A pointer to struct lbs_private structure
- *  @param cmd        A pointer to cmd_ds_command structure to be sent to
- *                    firmware with the cmd_DS_801_11_SCAN structure
- *  @param pdata_buf  Void pointer cast of a lbs_scan_cmd_config struct used
- *                    to set the fields/TLVs for the command sent to firmware
- *
- *  @return           0 or -1
- */
-int lbs_cmd_80211_scan(struct lbs_private *priv,
-       struct cmd_ds_command *cmd, void *pdata_buf)
-{
-       struct cmd_ds_802_11_scan *pscan = &cmd->params.scan;
-       struct lbs_scan_cmd_config *pscancfg = pdata_buf;
-
-       lbs_deb_enter(LBS_DEB_SCAN);
-
-       /* Set fixed field variables in scan command */
-       pscan->bsstype = pscancfg->bsstype;
-       memcpy(pscan->bssid, pscancfg->bssid, ETH_ALEN);
-       memcpy(pscan->tlvbuffer, pscancfg->tlvbuffer, pscancfg->tlvbufferlen);
-
-       /* size is equal to the sizeof(fixed portions) + the TLV len + header */
-       cmd->size = cpu_to_le16(sizeof(pscan->bsstype) + ETH_ALEN
-                               + pscancfg->tlvbufferlen + S_DS_GEN);
-
-       lbs_deb_leave(LBS_DEB_SCAN);
-       return 0;
-}
-
 /**
  *  @brief This function handles the command response of scan
  *
@@ -1531,13 +1511,14 @@ int lbs_cmd_80211_scan(struct lbs_private *priv,
  *
  *  @return        0 or -1
  */
-int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp)
+static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
+                             struct cmd_header *resp)
 {
-       struct cmd_ds_802_11_scan_rsp *pscan;
+       struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp;
        struct bss_descriptor * iter_bss;
        struct bss_descriptor * safe;
-       u8 *pbssinfo;
-       u16 scanrespsize;
+       uint8_t *bssinfo;
+       uint16_t scanrespsize;
        int bytesleft;
        int idx;
        int tlvbufsize;
@@ -1554,48 +1535,45 @@ int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp)
                clear_bss_descriptor(iter_bss);
        }
 
-       pscan = &resp->params.scanresp;
-
-       if (pscan->nr_sets > MAX_NETWORK_COUNT) {
-               lbs_deb_scan(
-                      "SCAN_RESP: too many scan results (%d, max %d)!!\n",
-                      pscan->nr_sets, MAX_NETWORK_COUNT);
+       if (scanresp->nr_sets > MAX_NETWORK_COUNT) {
+               lbs_deb_scan("SCAN_RESP: too many scan results (%d, max %d)\n",
+                            scanresp->nr_sets, MAX_NETWORK_COUNT);
                ret = -1;
                goto done;
        }
 
-       bytesleft = le16_to_cpu(pscan->bssdescriptsize);
+       bytesleft = le16_to_cpu(scanresp->bssdescriptsize);
        lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft);
 
        scanrespsize = le16_to_cpu(resp->size);
-       lbs_deb_scan("SCAN_RESP: scan results %d\n", pscan->nr_sets);
+       lbs_deb_scan("SCAN_RESP: scan results %d\n", scanresp->nr_sets);
 
-       pbssinfo = pscan->bssdesc_and_tlvbuffer;
+       bssinfo = scanresp->bssdesc_and_tlvbuffer;
 
        /* The size of the TLV buffer is equal to the entire command response
         *   size (scanrespsize) minus the fixed fields (sizeof()'s), the
         *   BSS Descriptions (bssdescriptsize as bytesLef) and the command
         *   response header (S_DS_GEN)
         */
-       tlvbufsize = scanrespsize - (bytesleft + sizeof(pscan->bssdescriptsize)
-                                    + sizeof(pscan->nr_sets)
+       tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize)
+                                    + sizeof(scanresp->nr_sets)
                                     + S_DS_GEN);
 
        /*
-        *  Process each scan response returned (pscan->nr_sets).  Save
+        *  Process each scan response returned (scanresp->nr_sets). Save
         *    the information in the newbssentry and then insert into the
         *    driver scan table either as an update to an existing entry
         *    or as an addition at the end of the table
         */
-       for (idx = 0; idx < pscan->nr_sets && bytesleft; idx++) {
+       for (idx = 0; idx < scanresp->nr_sets && bytesleft; idx++) {
                struct bss_descriptor new;
-               struct bss_descriptor * found = NULL;
-               struct bss_descriptor * oldest = NULL;
+               struct bss_descriptor *found = NULL;
+               struct bss_descriptor *oldest = NULL;
                DECLARE_MAC_BUF(mac);
 
                /* Process the data fields and IEs returned for this BSS */
                memset(&new, 0, sizeof (struct bss_descriptor));
-               if (lbs_process_bss(&new, &pbssinfo, &bytesleft) != 0) {
+               if (lbs_process_bss(&new, &bssinfo, &bytesleft) != 0) {
                        /* error parsing the scan response, skipped */
                        lbs_deb_scan("SCAN_RESP: process_bss returned ERROR\n");
                        continue;
@@ -1630,8 +1608,7 @@ int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp)
                        continue;
                }
 
-               lbs_deb_scan("SCAN_RESP: BSSID %s\n",
-                            print_mac(mac, new.bssid));
+               lbs_deb_scan("SCAN_RESP: BSSID %s\n", print_mac(mac, new.bssid));
 
                /* Copy the locally created newbssentry to the scan table */
                memcpy(found, &new, offsetof(struct bss_descriptor, list));