diff options
author | Masakazu Mokuno <mokuno@sm.sony.co.jp> | 2008-06-01 23:49:16 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-06-03 15:00:28 -0400 |
commit | 7fd871edf437362b62ddd807542638cbda8d8a39 (patch) | |
tree | f06b2c184a1e4c11506ad9d0eaeaa159e770534a /drivers/net | |
parent | 552fe53f48ef2fd54b031b37d304211cee893ba0 (diff) |
PS3: gelic: Add support for ESSID scan
This adds the support for ESSID scanning
Signed-off-by: Masakazu Mokuno <mokuno@sm.sony.co.jp>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ps3_gelic_wireless.c | 65 |
1 files changed, 58 insertions, 7 deletions
diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c index f5e5f13eaf43..aa963ac1e37b 100644 --- a/drivers/net/ps3_gelic_wireless.c +++ b/drivers/net/ps3_gelic_wireless.c | |||
@@ -45,7 +45,8 @@ | |||
45 | #include "ps3_gelic_wireless.h" | 45 | #include "ps3_gelic_wireless.h" |
46 | 46 | ||
47 | 47 | ||
48 | static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan); | 48 | static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan, |
49 | u8 *essid, size_t essid_len); | ||
49 | static int gelic_wl_try_associate(struct net_device *netdev); | 50 | static int gelic_wl_try_associate(struct net_device *netdev); |
50 | 51 | ||
51 | /* | 52 | /* |
@@ -105,6 +106,7 @@ static const struct eurus_cmd_arg_info cmd_info[GELIC_EURUS_CMD_MAX_INDEX] = { | |||
105 | [GELIC_EURUS_CMD_GET_WEP_CFG] = { .post_arg = 1}, | 106 | [GELIC_EURUS_CMD_GET_WEP_CFG] = { .post_arg = 1}, |
106 | [GELIC_EURUS_CMD_GET_WPA_CFG] = { .post_arg = 1}, | 107 | [GELIC_EURUS_CMD_GET_WPA_CFG] = { .post_arg = 1}, |
107 | [GELIC_EURUS_CMD_GET_RSSI_CFG] = { .post_arg = 1}, | 108 | [GELIC_EURUS_CMD_GET_RSSI_CFG] = { .post_arg = 1}, |
109 | [GELIC_EURUS_CMD_START_SCAN] = { .pre_arg = 1}, | ||
108 | [GELIC_EURUS_CMD_GET_SCAN] = { .post_arg = 1}, | 110 | [GELIC_EURUS_CMD_GET_SCAN] = { .post_arg = 1}, |
109 | }; | 111 | }; |
110 | 112 | ||
@@ -163,7 +165,9 @@ static void gelic_eurus_sync_cmd_worker(struct work_struct *work) | |||
163 | card = port_to_card(wl_port(wl)); | 165 | card = port_to_card(wl_port(wl)); |
164 | 166 | ||
165 | if (cmd_info[cmd->cmd].pre_arg) { | 167 | if (cmd_info[cmd->cmd].pre_arg) { |
166 | arg1 = ps3_mm_phys_to_lpar(__pa(cmd->buffer)); | 168 | arg1 = (cmd->buffer) ? |
169 | ps3_mm_phys_to_lpar(__pa(cmd->buffer)) : | ||
170 | 0; | ||
167 | arg2 = cmd->buf_size; | 171 | arg2 = cmd->buf_size; |
168 | } else { | 172 | } else { |
169 | arg1 = 0; | 173 | arg1 = 0; |
@@ -360,6 +364,9 @@ static int gelic_wl_get_range(struct net_device *netdev, | |||
360 | range->num_encoding_sizes = 3; | 364 | range->num_encoding_sizes = 3; |
361 | range->max_encoding_tokens = GELIC_WEP_KEYS; | 365 | range->max_encoding_tokens = GELIC_WEP_KEYS; |
362 | 366 | ||
367 | /* scan capability */ | ||
368 | range->scan_capa = IW_SCAN_CAPA_ESSID; | ||
369 | |||
363 | pr_debug("%s: ->\n", __func__); | 370 | pr_debug("%s: ->\n", __func__); |
364 | return 0; | 371 | return 0; |
365 | 372 | ||
@@ -371,8 +378,18 @@ static int gelic_wl_set_scan(struct net_device *netdev, | |||
371 | union iwreq_data *wrqu, char *extra) | 378 | union iwreq_data *wrqu, char *extra) |
372 | { | 379 | { |
373 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); | 380 | struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); |
374 | 381 | struct iw_scan_req *req; | |
375 | return gelic_wl_start_scan(wl, 1); | 382 | u8 *essid = NULL; |
383 | size_t essid_len = 0; | ||
384 | |||
385 | if (wrqu->data.length == sizeof(struct iw_scan_req) && | ||
386 | wrqu->data.flags & IW_SCAN_THIS_ESSID) { | ||
387 | req = (struct iw_scan_req*)extra; | ||
388 | essid = req->essid; | ||
389 | essid_len = req->essid_len; | ||
390 | pr_debug("%s: ESSID scan =%s\n", __func__, essid); | ||
391 | } | ||
392 | return gelic_wl_start_scan(wl, 1, essid, essid_len); | ||
376 | } | 393 | } |
377 | 394 | ||
378 | #define OUI_LEN 3 | 395 | #define OUI_LEN 3 |
@@ -1534,10 +1551,13 @@ static struct iw_statistics *gelic_wl_get_wireless_stats( | |||
1534 | /* | 1551 | /* |
1535 | * scanning helpers | 1552 | * scanning helpers |
1536 | */ | 1553 | */ |
1537 | static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan) | 1554 | static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan, |
1555 | u8 *essid, size_t essid_len) | ||
1538 | { | 1556 | { |
1539 | struct gelic_eurus_cmd *cmd; | 1557 | struct gelic_eurus_cmd *cmd; |
1540 | int ret = 0; | 1558 | int ret = 0; |
1559 | void *buf = NULL; | ||
1560 | size_t len; | ||
1541 | 1561 | ||
1542 | pr_debug("%s: <- always=%d\n", __func__, always_scan); | 1562 | pr_debug("%s: <- always=%d\n", __func__, always_scan); |
1543 | if (mutex_lock_interruptible(&wl->scan_lock)) | 1563 | if (mutex_lock_interruptible(&wl->scan_lock)) |
@@ -1560,12 +1580,27 @@ static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan) | |||
1560 | complete(&wl->scan_done); | 1580 | complete(&wl->scan_done); |
1561 | goto out; | 1581 | goto out; |
1562 | } | 1582 | } |
1583 | |||
1584 | /* ESSID scan ? */ | ||
1585 | if (essid_len && essid) { | ||
1586 | buf = (void *)__get_free_page(GFP_KERNEL); | ||
1587 | if (!buf) { | ||
1588 | ret = -ENOMEM; | ||
1589 | goto out; | ||
1590 | } | ||
1591 | len = IW_ESSID_MAX_SIZE; /* hypervisor always requires 32 */ | ||
1592 | memset(buf, 0, len); | ||
1593 | memcpy(buf, essid, essid_len); | ||
1594 | pr_debug("%s: essid scan='%s'\n", __func__, (char *)buf); | ||
1595 | } else | ||
1596 | len = 0; | ||
1597 | |||
1563 | /* | 1598 | /* |
1564 | * issue start scan request | 1599 | * issue start scan request |
1565 | */ | 1600 | */ |
1566 | wl->scan_stat = GELIC_WL_SCAN_STAT_SCANNING; | 1601 | wl->scan_stat = GELIC_WL_SCAN_STAT_SCANNING; |
1567 | cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_START_SCAN, | 1602 | cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_START_SCAN, |
1568 | NULL, 0); | 1603 | buf, len); |
1569 | if (!cmd || cmd->status || cmd->cmd_status) { | 1604 | if (!cmd || cmd->status || cmd->cmd_status) { |
1570 | wl->scan_stat = GELIC_WL_SCAN_STAT_INIT; | 1605 | wl->scan_stat = GELIC_WL_SCAN_STAT_INIT; |
1571 | complete(&wl->scan_done); | 1606 | complete(&wl->scan_done); |
@@ -1574,6 +1609,7 @@ static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan) | |||
1574 | } | 1609 | } |
1575 | kfree(cmd); | 1610 | kfree(cmd); |
1576 | out: | 1611 | out: |
1612 | free_page((unsigned long)buf); | ||
1577 | mutex_unlock(&wl->scan_lock); | 1613 | mutex_unlock(&wl->scan_lock); |
1578 | pr_debug("%s: ->\n", __func__); | 1614 | pr_debug("%s: ->\n", __func__); |
1579 | return ret; | 1615 | return ret; |
@@ -2261,6 +2297,9 @@ static void gelic_wl_assoc_worker(struct work_struct *work) | |||
2261 | 2297 | ||
2262 | struct gelic_wl_scan_info *best_bss; | 2298 | struct gelic_wl_scan_info *best_bss; |
2263 | int ret; | 2299 | int ret; |
2300 | unsigned long irqflag; | ||
2301 | u8 *essid; | ||
2302 | size_t essid_len; | ||
2264 | 2303 | ||
2265 | wl = container_of(work, struct gelic_wl_info, assoc_work.work); | 2304 | wl = container_of(work, struct gelic_wl_info, assoc_work.work); |
2266 | 2305 | ||
@@ -2269,7 +2308,19 @@ static void gelic_wl_assoc_worker(struct work_struct *work) | |||
2269 | if (wl->assoc_stat != GELIC_WL_ASSOC_STAT_DISCONN) | 2308 | if (wl->assoc_stat != GELIC_WL_ASSOC_STAT_DISCONN) |
2270 | goto out; | 2309 | goto out; |
2271 | 2310 | ||
2272 | ret = gelic_wl_start_scan(wl, 0); | 2311 | spin_lock_irqsave(&wl->lock, irqflag); |
2312 | if (test_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat)) { | ||
2313 | pr_debug("%s: assoc ESSID configured %s\n", __func__, | ||
2314 | wl->essid); | ||
2315 | essid = wl->essid; | ||
2316 | essid_len = wl->essid_len; | ||
2317 | } else { | ||
2318 | essid = NULL; | ||
2319 | essid_len = 0; | ||
2320 | } | ||
2321 | spin_unlock_irqrestore(&wl->lock, irqflag); | ||
2322 | |||
2323 | ret = gelic_wl_start_scan(wl, 0, essid, essid_len); | ||
2273 | if (ret == -ERESTARTSYS) { | 2324 | if (ret == -ERESTARTSYS) { |
2274 | pr_debug("%s: scan start failed association\n", __func__); | 2325 | pr_debug("%s: scan start failed association\n", __func__); |
2275 | schedule_delayed_work(&wl->assoc_work, HZ/10); /*FIXME*/ | 2326 | schedule_delayed_work(&wl->assoc_work, HZ/10); /*FIXME*/ |