aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ps3_gelic_wireless.c
diff options
context:
space:
mode:
authorMasakazu Mokuno <mokuno@sm.sony.co.jp>2008-06-01 23:49:16 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-06-03 15:00:28 -0400
commit7fd871edf437362b62ddd807542638cbda8d8a39 (patch)
treef06b2c184a1e4c11506ad9d0eaeaa159e770534a /drivers/net/ps3_gelic_wireless.c
parent552fe53f48ef2fd54b031b37d304211cee893ba0 (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/ps3_gelic_wireless.c')
-rw-r--r--drivers/net/ps3_gelic_wireless.c65
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
48static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan); 48static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan,
49 u8 *essid, size_t essid_len);
49static int gelic_wl_try_associate(struct net_device *netdev); 50static 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 */
1537static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan) 1554static 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);
1576out: 1611out:
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*/