2656 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * PS3 gelic network driver.4 *5 * Copyright (C) 2007 Sony Computer Entertainment Inc.6 * Copyright 2007 Sony Corporation7 */8#undef DEBUG9 10#include <linux/kernel.h>11#include <linux/module.h>12#include <linux/slab.h>13 14#include <linux/etherdevice.h>15#include <linux/ethtool.h>16#include <linux/if_vlan.h>17 18#include <linux/in.h>19#include <linux/ip.h>20#include <linux/tcp.h>21#include <linux/wireless.h>22#include <linux/ieee80211.h>23#include <linux/if_arp.h>24#include <linux/ctype.h>25#include <linux/string.h>26#include <net/iw_handler.h>27 28#include <linux/dma-mapping.h>29#include <net/checksum.h>30#include <asm/firmware.h>31#include <asm/ps3.h>32#include <asm/lv1call.h>33 34#include "ps3_gelic_net.h"35#include "ps3_gelic_wireless.h"36 37 38static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan,39 u8 *essid, size_t essid_len);40static int gelic_wl_try_associate(struct net_device *netdev);41 42/*43 * tables44 */45 46/* 802.11b/g channel to freq in MHz */47static const int channel_freq[] = {48 2412, 2417, 2422, 2427, 2432,49 2437, 2442, 2447, 2452, 2457,50 2462, 2467, 2472, 248451};52#define NUM_CHANNELS ARRAY_SIZE(channel_freq)53 54/* in bps */55static const int bitrate_list[] = {56 1000000,57 2000000,58 5500000,59 11000000,60 6000000,61 9000000,62 12000000,63 18000000,64 24000000,65 36000000,66 48000000,67 5400000068};69#define NUM_BITRATES ARRAY_SIZE(bitrate_list)70 71/*72 * wpa2 support requires the hypervisor version 2.0 or later73 */74static inline int wpa2_capable(void)75{76 return 0 <= ps3_compare_firmware_version(2, 0, 0);77}78 79static inline int precise_ie(void)80{81 return 0 <= ps3_compare_firmware_version(2, 2, 0);82}83/*84 * post_eurus_cmd helpers85 */86struct eurus_cmd_arg_info {87 int pre_arg; /* command requires arg1, arg2 at POST COMMAND */88 int post_arg; /* command requires arg1, arg2 at GET_RESULT */89};90 91static const struct eurus_cmd_arg_info cmd_info[GELIC_EURUS_CMD_MAX_INDEX] = {92 [GELIC_EURUS_CMD_SET_COMMON_CFG] = { .pre_arg = 1},93 [GELIC_EURUS_CMD_SET_WEP_CFG] = { .pre_arg = 1},94 [GELIC_EURUS_CMD_SET_WPA_CFG] = { .pre_arg = 1},95 [GELIC_EURUS_CMD_GET_COMMON_CFG] = { .post_arg = 1},96 [GELIC_EURUS_CMD_GET_WEP_CFG] = { .post_arg = 1},97 [GELIC_EURUS_CMD_GET_WPA_CFG] = { .post_arg = 1},98 [GELIC_EURUS_CMD_GET_RSSI_CFG] = { .post_arg = 1},99 [GELIC_EURUS_CMD_START_SCAN] = { .pre_arg = 1},100 [GELIC_EURUS_CMD_GET_SCAN] = { .post_arg = 1},101};102 103#ifdef DEBUG104static const char *cmdstr(enum gelic_eurus_command ix)105{106 switch (ix) {107 case GELIC_EURUS_CMD_ASSOC:108 return "ASSOC";109 case GELIC_EURUS_CMD_DISASSOC:110 return "DISASSOC";111 case GELIC_EURUS_CMD_START_SCAN:112 return "SCAN";113 case GELIC_EURUS_CMD_GET_SCAN:114 return "GET SCAN";115 case GELIC_EURUS_CMD_SET_COMMON_CFG:116 return "SET_COMMON_CFG";117 case GELIC_EURUS_CMD_GET_COMMON_CFG:118 return "GET_COMMON_CFG";119 case GELIC_EURUS_CMD_SET_WEP_CFG:120 return "SET_WEP_CFG";121 case GELIC_EURUS_CMD_GET_WEP_CFG:122 return "GET_WEP_CFG";123 case GELIC_EURUS_CMD_SET_WPA_CFG:124 return "SET_WPA_CFG";125 case GELIC_EURUS_CMD_GET_WPA_CFG:126 return "GET_WPA_CFG";127 case GELIC_EURUS_CMD_GET_RSSI_CFG:128 return "GET_RSSI";129 default:130 break;131 }132 return "";133};134#else135static inline const char *cmdstr(enum gelic_eurus_command ix)136{137 return "";138}139#endif140 141/* synchronously do eurus commands */142static void gelic_eurus_sync_cmd_worker(struct work_struct *work)143{144 struct gelic_eurus_cmd *cmd;145 struct gelic_card *card;146 struct gelic_wl_info *wl;147 148 u64 arg1, arg2;149 150 pr_debug("%s: <-\n", __func__);151 cmd = container_of(work, struct gelic_eurus_cmd, work);152 BUG_ON(cmd_info[cmd->cmd].pre_arg &&153 cmd_info[cmd->cmd].post_arg);154 wl = cmd->wl;155 card = port_to_card(wl_port(wl));156 157 if (cmd_info[cmd->cmd].pre_arg) {158 arg1 = (cmd->buffer) ?159 ps3_mm_phys_to_lpar(__pa(cmd->buffer)) :160 0;161 arg2 = cmd->buf_size;162 } else {163 arg1 = 0;164 arg2 = 0;165 }166 init_completion(&wl->cmd_done_intr);167 pr_debug("%s: cmd='%s' start\n", __func__, cmdstr(cmd->cmd));168 cmd->status = lv1_net_control(bus_id(card), dev_id(card),169 GELIC_LV1_POST_WLAN_CMD,170 cmd->cmd, arg1, arg2,171 &cmd->tag, &cmd->size);172 if (cmd->status) {173 complete(&cmd->done);174 pr_info("%s: cmd issue failed\n", __func__);175 return;176 }177 178 wait_for_completion(&wl->cmd_done_intr);179 180 if (cmd_info[cmd->cmd].post_arg) {181 arg1 = ps3_mm_phys_to_lpar(__pa(cmd->buffer));182 arg2 = cmd->buf_size;183 } else {184 arg1 = 0;185 arg2 = 0;186 }187 188 cmd->status = lv1_net_control(bus_id(card), dev_id(card),189 GELIC_LV1_GET_WLAN_CMD_RESULT,190 cmd->tag, arg1, arg2,191 &cmd->cmd_status, &cmd->size);192#ifdef DEBUG193 if (cmd->status || cmd->cmd_status) {194 pr_debug("%s: cmd done tag=%#lx arg1=%#lx, arg2=%#lx\n", __func__,195 cmd->tag, arg1, arg2);196 pr_debug("%s: cmd done status=%#x cmd_status=%#lx size=%#lx\n",197 __func__, cmd->status, cmd->cmd_status, cmd->size);198 }199#endif200 complete(&cmd->done);201 pr_debug("%s: cmd='%s' done\n", __func__, cmdstr(cmd->cmd));202}203 204static struct gelic_eurus_cmd *gelic_eurus_sync_cmd(struct gelic_wl_info *wl,205 unsigned int eurus_cmd,206 void *buffer,207 unsigned int buf_size)208{209 struct gelic_eurus_cmd *cmd;210 211 /* allocate cmd */212 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);213 if (!cmd)214 return NULL;215 216 /* initialize members */217 cmd->cmd = eurus_cmd;218 cmd->buffer = buffer;219 cmd->buf_size = buf_size;220 cmd->wl = wl;221 INIT_WORK(&cmd->work, gelic_eurus_sync_cmd_worker);222 init_completion(&cmd->done);223 queue_work(wl->eurus_cmd_queue, &cmd->work);224 225 /* wait for command completion */226 wait_for_completion(&cmd->done);227 228 return cmd;229}230 231static u32 gelic_wl_get_link(struct net_device *netdev)232{233 struct gelic_wl_info *wl = port_wl(netdev_port(netdev));234 u32 ret;235 236 pr_debug("%s: <-\n", __func__);237 mutex_lock(&wl->assoc_stat_lock);238 if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED)239 ret = 1;240 else241 ret = 0;242 mutex_unlock(&wl->assoc_stat_lock);243 pr_debug("%s: ->\n", __func__);244 return ret;245}246 247static void gelic_wl_send_iwap_event(struct gelic_wl_info *wl, u8 *bssid)248{249 union iwreq_data data;250 251 memset(&data, 0, sizeof(data));252 if (bssid)253 memcpy(data.ap_addr.sa_data, bssid, ETH_ALEN);254 data.ap_addr.sa_family = ARPHRD_ETHER;255 wireless_send_event(port_to_netdev(wl_port(wl)), SIOCGIWAP,256 &data, NULL);257}258 259/*260 * wireless extension handlers and helpers261 */262 263/* SIOGIWNAME */264static int gelic_wl_get_name(struct net_device *dev,265 struct iw_request_info *info,266 union iwreq_data *iwreq, char *extra)267{268 strcpy(iwreq->name, "IEEE 802.11bg");269 return 0;270}271 272static void gelic_wl_get_ch_info(struct gelic_wl_info *wl)273{274 struct gelic_card *card = port_to_card(wl_port(wl));275 u64 ch_info_raw, tmp;276 int status;277 278 if (!test_and_set_bit(GELIC_WL_STAT_CH_INFO, &wl->stat)) {279 status = lv1_net_control(bus_id(card), dev_id(card),280 GELIC_LV1_GET_CHANNEL, 0, 0, 0,281 &ch_info_raw,282 &tmp);283 /* some fw versions may return error */284 if (status) {285 if (status != LV1_NO_ENTRY)286 pr_info("%s: available ch unknown\n", __func__);287 wl->ch_info = 0x07ff;/* 11 ch */288 } else289 /* 16 bits of MSB has available channels */290 wl->ch_info = ch_info_raw >> 48;291 }292}293 294/* SIOGIWRANGE */295static int gelic_wl_get_range(struct net_device *netdev,296 struct iw_request_info *info,297 union iwreq_data *iwreq, char *extra)298{299 struct iw_point *point = &iwreq->data;300 struct iw_range *range = (struct iw_range *)extra;301 struct gelic_wl_info *wl = port_wl(netdev_port(netdev));302 unsigned int i, chs;303 304 pr_debug("%s: <-\n", __func__);305 point->length = sizeof(struct iw_range);306 memset(range, 0, sizeof(struct iw_range));307 308 range->we_version_compiled = WIRELESS_EXT;309 range->we_version_source = 22;310 311 /* available channels and frequencies */312 gelic_wl_get_ch_info(wl);313 314 for (i = 0, chs = 0;315 i < NUM_CHANNELS && chs < IW_MAX_FREQUENCIES; i++)316 if (wl->ch_info & (1 << i)) {317 range->freq[chs].i = i + 1;318 range->freq[chs].m = channel_freq[i];319 range->freq[chs].e = 6;320 chs++;321 }322 range->num_frequency = chs;323 range->old_num_frequency = chs;324 range->num_channels = chs;325 range->old_num_channels = chs;326 327 /* bitrates */328 for (i = 0; i < NUM_BITRATES; i++)329 range->bitrate[i] = bitrate_list[i];330 range->num_bitrates = i;331 332 /* signal levels */333 range->max_qual.qual = 100; /* relative value */334 range->max_qual.level = 100;335 range->avg_qual.qual = 50;336 range->avg_qual.level = 50;337 range->sensitivity = 0;338 339 /* Event capability */340 IW_EVENT_CAPA_SET_KERNEL(range->event_capa);341 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);342 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);343 344 /* encryption capability */345 range->enc_capa = IW_ENC_CAPA_WPA |346 IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP |347 IW_ENC_CAPA_4WAY_HANDSHAKE;348 if (wpa2_capable())349 range->enc_capa |= IW_ENC_CAPA_WPA2;350 range->encoding_size[0] = 5; /* 40bit WEP */351 range->encoding_size[1] = 13; /* 104bit WEP */352 range->encoding_size[2] = 32; /* WPA-PSK */353 range->num_encoding_sizes = 3;354 range->max_encoding_tokens = GELIC_WEP_KEYS;355 356 /* scan capability */357 range->scan_capa = IW_SCAN_CAPA_ESSID;358 359 pr_debug("%s: ->\n", __func__);360 return 0;361 362}363 364/* SIOC{G,S}IWSCAN */365static int gelic_wl_set_scan(struct net_device *netdev,366 struct iw_request_info *info,367 union iwreq_data *wrqu, char *extra)368{369 struct gelic_wl_info *wl = port_wl(netdev_priv(netdev));370 struct iw_scan_req *req;371 u8 *essid = NULL;372 size_t essid_len = 0;373 374 if (wrqu->data.length == sizeof(struct iw_scan_req) &&375 wrqu->data.flags & IW_SCAN_THIS_ESSID) {376 req = (struct iw_scan_req*)extra;377 essid = req->essid;378 essid_len = req->essid_len;379 pr_debug("%s: ESSID scan =%s\n", __func__, essid);380 }381 return gelic_wl_start_scan(wl, 1, essid, essid_len);382}383 384#define OUI_LEN 3385static const u8 rsn_oui[OUI_LEN] = { 0x00, 0x0f, 0xac };386static const u8 wpa_oui[OUI_LEN] = { 0x00, 0x50, 0xf2 };387 388/*389 * synthesize WPA/RSN IE data390 * See WiFi WPA specification and IEEE 802.11-2007 7.3.2.25391 * for the format392 */393static size_t gelic_wl_synthesize_ie(u8 *buf,394 struct gelic_eurus_scan_info *scan)395{396 397 const u8 *oui_header;398 u8 *start = buf;399 int rsn;400 int ccmp;401 402 pr_debug("%s: <- sec=%16x\n", __func__, scan->security);403 switch (be16_to_cpu(scan->security) & GELIC_EURUS_SCAN_SEC_MASK) {404 case GELIC_EURUS_SCAN_SEC_WPA:405 rsn = 0;406 break;407 case GELIC_EURUS_SCAN_SEC_WPA2:408 rsn = 1;409 break;410 default:411 /* WEP or none. No IE returned */412 return 0;413 }414 415 switch (be16_to_cpu(scan->security) & GELIC_EURUS_SCAN_SEC_WPA_MASK) {416 case GELIC_EURUS_SCAN_SEC_WPA_TKIP:417 ccmp = 0;418 break;419 case GELIC_EURUS_SCAN_SEC_WPA_AES:420 ccmp = 1;421 break;422 default:423 if (rsn) {424 ccmp = 1;425 pr_info("%s: no cipher info. defaulted to CCMP\n",426 __func__);427 } else {428 ccmp = 0;429 pr_info("%s: no cipher info. defaulted to TKIP\n",430 __func__);431 }432 }433 434 if (rsn)435 oui_header = rsn_oui;436 else437 oui_header = wpa_oui;438 439 /* element id */440 if (rsn)441 *buf++ = WLAN_EID_RSN;442 else443 *buf++ = WLAN_EID_VENDOR_SPECIFIC;444 445 /* length filed; set later */446 buf++;447 448 /* wpa special header */449 if (!rsn) {450 memcpy(buf, wpa_oui, OUI_LEN);451 buf += OUI_LEN;452 *buf++ = 0x01;453 }454 455 /* version */456 *buf++ = 0x01; /* version 1.0 */457 *buf++ = 0x00;458 459 /* group cipher */460 memcpy(buf, oui_header, OUI_LEN);461 buf += OUI_LEN;462 463 if (ccmp)464 *buf++ = 0x04; /* CCMP */465 else466 *buf++ = 0x02; /* TKIP */467 468 /* pairwise key count always 1 */469 *buf++ = 0x01;470 *buf++ = 0x00;471 472 /* pairwise key suit */473 memcpy(buf, oui_header, OUI_LEN);474 buf += OUI_LEN;475 if (ccmp)476 *buf++ = 0x04; /* CCMP */477 else478 *buf++ = 0x02; /* TKIP */479 480 /* AKM count is 1 */481 *buf++ = 0x01;482 *buf++ = 0x00;483 484 /* AKM suite is assumed as PSK*/485 memcpy(buf, oui_header, OUI_LEN);486 buf += OUI_LEN;487 *buf++ = 0x02; /* PSK */488 489 /* RSN capabilities is 0 */490 *buf++ = 0x00;491 *buf++ = 0x00;492 493 /* set length field */494 start[1] = (buf - start - 2);495 496 pr_debug("%s: ->\n", __func__);497 return buf - start;498}499 500struct ie_item {501 u8 *data;502 u8 len;503};504 505struct ie_info {506 struct ie_item wpa;507 struct ie_item rsn;508};509 510static void gelic_wl_parse_ie(u8 *data, size_t len,511 struct ie_info *ie_info)512{513 size_t data_left = len;514 u8 *pos = data;515 u8 item_len;516 u8 item_id;517 518 pr_debug("%s: data=%p len=%ld\n", __func__,519 data, len);520 memset(ie_info, 0, sizeof(struct ie_info));521 522 while (2 <= data_left) {523 item_id = *pos++;524 item_len = *pos++;525 data_left -= 2;526 527 if (data_left < item_len)528 break;529 530 switch (item_id) {531 case WLAN_EID_VENDOR_SPECIFIC:532 if ((OUI_LEN + 1 <= item_len) &&533 !memcmp(pos, wpa_oui, OUI_LEN) &&534 pos[OUI_LEN] == 0x01) {535 ie_info->wpa.data = pos - 2;536 ie_info->wpa.len = item_len + 2;537 }538 break;539 case WLAN_EID_RSN:540 ie_info->rsn.data = pos - 2;541 /* length includes the header */542 ie_info->rsn.len = item_len + 2;543 break;544 default:545 pr_debug("%s: ignore %#x,%d\n", __func__,546 item_id, item_len);547 break;548 }549 pos += item_len;550 data_left -= item_len;551 }552 pr_debug("%s: wpa=%p,%d wpa2=%p,%d\n", __func__,553 ie_info->wpa.data, ie_info->wpa.len,554 ie_info->rsn.data, ie_info->rsn.len);555}556 557 558/*559 * translate the scan informations from hypervisor to a560 * independent format561 */562static char *gelic_wl_translate_scan(struct net_device *netdev,563 struct iw_request_info *info,564 char *ev,565 char *stop,566 struct gelic_wl_scan_info *network)567{568 struct iw_event iwe;569 struct gelic_eurus_scan_info *scan = network->hwinfo;570 char *tmp;571 u8 rate;572 unsigned int i, j, len;573 u8 buf[64]; /* arbitrary size large enough */574 575 pr_debug("%s: <-\n", __func__);576 577 /* first entry should be AP's mac address */578 iwe.cmd = SIOCGIWAP;579 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;580 memcpy(iwe.u.ap_addr.sa_data, &scan->bssid[2], ETH_ALEN);581 ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_ADDR_LEN);582 583 /* ESSID */584 iwe.cmd = SIOCGIWESSID;585 iwe.u.data.flags = 1;586 iwe.u.data.length = strnlen(scan->essid, 32);587 ev = iwe_stream_add_point(info, ev, stop, &iwe, scan->essid);588 589 /* FREQUENCY */590 iwe.cmd = SIOCGIWFREQ;591 iwe.u.freq.m = be16_to_cpu(scan->channel);592 iwe.u.freq.e = 0; /* table value in MHz */593 iwe.u.freq.i = 0;594 ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_FREQ_LEN);595 596 /* RATES */597 iwe.cmd = SIOCGIWRATE;598 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;599 /* to stuff multiple values in one event */600 tmp = ev + iwe_stream_lcp_len(info);601 /* put them in ascendant order (older is first) */602 i = 0;603 j = 0;604 pr_debug("%s: rates=%d rate=%d\n", __func__,605 network->rate_len, network->rate_ext_len);606 while (i < network->rate_len) {607 if (j < network->rate_ext_len &&608 ((scan->ext_rate[j] & 0x7f) < (scan->rate[i] & 0x7f)))609 rate = scan->ext_rate[j++] & 0x7f;610 else611 rate = scan->rate[i++] & 0x7f;612 iwe.u.bitrate.value = rate * 500000; /* 500kbps unit */613 tmp = iwe_stream_add_value(info, ev, tmp, stop, &iwe,614 IW_EV_PARAM_LEN);615 }616 while (j < network->rate_ext_len) {617 iwe.u.bitrate.value = (scan->ext_rate[j++] & 0x7f) * 500000;618 tmp = iwe_stream_add_value(info, ev, tmp, stop, &iwe,619 IW_EV_PARAM_LEN);620 }621 /* Check if we added any rate */622 if (iwe_stream_lcp_len(info) < (tmp - ev))623 ev = tmp;624 625 /* ENCODE */626 iwe.cmd = SIOCGIWENCODE;627 if (be16_to_cpu(scan->capability) & WLAN_CAPABILITY_PRIVACY)628 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;629 else630 iwe.u.data.flags = IW_ENCODE_DISABLED;631 iwe.u.data.length = 0;632 ev = iwe_stream_add_point(info, ev, stop, &iwe, scan->essid);633 634 /* MODE */635 iwe.cmd = SIOCGIWMODE;636 if (be16_to_cpu(scan->capability) &637 (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {638 if (be16_to_cpu(scan->capability) & WLAN_CAPABILITY_ESS)639 iwe.u.mode = IW_MODE_MASTER;640 else641 iwe.u.mode = IW_MODE_ADHOC;642 ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_UINT_LEN);643 }644 645 /* QUAL */646 iwe.cmd = IWEVQUAL;647 iwe.u.qual.updated = IW_QUAL_ALL_UPDATED |648 IW_QUAL_QUAL_INVALID | IW_QUAL_NOISE_INVALID;649 iwe.u.qual.level = be16_to_cpu(scan->rssi);650 iwe.u.qual.qual = be16_to_cpu(scan->rssi);651 iwe.u.qual.noise = 0;652 ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_QUAL_LEN);653 654 /* RSN */655 memset(&iwe, 0, sizeof(iwe));656 if (be16_to_cpu(scan->size) <= sizeof(*scan)) {657 /* If wpa[2] capable station, synthesize IE and put it */658 len = gelic_wl_synthesize_ie(buf, scan);659 if (len) {660 iwe.cmd = IWEVGENIE;661 iwe.u.data.length = len;662 ev = iwe_stream_add_point(info, ev, stop, &iwe, buf);663 }664 } else {665 /* this scan info has IE data */666 struct ie_info ie_info;667 size_t data_len;668 669 data_len = be16_to_cpu(scan->size) - sizeof(*scan);670 671 gelic_wl_parse_ie(scan->elements, data_len, &ie_info);672 673 if (ie_info.wpa.len && (ie_info.wpa.len <= sizeof(buf))) {674 memcpy(buf, ie_info.wpa.data, ie_info.wpa.len);675 iwe.cmd = IWEVGENIE;676 iwe.u.data.length = ie_info.wpa.len;677 ev = iwe_stream_add_point(info, ev, stop, &iwe, buf);678 }679 680 if (ie_info.rsn.len && (ie_info.rsn.len <= sizeof(buf))) {681 memset(&iwe, 0, sizeof(iwe));682 memcpy(buf, ie_info.rsn.data, ie_info.rsn.len);683 iwe.cmd = IWEVGENIE;684 iwe.u.data.length = ie_info.rsn.len;685 ev = iwe_stream_add_point(info, ev, stop, &iwe, buf);686 }687 }688 689 pr_debug("%s: ->\n", __func__);690 return ev;691}692 693 694static int gelic_wl_get_scan(struct net_device *netdev,695 struct iw_request_info *info,696 union iwreq_data *wrqu, char *extra)697{698 struct gelic_wl_info *wl = port_wl(netdev_priv(netdev));699 struct gelic_wl_scan_info *scan_info;700 char *ev = extra;701 char *stop = ev + wrqu->data.length;702 int ret = 0;703 unsigned long this_time = jiffies;704 705 pr_debug("%s: <-\n", __func__);706 if (mutex_lock_interruptible(&wl->scan_lock))707 return -EAGAIN;708 709 switch (wl->scan_stat) {710 case GELIC_WL_SCAN_STAT_SCANNING:711 /* If a scan in progress, caller should call me again */712 ret = -EAGAIN;713 goto out;714 case GELIC_WL_SCAN_STAT_INIT:715 /* last scan request failed or never issued */716 ret = -ENODEV;717 goto out;718 case GELIC_WL_SCAN_STAT_GOT_LIST:719 /* ok, use current list */720 break;721 }722 723 list_for_each_entry(scan_info, &wl->network_list, list) {724 if (wl->scan_age == 0 ||725 time_after(scan_info->last_scanned + wl->scan_age,726 this_time))727 ev = gelic_wl_translate_scan(netdev, info,728 ev, stop,729 scan_info);730 else731 pr_debug("%s:entry too old\n", __func__);732 733 if (stop - ev <= IW_EV_ADDR_LEN) {734 ret = -E2BIG;735 goto out;736 }737 }738 739 wrqu->data.length = ev - extra;740 wrqu->data.flags = 0;741out:742 mutex_unlock(&wl->scan_lock);743 pr_debug("%s: -> %d %d\n", __func__, ret, wrqu->data.length);744 return ret;745}746 747#ifdef DEBUG748static void scan_list_dump(struct gelic_wl_info *wl)749{750 struct gelic_wl_scan_info *scan_info;751 int i;752 753 i = 0;754 list_for_each_entry(scan_info, &wl->network_list, list) {755 pr_debug("%s: item %d\n", __func__, i++);756 pr_debug("valid=%d eurusindex=%d last=%lx\n",757 scan_info->valid, scan_info->eurus_index,758 scan_info->last_scanned);759 pr_debug("r_len=%d r_ext_len=%d essid_len=%d\n",760 scan_info->rate_len, scan_info->rate_ext_len,761 scan_info->essid_len);762 /* -- */763 pr_debug("bssid=%pM\n", &scan_info->hwinfo->bssid[2]);764 pr_debug("essid=%s\n", scan_info->hwinfo->essid);765 }766}767#endif768 769static int gelic_wl_set_auth(struct net_device *netdev,770 struct iw_request_info *info,771 union iwreq_data *data, char *extra)772{773 struct iw_param *param = &data->param;774 struct gelic_wl_info *wl = port_wl(netdev_port(netdev));775 unsigned long irqflag;776 int ret = 0;777 778 pr_debug("%s: <- %d\n", __func__, param->flags & IW_AUTH_INDEX);779 spin_lock_irqsave(&wl->lock, irqflag);780 switch (param->flags & IW_AUTH_INDEX) {781 case IW_AUTH_WPA_VERSION:782 if (param->value & IW_AUTH_WPA_VERSION_DISABLED) {783 pr_debug("%s: NO WPA selected\n", __func__);784 wl->wpa_level = GELIC_WL_WPA_LEVEL_NONE;785 wl->group_cipher_method = GELIC_WL_CIPHER_WEP;786 wl->pairwise_cipher_method = GELIC_WL_CIPHER_WEP;787 }788 if (param->value & IW_AUTH_WPA_VERSION_WPA) {789 pr_debug("%s: WPA version 1 selected\n", __func__);790 wl->wpa_level = GELIC_WL_WPA_LEVEL_WPA;791 wl->group_cipher_method = GELIC_WL_CIPHER_TKIP;792 wl->pairwise_cipher_method = GELIC_WL_CIPHER_TKIP;793 wl->auth_method = GELIC_EURUS_AUTH_OPEN;794 }795 if (param->value & IW_AUTH_WPA_VERSION_WPA2) {796 /*797 * As the hypervisor may not tell the cipher798 * information of the AP if it is WPA2,799 * you will not decide suitable cipher from800 * its beacon.801 * You should have knowledge about the AP's802 * cipher information in other method prior to803 * the association.804 */805 if (!precise_ie())806 pr_info("%s: WPA2 may not work\n", __func__);807 if (wpa2_capable()) {808 wl->wpa_level = GELIC_WL_WPA_LEVEL_WPA2;809 wl->group_cipher_method = GELIC_WL_CIPHER_AES;810 wl->pairwise_cipher_method =811 GELIC_WL_CIPHER_AES;812 wl->auth_method = GELIC_EURUS_AUTH_OPEN;813 } else814 ret = -EINVAL;815 }816 break;817 818 case IW_AUTH_CIPHER_PAIRWISE:819 if (param->value &820 (IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40)) {821 pr_debug("%s: WEP selected\n", __func__);822 wl->pairwise_cipher_method = GELIC_WL_CIPHER_WEP;823 }824 if (param->value & IW_AUTH_CIPHER_TKIP) {825 pr_debug("%s: TKIP selected\n", __func__);826 wl->pairwise_cipher_method = GELIC_WL_CIPHER_TKIP;827 }828 if (param->value & IW_AUTH_CIPHER_CCMP) {829 pr_debug("%s: CCMP selected\n", __func__);830 wl->pairwise_cipher_method = GELIC_WL_CIPHER_AES;831 }832 if (param->value & IW_AUTH_CIPHER_NONE) {833 pr_debug("%s: no auth selected\n", __func__);834 wl->pairwise_cipher_method = GELIC_WL_CIPHER_NONE;835 }836 break;837 case IW_AUTH_CIPHER_GROUP:838 if (param->value &839 (IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40)) {840 pr_debug("%s: WEP selected\n", __func__);841 wl->group_cipher_method = GELIC_WL_CIPHER_WEP;842 }843 if (param->value & IW_AUTH_CIPHER_TKIP) {844 pr_debug("%s: TKIP selected\n", __func__);845 wl->group_cipher_method = GELIC_WL_CIPHER_TKIP;846 }847 if (param->value & IW_AUTH_CIPHER_CCMP) {848 pr_debug("%s: CCMP selected\n", __func__);849 wl->group_cipher_method = GELIC_WL_CIPHER_AES;850 }851 if (param->value & IW_AUTH_CIPHER_NONE) {852 pr_debug("%s: no auth selected\n", __func__);853 wl->group_cipher_method = GELIC_WL_CIPHER_NONE;854 }855 break;856 case IW_AUTH_80211_AUTH_ALG:857 if (param->value & IW_AUTH_ALG_SHARED_KEY) {858 pr_debug("%s: shared key specified\n", __func__);859 wl->auth_method = GELIC_EURUS_AUTH_SHARED;860 } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {861 pr_debug("%s: open system specified\n", __func__);862 wl->auth_method = GELIC_EURUS_AUTH_OPEN;863 } else864 ret = -EINVAL;865 break;866 867 case IW_AUTH_WPA_ENABLED:868 if (param->value) {869 pr_debug("%s: WPA enabled\n", __func__);870 wl->wpa_level = GELIC_WL_WPA_LEVEL_WPA;871 } else {872 pr_debug("%s: WPA disabled\n", __func__);873 wl->wpa_level = GELIC_WL_WPA_LEVEL_NONE;874 }875 break;876 877 case IW_AUTH_KEY_MGMT:878 if (param->value & IW_AUTH_KEY_MGMT_PSK)879 break;880 fallthrough;881 default:882 ret = -EOPNOTSUPP;883 break;884 }885 886 if (!ret)887 set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat);888 889 spin_unlock_irqrestore(&wl->lock, irqflag);890 pr_debug("%s: -> %d\n", __func__, ret);891 return ret;892}893 894static int gelic_wl_get_auth(struct net_device *netdev,895 struct iw_request_info *info,896 union iwreq_data *iwreq, char *extra)897{898 struct iw_param *param = &iwreq->param;899 struct gelic_wl_info *wl = port_wl(netdev_port(netdev));900 unsigned long irqflag;901 int ret = 0;902 903 pr_debug("%s: <- %d\n", __func__, param->flags & IW_AUTH_INDEX);904 spin_lock_irqsave(&wl->lock, irqflag);905 switch (param->flags & IW_AUTH_INDEX) {906 case IW_AUTH_WPA_VERSION:907 switch (wl->wpa_level) {908 case GELIC_WL_WPA_LEVEL_WPA:909 param->value |= IW_AUTH_WPA_VERSION_WPA;910 break;911 case GELIC_WL_WPA_LEVEL_WPA2:912 param->value |= IW_AUTH_WPA_VERSION_WPA2;913 break;914 default:915 param->value |= IW_AUTH_WPA_VERSION_DISABLED;916 }917 break;918 919 case IW_AUTH_80211_AUTH_ALG:920 if (wl->auth_method == GELIC_EURUS_AUTH_SHARED)921 param->value = IW_AUTH_ALG_SHARED_KEY;922 else if (wl->auth_method == GELIC_EURUS_AUTH_OPEN)923 param->value = IW_AUTH_ALG_OPEN_SYSTEM;924 break;925 926 case IW_AUTH_WPA_ENABLED:927 switch (wl->wpa_level) {928 case GELIC_WL_WPA_LEVEL_WPA:929 case GELIC_WL_WPA_LEVEL_WPA2:930 param->value = 1;931 break;932 default:933 param->value = 0;934 break;935 }936 break;937 default:938 ret = -EOPNOTSUPP;939 }940 941 spin_unlock_irqrestore(&wl->lock, irqflag);942 pr_debug("%s: -> %d\n", __func__, ret);943 return ret;944}945 946/* SIOC{S,G}IWESSID */947static int gelic_wl_set_essid(struct net_device *netdev,948 struct iw_request_info *info,949 union iwreq_data *data, char *extra)950{951 struct gelic_wl_info *wl = port_wl(netdev_priv(netdev));952 unsigned long irqflag;953 954 pr_debug("%s: <- l=%d f=%d\n", __func__,955 data->essid.length, data->essid.flags);956 if (IW_ESSID_MAX_SIZE < data->essid.length)957 return -EINVAL;958 959 spin_lock_irqsave(&wl->lock, irqflag);960 if (data->essid.flags) {961 wl->essid_len = data->essid.length;962 memcpy(wl->essid, extra, wl->essid_len);963 pr_debug("%s: essid = '%s'\n", __func__, extra);964 set_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat);965 } else {966 pr_debug("%s: ESSID any\n", __func__);967 clear_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat);968 }969 set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat);970 spin_unlock_irqrestore(&wl->lock, irqflag);971 972 973 gelic_wl_try_associate(netdev); /* FIXME */974 pr_debug("%s: ->\n", __func__);975 return 0;976}977 978static int gelic_wl_get_essid(struct net_device *netdev,979 struct iw_request_info *info,980 union iwreq_data *data, char *extra)981{982 struct gelic_wl_info *wl = port_wl(netdev_priv(netdev));983 unsigned long irqflag;984 985 pr_debug("%s: <-\n", __func__);986 mutex_lock(&wl->assoc_stat_lock);987 spin_lock_irqsave(&wl->lock, irqflag);988 if (test_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat) ||989 wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) {990 memcpy(extra, wl->essid, wl->essid_len);991 data->essid.length = wl->essid_len;992 data->essid.flags = 1;993 } else994 data->essid.flags = 0;995 996 mutex_unlock(&wl->assoc_stat_lock);997 spin_unlock_irqrestore(&wl->lock, irqflag);998 pr_debug("%s: -> len=%d\n", __func__, data->essid.length);999 1000 return 0;1001}1002 1003/* SIO{S,G}IWENCODE */1004static int gelic_wl_set_encode(struct net_device *netdev,1005 struct iw_request_info *info,1006 union iwreq_data *data, char *extra)1007{1008 struct gelic_wl_info *wl = port_wl(netdev_priv(netdev));1009 struct iw_point *enc = &data->encoding;1010 __u16 flags;1011 unsigned long irqflag;1012 int key_index, index_specified;1013 int ret = 0;1014 1015 pr_debug("%s: <-\n", __func__);1016 flags = enc->flags & IW_ENCODE_FLAGS;1017 key_index = enc->flags & IW_ENCODE_INDEX;1018 1019 pr_debug("%s: key_index = %d\n", __func__, key_index);1020 pr_debug("%s: key_len = %d\n", __func__, enc->length);1021 pr_debug("%s: flag=%x\n", __func__, enc->flags & IW_ENCODE_FLAGS);1022 1023 if (GELIC_WEP_KEYS < key_index)1024 return -EINVAL;1025 1026 spin_lock_irqsave(&wl->lock, irqflag);1027 if (key_index) {1028 index_specified = 1;1029 key_index--;1030 } else {1031 index_specified = 0;1032 key_index = wl->current_key;1033 }1034 1035 if (flags & IW_ENCODE_NOKEY) {1036 /* if just IW_ENCODE_NOKEY, change current key index */1037 if (!flags && index_specified) {1038 wl->current_key = key_index;1039 goto done;1040 }1041 1042 if (flags & IW_ENCODE_DISABLED) {1043 if (!index_specified) {1044 /* disable encryption */1045 wl->group_cipher_method = GELIC_WL_CIPHER_NONE;1046 wl->pairwise_cipher_method =1047 GELIC_WL_CIPHER_NONE;1048 /* invalidate all key */1049 wl->key_enabled = 0;1050 } else1051 clear_bit(key_index, &wl->key_enabled);1052 }1053 1054 if (flags & IW_ENCODE_OPEN)1055 wl->auth_method = GELIC_EURUS_AUTH_OPEN;1056 if (flags & IW_ENCODE_RESTRICTED) {1057 pr_info("%s: shared key mode enabled\n", __func__);1058 wl->auth_method = GELIC_EURUS_AUTH_SHARED;1059 }1060 } else {1061 if (IW_ENCODING_TOKEN_MAX < enc->length) {1062 ret = -EINVAL;1063 goto done;1064 }1065 wl->key_len[key_index] = enc->length;1066 memcpy(wl->key[key_index], extra, enc->length);1067 set_bit(key_index, &wl->key_enabled);1068 wl->pairwise_cipher_method = GELIC_WL_CIPHER_WEP;1069 wl->group_cipher_method = GELIC_WL_CIPHER_WEP;1070 }1071 set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat);1072done:1073 spin_unlock_irqrestore(&wl->lock, irqflag);1074 pr_debug("%s: ->\n", __func__);1075 return ret;1076}1077 1078static int gelic_wl_get_encode(struct net_device *netdev,1079 struct iw_request_info *info,1080 union iwreq_data *data, char *extra)1081{1082 struct gelic_wl_info *wl = port_wl(netdev_priv(netdev));1083 struct iw_point *enc = &data->encoding;1084 unsigned long irqflag;1085 unsigned int key_index;1086 int ret = 0;1087 1088 pr_debug("%s: <-\n", __func__);1089 key_index = enc->flags & IW_ENCODE_INDEX;1090 pr_debug("%s: flag=%#x point=%p len=%d extra=%p\n", __func__,1091 enc->flags, enc->pointer, enc->length, extra);1092 if (GELIC_WEP_KEYS < key_index)1093 return -EINVAL;1094 1095 spin_lock_irqsave(&wl->lock, irqflag);1096 if (key_index)1097 key_index--;1098 else1099 key_index = wl->current_key;1100 1101 if (wl->group_cipher_method == GELIC_WL_CIPHER_WEP) {1102 switch (wl->auth_method) {1103 case GELIC_EURUS_AUTH_OPEN:1104 enc->flags = IW_ENCODE_OPEN;1105 break;1106 case GELIC_EURUS_AUTH_SHARED:1107 enc->flags = IW_ENCODE_RESTRICTED;1108 break;1109 }1110 } else1111 enc->flags = IW_ENCODE_DISABLED;1112 1113 if (test_bit(key_index, &wl->key_enabled)) {1114 if (enc->length < wl->key_len[key_index]) {1115 ret = -EINVAL;1116 goto done;1117 }1118 enc->length = wl->key_len[key_index];1119 memcpy(extra, wl->key[key_index], wl->key_len[key_index]);1120 } else {1121 enc->length = 0;1122 enc->flags |= IW_ENCODE_NOKEY;1123 }1124 enc->flags |= key_index + 1;1125 pr_debug("%s: -> flag=%x len=%d\n", __func__,1126 enc->flags, enc->length);1127 1128done:1129 spin_unlock_irqrestore(&wl->lock, irqflag);1130 return ret;1131}1132 1133/* SIOC{S,G}IWAP */1134static int gelic_wl_set_ap(struct net_device *netdev,1135 struct iw_request_info *info,1136 union iwreq_data *data, char *extra)1137{1138 struct gelic_wl_info *wl = port_wl(netdev_priv(netdev));1139 unsigned long irqflag;1140 1141 pr_debug("%s: <-\n", __func__);1142 if (data->ap_addr.sa_family != ARPHRD_ETHER)1143 return -EINVAL;1144 1145 spin_lock_irqsave(&wl->lock, irqflag);1146 if (is_valid_ether_addr(data->ap_addr.sa_data)) {1147 memcpy(wl->bssid, data->ap_addr.sa_data,1148 ETH_ALEN);1149 set_bit(GELIC_WL_STAT_BSSID_SET, &wl->stat);1150 set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat);1151 pr_debug("%s: bss=%pM\n", __func__, wl->bssid);1152 } else {1153 pr_debug("%s: clear bssid\n", __func__);1154 clear_bit(GELIC_WL_STAT_BSSID_SET, &wl->stat);1155 eth_zero_addr(wl->bssid);1156 }1157 spin_unlock_irqrestore(&wl->lock, irqflag);1158 pr_debug("%s: ->\n", __func__);1159 return 0;1160}1161 1162static int gelic_wl_get_ap(struct net_device *netdev,1163 struct iw_request_info *info,1164 union iwreq_data *data, char *extra)1165{1166 struct gelic_wl_info *wl = port_wl(netdev_priv(netdev));1167 unsigned long irqflag;1168 1169 pr_debug("%s: <-\n", __func__);1170 mutex_lock(&wl->assoc_stat_lock);1171 spin_lock_irqsave(&wl->lock, irqflag);1172 if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) {1173 data->ap_addr.sa_family = ARPHRD_ETHER;1174 memcpy(data->ap_addr.sa_data, wl->active_bssid,1175 ETH_ALEN);1176 } else1177 eth_zero_addr(data->ap_addr.sa_data);1178 1179 spin_unlock_irqrestore(&wl->lock, irqflag);1180 mutex_unlock(&wl->assoc_stat_lock);1181 pr_debug("%s: ->\n", __func__);1182 return 0;1183}1184 1185/* SIOC{S,G}IWENCODEEXT */1186static int gelic_wl_set_encodeext(struct net_device *netdev,1187 struct iw_request_info *info,1188 union iwreq_data *data, char *extra)1189{1190 struct gelic_wl_info *wl = port_wl(netdev_priv(netdev));1191 struct iw_point *enc = &data->encoding;1192 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;1193 __u16 alg;1194 __u16 flags;1195 unsigned long irqflag;1196 int key_index;1197 int ret = 0;1198 1199 pr_debug("%s: <-\n", __func__);1200 flags = enc->flags & IW_ENCODE_FLAGS;1201 alg = ext->alg;1202 key_index = enc->flags & IW_ENCODE_INDEX;1203 1204 pr_debug("%s: key_index = %d\n", __func__, key_index);1205 pr_debug("%s: key_len = %d\n", __func__, enc->length);1206 pr_debug("%s: flag=%x\n", __func__, enc->flags & IW_ENCODE_FLAGS);1207 pr_debug("%s: ext_flag=%x\n", __func__, ext->ext_flags);1208 pr_debug("%s: ext_key_len=%x\n", __func__, ext->key_len);1209 1210 if (GELIC_WEP_KEYS < key_index)1211 return -EINVAL;1212 1213 spin_lock_irqsave(&wl->lock, irqflag);1214 if (key_index)1215 key_index--;1216 else1217 key_index = wl->current_key;1218 1219 if (!enc->length && (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) {1220 /* request to change default key index */1221 pr_debug("%s: request to change default key to %d\n",1222 __func__, key_index);1223 wl->current_key = key_index;1224 goto done;1225 }1226 1227 if (alg == IW_ENCODE_ALG_NONE || (flags & IW_ENCODE_DISABLED)) {1228 pr_debug("%s: alg disabled\n", __func__);1229 wl->wpa_level = GELIC_WL_WPA_LEVEL_NONE;1230 wl->group_cipher_method = GELIC_WL_CIPHER_NONE;1231 wl->pairwise_cipher_method = GELIC_WL_CIPHER_NONE;1232 wl->auth_method = GELIC_EURUS_AUTH_OPEN; /* should be open */1233 } else if (alg == IW_ENCODE_ALG_WEP) {1234 pr_debug("%s: WEP requested\n", __func__);1235 if (flags & IW_ENCODE_OPEN) {1236 pr_debug("%s: open key mode\n", __func__);1237 wl->auth_method = GELIC_EURUS_AUTH_OPEN;1238 }1239 if (flags & IW_ENCODE_RESTRICTED) {1240 pr_debug("%s: shared key mode\n", __func__);1241 wl->auth_method = GELIC_EURUS_AUTH_SHARED;1242 }1243 if (IW_ENCODING_TOKEN_MAX < ext->key_len) {1244 pr_info("%s: key is too long %d\n", __func__,1245 ext->key_len);1246 ret = -EINVAL;1247 goto done;1248 }1249 /* OK, update the key */1250 wl->key_len[key_index] = ext->key_len;1251 memset(wl->key[key_index], 0, IW_ENCODING_TOKEN_MAX);1252 memcpy(wl->key[key_index], ext->key, ext->key_len);1253 set_bit(key_index, &wl->key_enabled);1254 /* remember wep info changed */1255 set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat);1256 } else if (alg == IW_ENCODE_ALG_PMK) {1257 if (ext->key_len != WPA_PSK_LEN) {1258 pr_err("%s: PSK length wrong %d\n", __func__,1259 ext->key_len);1260 ret = -EINVAL;1261 goto done;1262 }1263 memset(wl->psk, 0, sizeof(wl->psk));1264 memcpy(wl->psk, ext->key, ext->key_len);1265 wl->psk_len = ext->key_len;1266 wl->psk_type = GELIC_EURUS_WPA_PSK_BIN;1267 /* remember PSK configured */1268 set_bit(GELIC_WL_STAT_WPA_PSK_SET, &wl->stat);1269 }1270done:1271 spin_unlock_irqrestore(&wl->lock, irqflag);1272 pr_debug("%s: ->\n", __func__);1273 return ret;1274}1275 1276static int gelic_wl_get_encodeext(struct net_device *netdev,1277 struct iw_request_info *info,1278 union iwreq_data *data, char *extra)1279{1280 struct gelic_wl_info *wl = port_wl(netdev_priv(netdev));1281 struct iw_point *enc = &data->encoding;1282 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;1283 unsigned long irqflag;1284 int key_index;1285 int ret = 0;1286 int max_key_len;1287 1288 pr_debug("%s: <-\n", __func__);1289 1290 max_key_len = enc->length - sizeof(struct iw_encode_ext);1291 if (max_key_len < 0)1292 return -EINVAL;1293 key_index = enc->flags & IW_ENCODE_INDEX;1294 1295 pr_debug("%s: key_index = %d\n", __func__, key_index);1296 pr_debug("%s: key_len = %d\n", __func__, enc->length);1297 pr_debug("%s: flag=%x\n", __func__, enc->flags & IW_ENCODE_FLAGS);1298 1299 if (GELIC_WEP_KEYS < key_index)1300 return -EINVAL;1301 1302 spin_lock_irqsave(&wl->lock, irqflag);1303 if (key_index)1304 key_index--;1305 else1306 key_index = wl->current_key;1307 1308 memset(ext, 0, sizeof(struct iw_encode_ext));1309 switch (wl->group_cipher_method) {1310 case GELIC_WL_CIPHER_WEP:1311 ext->alg = IW_ENCODE_ALG_WEP;1312 enc->flags |= IW_ENCODE_ENABLED;1313 break;1314 case GELIC_WL_CIPHER_TKIP:1315 ext->alg = IW_ENCODE_ALG_TKIP;1316 enc->flags |= IW_ENCODE_ENABLED;1317 break;1318 case GELIC_WL_CIPHER_AES:1319 ext->alg = IW_ENCODE_ALG_CCMP;1320 enc->flags |= IW_ENCODE_ENABLED;1321 break;1322 case GELIC_WL_CIPHER_NONE:1323 default:1324 ext->alg = IW_ENCODE_ALG_NONE;1325 enc->flags |= IW_ENCODE_NOKEY;1326 break;1327 }1328 1329 if (!(enc->flags & IW_ENCODE_NOKEY)) {1330 if (max_key_len < wl->key_len[key_index]) {1331 ret = -E2BIG;1332 goto out;1333 }1334 if (test_bit(key_index, &wl->key_enabled))1335 memcpy(ext->key, wl->key[key_index],1336 wl->key_len[key_index]);1337 else1338 pr_debug("%s: disabled key requested ix=%d\n",1339 __func__, key_index);1340 }1341out:1342 spin_unlock_irqrestore(&wl->lock, irqflag);1343 pr_debug("%s: ->\n", __func__);1344 return ret;1345}1346/* SIOC{S,G}IWMODE */1347static int gelic_wl_set_mode(struct net_device *netdev,1348 struct iw_request_info *info,1349 union iwreq_data *data, char *extra)1350{1351 __u32 mode = data->mode;1352 int ret;1353 1354 pr_debug("%s: <-\n", __func__);1355 if (mode == IW_MODE_INFRA)1356 ret = 0;1357 else1358 ret = -EOPNOTSUPP;1359 pr_debug("%s: -> %d\n", __func__, ret);1360 return ret;1361}1362 1363static int gelic_wl_get_mode(struct net_device *netdev,1364 struct iw_request_info *info,1365 union iwreq_data *data, char *extra)1366{1367 __u32 *mode = &data->mode;1368 pr_debug("%s: <-\n", __func__);1369 *mode = IW_MODE_INFRA;1370 pr_debug("%s: ->\n", __func__);1371 return 0;1372}1373 1374/* SIOCGIWNICKN */1375static int gelic_wl_get_nick(struct net_device *net_dev,1376 struct iw_request_info *info,1377 union iwreq_data *data, char *extra)1378{1379 strcpy(extra, "gelic_wl");1380 data->data.length = strlen(extra);1381 data->data.flags = 1;1382 return 0;1383}1384 1385 1386/* --- */1387 1388static struct iw_statistics *gelic_wl_get_wireless_stats(1389 struct net_device *netdev)1390{1391 1392 struct gelic_wl_info *wl = port_wl(netdev_priv(netdev));1393 struct gelic_eurus_cmd *cmd;1394 struct iw_statistics *is;1395 struct gelic_eurus_rssi_info *rssi;1396 void *buf;1397 1398 pr_debug("%s: <-\n", __func__);1399 1400 buf = (void *)__get_free_page(GFP_KERNEL);1401 if (!buf)1402 return NULL;1403 1404 is = &wl->iwstat;1405 memset(is, 0, sizeof(*is));1406 cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_GET_RSSI_CFG,1407 buf, sizeof(*rssi));1408 if (cmd && !cmd->status && !cmd->cmd_status) {1409 rssi = buf;1410 is->qual.level = be16_to_cpu(rssi->rssi);1411 is->qual.updated = IW_QUAL_LEVEL_UPDATED |1412 IW_QUAL_QUAL_INVALID | IW_QUAL_NOISE_INVALID;1413 } else1414 /* not associated */1415 is->qual.updated = IW_QUAL_ALL_INVALID;1416 1417 kfree(cmd);1418 free_page((unsigned long)buf);1419 pr_debug("%s: ->\n", __func__);1420 return is;1421}1422 1423/*1424 * scanning helpers1425 */1426static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan,1427 u8 *essid, size_t essid_len)1428{1429 struct gelic_eurus_cmd *cmd;1430 int ret = 0;1431 void *buf = NULL;1432 size_t len;1433 1434 pr_debug("%s: <- always=%d\n", __func__, always_scan);1435 if (mutex_lock_interruptible(&wl->scan_lock))1436 return -ERESTARTSYS;1437 1438 /*1439 * If already a scan in progress, do not trigger more1440 */1441 if (wl->scan_stat == GELIC_WL_SCAN_STAT_SCANNING) {1442 pr_debug("%s: scanning now\n", __func__);1443 goto out;1444 }1445 1446 init_completion(&wl->scan_done);1447 /*1448 * If we have already a bss list, don't try to get new1449 * unless we are doing an ESSID scan1450 */1451 if ((!essid_len && !always_scan)1452 && wl->scan_stat == GELIC_WL_SCAN_STAT_GOT_LIST) {1453 pr_debug("%s: already has the list\n", __func__);1454 complete(&wl->scan_done);1455 goto out;1456 }1457 1458 /* ESSID scan ? */1459 if (essid_len && essid) {1460 buf = (void *)__get_free_page(GFP_KERNEL);1461 if (!buf) {1462 ret = -ENOMEM;1463 goto out;1464 }1465 len = IW_ESSID_MAX_SIZE; /* hypervisor always requires 32 */1466 memset(buf, 0, len);1467 memcpy(buf, essid, essid_len);1468 pr_debug("%s: essid scan='%s'\n", __func__, (char *)buf);1469 } else1470 len = 0;1471 1472 /*1473 * issue start scan request1474 */1475 wl->scan_stat = GELIC_WL_SCAN_STAT_SCANNING;1476 cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_START_SCAN,1477 buf, len);1478 if (!cmd || cmd->status || cmd->cmd_status) {1479 wl->scan_stat = GELIC_WL_SCAN_STAT_INIT;1480 complete(&wl->scan_done);1481 ret = -ENOMEM;1482 goto out;1483 }1484 kfree(cmd);1485out:1486 free_page((unsigned long)buf);1487 mutex_unlock(&wl->scan_lock);1488 pr_debug("%s: ->\n", __func__);1489 return ret;1490}1491 1492/*1493 * retrieve scan result from the chip (hypervisor)1494 * this function is invoked by schedule work.1495 */1496static void gelic_wl_scan_complete_event(struct gelic_wl_info *wl)1497{1498 struct gelic_eurus_cmd *cmd = NULL;1499 struct gelic_wl_scan_info *target, *tmp;1500 struct gelic_wl_scan_info *oldest = NULL;1501 struct gelic_eurus_scan_info *scan_info;1502 unsigned int scan_info_size;1503 union iwreq_data data;1504 unsigned long this_time = jiffies;1505 unsigned int data_len, i, found, r;1506 void *buf;1507 1508 pr_debug("%s:start\n", __func__);1509 mutex_lock(&wl->scan_lock);1510 1511 buf = (void *)__get_free_page(GFP_KERNEL);1512 if (!buf) {1513 pr_info("%s: scan buffer alloc failed\n", __func__);1514 goto out;1515 }1516 1517 if (wl->scan_stat != GELIC_WL_SCAN_STAT_SCANNING) {1518 /*1519 * stop() may be called while scanning, ignore result1520 */1521 pr_debug("%s: scan complete when stat != scanning(%d)\n",1522 __func__, wl->scan_stat);1523 goto out;1524 }1525 1526 cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_GET_SCAN,1527 buf, PAGE_SIZE);1528 if (!cmd || cmd->status || cmd->cmd_status) {1529 wl->scan_stat = GELIC_WL_SCAN_STAT_INIT;1530 pr_info("%s:cmd failed\n", __func__);1531 kfree(cmd);1532 goto out;1533 }1534 data_len = cmd->size;1535 pr_debug("%s: data_len = %d\n", __func__, data_len);1536 kfree(cmd);1537 1538 /* OK, bss list retrieved */1539 wl->scan_stat = GELIC_WL_SCAN_STAT_GOT_LIST;1540 1541 /* mark all entries are old */1542 list_for_each_entry_safe(target, tmp, &wl->network_list, list) {1543 target->valid = 0;1544 /* expire too old entries */1545 if (time_before(target->last_scanned + wl->scan_age,1546 this_time)) {1547 kfree(target->hwinfo);1548 target->hwinfo = NULL;1549 list_move_tail(&target->list, &wl->network_free_list);1550 }1551 }1552 1553 /* put them in the network_list */1554 for (i = 0, scan_info_size = 0, scan_info = buf;1555 scan_info_size < data_len;1556 i++, scan_info_size += be16_to_cpu(scan_info->size),1557 scan_info = (void *)scan_info + be16_to_cpu(scan_info->size)) {1558 pr_debug("%s:size=%d bssid=%pM scan_info=%p\n", __func__,1559 be16_to_cpu(scan_info->size),1560 &scan_info->bssid[2], scan_info);1561 1562 /*1563 * The wireless firmware may return invalid channel 0 and/or1564 * invalid rate if the AP emits zero length SSID ie. As this1565 * scan information is useless, ignore it1566 */1567 if (!be16_to_cpu(scan_info->channel) || !scan_info->rate[0]) {1568 pr_debug("%s: invalid scan info\n", __func__);1569 continue;1570 }1571 1572 found = 0;1573 oldest = NULL;1574 list_for_each_entry(target, &wl->network_list, list) {1575 if (ether_addr_equal(&target->hwinfo->bssid[2],1576 &scan_info->bssid[2])) {1577 found = 1;1578 pr_debug("%s: same BBS found scanned list\n",1579 __func__);1580 break;1581 }1582 if (!oldest ||1583 (target->last_scanned < oldest->last_scanned))1584 oldest = target;1585 }1586 1587 if (!found) {1588 /* not found in the list */1589 if (list_empty(&wl->network_free_list)) {1590 /* expire oldest */1591 target = oldest;1592 } else {1593 target = list_entry(wl->network_free_list.next,1594 struct gelic_wl_scan_info,1595 list);1596 }1597 }1598 1599 /* update the item */1600 target->last_scanned = this_time;1601 target->valid = 1;1602 target->eurus_index = i;1603 kfree(target->hwinfo);1604 target->hwinfo = kmemdup(scan_info,1605 be16_to_cpu(scan_info->size),1606 GFP_KERNEL);1607 if (!target->hwinfo)1608 continue;1609 1610 /* copy hw scan info */1611 target->essid_len = strnlen(scan_info->essid,1612 sizeof(scan_info->essid));1613 target->rate_len = 0;1614 for (r = 0; r < 12; r++)1615 if (scan_info->rate[r])1616 target->rate_len++;1617 if (8 < target->rate_len)1618 pr_info("%s: AP returns %d rates\n", __func__,1619 target->rate_len);1620 target->rate_ext_len = 0;1621 for (r = 0; r < 16; r++)1622 if (scan_info->ext_rate[r])1623 target->rate_ext_len++;1624 list_move_tail(&target->list, &wl->network_list);1625 }1626 memset(&data, 0, sizeof(data));1627 wireless_send_event(port_to_netdev(wl_port(wl)), SIOCGIWSCAN, &data,1628 NULL);1629out:1630 free_page((unsigned long)buf);1631 complete(&wl->scan_done);1632 mutex_unlock(&wl->scan_lock);1633 pr_debug("%s:end\n", __func__);1634}1635 1636/*1637 * Select an appropriate bss from current scan list regarding1638 * current settings from userspace.1639 * The caller must hold wl->scan_lock,1640 * and on the state of wl->scan_state == GELIC_WL_SCAN_GOT_LIST1641 */1642static void update_best(struct gelic_wl_scan_info **best,1643 struct gelic_wl_scan_info *candid,1644 int *best_weight,1645 int *weight)1646{1647 if (*best_weight < ++(*weight)) {1648 *best_weight = *weight;1649 *best = candid;1650 }1651}1652 1653static1654struct gelic_wl_scan_info *gelic_wl_find_best_bss(struct gelic_wl_info *wl)1655{1656 struct gelic_wl_scan_info *scan_info;1657 struct gelic_wl_scan_info *best_bss;1658 int weight, best_weight;1659 u16 security;1660 1661 pr_debug("%s: <-\n", __func__);1662 1663 best_bss = NULL;1664 best_weight = 0;1665 1666 list_for_each_entry(scan_info, &wl->network_list, list) {1667 pr_debug("%s: station %p\n", __func__, scan_info);1668 1669 if (!scan_info->valid) {1670 pr_debug("%s: station invalid\n", __func__);1671 continue;1672 }1673 1674 /* If bss specified, check it only */1675 if (test_bit(GELIC_WL_STAT_BSSID_SET, &wl->stat)) {1676 if (ether_addr_equal(&scan_info->hwinfo->bssid[2],1677 wl->bssid)) {1678 best_bss = scan_info;1679 pr_debug("%s: bssid matched\n", __func__);1680 break;1681 } else {1682 pr_debug("%s: bssid unmatched\n", __func__);1683 continue;1684 }1685 }1686 1687 weight = 0;1688 1689 /* security */1690 security = be16_to_cpu(scan_info->hwinfo->security) &1691 GELIC_EURUS_SCAN_SEC_MASK;1692 if (wl->wpa_level == GELIC_WL_WPA_LEVEL_WPA2) {1693 if (security == GELIC_EURUS_SCAN_SEC_WPA2)1694 update_best(&best_bss, scan_info,1695 &best_weight, &weight);1696 else1697 continue;1698 } else if (wl->wpa_level == GELIC_WL_WPA_LEVEL_WPA) {1699 if (security == GELIC_EURUS_SCAN_SEC_WPA)1700 update_best(&best_bss, scan_info,1701 &best_weight, &weight);1702 else1703 continue;1704 } else if (wl->wpa_level == GELIC_WL_WPA_LEVEL_NONE &&1705 wl->group_cipher_method == GELIC_WL_CIPHER_WEP) {1706 if (security == GELIC_EURUS_SCAN_SEC_WEP)1707 update_best(&best_bss, scan_info,1708 &best_weight, &weight);1709 else1710 continue;1711 }1712 1713 /* If ESSID is set, check it */1714 if (test_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat)) {1715 if ((scan_info->essid_len == wl->essid_len) &&1716 !strncmp(wl->essid,1717 scan_info->hwinfo->essid,1718 scan_info->essid_len))1719 update_best(&best_bss, scan_info,1720 &best_weight, &weight);1721 else1722 continue;1723 }1724 }1725 1726#ifdef DEBUG1727 pr_debug("%s: -> bss=%p\n", __func__, best_bss);1728 if (best_bss) {1729 pr_debug("%s:addr=%pM\n", __func__,1730 &best_bss->hwinfo->bssid[2]);1731 }1732#endif1733 return best_bss;1734}1735 1736/*1737 * Setup WEP configuration to the chip1738 * The caller must hold wl->scan_lock,1739 * and on the state of wl->scan_state == GELIC_WL_SCAN_GOT_LIST1740 */1741static int gelic_wl_do_wep_setup(struct gelic_wl_info *wl)1742{1743 unsigned int i;1744 struct gelic_eurus_wep_cfg *wep;1745 struct gelic_eurus_cmd *cmd;1746 int wep104 = 0;1747 int have_key = 0;1748 int ret = 0;1749 1750 pr_debug("%s: <-\n", __func__);1751 /* we can assume no one should uses the buffer */1752 wep = (struct gelic_eurus_wep_cfg *)__get_free_page(GFP_KERNEL);1753 if (!wep)1754 return -ENOMEM;1755 1756 memset(wep, 0, sizeof(*wep));1757 1758 if (wl->group_cipher_method == GELIC_WL_CIPHER_WEP) {1759 pr_debug("%s: WEP mode\n", __func__);1760 for (i = 0; i < GELIC_WEP_KEYS; i++) {1761 if (!test_bit(i, &wl->key_enabled))1762 continue;1763 1764 pr_debug("%s: key#%d enabled\n", __func__, i);1765 have_key = 1;1766 if (wl->key_len[i] == 13)1767 wep104 = 1;1768 else if (wl->key_len[i] != 5) {1769 pr_info("%s: wrong wep key[%d]=%d\n",1770 __func__, i, wl->key_len[i]);1771 ret = -EINVAL;1772 goto out;1773 }1774 memcpy(wep->key[i], wl->key[i], wl->key_len[i]);1775 }1776 1777 if (!have_key) {1778 pr_info("%s: all wep key disabled\n", __func__);1779 ret = -EINVAL;1780 goto out;1781 }1782 1783 if (wep104) {1784 pr_debug("%s: 104bit key\n", __func__);1785 wep->security = cpu_to_be16(GELIC_EURUS_WEP_SEC_104BIT);1786 } else {1787 pr_debug("%s: 40bit key\n", __func__);1788 wep->security = cpu_to_be16(GELIC_EURUS_WEP_SEC_40BIT);1789 }1790 } else {1791 pr_debug("%s: NO encryption\n", __func__);1792 wep->security = cpu_to_be16(GELIC_EURUS_WEP_SEC_NONE);1793 }1794 1795 /* issue wep setup */1796 cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_SET_WEP_CFG,1797 wep, sizeof(*wep));1798 if (!cmd)1799 ret = -ENOMEM;1800 else if (cmd->status || cmd->cmd_status)1801 ret = -ENXIO;1802 1803 kfree(cmd);1804out:1805 free_page((unsigned long)wep);1806 pr_debug("%s: ->\n", __func__);1807 return ret;1808}1809 1810#ifdef DEBUG1811static const char *wpasecstr(enum gelic_eurus_wpa_security sec)1812{1813 switch (sec) {1814 case GELIC_EURUS_WPA_SEC_NONE:1815 return "NONE";1816 case GELIC_EURUS_WPA_SEC_WPA_TKIP_TKIP:1817 return "WPA_TKIP_TKIP";1818 case GELIC_EURUS_WPA_SEC_WPA_TKIP_AES:1819 return "WPA_TKIP_AES";1820 case GELIC_EURUS_WPA_SEC_WPA_AES_AES:1821 return "WPA_AES_AES";1822 case GELIC_EURUS_WPA_SEC_WPA2_TKIP_TKIP:1823 return "WPA2_TKIP_TKIP";1824 case GELIC_EURUS_WPA_SEC_WPA2_TKIP_AES:1825 return "WPA2_TKIP_AES";1826 case GELIC_EURUS_WPA_SEC_WPA2_AES_AES:1827 return "WPA2_AES_AES";1828 }1829 return "";1830};1831#endif1832 1833static int gelic_wl_do_wpa_setup(struct gelic_wl_info *wl)1834{1835 struct gelic_eurus_wpa_cfg *wpa;1836 struct gelic_eurus_cmd *cmd;1837 u16 security;1838 int ret = 0;1839 1840 pr_debug("%s: <-\n", __func__);1841 /* we can assume no one should uses the buffer */1842 wpa = (struct gelic_eurus_wpa_cfg *)__get_free_page(GFP_KERNEL);1843 if (!wpa)1844 return -ENOMEM;1845 1846 memset(wpa, 0, sizeof(*wpa));1847 1848 if (!test_bit(GELIC_WL_STAT_WPA_PSK_SET, &wl->stat))1849 pr_info("%s: PSK not configured yet\n", __func__);1850 1851 /* copy key */1852 memcpy(wpa->psk, wl->psk, wl->psk_len);1853 1854 /* set security level */1855 if (wl->wpa_level == GELIC_WL_WPA_LEVEL_WPA2) {1856 if (wl->group_cipher_method == GELIC_WL_CIPHER_AES) {1857 security = GELIC_EURUS_WPA_SEC_WPA2_AES_AES;1858 } else {1859 if (wl->pairwise_cipher_method == GELIC_WL_CIPHER_AES &&1860 precise_ie())1861 security = GELIC_EURUS_WPA_SEC_WPA2_TKIP_AES;1862 else1863 security = GELIC_EURUS_WPA_SEC_WPA2_TKIP_TKIP;1864 }1865 } else {1866 if (wl->group_cipher_method == GELIC_WL_CIPHER_AES) {1867 security = GELIC_EURUS_WPA_SEC_WPA_AES_AES;1868 } else {1869 if (wl->pairwise_cipher_method == GELIC_WL_CIPHER_AES &&1870 precise_ie())1871 security = GELIC_EURUS_WPA_SEC_WPA_TKIP_AES;1872 else1873 security = GELIC_EURUS_WPA_SEC_WPA_TKIP_TKIP;1874 }1875 }1876 wpa->security = cpu_to_be16(security);1877 1878 /* PSK type */1879 wpa->psk_type = cpu_to_be16(wl->psk_type);1880#ifdef DEBUG1881 pr_debug("%s: sec=%s psktype=%s\n", __func__,1882 wpasecstr(wpa->security),1883 (wpa->psk_type == GELIC_EURUS_WPA_PSK_BIN) ?1884 "BIN" : "passphrase");1885#if 01886 /*1887 * don't enable here if you plan to submit1888 * the debug log because this dumps your precious1889 * passphrase/key.1890 */1891 pr_debug("%s: psk=%s\n", __func__,1892 (wpa->psk_type == GELIC_EURUS_WPA_PSK_BIN) ?1893 "N/A" : wpa->psk);1894#endif1895#endif1896 /* issue wpa setup */1897 cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_SET_WPA_CFG,1898 wpa, sizeof(*wpa));1899 if (!cmd)1900 ret = -ENOMEM;1901 else if (cmd->status || cmd->cmd_status)1902 ret = -ENXIO;1903 kfree(cmd);1904 free_page((unsigned long)wpa);1905 pr_debug("%s: --> %d\n", __func__, ret);1906 return ret;1907}1908 1909/*1910 * Start association. caller must hold assoc_stat_lock1911 */1912static int gelic_wl_associate_bss(struct gelic_wl_info *wl,1913 struct gelic_wl_scan_info *bss)1914{1915 struct gelic_eurus_cmd *cmd;1916 struct gelic_eurus_common_cfg *common;1917 int ret = 0;1918 unsigned long rc;1919 1920 pr_debug("%s: <-\n", __func__);1921 1922 /* do common config */1923 common = (struct gelic_eurus_common_cfg *)__get_free_page(GFP_KERNEL);1924 if (!common)1925 return -ENOMEM;1926 1927 memset(common, 0, sizeof(*common));1928 common->bss_type = cpu_to_be16(GELIC_EURUS_BSS_INFRA);1929 common->op_mode = cpu_to_be16(GELIC_EURUS_OPMODE_11BG);1930 1931 common->scan_index = cpu_to_be16(bss->eurus_index);1932 switch (wl->auth_method) {1933 case GELIC_EURUS_AUTH_OPEN:1934 common->auth_method = cpu_to_be16(GELIC_EURUS_AUTH_OPEN);1935 break;1936 case GELIC_EURUS_AUTH_SHARED:1937 common->auth_method = cpu_to_be16(GELIC_EURUS_AUTH_SHARED);1938 break;1939 }1940 1941#ifdef DEBUG1942 scan_list_dump(wl);1943#endif1944 pr_debug("%s: common cfg index=%d bsstype=%d auth=%d\n", __func__,1945 be16_to_cpu(common->scan_index),1946 be16_to_cpu(common->bss_type),1947 be16_to_cpu(common->auth_method));1948 1949 cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_SET_COMMON_CFG,1950 common, sizeof(*common));1951 if (!cmd || cmd->status || cmd->cmd_status) {1952 ret = -ENOMEM;1953 kfree(cmd);1954 goto out;1955 }1956 kfree(cmd);1957 1958 /* WEP/WPA */1959 switch (wl->wpa_level) {1960 case GELIC_WL_WPA_LEVEL_NONE:1961 /* If WEP or no security, setup WEP config */1962 ret = gelic_wl_do_wep_setup(wl);1963 break;1964 case GELIC_WL_WPA_LEVEL_WPA:1965 case GELIC_WL_WPA_LEVEL_WPA2:1966 ret = gelic_wl_do_wpa_setup(wl);1967 break;1968 }1969 1970 if (ret) {1971 pr_debug("%s: WEP/WPA setup failed %d\n", __func__,1972 ret);1973 ret = -EPERM;1974 gelic_wl_send_iwap_event(wl, NULL);1975 goto out;1976 }1977 1978 /* start association */1979 init_completion(&wl->assoc_done);1980 wl->assoc_stat = GELIC_WL_ASSOC_STAT_ASSOCIATING;1981 cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_ASSOC,1982 NULL, 0);1983 if (!cmd || cmd->status || cmd->cmd_status) {1984 pr_debug("%s: assoc request failed\n", __func__);1985 wl->assoc_stat = GELIC_WL_ASSOC_STAT_DISCONN;1986 kfree(cmd);1987 ret = -ENOMEM;1988 gelic_wl_send_iwap_event(wl, NULL);1989 goto out;1990 }1991 kfree(cmd);1992 1993 /* wait for connected event */1994 rc = wait_for_completion_timeout(&wl->assoc_done, HZ * 4);/*FIXME*/1995 1996 if (!rc) {1997 /* timeouted. Maybe key or cyrpt mode is wrong */1998 pr_info("%s: connect timeout\n", __func__);1999 cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_DISASSOC,2000 NULL, 0);2001 kfree(cmd);2002 wl->assoc_stat = GELIC_WL_ASSOC_STAT_DISCONN;2003 gelic_wl_send_iwap_event(wl, NULL);2004 ret = -ENXIO;2005 } else {2006 wl->assoc_stat = GELIC_WL_ASSOC_STAT_ASSOCIATED;2007 /* copy bssid */2008 memcpy(wl->active_bssid, &bss->hwinfo->bssid[2], ETH_ALEN);2009 2010 /* send connect event */2011 gelic_wl_send_iwap_event(wl, wl->active_bssid);2012 pr_info("%s: connected\n", __func__);2013 }2014out:2015 free_page((unsigned long)common);2016 pr_debug("%s: ->\n", __func__);2017 return ret;2018}2019 2020/*2021 * connected event2022 */2023static void gelic_wl_connected_event(struct gelic_wl_info *wl,2024 u64 event)2025{2026 u64 desired_event = 0;2027 2028 switch (wl->wpa_level) {2029 case GELIC_WL_WPA_LEVEL_NONE:2030 desired_event = GELIC_LV1_WL_EVENT_CONNECTED;2031 break;2032 case GELIC_WL_WPA_LEVEL_WPA:2033 case GELIC_WL_WPA_LEVEL_WPA2:2034 desired_event = GELIC_LV1_WL_EVENT_WPA_CONNECTED;2035 break;2036 }2037 2038 if (desired_event == event) {2039 pr_debug("%s: completed\n", __func__);2040 complete(&wl->assoc_done);2041 netif_carrier_on(port_to_netdev(wl_port(wl)));2042 } else2043 pr_debug("%s: event %#llx under wpa\n",2044 __func__, event);2045}2046 2047/*2048 * disconnect event2049 */2050static void gelic_wl_disconnect_event(struct gelic_wl_info *wl,2051 u64 event)2052{2053 struct gelic_eurus_cmd *cmd;2054 int lock;2055 2056 /*2057 * If we fall here in the middle of association,2058 * associate_bss() should be waiting for complation of2059 * wl->assoc_done.2060 * As it waits with timeout, just leave assoc_done2061 * uncompleted, then it terminates with timeout2062 */2063 if (!mutex_trylock(&wl->assoc_stat_lock)) {2064 pr_debug("%s: already locked\n", __func__);2065 lock = 0;2066 } else {2067 pr_debug("%s: obtain lock\n", __func__);2068 lock = 1;2069 }2070 2071 cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_DISASSOC, NULL, 0);2072 kfree(cmd);2073 2074 /* send disconnected event to the supplicant */2075 if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED)2076 gelic_wl_send_iwap_event(wl, NULL);2077 2078 wl->assoc_stat = GELIC_WL_ASSOC_STAT_DISCONN;2079 netif_carrier_off(port_to_netdev(wl_port(wl)));2080 2081 if (lock)2082 mutex_unlock(&wl->assoc_stat_lock);2083}2084/*2085 * event worker2086 */2087#ifdef DEBUG2088static const char *eventstr(enum gelic_lv1_wl_event event)2089{2090 static char buf[32];2091 char *ret;2092 if (event & GELIC_LV1_WL_EVENT_DEVICE_READY)2093 ret = "EURUS_READY";2094 else if (event & GELIC_LV1_WL_EVENT_SCAN_COMPLETED)2095 ret = "SCAN_COMPLETED";2096 else if (event & GELIC_LV1_WL_EVENT_DEAUTH)2097 ret = "DEAUTH";2098 else if (event & GELIC_LV1_WL_EVENT_BEACON_LOST)2099 ret = "BEACON_LOST";2100 else if (event & GELIC_LV1_WL_EVENT_CONNECTED)2101 ret = "CONNECTED";2102 else if (event & GELIC_LV1_WL_EVENT_WPA_CONNECTED)2103 ret = "WPA_CONNECTED";2104 else if (event & GELIC_LV1_WL_EVENT_WPA_ERROR)2105 ret = "WPA_ERROR";2106 else {2107 sprintf(buf, "Unknown(%#x)", event);2108 ret = buf;2109 }2110 return ret;2111}2112#else2113static const char *eventstr(enum gelic_lv1_wl_event event)2114{2115 return NULL;2116}2117#endif2118static void gelic_wl_event_worker(struct work_struct *work)2119{2120 struct gelic_wl_info *wl;2121 struct gelic_port *port;2122 u64 event, tmp;2123 int status;2124 2125 pr_debug("%s:start\n", __func__);2126 wl = container_of(work, struct gelic_wl_info, event_work.work);2127 port = wl_port(wl);2128 while (1) {2129 status = lv1_net_control(bus_id(port->card), dev_id(port->card),2130 GELIC_LV1_GET_WLAN_EVENT, 0, 0, 0,2131 &event, &tmp);2132 if (status) {2133 if (status != LV1_NO_ENTRY)2134 pr_debug("%s:wlan event failed %d\n",2135 __func__, status);2136 /* got all events */2137 pr_debug("%s:end\n", __func__);2138 return;2139 }2140 pr_debug("%s: event=%s\n", __func__, eventstr(event));2141 switch (event) {2142 case GELIC_LV1_WL_EVENT_SCAN_COMPLETED:2143 gelic_wl_scan_complete_event(wl);2144 break;2145 case GELIC_LV1_WL_EVENT_BEACON_LOST:2146 case GELIC_LV1_WL_EVENT_DEAUTH:2147 gelic_wl_disconnect_event(wl, event);2148 break;2149 case GELIC_LV1_WL_EVENT_CONNECTED:2150 case GELIC_LV1_WL_EVENT_WPA_CONNECTED:2151 gelic_wl_connected_event(wl, event);2152 break;2153 default:2154 break;2155 }2156 } /* while */2157}2158/*2159 * association worker2160 */2161static void gelic_wl_assoc_worker(struct work_struct *work)2162{2163 struct gelic_wl_info *wl;2164 2165 struct gelic_wl_scan_info *best_bss;2166 int ret;2167 unsigned long irqflag;2168 u8 *essid;2169 size_t essid_len;2170 2171 wl = container_of(work, struct gelic_wl_info, assoc_work.work);2172 2173 mutex_lock(&wl->assoc_stat_lock);2174 2175 if (wl->assoc_stat != GELIC_WL_ASSOC_STAT_DISCONN)2176 goto out;2177 2178 spin_lock_irqsave(&wl->lock, irqflag);2179 if (test_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat)) {2180 pr_debug("%s: assoc ESSID configured %s\n", __func__,2181 wl->essid);2182 essid = wl->essid;2183 essid_len = wl->essid_len;2184 } else {2185 essid = NULL;2186 essid_len = 0;2187 }2188 spin_unlock_irqrestore(&wl->lock, irqflag);2189 2190 ret = gelic_wl_start_scan(wl, 0, essid, essid_len);2191 if (ret == -ERESTARTSYS) {2192 pr_debug("%s: scan start failed association\n", __func__);2193 schedule_delayed_work(&wl->assoc_work, HZ/10); /*FIXME*/2194 goto out;2195 } else if (ret) {2196 pr_info("%s: scan prerequisite failed\n", __func__);2197 goto out;2198 }2199 2200 /*2201 * Wait for bss scan completion2202 * If we have scan list already, gelic_wl_start_scan()2203 * returns OK and raises the complete. Thus,2204 * it's ok to wait unconditionally here2205 */2206 wait_for_completion(&wl->scan_done);2207 2208 pr_debug("%s: scan done\n", __func__);2209 mutex_lock(&wl->scan_lock);2210 if (wl->scan_stat != GELIC_WL_SCAN_STAT_GOT_LIST) {2211 gelic_wl_send_iwap_event(wl, NULL);2212 pr_info("%s: no scan list. association failed\n", __func__);2213 goto scan_lock_out;2214 }2215 2216 /* find best matching bss */2217 best_bss = gelic_wl_find_best_bss(wl);2218 if (!best_bss) {2219 gelic_wl_send_iwap_event(wl, NULL);2220 pr_info("%s: no bss matched. association failed\n", __func__);2221 goto scan_lock_out;2222 }2223 2224 /* ok, do association */2225 ret = gelic_wl_associate_bss(wl, best_bss);2226 if (ret)2227 pr_info("%s: association failed %d\n", __func__, ret);2228scan_lock_out:2229 mutex_unlock(&wl->scan_lock);2230out:2231 mutex_unlock(&wl->assoc_stat_lock);2232}2233/*2234 * Interrupt handler2235 * Called from the ethernet interrupt handler2236 * Processes wireless specific virtual interrupts only2237 */2238void gelic_wl_interrupt(struct net_device *netdev, u64 status)2239{2240 struct gelic_wl_info *wl = port_wl(netdev_priv(netdev));2241 2242 if (status & GELIC_CARD_WLAN_COMMAND_COMPLETED) {2243 pr_debug("%s:cmd complete\n", __func__);2244 complete(&wl->cmd_done_intr);2245 }2246 2247 if (status & GELIC_CARD_WLAN_EVENT_RECEIVED) {2248 pr_debug("%s:event received\n", __func__);2249 queue_delayed_work(wl->event_queue, &wl->event_work, 0);2250 }2251}2252 2253/*2254 * driver helpers2255 */2256static const iw_handler gelic_wl_wext_handler[] =2257{2258 IW_HANDLER(SIOCGIWNAME, gelic_wl_get_name),2259 IW_HANDLER(SIOCGIWRANGE, gelic_wl_get_range),2260 IW_HANDLER(SIOCSIWSCAN, gelic_wl_set_scan),2261 IW_HANDLER(SIOCGIWSCAN, gelic_wl_get_scan),2262 IW_HANDLER(SIOCSIWAUTH, gelic_wl_set_auth),2263 IW_HANDLER(SIOCGIWAUTH, gelic_wl_get_auth),2264 IW_HANDLER(SIOCSIWESSID, gelic_wl_set_essid),2265 IW_HANDLER(SIOCGIWESSID, gelic_wl_get_essid),2266 IW_HANDLER(SIOCSIWENCODE, gelic_wl_set_encode),2267 IW_HANDLER(SIOCGIWENCODE, gelic_wl_get_encode),2268 IW_HANDLER(SIOCSIWAP, gelic_wl_set_ap),2269 IW_HANDLER(SIOCGIWAP, gelic_wl_get_ap),2270 IW_HANDLER(SIOCSIWENCODEEXT, gelic_wl_set_encodeext),2271 IW_HANDLER(SIOCGIWENCODEEXT, gelic_wl_get_encodeext),2272 IW_HANDLER(SIOCSIWMODE, gelic_wl_set_mode),2273 IW_HANDLER(SIOCGIWMODE, gelic_wl_get_mode),2274 IW_HANDLER(SIOCGIWNICKN, gelic_wl_get_nick),2275};2276 2277static const struct iw_handler_def gelic_wl_wext_handler_def = {2278 .num_standard = ARRAY_SIZE(gelic_wl_wext_handler),2279 .standard = gelic_wl_wext_handler,2280 .get_wireless_stats = gelic_wl_get_wireless_stats,2281};2282 2283static struct net_device *gelic_wl_alloc(struct gelic_card *card)2284{2285 struct net_device *netdev;2286 struct gelic_port *port;2287 struct gelic_wl_info *wl;2288 unsigned int i;2289 2290 pr_debug("%s:start\n", __func__);2291 netdev = alloc_etherdev(sizeof(struct gelic_port) +2292 sizeof(struct gelic_wl_info));2293 pr_debug("%s: netdev =%p card=%p\n", __func__, netdev, card);2294 if (!netdev)2295 return NULL;2296 2297 strcpy(netdev->name, "wlan%d");2298 2299 port = netdev_priv(netdev);2300 port->netdev = netdev;2301 port->card = card;2302 port->type = GELIC_PORT_WIRELESS;2303 2304 wl = port_wl(port);2305 pr_debug("%s: wl=%p port=%p\n", __func__, wl, port);2306 2307 /* allocate scan list */2308 wl->networks = kcalloc(GELIC_WL_BSS_MAX_ENT,2309 sizeof(struct gelic_wl_scan_info),2310 GFP_KERNEL);2311 2312 if (!wl->networks)2313 goto fail_bss;2314 2315 wl->eurus_cmd_queue = create_singlethread_workqueue("gelic_cmd");2316 if (!wl->eurus_cmd_queue)2317 goto fail_cmd_workqueue;2318 2319 wl->event_queue = create_singlethread_workqueue("gelic_event");2320 if (!wl->event_queue)2321 goto fail_event_workqueue;2322 2323 INIT_LIST_HEAD(&wl->network_free_list);2324 INIT_LIST_HEAD(&wl->network_list);2325 for (i = 0; i < GELIC_WL_BSS_MAX_ENT; i++)2326 list_add_tail(&wl->networks[i].list,2327 &wl->network_free_list);2328 init_completion(&wl->cmd_done_intr);2329 2330 INIT_DELAYED_WORK(&wl->event_work, gelic_wl_event_worker);2331 INIT_DELAYED_WORK(&wl->assoc_work, gelic_wl_assoc_worker);2332 mutex_init(&wl->scan_lock);2333 mutex_init(&wl->assoc_stat_lock);2334 2335 init_completion(&wl->scan_done);2336 /* for the case that no scan request is issued and stop() is called */2337 complete(&wl->scan_done);2338 2339 spin_lock_init(&wl->lock);2340 2341 wl->scan_age = 5*HZ; /* FIXME */2342 2343 /* buffer for receiving scanned list etc */2344 BUILD_BUG_ON(PAGE_SIZE <2345 sizeof(struct gelic_eurus_scan_info) *2346 GELIC_EURUS_MAX_SCAN);2347 pr_debug("%s:end\n", __func__);2348 return netdev;2349 2350fail_event_workqueue:2351 destroy_workqueue(wl->eurus_cmd_queue);2352fail_cmd_workqueue:2353 kfree(wl->networks);2354fail_bss:2355 free_netdev(netdev);2356 pr_debug("%s:end error\n", __func__);2357 return NULL;2358 2359}2360 2361static void gelic_wl_free(struct gelic_wl_info *wl)2362{2363 struct gelic_wl_scan_info *scan_info;2364 unsigned int i;2365 2366 pr_debug("%s: <-\n", __func__);2367 2368 pr_debug("%s: destroy queues\n", __func__);2369 destroy_workqueue(wl->eurus_cmd_queue);2370 destroy_workqueue(wl->event_queue);2371 2372 scan_info = wl->networks;2373 for (i = 0; i < GELIC_WL_BSS_MAX_ENT; i++, scan_info++)2374 kfree(scan_info->hwinfo);2375 kfree(wl->networks);2376 2377 free_netdev(port_to_netdev(wl_port(wl)));2378 2379 pr_debug("%s: ->\n", __func__);2380}2381 2382static int gelic_wl_try_associate(struct net_device *netdev)2383{2384 struct gelic_wl_info *wl = port_wl(netdev_priv(netdev));2385 int ret = -1;2386 unsigned int i;2387 2388 pr_debug("%s: <-\n", __func__);2389 2390 /* check constraits for start association */2391 /* for no access restriction AP */2392 if (wl->group_cipher_method == GELIC_WL_CIPHER_NONE) {2393 if (test_bit(GELIC_WL_STAT_CONFIGURED,2394 &wl->stat))2395 goto do_associate;2396 else {2397 pr_debug("%s: no wep, not configured\n", __func__);2398 return ret;2399 }2400 }2401 2402 /* for WEP, one of four keys should be set */2403 if (wl->group_cipher_method == GELIC_WL_CIPHER_WEP) {2404 /* one of keys set */2405 for (i = 0; i < GELIC_WEP_KEYS; i++) {2406 if (test_bit(i, &wl->key_enabled))2407 goto do_associate;2408 }2409 pr_debug("%s: WEP, but no key specified\n", __func__);2410 return ret;2411 }2412 2413 /* for WPA[2], psk should be set */2414 if ((wl->group_cipher_method == GELIC_WL_CIPHER_TKIP) ||2415 (wl->group_cipher_method == GELIC_WL_CIPHER_AES)) {2416 if (test_bit(GELIC_WL_STAT_WPA_PSK_SET,2417 &wl->stat))2418 goto do_associate;2419 else {2420 pr_debug("%s: AES/TKIP, but PSK not configured\n",2421 __func__);2422 return ret;2423 }2424 }2425 2426do_associate:2427 ret = schedule_delayed_work(&wl->assoc_work, 0);2428 pr_debug("%s: start association work %d\n", __func__, ret);2429 return ret;2430}2431 2432/*2433 * netdev handlers2434 */2435static int gelic_wl_open(struct net_device *netdev)2436{2437 struct gelic_card *card = netdev_card(netdev);2438 2439 pr_debug("%s:->%p\n", __func__, netdev);2440 2441 gelic_card_up(card);2442 2443 /* try to associate */2444 gelic_wl_try_associate(netdev);2445 2446 netif_start_queue(netdev);2447 2448 pr_debug("%s:<-\n", __func__);2449 return 0;2450}2451 2452/*2453 * reset state machine2454 */2455static int gelic_wl_reset_state(struct gelic_wl_info *wl)2456{2457 struct gelic_wl_scan_info *target;2458 struct gelic_wl_scan_info *tmp;2459 2460 /* empty scan list */2461 list_for_each_entry_safe(target, tmp, &wl->network_list, list) {2462 list_move_tail(&target->list, &wl->network_free_list);2463 }2464 wl->scan_stat = GELIC_WL_SCAN_STAT_INIT;2465 2466 /* clear configuration */2467 wl->auth_method = GELIC_EURUS_AUTH_OPEN;2468 wl->group_cipher_method = GELIC_WL_CIPHER_NONE;2469 wl->pairwise_cipher_method = GELIC_WL_CIPHER_NONE;2470 wl->wpa_level = GELIC_WL_WPA_LEVEL_NONE;2471 2472 wl->key_enabled = 0;2473 wl->current_key = 0;2474 2475 wl->psk_type = GELIC_EURUS_WPA_PSK_PASSPHRASE;2476 wl->psk_len = 0;2477 2478 wl->essid_len = 0;2479 memset(wl->essid, 0, sizeof(wl->essid));2480 memset(wl->bssid, 0, sizeof(wl->bssid));2481 memset(wl->active_bssid, 0, sizeof(wl->active_bssid));2482 2483 wl->assoc_stat = GELIC_WL_ASSOC_STAT_DISCONN;2484 2485 memset(&wl->iwstat, 0, sizeof(wl->iwstat));2486 /* all status bit clear */2487 wl->stat = 0;2488 return 0;2489}2490 2491/*2492 * Tell eurus to terminate association2493 */2494static void gelic_wl_disconnect(struct net_device *netdev)2495{2496 struct gelic_port *port = netdev_priv(netdev);2497 struct gelic_wl_info *wl = port_wl(port);2498 struct gelic_eurus_cmd *cmd;2499 2500 /*2501 * If scann process is running on chip,2502 * further requests will be rejected2503 */2504 if (wl->scan_stat == GELIC_WL_SCAN_STAT_SCANNING)2505 wait_for_completion_timeout(&wl->scan_done, HZ);2506 2507 cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_DISASSOC, NULL, 0);2508 kfree(cmd);2509 gelic_wl_send_iwap_event(wl, NULL);2510};2511 2512static int gelic_wl_stop(struct net_device *netdev)2513{2514 struct gelic_port *port = netdev_priv(netdev);2515 struct gelic_wl_info *wl = port_wl(port);2516 struct gelic_card *card = netdev_card(netdev);2517 2518 pr_debug("%s:<-\n", __func__);2519 2520 /*2521 * Cancel pending association work.2522 * event work can run after netdev down2523 */2524 cancel_delayed_work(&wl->assoc_work);2525 2526 if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED)2527 gelic_wl_disconnect(netdev);2528 2529 /* reset our state machine */2530 gelic_wl_reset_state(wl);2531 2532 netif_stop_queue(netdev);2533 2534 gelic_card_down(card);2535 2536 pr_debug("%s:->\n", __func__);2537 return 0;2538}2539 2540/* -- */2541 2542static const struct net_device_ops gelic_wl_netdevice_ops = {2543 .ndo_open = gelic_wl_open,2544 .ndo_stop = gelic_wl_stop,2545 .ndo_start_xmit = gelic_net_xmit,2546 .ndo_set_rx_mode = gelic_net_set_multi,2547 .ndo_tx_timeout = gelic_net_tx_timeout,2548 .ndo_set_mac_address = eth_mac_addr,2549 .ndo_validate_addr = eth_validate_addr,2550#ifdef CONFIG_NET_POLL_CONTROLLER2551 .ndo_poll_controller = gelic_net_poll_controller,2552#endif2553};2554 2555static const struct ethtool_ops gelic_wl_ethtool_ops = {2556 .get_drvinfo = gelic_net_get_drvinfo,2557 .get_link = gelic_wl_get_link,2558};2559 2560static void gelic_wl_setup_netdev_ops(struct net_device *netdev)2561{2562 struct gelic_wl_info *wl;2563 wl = port_wl(netdev_priv(netdev));2564 BUG_ON(!wl);2565 netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT;2566 2567 netdev->ethtool_ops = &gelic_wl_ethtool_ops;2568 netdev->netdev_ops = &gelic_wl_netdevice_ops;2569 netdev->wireless_data = &wl->wireless_data;2570 netdev->wireless_handlers = &gelic_wl_wext_handler_def;2571}2572 2573/*2574 * driver probe/remove2575 */2576int gelic_wl_driver_probe(struct gelic_card *card)2577{2578 int ret;2579 struct net_device *netdev;2580 2581 pr_debug("%s:start\n", __func__);2582 2583 if (ps3_compare_firmware_version(1, 6, 0) < 0)2584 return 0;2585 if (!card->vlan[GELIC_PORT_WIRELESS].tx)2586 return 0;2587 2588 /* alloc netdevice for wireless */2589 netdev = gelic_wl_alloc(card);2590 if (!netdev)2591 return -ENOMEM;2592 2593 /* setup net_device structure */2594 SET_NETDEV_DEV(netdev, &card->dev->core);2595 gelic_wl_setup_netdev_ops(netdev);2596 2597 /* setup some of net_device and register it */2598 ret = gelic_net_setup_netdev(netdev, card);2599 if (ret)2600 goto fail_setup;2601 card->netdev[GELIC_PORT_WIRELESS] = netdev;2602 2603 /* add enable wireless interrupt */2604 card->irq_mask |= GELIC_CARD_WLAN_EVENT_RECEIVED |2605 GELIC_CARD_WLAN_COMMAND_COMPLETED;2606 /* to allow wireless commands while both interfaces are down */2607 gelic_card_set_irq_mask(card, GELIC_CARD_WLAN_EVENT_RECEIVED |2608 GELIC_CARD_WLAN_COMMAND_COMPLETED);2609 pr_debug("%s:end\n", __func__);2610 return 0;2611 2612fail_setup:2613 gelic_wl_free(port_wl(netdev_port(netdev)));2614 2615 return ret;2616}2617 2618int gelic_wl_driver_remove(struct gelic_card *card)2619{2620 struct gelic_wl_info *wl;2621 struct net_device *netdev;2622 2623 pr_debug("%s:start\n", __func__);2624 2625 if (ps3_compare_firmware_version(1, 6, 0) < 0)2626 return 0;2627 if (!card->vlan[GELIC_PORT_WIRELESS].tx)2628 return 0;2629 2630 netdev = card->netdev[GELIC_PORT_WIRELESS];2631 wl = port_wl(netdev_priv(netdev));2632 2633 /* if the interface was not up, but associated */2634 if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED)2635 gelic_wl_disconnect(netdev);2636 2637 complete(&wl->cmd_done_intr);2638 2639 /* cancel all work queue */2640 cancel_delayed_work(&wl->assoc_work);2641 cancel_delayed_work(&wl->event_work);2642 flush_workqueue(wl->eurus_cmd_queue);2643 flush_workqueue(wl->event_queue);2644 2645 unregister_netdev(netdev);2646 2647 /* disable wireless interrupt */2648 pr_debug("%s: disable intr\n", __func__);2649 card->irq_mask &= ~(GELIC_CARD_WLAN_EVENT_RECEIVED |2650 GELIC_CARD_WLAN_COMMAND_COMPLETED);2651 /* free bss list, netdev*/2652 gelic_wl_free(wl);2653 pr_debug("%s:end\n", __func__);2654 return 0;2655}2656