sky2: Refactor down/up code out of sky2_restart()
[safe/jmp/linux-2.6] / drivers / net / ps3_gelic_wireless.c
index 1dae1f2..a7bc406 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/slab.h>
 
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/wireless.h>
+#include <linux/ieee80211.h>
+#include <linux/if_arp.h>
 #include <linux/ctype.h>
 #include <linux/string.h>
 #include <net/iw_handler.h>
-#include <net/ieee80211.h>
 
 #include <linux/dma-mapping.h>
 #include <net/checksum.h>
@@ -45,7 +47,8 @@
 #include "ps3_gelic_wireless.h"
 
 
-static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan);
+static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan,
+                              u8 *essid, size_t essid_len);
 static int gelic_wl_try_associate(struct net_device *netdev);
 
 /*
@@ -105,6 +108,7 @@ static const struct eurus_cmd_arg_info cmd_info[GELIC_EURUS_CMD_MAX_INDEX] = {
        [GELIC_EURUS_CMD_GET_WEP_CFG]    = { .post_arg = 1},
        [GELIC_EURUS_CMD_GET_WPA_CFG]    = { .post_arg = 1},
        [GELIC_EURUS_CMD_GET_RSSI_CFG]   = { .post_arg = 1},
+       [GELIC_EURUS_CMD_START_SCAN]     = { .pre_arg = 1},
        [GELIC_EURUS_CMD_GET_SCAN]       = { .post_arg = 1},
 };
 
@@ -163,7 +167,9 @@ static void gelic_eurus_sync_cmd_worker(struct work_struct *work)
        card = port_to_card(wl_port(wl));
 
        if (cmd_info[cmd->cmd].pre_arg) {
-               arg1 = ps3_mm_phys_to_lpar(__pa(cmd->buffer));
+               arg1 = (cmd->buffer) ?
+                       ps3_mm_phys_to_lpar(__pa(cmd->buffer)) :
+                       0;
                arg2 = cmd->buf_size;
        } else {
                arg1 = 0;
@@ -240,12 +246,12 @@ static u32 gelic_wl_get_link(struct net_device *netdev)
        u32 ret;
 
        pr_debug("%s: <-\n", __func__);
-       down(&wl->assoc_stat_lock);
+       mutex_lock(&wl->assoc_stat_lock);
        if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED)
                ret = 1;
        else
                ret = 0;
-       up(&wl->assoc_stat_lock);
+       mutex_unlock(&wl->assoc_stat_lock);
        pr_debug("%s: ->\n", __func__);
        return ret;
 }
@@ -295,7 +301,6 @@ static void gelic_wl_get_ch_info(struct gelic_wl_info *wl)
                        /* 16 bits of MSB has available channels */
                        wl->ch_info = ch_info_raw >> 48;
        }
-       return;
 }
 
 /* SIOGIWRANGE */
@@ -350,7 +355,8 @@ static int gelic_wl_get_range(struct net_device *netdev,
 
        /* encryption capability */
        range->enc_capa = IW_ENC_CAPA_WPA |
-               IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+               IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP |
+               IW_ENC_CAPA_4WAY_HANDSHAKE;
        if (wpa2_capable())
                range->enc_capa |= IW_ENC_CAPA_WPA2;
        range->encoding_size[0] = 5;    /* 40bit WEP */
@@ -359,6 +365,9 @@ static int gelic_wl_get_range(struct net_device *netdev,
        range->num_encoding_sizes = 3;
        range->max_encoding_tokens = GELIC_WEP_KEYS;
 
+       /* scan capability */
+       range->scan_capa = IW_SCAN_CAPA_ESSID;
+
        pr_debug("%s: ->\n", __func__);
        return 0;
 
@@ -370,8 +379,18 @@ static int gelic_wl_set_scan(struct net_device *netdev,
                           union iwreq_data *wrqu, char *extra)
 {
        struct gelic_wl_info *wl = port_wl(netdev_priv(netdev));
-
-       return gelic_wl_start_scan(wl, 1);
+       struct iw_scan_req *req;
+       u8 *essid = NULL;
+       size_t essid_len = 0;
+
+       if (wrqu->data.length == sizeof(struct iw_scan_req) &&
+           wrqu->data.flags & IW_SCAN_THIS_ESSID) {
+               req = (struct iw_scan_req*)extra;
+               essid = req->essid;
+               essid_len = req->essid_len;
+               pr_debug("%s: ESSID scan =%s\n", __func__, essid);
+       }
+       return gelic_wl_start_scan(wl, 1, essid, essid_len);
 }
 
 #define OUI_LEN 3
@@ -431,9 +450,9 @@ static size_t gelic_wl_synthesize_ie(u8 *buf,
 
        /* element id */
        if (rsn)
-               *buf++ = MFIE_TYPE_RSN;
+               *buf++ = WLAN_EID_RSN;
        else
-               *buf++ = MFIE_TYPE_GENERIC;
+               *buf++ = WLAN_EID_GENERIC;
 
        /* length filed; set later */
        buf++;
@@ -508,7 +527,7 @@ static void gelic_wl_parse_ie(u8 *data, size_t len,
        u8 item_len;
        u8 item_id;
 
-       pr_debug("%s: data=%p len=%ld \n", __func__,
+       pr_debug("%s: data=%p len=%ld\n", __func__,
                 data, len);
        memset(ie_info, 0, sizeof(struct ie_info));
 
@@ -521,7 +540,7 @@ static void gelic_wl_parse_ie(u8 *data, size_t len,
                        break;
 
                switch (item_id) {
-               case MFIE_TYPE_GENERIC:
+               case WLAN_EID_GENERIC:
                        if ((OUI_LEN + 1 <= item_len) &&
                            !memcmp(pos, wpa_oui, OUI_LEN) &&
                            pos[OUI_LEN] == 0x01) {
@@ -529,7 +548,7 @@ static void gelic_wl_parse_ie(u8 *data, size_t len,
                                ie_info->wpa.len = item_len + 2;
                        }
                        break;
-               case MFIE_TYPE_RSN:
+               case WLAN_EID_RSN:
                        ie_info->rsn.data = pos - 2;
                        /* length includes the header */
                        ie_info->rsn.len = item_len + 2;
@@ -553,6 +572,7 @@ static void gelic_wl_parse_ie(u8 *data, size_t len,
  * independent format
  */
 static char *gelic_wl_translate_scan(struct net_device *netdev,
+                                    struct iw_request_info *info,
                                     char *ev,
                                     char *stop,
                                     struct gelic_wl_scan_info *network)
@@ -562,7 +582,7 @@ static char *gelic_wl_translate_scan(struct net_device *netdev,
        char *tmp;
        u8 rate;
        unsigned int i, j, len;
-       u8 buf[MAX_WPA_IE_LEN];
+       u8 buf[64]; /* arbitrary size large enough */
 
        pr_debug("%s: <-\n", __func__);
 
@@ -570,26 +590,26 @@ static char *gelic_wl_translate_scan(struct net_device *netdev,
        iwe.cmd = SIOCGIWAP;
        iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
        memcpy(iwe.u.ap_addr.sa_data, &scan->bssid[2], ETH_ALEN);
-       ev = iwe_stream_add_event(ev, stop, &iwe, IW_EV_ADDR_LEN);
+       ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_ADDR_LEN);
 
        /* ESSID */
        iwe.cmd = SIOCGIWESSID;
        iwe.u.data.flags = 1;
        iwe.u.data.length = strnlen(scan->essid, 32);
-       ev = iwe_stream_add_point(ev, stop, &iwe, scan->essid);
+       ev = iwe_stream_add_point(info, ev, stop, &iwe, scan->essid);
 
        /* FREQUENCY */
        iwe.cmd = SIOCGIWFREQ;
        iwe.u.freq.m = be16_to_cpu(scan->channel);
        iwe.u.freq.e = 0; /* table value in MHz */
        iwe.u.freq.i = 0;
-       ev = iwe_stream_add_event(ev, stop, &iwe, IW_EV_FREQ_LEN);
+       ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_FREQ_LEN);
 
        /* RATES */
        iwe.cmd = SIOCGIWRATE;
        iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
        /* to stuff multiple values in one event */
-       tmp = ev + IW_EV_LCP_LEN;
+       tmp = ev + iwe_stream_lcp_len(info);
        /* put them in ascendant order (older is first) */
        i = 0;
        j = 0;
@@ -602,16 +622,16 @@ static char *gelic_wl_translate_scan(struct net_device *netdev,
                else
                    rate = scan->rate[i++] & 0x7f;
                iwe.u.bitrate.value = rate * 500000; /* 500kbps unit */
-               tmp = iwe_stream_add_value(ev, tmp, stop, &iwe,
+               tmp = iwe_stream_add_value(info, ev, tmp, stop, &iwe,
                                           IW_EV_PARAM_LEN);
        }
        while (j < network->rate_ext_len) {
                iwe.u.bitrate.value = (scan->ext_rate[j++] & 0x7f) * 500000;
-               tmp = iwe_stream_add_value(ev, tmp, stop, &iwe,
+               tmp = iwe_stream_add_value(info, ev, tmp, stop, &iwe,
                                           IW_EV_PARAM_LEN);
        }
        /* Check if we added any rate */
-       if (IW_EV_LCP_LEN < (tmp - ev))
+       if (iwe_stream_lcp_len(info) < (tmp - ev))
                ev = tmp;
 
        /* ENCODE */
@@ -621,7 +641,7 @@ static char *gelic_wl_translate_scan(struct net_device *netdev,
        else
                iwe.u.data.flags = IW_ENCODE_DISABLED;
        iwe.u.data.length = 0;
-       ev = iwe_stream_add_point(ev, stop, &iwe, scan->essid);
+       ev = iwe_stream_add_point(info, ev, stop, &iwe, scan->essid);
 
        /* MODE */
        iwe.cmd = SIOCGIWMODE;
@@ -631,7 +651,7 @@ static char *gelic_wl_translate_scan(struct net_device *netdev,
                        iwe.u.mode = IW_MODE_MASTER;
                else
                        iwe.u.mode = IW_MODE_ADHOC;
-               ev = iwe_stream_add_event(ev, stop, &iwe, IW_EV_UINT_LEN);
+               ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_UINT_LEN);
        }
 
        /* QUAL */
@@ -641,7 +661,7 @@ static char *gelic_wl_translate_scan(struct net_device *netdev,
        iwe.u.qual.level = be16_to_cpu(scan->rssi);
        iwe.u.qual.qual = be16_to_cpu(scan->rssi);
        iwe.u.qual.noise = 0;
-       ev  = iwe_stream_add_event(ev, stop, &iwe, IW_EV_QUAL_LEN);
+       ev  = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_QUAL_LEN);
 
        /* RSN */
        memset(&iwe, 0, sizeof(iwe));
@@ -651,7 +671,7 @@ static char *gelic_wl_translate_scan(struct net_device *netdev,
                if (len) {
                        iwe.cmd = IWEVGENIE;
                        iwe.u.data.length = len;
-                       ev = iwe_stream_add_point(ev, stop, &iwe, buf);
+                       ev = iwe_stream_add_point(info, ev, stop, &iwe, buf);
                }
        } else {
                /* this scan info has IE data */
@@ -666,7 +686,7 @@ static char *gelic_wl_translate_scan(struct net_device *netdev,
                        memcpy(buf, ie_info.wpa.data, ie_info.wpa.len);
                        iwe.cmd = IWEVGENIE;
                        iwe.u.data.length = ie_info.wpa.len;
-                       ev = iwe_stream_add_point(ev, stop, &iwe, buf);
+                       ev = iwe_stream_add_point(info, ev, stop, &iwe, buf);
                }
 
                if (ie_info.rsn.len && (ie_info.rsn.len <= sizeof(buf))) {
@@ -674,7 +694,7 @@ static char *gelic_wl_translate_scan(struct net_device *netdev,
                        memcpy(buf, ie_info.rsn.data, ie_info.rsn.len);
                        iwe.cmd = IWEVGENIE;
                        iwe.u.data.length = ie_info.rsn.len;
-                       ev = iwe_stream_add_point(ev, stop, &iwe, buf);
+                       ev = iwe_stream_add_point(info, ev, stop, &iwe, buf);
                }
        }
 
@@ -695,7 +715,7 @@ static int gelic_wl_get_scan(struct net_device *netdev,
        unsigned long this_time = jiffies;
 
        pr_debug("%s: <-\n", __func__);
-       if (down_interruptible(&wl->scan_lock))
+       if (mutex_lock_interruptible(&wl->scan_lock))
                return -EAGAIN;
 
        switch (wl->scan_stat) {
@@ -719,7 +739,8 @@ static int gelic_wl_get_scan(struct net_device *netdev,
                if (wl->scan_age == 0 ||
                    time_after(scan_info->last_scanned + wl->scan_age,
                               this_time))
-                       ev = gelic_wl_translate_scan(netdev, ev, stop,
+                       ev = gelic_wl_translate_scan(netdev, info,
+                                                    ev, stop,
                                                     scan_info);
                else
                        pr_debug("%s:entry too old\n", __func__);
@@ -733,7 +754,7 @@ static int gelic_wl_get_scan(struct net_device *netdev,
        wrqu->data.length = ev - extra;
        wrqu->data.flags = 0;
 out:
-       up(&wl->scan_lock);
+       mutex_unlock(&wl->scan_lock);
        pr_debug("%s: -> %d %d\n", __func__, ret, wrqu->data.length);
        return ret;
 }
@@ -743,7 +764,6 @@ static void scan_list_dump(struct gelic_wl_info *wl)
 {
        struct gelic_wl_scan_info *scan_info;
        int i;
-       DECLARE_MAC_BUF(mac);
 
        i = 0;
        list_for_each_entry(scan_info, &wl->network_list, list) {
@@ -755,8 +775,7 @@ static void scan_list_dump(struct gelic_wl_info *wl)
                         scan_info->rate_len, scan_info->rate_ext_len,
                         scan_info->essid_len);
                /* -- */
-               pr_debug("bssid=%s\n",
-                        print_mac(mac, &scan_info->hwinfo->bssid[2]));
+               pr_debug("bssid=%pM\n", &scan_info->hwinfo->bssid[2]);
                pr_debug("essid=%s\n", scan_info->hwinfo->essid);
        }
 }
@@ -959,7 +978,7 @@ static int gelic_wl_set_essid(struct net_device *netdev,
                pr_debug("%s: essid = '%s'\n", __func__, extra);
                set_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat);
        } else {
-               pr_debug("%s: ESSID any \n", __func__);
+               pr_debug("%s: ESSID any\n", __func__);
                clear_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat);
        }
        set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat);
@@ -967,7 +986,7 @@ static int gelic_wl_set_essid(struct net_device *netdev,
 
 
        gelic_wl_try_associate(netdev); /* FIXME */
-       pr_debug("%s: -> \n", __func__);
+       pr_debug("%s: ->\n", __func__);
        return 0;
 }
 
@@ -978,8 +997,8 @@ static int gelic_wl_get_essid(struct net_device *netdev,
        struct gelic_wl_info *wl = port_wl(netdev_priv(netdev));
        unsigned long irqflag;
 
-       pr_debug("%s: <- \n", __func__);
-       down(&wl->assoc_stat_lock);
+       pr_debug("%s: <-\n", __func__);
+       mutex_lock(&wl->assoc_stat_lock);
        spin_lock_irqsave(&wl->lock, irqflag);
        if (test_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat) ||
            wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) {
@@ -989,9 +1008,9 @@ static int gelic_wl_get_essid(struct net_device *netdev,
        } else
                data->essid.flags = 0;
 
-       up(&wl->assoc_stat_lock);
+       mutex_unlock(&wl->assoc_stat_lock);
        spin_unlock_irqrestore(&wl->lock, irqflag);
-       pr_debug("%s: -> len=%d \n", __func__, data->essid.length);
+       pr_debug("%s: -> len=%d\n", __func__, data->essid.length);
 
        return 0;
 }
@@ -1004,11 +1023,11 @@ static int gelic_wl_set_encode(struct net_device *netdev,
        struct gelic_wl_info *wl = port_wl(netdev_priv(netdev));
        struct iw_point *enc = &data->encoding;
        __u16 flags;
-       unsigned int irqflag;
+       unsigned long irqflag;
        int key_index, index_specified;
        int ret = 0;
 
-       pr_debug("%s: <- \n", __func__);
+       pr_debug("%s: <-\n", __func__);
        flags = enc->flags & IW_ENCODE_FLAGS;
        key_index = enc->flags & IW_ENCODE_INDEX;
 
@@ -1067,7 +1086,7 @@ static int gelic_wl_set_encode(struct net_device *netdev,
        set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat);
 done:
        spin_unlock_irqrestore(&wl->lock, irqflag);
-       pr_debug("%s: -> \n", __func__);
+       pr_debug("%s: ->\n", __func__);
        return ret;
 }
 
@@ -1077,11 +1096,11 @@ static int gelic_wl_get_encode(struct net_device *netdev,
 {
        struct gelic_wl_info *wl = port_wl(netdev_priv(netdev));
        struct iw_point *enc = &data->encoding;
-       unsigned int irqflag;
+       unsigned long irqflag;
        unsigned int key_index, index_specified;
        int ret = 0;
 
-       pr_debug("%s: <- \n", __func__);
+       pr_debug("%s: <-\n", __func__);
        key_index = enc->flags & IW_ENCODE_INDEX;
        pr_debug("%s: flag=%#x point=%p len=%d extra=%p\n", __func__,
                 enc->flags, enc->pointer, enc->length, extra);
@@ -1147,11 +1166,7 @@ static int gelic_wl_set_ap(struct net_device *netdev,
                       ETH_ALEN);
                set_bit(GELIC_WL_STAT_BSSID_SET, &wl->stat);
                set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat);
-               pr_debug("%s: bss=%02x:%02x:%02x:%02x:%02x:%02x\n",
-                        __func__,
-                        wl->bssid[0], wl->bssid[1],
-                        wl->bssid[2], wl->bssid[3],
-                        wl->bssid[4], wl->bssid[5]);
+               pr_debug("%s: bss=%pM\n", __func__, wl->bssid);
        } else {
                pr_debug("%s: clear bssid\n", __func__);
                clear_bit(GELIC_WL_STAT_BSSID_SET, &wl->stat);
@@ -1170,7 +1185,7 @@ static int gelic_wl_get_ap(struct net_device *netdev,
        unsigned long irqflag;
 
        pr_debug("%s: <-\n", __func__);
-       down(&wl->assoc_stat_lock);
+       mutex_lock(&wl->assoc_stat_lock);
        spin_lock_irqsave(&wl->lock, irqflag);
        if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) {
                data->ap_addr.sa_family = ARPHRD_ETHER;
@@ -1180,7 +1195,7 @@ static int gelic_wl_get_ap(struct net_device *netdev,
                memset(data->ap_addr.sa_data, 0, ETH_ALEN);
 
        spin_unlock_irqrestore(&wl->lock, irqflag);
-       up(&wl->assoc_stat_lock);
+       mutex_unlock(&wl->assoc_stat_lock);
        pr_debug("%s: ->\n", __func__);
        return 0;
 }
@@ -1195,11 +1210,11 @@ static int gelic_wl_set_encodeext(struct net_device *netdev,
        struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
        __u16 alg;
        __u16 flags;
-       unsigned int irqflag;
+       unsigned long irqflag;
        int key_index;
        int ret = 0;
 
-       pr_debug("%s: <- \n", __func__);
+       pr_debug("%s: <-\n", __func__);
        flags = enc->flags & IW_ENCODE_FLAGS;
        alg = ext->alg;
        key_index = enc->flags & IW_ENCODE_INDEX;
@@ -1256,46 +1271,23 @@ static int gelic_wl_set_encodeext(struct net_device *netdev,
                set_bit(key_index, &wl->key_enabled);
                /* remember wep info changed */
                set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat);
-       } else if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) {
-               pr_debug("%s: TKIP/CCMP requested alg=%d\n", __func__, alg);
-               /* check key length */
-               if (IW_ENCODING_TOKEN_MAX < ext->key_len) {
-                       pr_info("%s: key is too long %d\n", __func__,
-                               ext->key_len);
+       } else if (alg == IW_ENCODE_ALG_PMK) {
+               if (ext->key_len != WPA_PSK_LEN) {
+                       pr_err("%s: PSK length wrong %d\n", __func__,
+                              ext->key_len);
                        ret = -EINVAL;
                        goto done;
                }
-               if (alg == IW_ENCODE_ALG_CCMP) {
-                       pr_debug("%s: AES selected\n", __func__);
-                       wl->group_cipher_method = GELIC_WL_CIPHER_AES;
-                       wl->pairwise_cipher_method = GELIC_WL_CIPHER_AES;
-                       wl->wpa_level = GELIC_WL_WPA_LEVEL_WPA2;
-               } else {
-                       pr_debug("%s: TKIP selected, WPA forced\n", __func__);
-                       wl->group_cipher_method = GELIC_WL_CIPHER_TKIP;
-                       wl->pairwise_cipher_method = GELIC_WL_CIPHER_TKIP;
-                       /* FIXME: how do we do if WPA2 + TKIP? */
-                       wl->wpa_level = GELIC_WL_WPA_LEVEL_WPA;
-               }
-               if (flags & IW_ENCODE_RESTRICTED)
-                       BUG();
-               wl->auth_method = GELIC_EURUS_AUTH_OPEN;
-               /* We should use same key for both and unicast */
-               if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
-                       pr_debug("%s: group key \n", __func__);
-               else
-                       pr_debug("%s: unicast key \n", __func__);
-               /* OK, update the key */
-               wl->key_len[key_index] = ext->key_len;
-               memset(wl->key[key_index], 0, IW_ENCODING_TOKEN_MAX);
-               memcpy(wl->key[key_index], ext->key, ext->key_len);
-               set_bit(key_index, &wl->key_enabled);
-               /* remember info changed */
-               set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat);
+               memset(wl->psk, 0, sizeof(wl->psk));
+               memcpy(wl->psk, ext->key, ext->key_len);
+               wl->psk_len = ext->key_len;
+               wl->psk_type = GELIC_EURUS_WPA_PSK_BIN;
+               /* remember PSK configured */
+               set_bit(GELIC_WL_STAT_WPA_PSK_SET, &wl->stat);
        }
 done:
        spin_unlock_irqrestore(&wl->lock, irqflag);
-       pr_debug("%s: -> \n", __func__);
+       pr_debug("%s: ->\n", __func__);
        return ret;
 }
 
@@ -1306,12 +1298,12 @@ static int gelic_wl_get_encodeext(struct net_device *netdev,
        struct gelic_wl_info *wl = port_wl(netdev_priv(netdev));
        struct iw_point *enc = &data->encoding;
        struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
-       unsigned int irqflag;
+       unsigned long irqflag;
        int key_index;
        int ret = 0;
        int max_key_len;
 
-       pr_debug("%s: <- \n", __func__);
+       pr_debug("%s: <-\n", __func__);
 
        max_key_len = enc->length - sizeof(struct iw_encode_ext);
        if (max_key_len < 0)
@@ -1366,7 +1358,7 @@ static int gelic_wl_get_encodeext(struct net_device *netdev,
        }
 out:
        spin_unlock_irqrestore(&wl->lock, irqflag);
-       pr_debug("%s: -> \n", __func__);
+       pr_debug("%s: ->\n", __func__);
        return ret;
 }
 /* SIOC{S,G}IWMODE */
@@ -1377,7 +1369,7 @@ static int gelic_wl_set_mode(struct net_device *netdev,
        __u32 mode = data->mode;
        int ret;
 
-       pr_debug("%s: <- \n", __func__);
+       pr_debug("%s: <-\n", __func__);
        if (mode == IW_MODE_INFRA)
                ret = 0;
        else
@@ -1391,117 +1383,12 @@ static int gelic_wl_get_mode(struct net_device *netdev,
                             union iwreq_data *data, char *extra)
 {
        __u32 *mode = &data->mode;
-       pr_debug("%s: <- \n", __func__);
+       pr_debug("%s: <-\n", __func__);
        *mode = IW_MODE_INFRA;
        pr_debug("%s: ->\n", __func__);
        return 0;
 }
 
-/* SIOCIWFIRSTPRIV */
-static int hex2bin(u8 *str, u8 *bin, unsigned int len)
-{
-       unsigned int i;
-       static unsigned char *hex = "0123456789ABCDEF";
-       unsigned char *p, *q;
-       u8 tmp;
-
-       if (len != WPA_PSK_LEN * 2)
-               return -EINVAL;
-
-       for (i = 0; i < WPA_PSK_LEN * 2; i += 2) {
-               p = strchr(hex, toupper(str[i]));
-               q = strchr(hex, toupper(str[i + 1]));
-               if (!p || !q) {
-                       pr_info("%s: unconvertible PSK digit=%d\n",
-                               __func__, i);
-                       return -EINVAL;
-               }
-               tmp = ((p - hex) << 4) + (q - hex);
-               *bin++ = tmp;
-       }
-       return 0;
-};
-
-static int gelic_wl_priv_set_psk(struct net_device *net_dev,
-                                struct iw_request_info *info,
-                                union iwreq_data *data, char *extra)
-{
-       struct gelic_wl_info *wl = port_wl(netdev_priv(net_dev));
-       unsigned int len;
-       unsigned int irqflag;
-       int ret = 0;
-
-       pr_debug("%s:<- len=%d\n", __func__, data->data.length);
-       len = data->data.length - 1;
-       if (len <= 2)
-               return -EINVAL;
-
-       spin_lock_irqsave(&wl->lock, irqflag);
-       if (extra[0] == '"' && extra[len - 1] == '"') {
-               pr_debug("%s: passphrase mode\n", __func__);
-               /* pass phrase */
-               if (GELIC_WL_EURUS_PSK_MAX_LEN < (len - 2)) {
-                       pr_info("%s: passphrase too long\n", __func__);
-                       ret = -E2BIG;
-                       goto out;
-               }
-               memset(wl->psk, 0, sizeof(wl->psk));
-               wl->psk_len = len - 2;
-               memcpy(wl->psk, &(extra[1]), wl->psk_len);
-               wl->psk_type = GELIC_EURUS_WPA_PSK_PASSPHRASE;
-       } else {
-               ret = hex2bin(extra, wl->psk, len);
-               if (ret)
-                       goto out;
-               wl->psk_len = WPA_PSK_LEN;
-               wl->psk_type = GELIC_EURUS_WPA_PSK_BIN;
-       }
-       set_bit(GELIC_WL_STAT_WPA_PSK_SET, &wl->stat);
-out:
-       spin_unlock_irqrestore(&wl->lock, irqflag);
-       pr_debug("%s:->\n", __func__);
-       return ret;
-}
-
-static int gelic_wl_priv_get_psk(struct net_device *net_dev,
-                                struct iw_request_info *info,
-                                union iwreq_data *data, char *extra)
-{
-       struct gelic_wl_info *wl = port_wl(netdev_priv(net_dev));
-       char *p;
-       unsigned int irqflag;
-       unsigned int i;
-
-       pr_debug("%s:<-\n", __func__);
-       if (!capable(CAP_NET_ADMIN))
-               return -EPERM;
-
-       spin_lock_irqsave(&wl->lock, irqflag);
-       p = extra;
-       if (test_bit(GELIC_WL_STAT_WPA_PSK_SET, &wl->stat)) {
-               if (wl->psk_type == GELIC_EURUS_WPA_PSK_BIN) {
-                       for (i = 0; i < wl->psk_len; i++) {
-                               sprintf(p, "%02xu", wl->psk[i]);
-                               p += 2;
-                       }
-                       *p = '\0';
-                       data->data.length = wl->psk_len * 2;
-               } else {
-                       *p++ = '"';
-                       memcpy(p, wl->psk, wl->psk_len);
-                       p += wl->psk_len;
-                       *p++ = '"';
-                       *p = '\0';
-                       data->data.length = wl->psk_len + 2;
-               }
-       } else
-               /* no psk set */
-               data->data.length = 0;
-       spin_unlock_irqrestore(&wl->lock, irqflag);
-       pr_debug("%s:-> %d\n", __func__, data->data.length);
-       return 0;
-}
-
 /* SIOCGIWNICKN */
 static int gelic_wl_get_nick(struct net_device *net_dev,
                                  struct iw_request_info *info,
@@ -1524,15 +1411,20 @@ static struct iw_statistics *gelic_wl_get_wireless_stats(
        struct gelic_eurus_cmd *cmd;
        struct iw_statistics *is;
        struct gelic_eurus_rssi_info *rssi;
+       void *buf;
 
        pr_debug("%s: <-\n", __func__);
 
+       buf = (void *)__get_free_page(GFP_KERNEL);
+       if (!buf)
+               return NULL;
+
        is = &wl->iwstat;
        memset(is, 0, sizeof(*is));
        cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_GET_RSSI_CFG,
-                                  wl->buf, sizeof(*rssi));
+                                  buf, sizeof(*rssi));
        if (cmd && !cmd->status && !cmd->cmd_status) {
-               rssi = wl->buf;
+               rssi = buf;
                is->qual.level = be16_to_cpu(rssi->rssi);
                is->qual.updated = IW_QUAL_LEVEL_UPDATED |
                        IW_QUAL_QUAL_INVALID | IW_QUAL_NOISE_INVALID;
@@ -1541,6 +1433,7 @@ static struct iw_statistics *gelic_wl_get_wireless_stats(
                is->qual.updated = IW_QUAL_ALL_INVALID;
 
        kfree(cmd);
+       free_page((unsigned long)buf);
        pr_debug("%s: ->\n", __func__);
        return is;
 }
@@ -1548,13 +1441,16 @@ static struct iw_statistics *gelic_wl_get_wireless_stats(
 /*
  *  scanning helpers
  */
-static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan)
+static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan,
+                              u8 *essid, size_t essid_len)
 {
        struct gelic_eurus_cmd *cmd;
        int ret = 0;
+       void *buf = NULL;
+       size_t len;
 
        pr_debug("%s: <- always=%d\n", __func__, always_scan);
-       if (down_interruptible(&wl->scan_lock))
+       if (mutex_lock_interruptible(&wl->scan_lock))
                return -ERESTARTSYS;
 
        /*
@@ -1568,18 +1464,35 @@ static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan)
        init_completion(&wl->scan_done);
        /*
         * If we have already a bss list, don't try to get new
+        * unless we are doing an ESSID scan
         */
-       if (!always_scan && wl->scan_stat == GELIC_WL_SCAN_STAT_GOT_LIST) {
+       if ((!essid_len && !always_scan)
+           && wl->scan_stat == GELIC_WL_SCAN_STAT_GOT_LIST) {
                pr_debug("%s: already has the list\n", __func__);
                complete(&wl->scan_done);
                goto out;
        }
+
+       /* ESSID scan ? */
+       if (essid_len && essid) {
+               buf = (void *)__get_free_page(GFP_KERNEL);
+               if (!buf) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               len = IW_ESSID_MAX_SIZE; /* hypervisor always requires 32 */
+               memset(buf, 0, len);
+               memcpy(buf, essid, essid_len);
+               pr_debug("%s: essid scan='%s'\n", __func__, (char *)buf);
+       } else
+               len = 0;
+
        /*
         * issue start scan request
         */
        wl->scan_stat = GELIC_WL_SCAN_STAT_SCANNING;
        cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_START_SCAN,
-                                  NULL, 0);
+                                  buf, len);
        if (!cmd || cmd->status || cmd->cmd_status) {
                wl->scan_stat = GELIC_WL_SCAN_STAT_INIT;
                complete(&wl->scan_done);
@@ -1588,7 +1501,8 @@ static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan)
        }
        kfree(cmd);
 out:
-       up(&wl->scan_lock);
+       free_page((unsigned long)buf);
+       mutex_unlock(&wl->scan_lock);
        pr_debug("%s: ->\n", __func__);
        return ret;
 }
@@ -1607,10 +1521,16 @@ static void gelic_wl_scan_complete_event(struct gelic_wl_info *wl)
        union iwreq_data data;
        unsigned long this_time = jiffies;
        unsigned int data_len, i, found, r;
-       DECLARE_MAC_BUF(mac);
+       void *buf;
 
        pr_debug("%s:start\n", __func__);
-       down(&wl->scan_lock);
+       mutex_lock(&wl->scan_lock);
+
+       buf = (void *)__get_free_page(GFP_KERNEL);
+       if (!buf) {
+               pr_info("%s: scan buffer alloc failed\n", __func__);
+               goto out;
+       }
 
        if (wl->scan_stat != GELIC_WL_SCAN_STAT_SCANNING) {
                /*
@@ -1622,7 +1542,7 @@ static void gelic_wl_scan_complete_event(struct gelic_wl_info *wl)
        }
 
        cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_GET_SCAN,
-                                  wl->buf, PAGE_SIZE);
+                                  buf, PAGE_SIZE);
        if (!cmd || cmd->status || cmd->cmd_status) {
                wl->scan_stat = GELIC_WL_SCAN_STAT_INIT;
                pr_info("%s:cmd failed\n", __func__);
@@ -1648,14 +1568,14 @@ static void gelic_wl_scan_complete_event(struct gelic_wl_info *wl)
                }
        }
 
-       /* put them in the newtork_list */
-       for (i = 0, scan_info_size = 0, scan_info = wl->buf;
+       /* put them in the network_list */
+       for (i = 0, scan_info_size = 0, scan_info = buf;
             scan_info_size < data_len;
             i++, scan_info_size += be16_to_cpu(scan_info->size),
             scan_info = (void *)scan_info + be16_to_cpu(scan_info->size)) {
-               pr_debug("%s:size=%d bssid=%s scan_info=%p\n", __func__,
+               pr_debug("%s:size=%d bssid=%pM scan_info=%p\n", __func__,
                         be16_to_cpu(scan_info->size),
-                        print_mac(mac, &scan_info->bssid[2]), scan_info);
+                        &scan_info->bssid[2], scan_info);
 
                /*
                 * The wireless firmware may return invalid channel 0 and/or
@@ -1710,14 +1630,14 @@ static void gelic_wl_scan_complete_event(struct gelic_wl_info *wl)
                target->essid_len = strnlen(scan_info->essid,
                                            sizeof(scan_info->essid));
                target->rate_len = 0;
-               for (r = 0; r < MAX_RATES_LENGTH; r++)
+               for (r = 0; r < 12; r++)
                        if (scan_info->rate[r])
                                target->rate_len++;
                if (8 < target->rate_len)
                        pr_info("%s: AP returns %d rates\n", __func__,
                                target->rate_len);
                target->rate_ext_len = 0;
-               for (r = 0; r < MAX_RATES_EX_LENGTH; r++)
+               for (r = 0; r < 16; r++)
                        if (scan_info->ext_rate[r])
                                target->rate_ext_len++;
                list_move_tail(&target->list, &wl->network_list);
@@ -1726,8 +1646,9 @@ static void gelic_wl_scan_complete_event(struct gelic_wl_info *wl)
        wireless_send_event(port_to_netdev(wl_port(wl)), SIOCGIWSCAN, &data,
                            NULL);
 out:
+       free_page((unsigned long)buf);
        complete(&wl->scan_done);
-       up(&wl->scan_lock);
+       mutex_unlock(&wl->scan_lock);
        pr_debug("%s:end\n", __func__);
 }
 
@@ -1755,7 +1676,6 @@ struct gelic_wl_scan_info *gelic_wl_find_best_bss(struct gelic_wl_info *wl)
        struct gelic_wl_scan_info *best_bss;
        int weight, best_weight;
        u16 security;
-       DECLARE_MAC_BUF(mac);
 
        pr_debug("%s: <-\n", __func__);
 
@@ -1825,8 +1745,8 @@ struct gelic_wl_scan_info *gelic_wl_find_best_bss(struct gelic_wl_info *wl)
 #ifdef DEBUG
        pr_debug("%s: -> bss=%p\n", __func__, best_bss);
        if (best_bss) {
-               pr_debug("%s:addr=%s\n", __func__,
-                        print_mac(mac, &best_bss->hwinfo->bssid[2]));
+               pr_debug("%s:addr=%pM\n", __func__,
+                        &best_bss->hwinfo->bssid[2]);
        }
 #endif
        return best_bss;
@@ -1848,7 +1768,10 @@ static int gelic_wl_do_wep_setup(struct gelic_wl_info *wl)
 
        pr_debug("%s: <-\n", __func__);
        /* we can assume no one should uses the buffer */
-       wep = wl->buf;
+       wep = (struct gelic_eurus_wep_cfg *)__get_free_page(GFP_KERNEL);
+       if (!wep)
+               return -ENOMEM;
+
        memset(wep, 0, sizeof(*wep));
 
        if (wl->group_cipher_method == GELIC_WL_CIPHER_WEP) {
@@ -1898,6 +1821,7 @@ static int gelic_wl_do_wep_setup(struct gelic_wl_info *wl)
 
        kfree(cmd);
 out:
+       free_page((unsigned long)wep);
        pr_debug("%s: ->\n", __func__);
        return ret;
 }
@@ -1941,7 +1865,10 @@ static int gelic_wl_do_wpa_setup(struct gelic_wl_info *wl)
 
        pr_debug("%s: <-\n", __func__);
        /* we can assume no one should uses the buffer */
-       wpa = wl->buf;
+       wpa = (struct gelic_eurus_wpa_cfg *)__get_free_page(GFP_KERNEL);
+       if (!wpa)
+               return -ENOMEM;
+
        memset(wpa, 0, sizeof(*wpa));
 
        if (!test_bit(GELIC_WL_STAT_WPA_PSK_SET, &wl->stat))
@@ -1977,7 +1904,7 @@ static int gelic_wl_do_wpa_setup(struct gelic_wl_info *wl)
        /* PSK type */
        wpa->psk_type = cpu_to_be16(wl->psk_type);
 #ifdef DEBUG
-       pr_debug("%s: sec=%s psktype=%s\nn", __func__,
+       pr_debug("%s: sec=%s psktype=%s\n", __func__,
                 wpasecstr(wpa->security),
                 (wpa->psk_type == GELIC_EURUS_WPA_PSK_BIN) ?
                 "BIN" : "passphrase");
@@ -1987,9 +1914,9 @@ static int gelic_wl_do_wpa_setup(struct gelic_wl_info *wl)
         * the debug log because this dumps your precious
         * passphrase/key.
         */
-       pr_debug("%s: psk=%s\n",
+       pr_debug("%s: psk=%s\n", __func__,
                 (wpa->psk_type == GELIC_EURUS_WPA_PSK_BIN) ?
-                (char *)"N/A" : (char *)wpa->psk);
+                "N/A" : wpa->psk);
 #endif
 #endif
        /* issue wpa setup */
@@ -2000,6 +1927,7 @@ static int gelic_wl_do_wpa_setup(struct gelic_wl_info *wl)
        else if (cmd->status || cmd->cmd_status)
                ret = -ENXIO;
        kfree(cmd);
+       free_page((unsigned long)wpa);
        pr_debug("%s: --> %d\n", __func__, ret);
        return ret;
 }
@@ -2018,7 +1946,10 @@ static int gelic_wl_associate_bss(struct gelic_wl_info *wl,
        pr_debug("%s: <-\n", __func__);
 
        /* do common config */
-       common = wl->buf;
+       common = (struct gelic_eurus_common_cfg *)__get_free_page(GFP_KERNEL);
+       if (!common)
+               return -ENOMEM;
+
        memset(common, 0, sizeof(*common));
        common->bss_type = cpu_to_be16(GELIC_EURUS_BSS_INFRA);
        common->op_mode = cpu_to_be16(GELIC_EURUS_OPMODE_11BG);
@@ -2065,6 +1996,9 @@ static int gelic_wl_associate_bss(struct gelic_wl_info *wl,
        if (ret) {
                pr_debug("%s: WEP/WPA setup failed %d\n", __func__,
                         ret);
+               ret = -EPERM;
+               gelic_wl_send_iwap_event(wl, NULL);
+               goto out;
        }
 
        /* start association */
@@ -2087,7 +2021,7 @@ static int gelic_wl_associate_bss(struct gelic_wl_info *wl,
 
        if (!rc) {
                /* timeouted.  Maybe key or cyrpt mode is wrong */
-               pr_info("%s: connect timeout \n", __func__);
+               pr_info("%s: connect timeout\n", __func__);
                cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_DISASSOC,
                                           NULL, 0);
                kfree(cmd);
@@ -2104,6 +2038,7 @@ static int gelic_wl_associate_bss(struct gelic_wl_info *wl,
                pr_info("%s: connected\n", __func__);
        }
 out:
+       free_page((unsigned long)common);
        pr_debug("%s: ->\n", __func__);
        return ret;
 }
@@ -2127,11 +2062,11 @@ static void gelic_wl_connected_event(struct gelic_wl_info *wl,
        }
 
        if (desired_event == event) {
-               pr_debug("%s: completed \n", __func__);
+               pr_debug("%s: completed\n", __func__);
                complete(&wl->assoc_done);
                netif_carrier_on(port_to_netdev(wl_port(wl)));
        } else
-               pr_debug("%s: event %#lx under wpa\n",
+               pr_debug("%s: event %#llx under wpa\n",
                                 __func__, event);
 }
 
@@ -2151,7 +2086,7 @@ static void gelic_wl_disconnect_event(struct gelic_wl_info *wl,
         * As it waits with timeout, just leave assoc_done
         * uncompleted, then it terminates with timeout
         */
-       if (down_trylock(&wl->assoc_stat_lock)) {
+       if (!mutex_trylock(&wl->assoc_stat_lock)) {
                pr_debug("%s: already locked\n", __func__);
                lock = 0;
        } else {
@@ -2170,7 +2105,7 @@ static void gelic_wl_disconnect_event(struct gelic_wl_info *wl,
        netif_carrier_off(port_to_netdev(wl_port(wl)));
 
        if (lock)
-               up(&wl->assoc_stat_lock);
+               mutex_unlock(&wl->assoc_stat_lock);
 }
 /*
  * event worker
@@ -2255,15 +2190,30 @@ static void gelic_wl_assoc_worker(struct work_struct *work)
 
        struct gelic_wl_scan_info *best_bss;
        int ret;
+       unsigned long irqflag;
+       u8 *essid;
+       size_t essid_len;
 
        wl = container_of(work, struct gelic_wl_info, assoc_work.work);
 
-       down(&wl->assoc_stat_lock);
+       mutex_lock(&wl->assoc_stat_lock);
 
        if (wl->assoc_stat != GELIC_WL_ASSOC_STAT_DISCONN)
                goto out;
 
-       ret = gelic_wl_start_scan(wl, 0);
+       spin_lock_irqsave(&wl->lock, irqflag);
+       if (test_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat)) {
+               pr_debug("%s: assoc ESSID configured %s\n", __func__,
+                        wl->essid);
+               essid = wl->essid;
+               essid_len = wl->essid_len;
+       } else {
+               essid = NULL;
+               essid_len = 0;
+       }
+       spin_unlock_irqrestore(&wl->lock, irqflag);
+
+       ret = gelic_wl_start_scan(wl, 0, essid, essid_len);
        if (ret == -ERESTARTSYS) {
                pr_debug("%s: scan start failed association\n", __func__);
                schedule_delayed_work(&wl->assoc_work, HZ/10); /*FIXME*/
@@ -2282,7 +2232,7 @@ static void gelic_wl_assoc_worker(struct work_struct *work)
        wait_for_completion(&wl->scan_done);
 
        pr_debug("%s: scan done\n", __func__);
-       down(&wl->scan_lock);
+       mutex_lock(&wl->scan_lock);
        if (wl->scan_stat != GELIC_WL_SCAN_STAT_GOT_LIST) {
                gelic_wl_send_iwap_event(wl, NULL);
                pr_info("%s: no scan list. association failed\n", __func__);
@@ -2302,9 +2252,9 @@ static void gelic_wl_assoc_worker(struct work_struct *work)
        if (ret)
                pr_info("%s: association failed %d\n", __func__, ret);
 scan_lock_out:
-       up(&wl->scan_lock);
+       mutex_unlock(&wl->scan_lock);
 out:
-       up(&wl->assoc_stat_lock);
+       mutex_unlock(&wl->assoc_stat_lock);
 }
 /*
  * Interrupt handler
@@ -2329,61 +2279,34 @@ void gelic_wl_interrupt(struct net_device *netdev, u64 status)
 /*
  * driver helpers
  */
-#define IW_IOCTL(n) [(n) - SIOCSIWCOMMIT]
 static const iw_handler gelic_wl_wext_handler[] =
 {
-       IW_IOCTL(SIOCGIWNAME)           = gelic_wl_get_name,
-       IW_IOCTL(SIOCGIWRANGE)          = gelic_wl_get_range,
-       IW_IOCTL(SIOCSIWSCAN)           = gelic_wl_set_scan,
-       IW_IOCTL(SIOCGIWSCAN)           = gelic_wl_get_scan,
-       IW_IOCTL(SIOCSIWAUTH)           = gelic_wl_set_auth,
-       IW_IOCTL(SIOCGIWAUTH)           = gelic_wl_get_auth,
-       IW_IOCTL(SIOCSIWESSID)          = gelic_wl_set_essid,
-       IW_IOCTL(SIOCGIWESSID)          = gelic_wl_get_essid,
-       IW_IOCTL(SIOCSIWENCODE)         = gelic_wl_set_encode,
-       IW_IOCTL(SIOCGIWENCODE)         = gelic_wl_get_encode,
-       IW_IOCTL(SIOCSIWAP)             = gelic_wl_set_ap,
-       IW_IOCTL(SIOCGIWAP)             = gelic_wl_get_ap,
-       IW_IOCTL(SIOCSIWENCODEEXT)      = gelic_wl_set_encodeext,
-       IW_IOCTL(SIOCGIWENCODEEXT)      = gelic_wl_get_encodeext,
-       IW_IOCTL(SIOCSIWMODE)           = gelic_wl_set_mode,
-       IW_IOCTL(SIOCGIWMODE)           = gelic_wl_get_mode,
-       IW_IOCTL(SIOCGIWNICKN)          = gelic_wl_get_nick,
-};
-
-static struct iw_priv_args gelic_wl_private_args[] =
-{
-       {
-               .cmd = GELIC_WL_PRIV_SET_PSK,
-               .set_args = IW_PRIV_TYPE_CHAR |
-               (GELIC_WL_EURUS_PSK_MAX_LEN + 2),
-               .name = "set_psk"
-       },
-       {
-               .cmd = GELIC_WL_PRIV_GET_PSK,
-               .get_args = IW_PRIV_TYPE_CHAR |
-               (GELIC_WL_EURUS_PSK_MAX_LEN + 2),
-               .name = "get_psk"
-       }
-};
-
-static const iw_handler gelic_wl_private_handler[] =
-{
-       gelic_wl_priv_set_psk,
-       gelic_wl_priv_get_psk,
+       IW_HANDLER(SIOCGIWNAME, gelic_wl_get_name),
+       IW_HANDLER(SIOCGIWRANGE, gelic_wl_get_range),
+       IW_HANDLER(SIOCSIWSCAN, gelic_wl_set_scan),
+       IW_HANDLER(SIOCGIWSCAN, gelic_wl_get_scan),
+       IW_HANDLER(SIOCSIWAUTH, gelic_wl_set_auth),
+       IW_HANDLER(SIOCGIWAUTH, gelic_wl_get_auth),
+       IW_HANDLER(SIOCSIWESSID, gelic_wl_set_essid),
+       IW_HANDLER(SIOCGIWESSID, gelic_wl_get_essid),
+       IW_HANDLER(SIOCSIWENCODE, gelic_wl_set_encode),
+       IW_HANDLER(SIOCGIWENCODE, gelic_wl_get_encode),
+       IW_HANDLER(SIOCSIWAP, gelic_wl_set_ap),
+       IW_HANDLER(SIOCGIWAP, gelic_wl_get_ap),
+       IW_HANDLER(SIOCSIWENCODEEXT, gelic_wl_set_encodeext),
+       IW_HANDLER(SIOCGIWENCODEEXT, gelic_wl_get_encodeext),
+       IW_HANDLER(SIOCSIWMODE, gelic_wl_set_mode),
+       IW_HANDLER(SIOCGIWMODE, gelic_wl_get_mode),
+       IW_HANDLER(SIOCGIWNICKN, gelic_wl_get_nick),
 };
 
 static const struct iw_handler_def gelic_wl_wext_handler_def = {
        .num_standard           = ARRAY_SIZE(gelic_wl_wext_handler),
        .standard               = gelic_wl_wext_handler,
        .get_wireless_stats     = gelic_wl_get_wireless_stats,
-       .num_private            = ARRAY_SIZE(gelic_wl_private_handler),
-       .num_private_args       = ARRAY_SIZE(gelic_wl_private_args),
-       .private                = gelic_wl_private_handler,
-       .private_args           = gelic_wl_private_args,
 };
 
-static struct net_device *gelic_wl_alloc(struct gelic_card *card)
+static struct net_device * __devinit gelic_wl_alloc(struct gelic_card *card)
 {
        struct net_device *netdev;
        struct gelic_port *port;
@@ -2393,7 +2316,7 @@ static struct net_device *gelic_wl_alloc(struct gelic_card *card)
        pr_debug("%s:start\n", __func__);
        netdev = alloc_etherdev(sizeof(struct gelic_port) +
                                sizeof(struct gelic_wl_info));
-       pr_debug("%s: netdev =%p card=%p \np", __func__, netdev, card);
+       pr_debug("%s: netdev =%p card=%p\n", __func__, netdev, card);
        if (!netdev)
                return NULL;
 
@@ -2431,8 +2354,8 @@ static struct net_device *gelic_wl_alloc(struct gelic_card *card)
 
        INIT_DELAYED_WORK(&wl->event_work, gelic_wl_event_worker);
        INIT_DELAYED_WORK(&wl->assoc_work, gelic_wl_assoc_worker);
-       init_MUTEX(&wl->scan_lock);
-       init_MUTEX(&wl->assoc_stat_lock);
+       mutex_init(&wl->scan_lock);
+       mutex_init(&wl->assoc_stat_lock);
 
        init_completion(&wl->scan_done);
        /* for the case that no scan request is issued and stop() is called */
@@ -2446,16 +2369,9 @@ static struct net_device *gelic_wl_alloc(struct gelic_card *card)
        BUILD_BUG_ON(PAGE_SIZE <
                     sizeof(struct gelic_eurus_scan_info) *
                     GELIC_EURUS_MAX_SCAN);
-       wl->buf = (void *)get_zeroed_page(GFP_KERNEL);
-       if (!wl->buf) {
-               pr_info("%s:buffer allocation failed\n", __func__);
-               goto fail_getpage;
-       }
        pr_debug("%s:end\n", __func__);
        return netdev;
 
-fail_getpage:
-       destroy_workqueue(wl->event_queue);
 fail_event_workqueue:
        destroy_workqueue(wl->eurus_cmd_queue);
 fail_cmd_workqueue:
@@ -2474,8 +2390,6 @@ static void gelic_wl_free(struct gelic_wl_info *wl)
 
        pr_debug("%s: <-\n", __func__);
 
-       free_page((unsigned long)wl->buf);
-
        pr_debug("%s: destroy queues\n", __func__);
        destroy_workqueue(wl->eurus_cmd_queue);
        destroy_workqueue(wl->event_queue);
@@ -2650,7 +2564,21 @@ static int gelic_wl_stop(struct net_device *netdev)
 
 /* -- */
 
-static struct ethtool_ops gelic_wl_ethtool_ops = {
+static const struct net_device_ops gelic_wl_netdevice_ops = {
+       .ndo_open = gelic_wl_open,
+       .ndo_stop = gelic_wl_stop,
+       .ndo_start_xmit = gelic_net_xmit,
+       .ndo_set_multicast_list = gelic_net_set_multi,
+       .ndo_change_mtu = gelic_net_change_mtu,
+       .ndo_tx_timeout = gelic_net_tx_timeout,
+       .ndo_set_mac_address = eth_mac_addr,
+       .ndo_validate_addr = eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller = gelic_net_poll_controller,
+#endif
+};
+
+static const struct ethtool_ops gelic_wl_ethtool_ops = {
        .get_drvinfo    = gelic_net_get_drvinfo,
        .get_link       = gelic_wl_get_link,
        .get_tx_csum    = ethtool_op_get_tx_csum,
@@ -2659,32 +2587,23 @@ static struct ethtool_ops gelic_wl_ethtool_ops = {
        .set_rx_csum    = gelic_net_set_rx_csum,
 };
 
-static void gelic_wl_setup_netdev_ops(struct net_device *netdev)
+static void __devinit gelic_wl_setup_netdev_ops(struct net_device *netdev)
 {
        struct gelic_wl_info *wl;
        wl = port_wl(netdev_priv(netdev));
        BUG_ON(!wl);
-       netdev->open = &gelic_wl_open;
-       netdev->stop = &gelic_wl_stop;
-       netdev->hard_start_xmit = &gelic_net_xmit;
-       netdev->set_multicast_list = &gelic_net_set_multi;
-       netdev->change_mtu = &gelic_net_change_mtu;
-       netdev->wireless_data = &wl->wireless_data;
-       netdev->wireless_handlers = &gelic_wl_wext_handler_def;
-       /* tx watchdog */
-       netdev->tx_timeout = &gelic_net_tx_timeout;
        netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT;
 
        netdev->ethtool_ops = &gelic_wl_ethtool_ops;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       netdev->poll_controller = gelic_net_poll_controller;
-#endif
+       netdev->netdev_ops = &gelic_wl_netdevice_ops;
+       netdev->wireless_data = &wl->wireless_data;
+       netdev->wireless_handlers = &gelic_wl_wext_handler_def;
 }
 
 /*
  * driver probe/remove
  */
-int gelic_wl_driver_probe(struct gelic_card *card)
+int __devinit gelic_wl_driver_probe(struct gelic_card *card)
 {
        int ret;
        struct net_device *netdev;