libertas: move SIOCGIWAP calls to wext.c
[safe/jmp/linux-2.6] / drivers / net / wireless / libertas / wext.c
index d86fcf0..dc63b33 100644 (file)
@@ -8,7 +8,7 @@
 #include <linux/wireless.h>
 #include <linux/bitops.h>
 
-#include <net/ieee80211.h>
+#include <net/lib80211.h>
 #include <net/iw_handler.h>
 
 #include "host.h"
@@ -30,6 +30,14 @@ static inline void lbs_postpone_association_work(struct lbs_private *priv)
        queue_delayed_work(priv->work_thread, &priv->assoc_work, HZ / 2);
 }
 
+static inline void lbs_do_association_work(struct lbs_private *priv)
+{
+       if (priv->surpriseremoved)
+               return;
+       cancel_delayed_work(&priv->assoc_work);
+       queue_delayed_work(priv->work_thread, &priv->assoc_work, 0);
+}
+
 static inline void lbs_cancel_association_work(struct lbs_private *priv)
 {
        cancel_delayed_work(&priv->assoc_work);
@@ -37,6 +45,38 @@ static inline void lbs_cancel_association_work(struct lbs_private *priv)
        priv->pending_assoc_req = NULL;
 }
 
+void lbs_send_disconnect_notification(struct lbs_private *priv)
+{
+       union iwreq_data wrqu;
+
+       memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
+       wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+       wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
+}
+
+void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str)
+{
+       union iwreq_data iwrq;
+       u8 buf[50];
+
+       lbs_deb_enter(LBS_DEB_WEXT);
+
+       memset(&iwrq, 0, sizeof(union iwreq_data));
+       memset(buf, 0, sizeof(buf));
+
+       snprintf(buf, sizeof(buf) - 1, "%s", str);
+
+       iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN;
+
+       /* Send Event to upper layer */
+       lbs_deb_wext("event indication string %s\n", (char *)buf);
+       lbs_deb_wext("event indication length %d\n", iwrq.data.length);
+       lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str);
+
+       wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf);
+
+       lbs_deb_leave(LBS_DEB_WEXT);
+}
 
 /**
  *  @brief Find the channel frequency power info with specific channel
@@ -58,8 +98,6 @@ struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
        for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) {
                rc = &priv->region_channel[j];
 
-               if (priv->enable11d)
-                       rc = &priv->universal_channel[j];
                if (!rc->valid || !rc->CFP)
                        continue;
                if (rc->band != band)
@@ -99,8 +137,6 @@ static struct chan_freq_power *find_cfp_by_band_and_freq(
        for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) {
                rc = &priv->region_channel[j];
 
-               if (priv->enable11d)
-                       rc = &priv->universal_channel[j];
                if (!rc->valid || !rc->CFP)
                        continue;
                if (rc->band != band)
@@ -155,18 +191,18 @@ static int lbs_get_name(struct net_device *dev, struct iw_request_info *info,
 static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info,
                         struct iw_freq *fwrq, char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        struct chan_freq_power *cfp;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
        cfp = lbs_find_cfp_by_band_and_channel(priv, 0,
-                                          priv->curbssparams.channel);
+                                          priv->channel);
 
        if (!cfp) {
-               if (priv->curbssparams.channel)
+               if (priv->channel)
                        lbs_deb_wext("invalid channel %d\n",
-                              priv->curbssparams.channel);
+                              priv->channel);
                return -EINVAL;
        }
 
@@ -181,7 +217,7 @@ static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info,
 static int lbs_get_wap(struct net_device *dev, struct iw_request_info *info,
                        struct sockaddr *awrq, char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -199,7 +235,7 @@ static int lbs_get_wap(struct net_device *dev, struct iw_request_info *info,
 static int lbs_set_nick(struct net_device *dev, struct iw_request_info *info,
                         struct iw_point *dwrq, char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -223,7 +259,7 @@ static int lbs_set_nick(struct net_device *dev, struct iw_request_info *info,
 static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info,
                         struct iw_point *dwrq, char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -240,7 +276,7 @@ static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info,
 static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info,
                         struct iw_point *dwrq, char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -265,7 +301,7 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info,
                        struct iw_param *vwrq, char *extra)
 {
        int ret = 0;
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        u32 val = vwrq->value;
 
        lbs_deb_enter(LBS_DEB_WEXT);
@@ -273,7 +309,7 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info,
        if (vwrq->disabled)
                val = MRVDRV_RTS_MAX_VALUE;
 
-       if (val < MRVDRV_RTS_MIN_VALUE || val > MRVDRV_RTS_MAX_VALUE)
+       if (val > MRVDRV_RTS_MAX_VALUE) /* min rts value is 0 */
                return -EINVAL;
 
        ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, (u16) val);
@@ -285,7 +321,7 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info,
 static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info,
                        struct iw_param *vwrq, char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        int ret = 0;
        u16 val = 0;
 
@@ -296,8 +332,7 @@ static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info,
                goto out;
 
        vwrq->value = val;
-       vwrq->disabled = ((val < MRVDRV_RTS_MIN_VALUE)
-                         || (val > MRVDRV_RTS_MAX_VALUE));
+       vwrq->disabled = val > MRVDRV_RTS_MAX_VALUE; /* min rts value is 0 */
        vwrq->fixed = 1;
 
 out:
@@ -308,7 +343,7 @@ out:
 static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info,
                         struct iw_param *vwrq, char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        int ret = 0;
        u32 val = vwrq->value;
 
@@ -329,7 +364,7 @@ static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info,
 static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info,
                         struct iw_param *vwrq, char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        int ret = 0;
        u16 val = 0;
 
@@ -352,7 +387,7 @@ out:
 static int lbs_get_mode(struct net_device *dev,
                         struct iw_request_info *info, u32 * uwrq, char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -378,7 +413,7 @@ static int lbs_get_txpow(struct net_device *dev,
                          struct iw_request_info *info,
                          struct iw_param *vwrq, char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        s16 curlevel = 0;
        int ret = 0;
 
@@ -411,7 +446,7 @@ out:
 static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info,
                          struct iw_param *vwrq, char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        int ret = 0;
        u16 slimit = 0, llimit = 0;
 
@@ -459,7 +494,7 @@ out:
 static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info,
                          struct iw_param *vwrq, char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        int ret = 0;
        u16 val = 0;
 
@@ -535,13 +570,11 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
                          struct iw_point *dwrq, char *extra)
 {
        int i, j;
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        struct iw_range *range = (struct iw_range *)extra;
        struct chan_freq_power *cfp;
        u8 rates[MAX_RATES + 1];
 
-       u8 flag = 0;
-
        lbs_deb_enter(LBS_DEB_WEXT);
 
        dwrq->length = sizeof(struct iw_range);
@@ -563,52 +596,21 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
 
        range->scan_capa = IW_SCAN_CAPA_ESSID;
 
-       if (priv->enable11d &&
-           (priv->connect_status == LBS_CONNECTED ||
-           priv->mesh_connect_status == LBS_CONNECTED)) {
-               u8 chan_no;
-               u8 band;
-
-               struct parsed_region_chan_11d *parsed_region_chan =
-                   &priv->parsed_region_chan;
-
-               if (parsed_region_chan == NULL) {
-                       lbs_deb_wext("11d: parsed_region_chan is NULL\n");
-                       goto out;
-               }
-               band = parsed_region_chan->band;
-               lbs_deb_wext("band %d, nr_char %d\n", band,
-                      parsed_region_chan->nr_chan);
-
+       for (j = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
+            && (j < ARRAY_SIZE(priv->region_channel)); j++) {
+               cfp = priv->region_channel[j].CFP;
                for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
-                    && (i < parsed_region_chan->nr_chan); i++) {
-                       chan_no = parsed_region_chan->chanpwr[i].chan;
-                       lbs_deb_wext("chan_no %d\n", chan_no);
-                       range->freq[range->num_frequency].i = (long)chan_no;
+                    && priv->region_channel[j].valid
+                    && cfp
+                    && (i < priv->region_channel[j].nrcfp); i++) {
+                       range->freq[range->num_frequency].i =
+                           (long)cfp->channel;
                        range->freq[range->num_frequency].m =
-                           (long)lbs_chan_2_freq(chan_no) * 100000;
+                           (long)cfp->freq * 100000;
                        range->freq[range->num_frequency].e = 1;
+                       cfp++;
                        range->num_frequency++;
                }
-               flag = 1;
-       }
-       if (!flag) {
-               for (j = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
-                    && (j < ARRAY_SIZE(priv->region_channel)); j++) {
-                       cfp = priv->region_channel[j].CFP;
-                       for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
-                            && priv->region_channel[j].valid
-                            && cfp
-                            && (i < priv->region_channel[j].nrcfp); i++) {
-                               range->freq[range->num_frequency].i =
-                                   (long)cfp->channel;
-                               range->freq[range->num_frequency].m =
-                                   (long)cfp->freq * 100000;
-                               range->freq[range->num_frequency].e = 1;
-                               cfp++;
-                               range->num_frequency++;
-                       }
-               }
        }
 
        lbs_deb_wext("IW_MAX_FREQUENCIES %d, num_frequency %d\n",
@@ -693,7 +695,6 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
                                  | IW_ENC_CAPA_CIPHER_CCMP;
        }
 
-out:
        lbs_deb_leave(LBS_DEB_WEXT);
        return 0;
 }
@@ -701,11 +702,12 @@ out:
 static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
                          struct iw_param *vwrq, char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
+       int ret = 0;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
-       if (!priv->ps_supported) {
+       if (!(priv->fwcapinfo & FW_CAPINFO_PS)) {
                if (vwrq->disabled)
                        return 0;
                else
@@ -730,8 +732,54 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
                       "setting power timeout is not supported\n");
                return -EINVAL;
        } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
-               lbs_deb_wext("setting power period not supported\n");
-               return -EINVAL;
+               vwrq->value = vwrq->value / 1000;
+               if (!priv->enter_deep_sleep) {
+                       lbs_pr_err("deep sleep feature is not implemented "
+                                       "for this interface driver\n");
+                       return -EINVAL;
+               }
+
+               if (priv->connect_status == LBS_CONNECTED) {
+                       if ((priv->is_auto_deep_sleep_enabled) &&
+                                               (vwrq->value == -1000)) {
+                               lbs_exit_auto_deep_sleep(priv);
+                               return 0;
+                       } else {
+                               lbs_pr_err("can't use deep sleep cmd in "
+                                               "connected state\n");
+                               return -EINVAL;
+                       }
+               }
+
+               if ((vwrq->value < 0) && (vwrq->value != -1000)) {
+                       lbs_pr_err("unknown option\n");
+                       return -EINVAL;
+               }
+
+               if (vwrq->value > 0) {
+                       if (!priv->is_auto_deep_sleep_enabled) {
+                               priv->is_activity_detected = 0;
+                               priv->auto_deep_sleep_timeout = vwrq->value;
+                               lbs_enter_auto_deep_sleep(priv);
+                       } else {
+                               priv->auto_deep_sleep_timeout = vwrq->value;
+                               lbs_deb_debugfs("auto deep sleep: "
+                                               "already enabled\n");
+                       }
+                       return 0;
+               } else {
+                       if (priv->is_auto_deep_sleep_enabled) {
+                               lbs_exit_auto_deep_sleep(priv);
+                               /* Try to exit deep sleep if auto */
+                               /*deep sleep disabled */
+                               ret = lbs_set_deep_sleep(priv, 0);
+                       }
+                       if (vwrq->value == 0)
+                               ret = lbs_set_deep_sleep(priv, 1);
+                       else if (vwrq->value == -1000)
+                               ret = lbs_set_deep_sleep(priv, 0);
+                       return ret;
+               }
        }
 
        if (priv->psmode != LBS802_11POWERMODECAM) {
@@ -745,13 +793,14 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
        }
 
        lbs_deb_leave(LBS_DEB_WEXT);
+
        return 0;
 }
 
 static int lbs_get_power(struct net_device *dev, struct iw_request_info *info,
                          struct iw_param *vwrq, char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -774,11 +823,11 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
                EXCELLENT = 95,
                PERFECT = 100
        };
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        u32 rssi_qual;
        u32 tx_qual;
        u32 quality = 0;
-       int stats_valid = 0;
+       int ret, stats_valid = 0;
        u8 rssi;
        u32 tx_retries;
        struct cmd_ds_802_11_get_log log;
@@ -823,11 +872,13 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
        quality = rssi_qual;
 
        /* Quality by TX errors */
-       priv->wstats.discard.retries = priv->stats.tx_errors;
+       priv->wstats.discard.retries = dev->stats.tx_errors;
 
        memset(&log, 0, sizeof(log));
        log.hdr.size = cpu_to_le16(sizeof(log));
-       lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log);
+       ret = lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log);
+       if (ret)
+               goto out;
 
        tx_retries = le32_to_cpu(log.retry);
 
@@ -855,8 +906,10 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
        stats_valid = 1;
 
        /* update stats asynchronously for future calls */
-       lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
+       ret = lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
                                        0, 0, NULL);
+       if (ret)
+               lbs_pr_err("RSSI command failed\n");
 out:
        if (!stats_valid) {
                priv->wstats.miss.beacon = 0;
@@ -879,7 +932,7 @@ static int lbs_set_freq(struct net_device *dev, struct iw_request_info *info,
                  struct iw_freq *fwrq, char *extra)
 {
        int ret = -EINVAL;
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        struct chan_freq_power *cfp;
        struct assoc_request * assoc_req;
 
@@ -936,7 +989,7 @@ static int lbs_mesh_set_freq(struct net_device *dev,
                             struct iw_request_info *info,
                             struct iw_freq *fwrq, char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        struct chan_freq_power *cfp;
        int ret = -EINVAL;
 
@@ -966,7 +1019,7 @@ static int lbs_mesh_set_freq(struct net_device *dev,
                goto out;
        }
 
-       if (fwrq->m != priv->curbssparams.channel) {
+       if (fwrq->m != priv->channel) {
                lbs_deb_wext("mesh channel change forces eth disconnect\n");
                if (priv->mode == IW_MODE_INFRA)
                        lbs_cmd_80211_deauthenticate(priv,
@@ -987,12 +1040,13 @@ out:
 static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info,
                  struct iw_param *vwrq, char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        u8 new_rate = 0;
        int ret = -EINVAL;
        u8 rates[MAX_RATES + 1];
 
        lbs_deb_enter(LBS_DEB_WEXT);
+
        lbs_deb_wext("vwrq->value %d\n", vwrq->value);
        lbs_deb_wext("vwrq->fixed %d\n", vwrq->fixed);
 
@@ -1018,6 +1072,18 @@ static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info,
                                new_rate);
                        goto out;
                }
+               if (priv->fwrelease < 0x09000000) {
+                       ret = lbs_set_power_adapt_cfg(priv, 0,
+                                       POW_ADAPT_DEFAULT_P0,
+                                       POW_ADAPT_DEFAULT_P1,
+                                       POW_ADAPT_DEFAULT_P2);
+                       if (ret)
+                               goto out;
+               }
+               ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1,
+                               TPC_DEFAULT_P2, 1);
+               if (ret)
+                       goto out;
        }
 
        /* Try the newer command first (Firmware Spec 5.1 and above) */
@@ -1035,7 +1101,7 @@ out:
 static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info,
                  struct iw_param *vwrq, char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -1060,7 +1126,7 @@ static int lbs_set_mode(struct net_device *dev,
                  struct iw_request_info *info, u32 * uwrq, char *extra)
 {
        int ret = 0;
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        struct assoc_request * assoc_req;
 
        lbs_deb_enter(LBS_DEB_WEXT);
@@ -1105,7 +1171,7 @@ static int lbs_get_encode(struct net_device *dev,
                           struct iw_request_info *info,
                           struct iw_point *dwrq, u8 * extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
 
        lbs_deb_enter(LBS_DEB_WEXT);
@@ -1300,7 +1366,7 @@ static int lbs_set_encode(struct net_device *dev,
                    struct iw_point *dwrq, char *extra)
 {
        int ret = 0;
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        struct assoc_request * assoc_req;
        u16 is_default = 0, index = 0, set_tx_key = 0;
 
@@ -1376,7 +1442,7 @@ static int lbs_get_encodeext(struct net_device *dev,
                              char *extra)
 {
        int ret = -EINVAL;
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
        int index, max_key_len;
 
@@ -1482,7 +1548,7 @@ static int lbs_set_encodeext(struct net_device *dev,
                              char *extra)
 {
        int ret = 0;
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
        int alg = ext->alg;
        struct assoc_request * assoc_req;
@@ -1585,12 +1651,26 @@ static int lbs_set_encodeext(struct net_device *dev,
                        set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
                }
 
-               disable_wep (assoc_req);
+               /* Only disable wep if necessary: can't waste time here. */
+               if (priv->mac_control & CMD_ACT_MAC_WEP_ENABLE)
+                       disable_wep(assoc_req);
        }
 
 out:
        if (ret == 0) {
-               lbs_postpone_association_work(priv);
+               /* 802.1x and WPA rekeying must happen as quickly as possible,
+                * especially during the 4-way handshake; thus if in
+                * infrastructure mode, and either (a) 802.1x is enabled or
+                * (b) WPA is being used, set the key right away.
+                */
+               if (assoc_req->mode == IW_MODE_INFRA &&
+                   ((assoc_req->secinfo.key_mgmt & IW_AUTH_KEY_MGMT_802_1X) ||
+                    (assoc_req->secinfo.key_mgmt & IW_AUTH_KEY_MGMT_PSK) ||
+                     assoc_req->secinfo.WPAenabled ||
+                     assoc_req->secinfo.WPA2enabled)) {
+                       lbs_do_association_work(priv);
+               } else
+                       lbs_postpone_association_work(priv);
        } else {
                lbs_cancel_association_work(priv);
        }
@@ -1606,7 +1686,7 @@ static int lbs_set_genie(struct net_device *dev,
                          struct iw_point *dwrq,
                          char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        int ret = 0;
        struct assoc_request * assoc_req;
 
@@ -1652,7 +1732,7 @@ static int lbs_get_genie(struct net_device *dev,
                          char *extra)
 {
        int ret = 0;
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -1680,7 +1760,7 @@ static int lbs_set_auth(struct net_device *dev,
                         struct iw_param *dwrq,
                         char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        struct assoc_request * assoc_req;
        int ret = 0;
        int updated = 0;
@@ -1695,16 +1775,22 @@ static int lbs_set_auth(struct net_device *dev,
        }
 
        switch (dwrq->flags & IW_AUTH_INDEX) {
+       case IW_AUTH_PRIVACY_INVOKED:
+       case IW_AUTH_RX_UNENCRYPTED_EAPOL:
        case IW_AUTH_TKIP_COUNTERMEASURES:
        case IW_AUTH_CIPHER_PAIRWISE:
        case IW_AUTH_CIPHER_GROUP:
-       case IW_AUTH_KEY_MGMT:
        case IW_AUTH_DROP_UNENCRYPTED:
                /*
                 * libertas does not use these parameters
                 */
                break;
 
+       case IW_AUTH_KEY_MGMT:
+               assoc_req->secinfo.key_mgmt = dwrq->value;
+               updated = 1;
+               break;
+
        case IW_AUTH_WPA_VERSION:
                if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) {
                        assoc_req->secinfo.WPAenabled = 0;
@@ -1779,11 +1865,15 @@ static int lbs_get_auth(struct net_device *dev,
                         char *extra)
 {
        int ret = 0;
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
        switch (dwrq->flags & IW_AUTH_INDEX) {
+       case IW_AUTH_KEY_MGMT:
+               dwrq->value = priv->secinfo.key_mgmt;
+               break;
+
        case IW_AUTH_WPA_VERSION:
                dwrq->value = 0;
                if (priv->secinfo.WPAenabled)
@@ -1816,7 +1906,7 @@ static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info,
                   struct iw_param *vwrq, char *extra)
 {
        int ret = 0;
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        s16 dbm = (s16) vwrq->value;
 
        lbs_deb_enter(LBS_DEB_WEXT);
@@ -1895,7 +1985,7 @@ out:
 static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info,
                   struct iw_point *dwrq, char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -1930,12 +2020,13 @@ static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info,
 static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info,
                   struct iw_point *dwrq, char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        int ret = 0;
-       u8 ssid[IW_ESSID_MAX_SIZE];
+       u8 ssid[IEEE80211_MAX_SSID_LEN];
        u8 ssid_len = 0;
        struct assoc_request * assoc_req;
        int in_ssid_len = dwrq->length;
+       DECLARE_SSID_BUF(ssid_buf);
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -1945,7 +2036,7 @@ static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info,
        }
 
        /* Check the size of the string */
-       if (in_ssid_len > IW_ESSID_MAX_SIZE) {
+       if (in_ssid_len > IEEE80211_MAX_SSID_LEN) {
                ret = -E2BIG;
                goto out;
        }
@@ -1964,7 +2055,7 @@ static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info,
                lbs_deb_wext("requested any SSID\n");
        } else {
                lbs_deb_wext("requested SSID '%s'\n",
-                            escape_essid(ssid, ssid_len));
+                            print_ssid(ssid_buf, ssid, ssid_len));
        }
 
 out:
@@ -1976,7 +2067,7 @@ out:
                        ret = -ENOMEM;
                } else {
                        /* Copy the SSID to the association request */
-                       memcpy(&assoc_req->ssid, &ssid, IW_ESSID_MAX_SIZE);
+                       memcpy(&assoc_req->ssid, &ssid, IEEE80211_MAX_SSID_LEN);
                        assoc_req->ssid_len = ssid_len;
                        set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
                        lbs_postpone_association_work(priv);
@@ -1998,7 +2089,7 @@ static int lbs_mesh_get_essid(struct net_device *dev,
                              struct iw_request_info *info,
                              struct iw_point *dwrq, char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -2016,7 +2107,7 @@ static int lbs_mesh_set_essid(struct net_device *dev,
                              struct iw_request_info *info,
                              struct iw_point *dwrq, char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        int ret = 0;
 
        lbs_deb_enter(LBS_DEB_WEXT);
@@ -2027,7 +2118,7 @@ static int lbs_mesh_set_essid(struct net_device *dev,
        }
 
        /* Check the size of the string */
-       if (dwrq->length > IW_ESSID_MAX_SIZE) {
+       if (dwrq->length > IEEE80211_MAX_SSID_LEN) {
                ret = -E2BIG;
                goto out;
        }
@@ -2042,7 +2133,7 @@ static int lbs_mesh_set_essid(struct net_device *dev,
        }
 
        lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
-                       priv->curbssparams.channel);
+                       priv->channel);
  out:
        lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
        return ret;
@@ -2060,10 +2151,9 @@ static int lbs_mesh_set_essid(struct net_device *dev,
 static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info,
                 struct sockaddr *awrq, char *extra)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        struct assoc_request * assoc_req;
        int ret = 0;
-       DECLARE_MAC_BUF(mac);
 
        lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -2073,7 +2163,7 @@ static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info,
        if (awrq->sa_family != ARPHRD_ETHER)
                return -EINVAL;
 
-       lbs_deb_wext("ASSOC: WAP: sa_data %s\n", print_mac(mac, awrq->sa_data));
+       lbs_deb_wext("ASSOC: WAP: sa_data %pM\n", awrq->sa_data);
 
        mutex_lock(&priv->lock);