2008-05-30 07:17:44

by Masakazu Mokuno

[permalink] [raw]
Subject: [PATCH 0/3] PS3: gelic: gelic updates

Hi,

Here are PS3 gelic wireless updates.

Patches 1 and 2 change the allocation way for the wireless bounce buffer.
#3 adds ESSID scanning support.

#1 Allocate the bounce buffer dynamically
#2 Kill the static bounce buffer
#3 Add support for ESSID scan

They depend on the patch set which converts semaphores to mutexes
posted to netdev@vger by Daniel Walker <[email protected]> on May 22.

Best regards.

--
Masakazu Mokuno



2008-05-30 07:27:50

by Masakazu Mokuno

[permalink] [raw]
Subject: [PATCH 2/3] PS3: gelic: Kill the static bounce buffer

As the bounce buffer is allocaetd dynamically, kill the static bounce buffer.

Signed-off-by: Masakazu Mokuno <[email protected]>
---
drivers/net/ps3_gelic_wireless.c | 9 ---------
drivers/net/ps3_gelic_wireless.h | 3 ---
2 files changed, 12 deletions(-)

--- a/drivers/net/ps3_gelic_wireless.c
+++ b/drivers/net/ps3_gelic_wireless.c
@@ -2472,16 +2472,9 @@ static struct net_device *gelic_wl_alloc
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:
@@ -2500,8 +2493,6 @@ static void gelic_wl_free(struct gelic_w

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);
--- a/drivers/net/ps3_gelic_wireless.h
+++ b/drivers/net/ps3_gelic_wireless.h
@@ -288,9 +288,6 @@ struct gelic_wl_info {
u8 active_bssid[ETH_ALEN]; /* associated bssid */
unsigned int essid_len;

- /* buffer for hypervisor IO */
- void *buf;
-
struct iw_public_data wireless_data;
struct iw_statistics iwstat;
};


2008-05-30 07:27:40

by Masakazu Mokuno

[permalink] [raw]
Subject: [PATCH 1/3] PS3: gelic: Allocate the bounce buffer dynamically

Allocate the bouce buffer for the wireless command dynamically.

Signed-off-by: Masakazu Mokuno <[email protected]>
---
drivers/net/ps3_gelic_wireless.c | 40 ++++++++++++++++++++++++++++++++-------
1 file changed, 33 insertions(+), 7 deletions(-)

--- a/drivers/net/ps3_gelic_wireless.c
+++ b/drivers/net/ps3_gelic_wireless.c
@@ -1524,15 +1524,20 @@ static struct iw_statistics *gelic_wl_ge
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 +1546,7 @@ static struct iw_statistics *gelic_wl_ge
is->qual.updated = IW_QUAL_ALL_INVALID;

kfree(cmd);
+ free_page((unsigned long)buf);
pr_debug("%s: ->\n", __func__);
return is;
}
@@ -1607,11 +1613,18 @@ static void gelic_wl_scan_complete_event
union iwreq_data data;
unsigned long this_time = jiffies;
unsigned int data_len, i, found, r;
+ void *buf;
DECLARE_MAC_BUF(mac);

pr_debug("%s:start\n", __func__);
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) {
/*
* stop() may be called while scanning, ignore result
@@ -1622,7 +1635,7 @@ static void gelic_wl_scan_complete_event
}

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__);
@@ -1649,7 +1662,7 @@ static void gelic_wl_scan_complete_event
}

/* put them in the newtork_list */
- for (i = 0, scan_info_size = 0, scan_info = wl->buf;
+ 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)) {
@@ -1726,6 +1739,7 @@ static void gelic_wl_scan_complete_event
wireless_send_event(port_to_netdev(wl_port(wl)), SIOCGIWSCAN, &data,
NULL);
out:
+ free_page((unsigned long)buf);
complete(&wl->scan_done);
mutex_unlock(&wl->scan_lock);
pr_debug("%s:end\n", __func__);
@@ -1848,7 +1862,10 @@ static int gelic_wl_do_wep_setup(struct

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 +1915,7 @@ static int gelic_wl_do_wep_setup(struct

kfree(cmd);
out:
+ free_page((unsigned long)wep);
pr_debug("%s: ->\n", __func__);
return ret;
}
@@ -1941,7 +1959,10 @@ static int gelic_wl_do_wpa_setup(struct

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))
@@ -2000,6 +2021,7 @@ static int gelic_wl_do_wpa_setup(struct
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 +2040,10 @@ static int gelic_wl_associate_bss(struct
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);
@@ -2104,6 +2129,7 @@ static int gelic_wl_associate_bss(struct
pr_info("%s: connected\n", __func__);
}
out:
+ free_page((unsigned long)common);
pr_debug("%s: ->\n", __func__);
return ret;
}


2008-05-30 17:52:12

by Dan Williams

[permalink] [raw]
Subject: Re: [PATCH 3/3] PS3: gelic: Add support for ESSID scan

On Fri, 2008-05-30 at 16:27 +0900, Masakazu Mokuno wrote:
> This adds the support for ESSID scanning

You'll want to:

range->scan_capa = IW_SCAN_CAPA_ESSID;

in your SIOCGIWRANGE handler too.

Dan

> Signed-off-by: Masakazu Mokuno <[email protected]>
> ---
> drivers/net/ps3_gelic_wireless.c | 62 ++++++++++++++++++++++++++++++++++-----
> 1 file changed, 55 insertions(+), 7 deletions(-)
>
> --- a/drivers/net/ps3_gelic_wireless.c
> +++ b/drivers/net/ps3_gelic_wireless.c
> @@ -45,7 +45,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 +106,7 @@ static const struct eurus_cmd_arg_info c
> [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 +165,9 @@ static void gelic_eurus_sync_cmd_worker(
> 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;
> @@ -370,8 +374,18 @@ static int gelic_wl_set_scan(struct net_
> 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
> @@ -1554,10 +1568,13 @@ static struct iw_statistics *gelic_wl_ge
> /*
> * 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 (mutex_lock_interruptible(&wl->scan_lock))
> @@ -1580,12 +1597,27 @@ static int gelic_wl_start_scan(struct ge
> 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);
> @@ -1594,6 +1626,7 @@ static int gelic_wl_start_scan(struct ge
> }
> kfree(cmd);
> out:
> + free_page((unsigned long)buf);
> mutex_unlock(&wl->scan_lock);
> pr_debug("%s: ->\n", __func__);
> return ret;
> @@ -2281,6 +2314,9 @@ static void gelic_wl_assoc_worker(struct
>
> 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);
>
> @@ -2289,7 +2325,19 @@ static void gelic_wl_assoc_worker(struct
> 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*/
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html


2008-05-30 07:28:04

by Masakazu Mokuno

[permalink] [raw]
Subject: [PATCH 3/3] PS3: gelic: Add support for ESSID scan

This adds the support for ESSID scanning

Signed-off-by: Masakazu Mokuno <[email protected]>
---
drivers/net/ps3_gelic_wireless.c | 62 ++++++++++++++++++++++++++++++++++-----
1 file changed, 55 insertions(+), 7 deletions(-)

--- a/drivers/net/ps3_gelic_wireless.c
+++ b/drivers/net/ps3_gelic_wireless.c
@@ -45,7 +45,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 +106,7 @@ static const struct eurus_cmd_arg_info c
[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 +165,9 @@ static void gelic_eurus_sync_cmd_worker(
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;
@@ -370,8 +374,18 @@ static int gelic_wl_set_scan(struct net_
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
@@ -1554,10 +1568,13 @@ static struct iw_statistics *gelic_wl_ge
/*
* 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 (mutex_lock_interruptible(&wl->scan_lock))
@@ -1580,12 +1597,27 @@ static int gelic_wl_start_scan(struct ge
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);
@@ -1594,6 +1626,7 @@ static int gelic_wl_start_scan(struct ge
}
kfree(cmd);
out:
+ free_page((unsigned long)buf);
mutex_unlock(&wl->scan_lock);
pr_debug("%s: ->\n", __func__);
return ret;
@@ -2281,6 +2314,9 @@ static void gelic_wl_assoc_worker(struct

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);

@@ -2289,7 +2325,19 @@ static void gelic_wl_assoc_worker(struct
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*/


2008-06-02 03:43:18

by Masakazu Mokuno

[permalink] [raw]
Subject: Re: [PATCH 3/3] PS3: gelic: Add support for ESSID scan


On Fri, 30 May 2008 13:51:44 -0400
Dan Williams <[email protected]> wrote:

> On Fri, 2008-05-30 at 16:27 +0900, Masakazu Mokuno wrote:
> > This adds the support for ESSID scanning
>
> You'll want to:
>
> range->scan_capa = IW_SCAN_CAPA_ESSID;
>
> in your SIOCGIWRANGE handler too.

I didn't notice that this flag already was merged in.
I'll respin.

Thanks for pointing out.

--
Masakazu Mokuno


2008-06-02 13:40:32

by Dan Williams

[permalink] [raw]
Subject: Re: [PATCH 3/3 v2] PS3: gelic: Add support for ESSID scan

On Mon, 2008-06-02 at 12:49 +0900, Masakazu Mokuno wrote:
> This adds the support for ESSID scanning
>
> Signed-off-by: Masakazu Mokuno <[email protected]>

WEXT bits now look good, thanks for the scan_capa addition!

Acked-by: Dan Williams <[email protected]>

> ---
> v2
> Add IW_SCAN_CAPA_ESSID capability flag
>
> drivers/net/ps3_gelic_wireless.c | 65 ++++++++++++++++++++++++++++++++++-----
> 1 file changed, 58 insertions(+), 7 deletions(-)
>
> --- a/drivers/net/ps3_gelic_wireless.c
> +++ b/drivers/net/ps3_gelic_wireless.c
> @@ -45,7 +45,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 +106,7 @@ static const struct eurus_cmd_arg_info c
> [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 +165,9 @@ static void gelic_eurus_sync_cmd_worker(
> 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;
> @@ -359,6 +363,9 @@ static int gelic_wl_get_range(struct net
> 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 +377,18 @@ static int gelic_wl_set_scan(struct net_
> 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
> @@ -1554,10 +1571,13 @@ static struct iw_statistics *gelic_wl_ge
> /*
> * 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 (mutex_lock_interruptible(&wl->scan_lock))
> @@ -1580,12 +1600,27 @@ static int gelic_wl_start_scan(struct ge
> 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);
> @@ -1594,6 +1629,7 @@ static int gelic_wl_start_scan(struct ge
> }
> kfree(cmd);
> out:
> + free_page((unsigned long)buf);
> mutex_unlock(&wl->scan_lock);
> pr_debug("%s: ->\n", __func__);
> return ret;
> @@ -2281,6 +2317,9 @@ static void gelic_wl_assoc_worker(struct
>
> 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);
>
> @@ -2289,7 +2328,19 @@ static void gelic_wl_assoc_worker(struct
> 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*/
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html


2008-06-02 03:49:23

by Masakazu Mokuno

[permalink] [raw]
Subject: [PATCH 3/3 v2] PS3: gelic: Add support for ESSID scan

This adds the support for ESSID scanning

Signed-off-by: Masakazu Mokuno <[email protected]>
---
v2
Add IW_SCAN_CAPA_ESSID capability flag

drivers/net/ps3_gelic_wireless.c | 65 ++++++++++++++++++++++++++++++++++-----
1 file changed, 58 insertions(+), 7 deletions(-)

--- a/drivers/net/ps3_gelic_wireless.c
+++ b/drivers/net/ps3_gelic_wireless.c
@@ -45,7 +45,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 +106,7 @@ static const struct eurus_cmd_arg_info c
[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 +165,9 @@ static void gelic_eurus_sync_cmd_worker(
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;
@@ -359,6 +363,9 @@ static int gelic_wl_get_range(struct net
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 +377,18 @@ static int gelic_wl_set_scan(struct net_
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
@@ -1554,10 +1571,13 @@ static struct iw_statistics *gelic_wl_ge
/*
* 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 (mutex_lock_interruptible(&wl->scan_lock))
@@ -1580,12 +1600,27 @@ static int gelic_wl_start_scan(struct ge
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);
@@ -1594,6 +1629,7 @@ static int gelic_wl_start_scan(struct ge
}
kfree(cmd);
out:
+ free_page((unsigned long)buf);
mutex_unlock(&wl->scan_lock);
pr_debug("%s: ->\n", __func__);
return ret;
@@ -2281,6 +2317,9 @@ static void gelic_wl_assoc_worker(struct

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);

@@ -2289,7 +2328,19 @@ static void gelic_wl_assoc_worker(struct
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*/