Commit 3a188649 authored by Holger Schurig's avatar Holger Schurig Committed by David S. Miller

libertas: rework event subscription

This patch moves re-works the implementation of event subscription
via debugfs. For this:

* it tells cmd.c and cmdresp.c about CMD_802_11_SUBSCRIBE_EVENT
* removes lots of low-level cmd stuff from debugfs.c
* create unified functions to read/write snr, rssi, bcnmiss and
  failcount
* introduces #define's for subscription event bitmask values
* add a function to search for a specific element in an IE
  (a.k.a. TLV)
* add a function to find out the size of the TLV. This is needed
  because lbs_prepare_and_send_command() has an argument for a
  data buffer, but not for it's lengths and TLVs can be, by
  definition, vary in size.
* fix a bug where it was not possible to disable an event
Signed-off-by: default avatarHolger Schurig <hs4233@mail.mn-solutions.de>
Acked-by: default avatarDan Williams <dcbw@redhat.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 69f9032d
...@@ -246,6 +246,52 @@ static int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, ...@@ -246,6 +246,52 @@ static int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv,
} }
static ssize_t lbs_tlv_size(const u8 *tlv, u16 size)
{
ssize_t pos = 0;
struct mrvlietypesheader *tlv_h;
while (pos < size) {
u16 length;
tlv_h = (struct mrvlietypesheader *) tlv;
if (tlv_h->len == 0)
return pos;
length = le16_to_cpu(tlv_h->len) +
sizeof(struct mrvlietypesheader);
pos += length;
tlv += length;
}
return pos;
}
static void lbs_cmd_802_11_subscribe_event(struct lbs_private *priv,
struct cmd_ds_command *cmd, u16 cmd_action,
void *pdata_buf)
{
struct cmd_ds_802_11_subscribe_event *events =
(struct cmd_ds_802_11_subscribe_event *) pdata_buf;
/* pdata_buf points to a struct cmd_ds_802_11_subscribe_event and room
* for various Marvell TLVs */
lbs_deb_enter(LBS_DEB_CMD);
cmd->size = cpu_to_le16(sizeof(*events)
- sizeof(events->tlv)
+ S_DS_GEN);
cmd->params.subscribe_event.action = cpu_to_le16(cmd_action);
if (cmd_action == CMD_ACT_GET) {
cmd->params.subscribe_event.events = 0;
} else {
ssize_t sz = lbs_tlv_size(events->tlv, sizeof(events->tlv));
cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) + sz);
cmd->params.subscribe_event.events = events->events;
memcpy(cmd->params.subscribe_event.tlv, events->tlv, sz);
}
lbs_deb_leave(LBS_DEB_CMD);
}
static void set_one_wpa_key(struct MrvlIEtype_keyParamSet * pkeyparamset, static void set_one_wpa_key(struct MrvlIEtype_keyParamSet * pkeyparamset,
struct enc_key * pkey) struct enc_key * pkey)
{ {
...@@ -1394,6 +1440,10 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, ...@@ -1394,6 +1440,10 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
ret = 0; ret = 0;
break; break;
} }
case CMD_802_11_SUBSCRIBE_EVENT:
lbs_cmd_802_11_subscribe_event(priv, cmdptr,
cmd_action, pdata_buf);
break;
case CMD_802_11_PWR_CFG: case CMD_802_11_PWR_CFG:
cmdptr->command = cpu_to_le16(CMD_802_11_PWR_CFG); cmdptr->command = cpu_to_le16(CMD_802_11_PWR_CFG);
cmdptr->size = cmdptr->size =
......
...@@ -554,6 +554,26 @@ static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv, ...@@ -554,6 +554,26 @@ static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv,
return 0; return 0;
} }
static int lbs_ret_802_11_subscribe_event(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
struct lbs_adapter *adapter = priv->adapter;
struct cmd_ds_802_11_subscribe_event *cmd_event =
&resp->params.subscribe_event;
struct cmd_ds_802_11_subscribe_event *dst_event =
adapter->cur_cmd->pdata_buf;
lbs_deb_enter(LBS_DEB_CMD);
if (dst_event->action == cpu_to_le16(CMD_ACT_GET)) {
dst_event->events = le16_to_cpu(cmd_event->events);
memcpy(dst_event->tlv, cmd_event->tlv, sizeof(dst_event->tlv));
}
lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
static inline int handle_cmd_response(u16 respcmd, static inline int handle_cmd_response(u16 respcmd,
struct cmd_ds_command *resp, struct cmd_ds_command *resp,
struct lbs_private *priv) struct lbs_private *priv)
...@@ -689,6 +709,10 @@ static inline int handle_cmd_response(u16 respcmd, ...@@ -689,6 +709,10 @@ static inline int handle_cmd_response(u16 respcmd,
sizeof(struct cmd_ds_802_11_led_ctrl)); sizeof(struct cmd_ds_802_11_led_ctrl));
spin_unlock_irqrestore(&adapter->driver_lock, flags); spin_unlock_irqrestore(&adapter->driver_lock, flags);
break; break;
case CMD_RET(CMD_802_11_SUBSCRIBE_EVENT):
ret = lbs_ret_802_11_subscribe_event(priv, resp);
break;
case CMD_RET(CMD_802_11_PWR_CFG): case CMD_RET(CMD_802_11_PWR_CFG):
spin_lock_irqsave(&adapter->driver_lock, flags); spin_lock_irqsave(&adapter->driver_lock, flags);
memmove(adapter->cur_cmd->pdata_buf, &resp->params.pwrcfg, memmove(adapter->cur_cmd->pdata_buf, &resp->params.pwrcfg,
......
...@@ -384,524 +384,162 @@ static ssize_t lbs_setuserscan(struct file *file, ...@@ -384,524 +384,162 @@ static ssize_t lbs_setuserscan(struct file *file,
return count; return count;
} }
static int lbs_event_initcmd(struct lbs_private *priv, void **response_buf,
struct cmd_ctrl_node **cmdnode,
struct cmd_ds_command **cmd)
{
u16 wait_option = CMD_OPTION_WAITFORRSP;
if (!(*cmdnode = lbs_get_free_cmd_ctrl_node(priv))) { /*
lbs_deb_debugfs("failed lbs_get_free_cmd_ctrl_node\n"); * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might
return -ENOMEM; * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the
} * firmware. Here's an example:
if (!(*response_buf = kmalloc(3000, GFP_KERNEL))) { * 04 01 02 00 00 00 05 01 02 00 00 00 06 01 02 00
lbs_deb_debugfs("failed to allocate response buffer!\n"); * 00 00 07 01 02 00 3c 00 00 00 00 00 00 00 03 03
return -ENOMEM; * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
} *
lbs_set_cmd_ctrl_node(priv, *cmdnode, 0, wait_option, NULL); * The 04 01 is the TLV type (here TLV_TYPE_RSSI_LOW), 02 00 is the length,
init_waitqueue_head(&(*cmdnode)->cmdwait_q); * 00 00 are the data bytes of this TLV. For this TLV, their meaning is
(*cmdnode)->pdata_buf = *response_buf; * defined in mrvlietypes_thresholds
(*cmdnode)->cmdflags |= CMD_F_HOSTCMD; *
(*cmdnode)->cmdwaitqwoken = 0; * This function searches in this TLV data chunk for a given TLV type
*cmd = (struct cmd_ds_command *)(*cmdnode)->bufvirtualaddr; * and returns a pointer to the first data byte of the TLV, or to NULL
(*cmd)->command = cpu_to_le16(CMD_802_11_SUBSCRIBE_EVENT); * if the TLV hasn't been found.
(*cmd)->seqnum = cpu_to_le16(++priv->adapter->seqnum); */
(*cmd)->result = 0; static void *lbs_tlv_find(u16 tlv_type, const u8 *tlv, u16 size)
return 0;
}
static ssize_t lbs_lowrssi_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{ {
struct lbs_private *priv = file->private_data; __le16 le_type = cpu_to_le16(tlv_type);
struct lbs_adapter *adapter = priv->adapter;
struct cmd_ctrl_node *pcmdnode;
struct cmd_ds_command *pcmdptr;
struct cmd_ds_802_11_subscribe_event *event;
void *response_buf;
int res, cmd_len;
ssize_t pos = 0; ssize_t pos = 0;
unsigned long addr = get_zeroed_page(GFP_KERNEL); struct mrvlietypesheader *tlv_h;
char *buf = (char *)addr; while (pos < size) {
u16 length;
res = lbs_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr); tlv_h = (struct mrvlietypesheader *) tlv;
if (res < 0) { if (tlv_h->type == le_type)
free_page(addr); return tlv_h;
return res; if (tlv_h->len == 0)
} return NULL;
length = le16_to_cpu(tlv_h->len) +
event = &pcmdptr->params.subscribe_event; sizeof(struct mrvlietypesheader);
event->action = cpu_to_le16(CMD_ACT_GET); pos += length;
pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN); tlv += length;
lbs_queue_cmd(adapter, pcmdnode, 1); }
wake_up_interruptible(&priv->waitq); return NULL;
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
pcmdnode->cmdwaitqwoken);
pcmdptr = response_buf;
if (pcmdptr->result) {
lbs_pr_err("%s: fail, result=%d\n", __func__,
le16_to_cpu(pcmdptr->result));
kfree(response_buf);
free_page(addr);
return 0;
}
if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) {
lbs_pr_err("command response incorrect!\n");
kfree(response_buf);
free_page(addr);
return 0;
}
cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
event = (void *)(response_buf + S_DS_GEN);
while (cmd_len < le16_to_cpu(pcmdptr->size)) {
struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
switch (header->type) {
struct mrvlietypes_rssithreshold *Lowrssi;
case __constant_cpu_to_le16(TLV_TYPE_RSSI_LOW):
Lowrssi = (void *)(response_buf + cmd_len);
pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
Lowrssi->rssivalue,
Lowrssi->rssifreq,
(event->events & cpu_to_le16(0x0001))?1:0);
default:
cmd_len += sizeof(struct mrvlietypes_snrthreshold);
break;
}
}
kfree(response_buf);
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
free_page(addr);
return res;
} }
/*
* This just gets the bitmap of currently subscribed events. Used when
* adding an additonal event subscription.
*/
static u16 lbs_get_events_bitmap(struct lbs_private *priv) static u16 lbs_get_events_bitmap(struct lbs_private *priv)
{ {
struct lbs_adapter *adapter = priv->adapter; ssize_t res;
struct cmd_ctrl_node *pcmdnode;
struct cmd_ds_command *pcmdptr;
struct cmd_ds_802_11_subscribe_event *event;
void *response_buf;
int res;
u16 event_bitmap;
res = lbs_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
if (res < 0)
return res;
event = &pcmdptr->params.subscribe_event;
event->action = cpu_to_le16(CMD_ACT_GET);
pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
lbs_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->waitq);
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
pcmdnode->cmdwaitqwoken);
pcmdptr = response_buf; struct cmd_ds_802_11_subscribe_event *events = kzalloc(
sizeof(struct cmd_ds_802_11_subscribe_event),
GFP_KERNEL);
if (pcmdptr->result) { res = lbs_prepare_and_send_command(priv,
lbs_pr_err("%s: fail, result=%d\n", __func__, CMD_802_11_SUBSCRIBE_EVENT, CMD_ACT_GET,
le16_to_cpu(pcmdptr->result)); CMD_OPTION_WAITFORRSP, 0, events);
kfree(response_buf);
return 0;
}
if (le16_to_cpu(pcmdptr->command) != CMD_RET(CMD_802_11_SUBSCRIBE_EVENT)) { if (res) {
lbs_pr_err("command response incorrect!\n"); kfree(events);
kfree(response_buf);
return 0; return 0;
} }
return le16_to_cpu(events->events);
event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
event_bitmap = le16_to_cpu(event->events);
kfree(response_buf);
return event_bitmap;
} }
static ssize_t lbs_lowrssi_write(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
struct lbs_adapter *adapter = priv->adapter;
ssize_t res, buf_size;
int value, freq, subscribed, cmd_len;
struct cmd_ctrl_node *pcmdnode;
struct cmd_ds_command *pcmdptr;
struct cmd_ds_802_11_subscribe_event *event;
struct mrvlietypes_rssithreshold *rssi_threshold;
void *response_buf;
u16 event_bitmap;
u8 *ptr;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
buf_size = min(count, len - 1);
if (copy_from_user(buf, userbuf, buf_size)) {
res = -EFAULT;
goto out_unlock;
}
res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
if (res != 3) {
res = -EFAULT;
goto out_unlock;
}
event_bitmap = lbs_get_events_bitmap(priv);
res = lbs_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
if (res < 0)
goto out_unlock;
event = &pcmdptr->params.subscribe_event;
event->action = cpu_to_le16(CMD_ACT_SET);
pcmdptr->size = cpu_to_le16(S_DS_GEN +
sizeof(struct cmd_ds_802_11_subscribe_event) +
sizeof(struct mrvlietypes_rssithreshold));
cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
ptr = (u8*) pcmdptr+cmd_len;
rssi_threshold = (struct mrvlietypes_rssithreshold *)(ptr);
rssi_threshold->header.type = cpu_to_le16(0x0104);
rssi_threshold->header.len = cpu_to_le16(2);
rssi_threshold->rssivalue = value;
rssi_threshold->rssifreq = freq;
event_bitmap |= subscribed ? 0x0001 : 0x0;
event->events = cpu_to_le16(event_bitmap);
lbs_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->waitq);
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
pcmdnode->cmdwaitqwoken);
pcmdptr = response_buf;
if (pcmdptr->result) {
lbs_pr_err("%s: fail, result=%d\n", __func__,
le16_to_cpu(pcmdptr->result));
kfree(response_buf);
free_page(addr);
return 0;
}
if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) { static ssize_t lbs_threshold_read(
lbs_pr_err("command response incorrect!\n"); u16 tlv_type, u16 event_mask,
kfree(response_buf); struct file *file, char __user *userbuf,
free_page(addr); size_t count, loff_t *ppos)
return 0;
}
res = count;
out_unlock:
free_page(addr);
return res;
}
static ssize_t lbs_lowsnr_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{ {
struct lbs_private *priv = file->private_data; struct lbs_private *priv = file->private_data;
struct lbs_adapter *adapter = priv->adapter; ssize_t res = 0;
struct cmd_ctrl_node *pcmdnode; size_t pos = 0;
struct cmd_ds_command *pcmdptr;
struct cmd_ds_802_11_subscribe_event *event;
void *response_buf;
int res, cmd_len;
ssize_t pos = 0;
unsigned long addr = get_zeroed_page(GFP_KERNEL); unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr; char *buf = (char *)addr;
u8 value;
u8 freq;
res = lbs_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr); struct cmd_ds_802_11_subscribe_event *events = kzalloc(
if (res < 0) { sizeof(struct cmd_ds_802_11_subscribe_event),
free_page(addr); GFP_KERNEL);
return res; struct mrvlietypes_thresholds *got;
}
event = &pcmdptr->params.subscribe_event;
event->action = cpu_to_le16(CMD_ACT_GET);
pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
lbs_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->waitq);
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
pcmdnode->cmdwaitqwoken);
pcmdptr = response_buf; res = lbs_prepare_and_send_command(priv,
CMD_802_11_SUBSCRIBE_EVENT, CMD_ACT_GET,
if (pcmdptr->result) { CMD_OPTION_WAITFORRSP, 0, events);
lbs_pr_err("%s: fail, result=%d\n", __func__, if (res) {
le16_to_cpu(pcmdptr->result)); kfree(events);
kfree(response_buf); return res;
free_page(addr);
return 0;
}
if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) {
lbs_pr_err("command response incorrect!\n");
kfree(response_buf);
free_page(addr);
return 0;
} }
cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event); got = lbs_tlv_find(tlv_type, events->tlv, sizeof(events->tlv));
event = (void *)(response_buf + S_DS_GEN); if (got) {
while (cmd_len < le16_to_cpu(pcmdptr->size)) { value = got->value;
struct mrvlietypesheader *header = (void *)(response_buf + cmd_len); freq = got->freq;
switch (header->type) {
struct mrvlietypes_snrthreshold *LowSnr;
case __constant_cpu_to_le16(TLV_TYPE_SNR_LOW):
LowSnr = (void *)(response_buf + cmd_len);
pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
LowSnr->snrvalue,
LowSnr->snrfreq,
(event->events & cpu_to_le16(0x0002))?1:0);
default:
cmd_len += sizeof(struct mrvlietypes_snrthreshold);
break;
}
} }
kfree(events);
kfree(response_buf); if (got)
pos += snprintf(buf, len, "%d %d %d\n", value, freq,
!!(le16_to_cpu(events->events) & event_mask));
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
free_page(addr);
return res;
}
static ssize_t lbs_lowsnr_write(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
struct lbs_adapter *adapter = priv->adapter;
ssize_t res, buf_size;
int value, freq, subscribed, cmd_len;
struct cmd_ctrl_node *pcmdnode;
struct cmd_ds_command *pcmdptr;
struct cmd_ds_802_11_subscribe_event *event;
struct mrvlietypes_snrthreshold *snr_threshold;
void *response_buf;
u16 event_bitmap;
u8 *ptr;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
buf_size = min(count, len - 1);
if (copy_from_user(buf, userbuf, buf_size)) {
res = -EFAULT;
goto out_unlock;
}
res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
if (res != 3) {
res = -EFAULT;
goto out_unlock;
}
event_bitmap = lbs_get_events_bitmap(priv);
res = lbs_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
if (res < 0)
goto out_unlock;
event = &pcmdptr->params.subscribe_event;
event->action = cpu_to_le16(CMD_ACT_SET);
pcmdptr->size = cpu_to_le16(S_DS_GEN +
sizeof(struct cmd_ds_802_11_subscribe_event) +
sizeof(struct mrvlietypes_snrthreshold));
cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
ptr = (u8*) pcmdptr+cmd_len;
snr_threshold = (struct mrvlietypes_snrthreshold *)(ptr);
snr_threshold->header.type = cpu_to_le16(TLV_TYPE_SNR_LOW);
snr_threshold->header.len = cpu_to_le16(2);
snr_threshold->snrvalue = value;
snr_threshold->snrfreq = freq;
event_bitmap |= subscribed ? 0x0002 : 0x0;
event->events = cpu_to_le16(event_bitmap);
lbs_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->waitq);
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
pcmdnode->cmdwaitqwoken);
pcmdptr = response_buf;
if (pcmdptr->result) {
lbs_pr_err("%s: fail, result=%d\n", __func__,
le16_to_cpu(pcmdptr->result));
kfree(response_buf);
free_page(addr);
return 0;
}
if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) {
lbs_pr_err("command response incorrect!\n");
kfree(response_buf);
free_page(addr);
return 0;
}
res = count;
out_unlock:
free_page(addr); free_page(addr);
return res; return res;
} }
static ssize_t lbs_failcount_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
struct lbs_adapter *adapter = priv->adapter;
struct cmd_ctrl_node *pcmdnode;
struct cmd_ds_command *pcmdptr;
struct cmd_ds_802_11_subscribe_event *event;
void *response_buf;
int res, cmd_len;
ssize_t pos = 0;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
res = lbs_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
if (res < 0) {
free_page(addr);
return res;
}
event = &pcmdptr->params.subscribe_event;
event->action = cpu_to_le16(CMD_ACT_GET);
pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
lbs_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->waitq);
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
pcmdnode->cmdwaitqwoken);
pcmdptr = response_buf;
if (pcmdptr->result) {
lbs_pr_err("%s: fail, result=%d\n", __func__,
le16_to_cpu(pcmdptr->result));
kfree(response_buf);
free_page(addr);
return 0;
}
if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) {
lbs_pr_err("command response incorrect!\n");
kfree(response_buf);
free_page(addr);
return 0;
}
cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
event = (void *)(response_buf + S_DS_GEN);
while (cmd_len < le16_to_cpu(pcmdptr->size)) {
struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
switch (header->type) {
struct mrvlietypes_failurecount *failcount;
case __constant_cpu_to_le16(TLV_TYPE_FAILCOUNT):
failcount = (void *)(response_buf + cmd_len);
pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
failcount->failvalue,
failcount->Failfreq,
(event->events & cpu_to_le16(0x0004))?1:0);
default:
cmd_len += sizeof(struct mrvlietypes_failurecount);
break;
}
}
kfree(response_buf); static ssize_t lbs_threshold_write(
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); u16 tlv_type, u16 event_mask,
free_page(addr); struct file *file,
return res; const char __user *userbuf,
} size_t count, loff_t *ppos)
static ssize_t lbs_failcount_write(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{ {
struct lbs_private *priv = file->private_data; struct lbs_private *priv = file->private_data;
struct lbs_adapter *adapter = priv->adapter;
ssize_t res, buf_size; ssize_t res, buf_size;
int value, freq, subscribed, cmd_len; int value, freq, curr_mask, new_mask;
struct cmd_ctrl_node *pcmdnode;
struct cmd_ds_command *pcmdptr;
struct cmd_ds_802_11_subscribe_event *event;
struct mrvlietypes_failurecount *failcount;
void *response_buf;
u16 event_bitmap;
u8 *ptr;
unsigned long addr = get_zeroed_page(GFP_KERNEL); unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr; char *buf = (char *)addr;
struct cmd_ds_802_11_subscribe_event *events;
buf_size = min(count, len - 1); buf_size = min(count, len - 1);
if (copy_from_user(buf, userbuf, buf_size)) { if (copy_from_user(buf, userbuf, buf_size)) {
res = -EFAULT; res = -EFAULT;
goto out_unlock; goto out_unlock;
} }
res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed); res = sscanf(buf, "%d %d %d", &value, &freq, &new_mask);
if (res != 3) { if (res != 3) {
res = -EFAULT; res = -EFAULT;
goto out_unlock; goto out_unlock;
} }
curr_mask = lbs_get_events_bitmap(priv);
event_bitmap = lbs_get_events_bitmap(priv); if (new_mask)
new_mask = curr_mask | event_mask;
res = lbs_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr); else
if (res < 0) new_mask = curr_mask & ~event_mask;
goto out_unlock;
/* Now everything is set and we can send stuff down to the firmware */
event = &pcmdptr->params.subscribe_event; events = kzalloc(
event->action = cpu_to_le16(CMD_ACT_SET); sizeof(struct cmd_ds_802_11_subscribe_event),
pcmdptr->size = cpu_to_le16(S_DS_GEN + GFP_KERNEL);
sizeof(struct cmd_ds_802_11_subscribe_event) + if (events) {
sizeof(struct mrvlietypes_failurecount)); struct mrvlietypes_thresholds *tlv =
cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event); (struct mrvlietypes_thresholds *) events->tlv;
ptr = (u8*) pcmdptr+cmd_len; events->action = cpu_to_le16(CMD_ACT_SET);
failcount = (struct mrvlietypes_failurecount *)(ptr); events->events = cpu_to_le16(new_mask);
failcount->header.type = cpu_to_le16(TLV_TYPE_FAILCOUNT); tlv->header.type = cpu_to_le16(tlv_type);
failcount->header.len = cpu_to_le16(2); tlv->header.len = cpu_to_le16(
failcount->failvalue = value; sizeof(struct mrvlietypes_thresholds) -
failcount->Failfreq = freq; sizeof(struct mrvlietypesheader));
event_bitmap |= subscribed ? 0x0004 : 0x0; tlv->value = value;
event->events = cpu_to_le16(event_bitmap); if (tlv_type != TLV_TYPE_BCNMISS)
tlv->freq = freq;
lbs_queue_cmd(adapter, pcmdnode, 1); lbs_prepare_and_send_command(priv,
wake_up_interruptible(&priv->waitq); CMD_802_11_SUBSCRIBE_EVENT, CMD_ACT_SET,
CMD_OPTION_WAITFORRSP, 0, events);
/* Sleep until response is generated by FW */ kfree(events);
wait_event_interruptible(pcmdnode->cmdwait_q,
pcmdnode->cmdwaitqwoken);
pcmdptr = (struct cmd_ds_command *)response_buf;
if (pcmdptr->result) {
lbs_pr_err("%s: fail, result=%d\n", __func__,
le16_to_cpu(pcmdptr->result));
kfree(response_buf);
free_page(addr);
return 0;
}
if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) {
lbs_pr_err("command response incorrect!\n");
kfree(response_buf);
free_page(addr);
return 0;
} }
res = count; res = count;
...@@ -910,457 +548,119 @@ static ssize_t lbs_failcount_write(struct file *file, ...@@ -910,457 +548,119 @@ static ssize_t lbs_failcount_write(struct file *file,
return res; return res;
} }
static ssize_t lbs_bcnmiss_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
struct lbs_adapter *adapter = priv->adapter;
struct cmd_ctrl_node *pcmdnode;
struct cmd_ds_command *pcmdptr;
struct cmd_ds_802_11_subscribe_event *event;
void *response_buf;
int res, cmd_len;
ssize_t pos = 0;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
res = lbs_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
if (res < 0) {
free_page(addr);
return res;
}
event = &pcmdptr->params.subscribe_event;
event->action = cpu_to_le16(CMD_ACT_GET);
pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
lbs_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->waitq);
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
pcmdnode->cmdwaitqwoken);
pcmdptr = response_buf;
if (pcmdptr->result) {
lbs_pr_err("%s: fail, result=%d\n", __func__,
le16_to_cpu(pcmdptr->result));
free_page(addr);
kfree(response_buf);
return 0;
}
if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) {
lbs_pr_err("command response incorrect!\n");
free_page(addr);
kfree(response_buf);
return 0;
}
cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event); static ssize_t lbs_lowrssi_read(
event = (void *)(response_buf + S_DS_GEN); struct file *file, char __user *userbuf,
while (cmd_len < le16_to_cpu(pcmdptr->size)) { size_t count, loff_t *ppos)
struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
switch (header->type) {
struct mrvlietypes_beaconsmissed *bcnmiss;
case __constant_cpu_to_le16(TLV_TYPE_BCNMISS):
bcnmiss = (void *)(response_buf + cmd_len);
pos += snprintf(buf+pos, len-pos, "%d N/A %d\n",
bcnmiss->beaconmissed,
(event->events & cpu_to_le16(0x0008))?1:0);
default:
cmd_len += sizeof(struct mrvlietypes_beaconsmissed);
break;
}
}
kfree(response_buf);
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
free_page(addr);
return res;
}
static ssize_t lbs_bcnmiss_write(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{ {
struct lbs_private *priv = file->private_data; return lbs_threshold_read(TLV_TYPE_RSSI_LOW, CMD_SUBSCRIBE_RSSI_LOW,
struct lbs_adapter *adapter = priv->adapter; file, userbuf, count, ppos);
ssize_t res, buf_size;
int value, freq, subscribed, cmd_len;
struct cmd_ctrl_node *pcmdnode;
struct cmd_ds_command *pcmdptr;
struct cmd_ds_802_11_subscribe_event *event;
struct mrvlietypes_beaconsmissed *bcnmiss;
void *response_buf;
u16 event_bitmap;
u8 *ptr;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
buf_size = min(count, len - 1);
if (copy_from_user(buf, userbuf, buf_size)) {
res = -EFAULT;
goto out_unlock;
}
res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
if (res != 3) {
res = -EFAULT;
goto out_unlock;
}
event_bitmap = lbs_get_events_bitmap(priv);
res = lbs_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
if (res < 0)
goto out_unlock;
event = &pcmdptr->params.subscribe_event;
event->action = cpu_to_le16(CMD_ACT_SET);
pcmdptr->size = cpu_to_le16(S_DS_GEN +
sizeof(struct cmd_ds_802_11_subscribe_event) +
sizeof(struct mrvlietypes_beaconsmissed));
cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
ptr = (u8*) pcmdptr+cmd_len;
bcnmiss = (struct mrvlietypes_beaconsmissed *)(ptr);
bcnmiss->header.type = cpu_to_le16(TLV_TYPE_BCNMISS);
bcnmiss->header.len = cpu_to_le16(2);
bcnmiss->beaconmissed = value;
event_bitmap |= subscribed ? 0x0008 : 0x0;
event->events = cpu_to_le16(event_bitmap);
lbs_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->waitq);
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
pcmdnode->cmdwaitqwoken);
pcmdptr = response_buf;
if (pcmdptr->result) {
lbs_pr_err("%s: fail, result=%d\n", __func__,
le16_to_cpu(pcmdptr->result));
kfree(response_buf);
free_page(addr);
return 0;
}
if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) {
lbs_pr_err("command response incorrect!\n");
free_page(addr);
kfree(response_buf);
return 0;
}
res = count;
out_unlock:
free_page(addr);
return res;
} }
static ssize_t lbs_highrssi_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
struct lbs_adapter *adapter = priv->adapter;
struct cmd_ctrl_node *pcmdnode;
struct cmd_ds_command *pcmdptr;
struct cmd_ds_802_11_subscribe_event *event;
void *response_buf;
int res, cmd_len;
ssize_t pos = 0;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
res = lbs_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr); static ssize_t lbs_lowrssi_write(
if (res < 0) { struct file *file, const char __user *userbuf,
free_page(addr); size_t count, loff_t *ppos)
return res; {
} return lbs_threshold_write(TLV_TYPE_RSSI_LOW, CMD_SUBSCRIBE_RSSI_LOW,
file, userbuf, count, ppos);
}
event = &pcmdptr->params.subscribe_event;
event->action = cpu_to_le16(CMD_ACT_GET);
pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
lbs_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->waitq);
/* Sleep until response is generated by FW */ static ssize_t lbs_lowsnr_read(
wait_event_interruptible(pcmdnode->cmdwait_q, struct file *file, char __user *userbuf,
pcmdnode->cmdwaitqwoken); size_t count, loff_t *ppos)
{
return lbs_threshold_read(TLV_TYPE_SNR_LOW, CMD_SUBSCRIBE_SNR_LOW,
file, userbuf, count, ppos);
}
pcmdptr = response_buf;
if (pcmdptr->result) { static ssize_t lbs_lowsnr_write(
lbs_pr_err("%s: fail, result=%d\n", __func__, struct file *file, const char __user *userbuf,
le16_to_cpu(pcmdptr->result)); size_t count, loff_t *ppos)
kfree(response_buf); {
free_page(addr); return lbs_threshold_write(TLV_TYPE_SNR_LOW, CMD_SUBSCRIBE_SNR_LOW,
return 0; file, userbuf, count, ppos);
} }
if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) {
lbs_pr_err("command response incorrect!\n");
kfree(response_buf);
free_page(addr);
return 0;
}
cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event); static ssize_t lbs_failcount_read(
event = (void *)(response_buf + S_DS_GEN); struct file *file, char __user *userbuf,
while (cmd_len < le16_to_cpu(pcmdptr->size)) { size_t count, loff_t *ppos)
struct mrvlietypesheader *header = (void *)(response_buf + cmd_len); {
switch (header->type) { return lbs_threshold_read(TLV_TYPE_FAILCOUNT, CMD_SUBSCRIBE_FAILCOUNT,
struct mrvlietypes_rssithreshold *Highrssi; file, userbuf, count, ppos);
case __constant_cpu_to_le16(TLV_TYPE_RSSI_HIGH): }
Highrssi = (void *)(response_buf + cmd_len);
pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
Highrssi->rssivalue,
Highrssi->rssifreq,
(event->events & cpu_to_le16(0x0010))?1:0);
default:
cmd_len += sizeof(struct mrvlietypes_snrthreshold);
break;
}
}
kfree(response_buf);
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); static ssize_t lbs_failcount_write(
free_page(addr); struct file *file, const char __user *userbuf,
return res; size_t count, loff_t *ppos)
{
return lbs_threshold_write(TLV_TYPE_FAILCOUNT, CMD_SUBSCRIBE_FAILCOUNT,
file, userbuf, count, ppos);
} }
static ssize_t lbs_highrssi_write(struct file *file,
const char __user *userbuf, static ssize_t lbs_highrssi_read(
size_t count, loff_t *ppos) struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{ {
struct lbs_private *priv = file->private_data; return lbs_threshold_read(TLV_TYPE_RSSI_HIGH, CMD_SUBSCRIBE_RSSI_HIGH,
struct lbs_adapter *adapter = priv->adapter; file, userbuf, count, ppos);
ssize_t res, buf_size; }
int value, freq, subscribed, cmd_len;
struct cmd_ctrl_node *pcmdnode;
struct cmd_ds_command *pcmdptr;
struct cmd_ds_802_11_subscribe_event *event;
struct mrvlietypes_rssithreshold *rssi_threshold;
void *response_buf;
u16 event_bitmap;
u8 *ptr;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
buf_size = min(count, len - 1);
if (copy_from_user(buf, userbuf, buf_size)) {
res = -EFAULT;
goto out_unlock;
}
res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
if (res != 3) {
res = -EFAULT;
goto out_unlock;
}
event_bitmap = lbs_get_events_bitmap(priv); static ssize_t lbs_highrssi_write(
struct file *file, const char __user *userbuf,
size_t count, loff_t *ppos)
{
return lbs_threshold_write(TLV_TYPE_RSSI_HIGH, CMD_SUBSCRIBE_RSSI_HIGH,
file, userbuf, count, ppos);
}
res = lbs_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
if (res < 0)
goto out_unlock;
event = &pcmdptr->params.subscribe_event; static ssize_t lbs_highsnr_read(
event->action = cpu_to_le16(CMD_ACT_SET); struct file *file, char __user *userbuf,
pcmdptr->size = cpu_to_le16(S_DS_GEN + size_t count, loff_t *ppos)
sizeof(struct cmd_ds_802_11_subscribe_event) + {
sizeof(struct mrvlietypes_rssithreshold)); return lbs_threshold_read(TLV_TYPE_SNR_HIGH, CMD_SUBSCRIBE_SNR_HIGH,
cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event); file, userbuf, count, ppos);
ptr = (u8*) pcmdptr+cmd_len; }
rssi_threshold = (struct mrvlietypes_rssithreshold *)(ptr);
rssi_threshold->header.type = cpu_to_le16(TLV_TYPE_RSSI_HIGH);
rssi_threshold->header.len = cpu_to_le16(2);
rssi_threshold->rssivalue = value;
rssi_threshold->rssifreq = freq;
event_bitmap |= subscribed ? 0x0010 : 0x0;
event->events = cpu_to_le16(event_bitmap);
lbs_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->waitq);
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
pcmdnode->cmdwaitqwoken);
pcmdptr = response_buf;
if (pcmdptr->result) {
lbs_pr_err("%s: fail, result=%d\n", __func__,
le16_to_cpu(pcmdptr->result));
kfree(response_buf);
return 0;
}
if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) {
lbs_pr_err("command response incorrect!\n");
kfree(response_buf);
return 0;
}
res = count; static ssize_t lbs_highsnr_write(
out_unlock: struct file *file, const char __user *userbuf,
free_page(addr); size_t count, loff_t *ppos)
return res; {
return lbs_threshold_write(TLV_TYPE_SNR_HIGH, CMD_SUBSCRIBE_SNR_HIGH,
file, userbuf, count, ppos);
} }
static ssize_t lbs_highsnr_read(struct file *file, char __user *userbuf, static ssize_t lbs_bcnmiss_read(
size_t count, loff_t *ppos) struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{ {
struct lbs_private *priv = file->private_data; return lbs_threshold_read(TLV_TYPE_BCNMISS, CMD_SUBSCRIBE_BCNMISS,
struct lbs_adapter *adapter = priv->adapter; file, userbuf, count, ppos);
struct cmd_ctrl_node *pcmdnode; }
struct cmd_ds_command *pcmdptr;
struct cmd_ds_802_11_subscribe_event *event;
void *response_buf;
int res, cmd_len;
ssize_t pos = 0;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
res = lbs_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
if (res < 0) {
free_page(addr);
return res;
}
event = &pcmdptr->params.subscribe_event;
event->action = cpu_to_le16(CMD_ACT_GET);
pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
lbs_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->waitq);
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
pcmdnode->cmdwaitqwoken);
pcmdptr = response_buf;
if (pcmdptr->result) {
lbs_pr_err("%s: fail, result=%d\n", __func__,
le16_to_cpu(pcmdptr->result));
kfree(response_buf);
free_page(addr);
return 0;
}
if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) {
lbs_pr_err("command response incorrect!\n");
kfree(response_buf);
free_page(addr);
return 0;
}
cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
event = (void *)(response_buf + S_DS_GEN);
while (cmd_len < le16_to_cpu(pcmdptr->size)) {
struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
switch (header->type) {
struct mrvlietypes_snrthreshold *HighSnr;
case __constant_cpu_to_le16(TLV_TYPE_SNR_HIGH):
HighSnr = (void *)(response_buf + cmd_len);
pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
HighSnr->snrvalue,
HighSnr->snrfreq,
(event->events & cpu_to_le16(0x0020))?1:0);
default:
cmd_len += sizeof(struct mrvlietypes_snrthreshold);
break;
}
}
kfree(response_buf);
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); static ssize_t lbs_bcnmiss_write(
free_page(addr); struct file *file, const char __user *userbuf,
return res; size_t count, loff_t *ppos)
{
return lbs_threshold_write(TLV_TYPE_BCNMISS, CMD_SUBSCRIBE_BCNMISS,
file, userbuf, count, ppos);
} }
static ssize_t lbs_highsnr_write(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
struct lbs_adapter *adapter = priv->adapter;
ssize_t res, buf_size;
int value, freq, subscribed, cmd_len;
struct cmd_ctrl_node *pcmdnode;
struct cmd_ds_command *pcmdptr;
struct cmd_ds_802_11_subscribe_event *event;
struct mrvlietypes_snrthreshold *snr_threshold;
void *response_buf;
u16 event_bitmap;
u8 *ptr;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
buf_size = min(count, len - 1);
if (copy_from_user(buf, userbuf, buf_size)) {
res = -EFAULT;
goto out_unlock;
}
res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
if (res != 3) {
res = -EFAULT;
goto out_unlock;
}
event_bitmap = lbs_get_events_bitmap(priv);
res = lbs_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
if (res < 0)
goto out_unlock;
event = &pcmdptr->params.subscribe_event;
event->action = cpu_to_le16(CMD_ACT_SET);
pcmdptr->size = cpu_to_le16(S_DS_GEN +
sizeof(struct cmd_ds_802_11_subscribe_event) +
sizeof(struct mrvlietypes_snrthreshold));
cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
ptr = (u8*) pcmdptr+cmd_len;
snr_threshold = (struct mrvlietypes_snrthreshold *)(ptr);
snr_threshold->header.type = cpu_to_le16(TLV_TYPE_SNR_HIGH);
snr_threshold->header.len = cpu_to_le16(2);
snr_threshold->snrvalue = value;
snr_threshold->snrfreq = freq;
event_bitmap |= subscribed ? 0x0020 : 0x0;
event->events = cpu_to_le16(event_bitmap);
lbs_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->waitq);
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
pcmdnode->cmdwaitqwoken);
pcmdptr = response_buf;
if (pcmdptr->result) {
lbs_pr_err("%s: fail, result=%d\n", __func__,
le16_to_cpu(pcmdptr->result));
kfree(response_buf);
free_page(addr);
return 0;
}
if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) {
lbs_pr_err("command response incorrect!\n");
kfree(response_buf);
free_page(addr);
return 0;
}
res = count;
out_unlock:
free_page(addr);
return res;
}
static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf, static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
...@@ -1911,4 +1211,3 @@ static void lbs_debug_init(struct lbs_private *priv, struct net_device *dev) ...@@ -1911,4 +1211,3 @@ static void lbs_debug_init(struct lbs_private *priv, struct net_device *dev)
&lbs_debug_fops); &lbs_debug_fops);
} }
#endif #endif
...@@ -180,6 +180,14 @@ ...@@ -180,6 +180,14 @@
#define CMD_TYPE_SHORT_PREAMBLE 0x0002 #define CMD_TYPE_SHORT_PREAMBLE 0x0002
#define CMD_TYPE_LONG_PREAMBLE 0x0003 #define CMD_TYPE_LONG_PREAMBLE 0x0003
/* Event flags for CMD_802_11_SUBSCRIBE_EVENT */
#define CMD_SUBSCRIBE_RSSI_LOW 0x0001
#define CMD_SUBSCRIBE_SNR_LOW 0x0002
#define CMD_SUBSCRIBE_FAILCOUNT 0x0004
#define CMD_SUBSCRIBE_BCNMISS 0x0008
#define CMD_SUBSCRIBE_RSSI_HIGH 0x0010
#define CMD_SUBSCRIBE_SNR_HIGH 0x0020
#define TURN_ON_RF 0x01 #define TURN_ON_RF 0x01
#define RADIO_ON 0x01 #define RADIO_ON 0x01
#define RADIO_OFF 0x00 #define RADIO_OFF 0x00
......
...@@ -151,6 +151,13 @@ struct cmd_ds_802_11_reset { ...@@ -151,6 +151,13 @@ struct cmd_ds_802_11_reset {
struct cmd_ds_802_11_subscribe_event { struct cmd_ds_802_11_subscribe_event {
__le16 action; __le16 action;
__le16 events; __le16 events;
/* A TLV to the CMD_802_11_SUBSCRIBE_EVENT command can contain a
* number of TLVs. From the v5.1 manual, those TLVs would add up to
* 40 bytes. However, future firmware might add additional TLVs, so I
* bump this up a bit.
*/
u8 tlv[128];
}; };
/* /*
......
...@@ -201,22 +201,11 @@ struct mrvlietypes_powercapability { ...@@ -201,22 +201,11 @@ struct mrvlietypes_powercapability {
s8 maxpower; s8 maxpower;
} __attribute__ ((packed)); } __attribute__ ((packed));
struct mrvlietypes_rssithreshold { /* used in CMD_802_11_SUBSCRIBE_EVENT for SNR, RSSI and Failure */
struct mrvlietypes_thresholds {
struct mrvlietypesheader header; struct mrvlietypesheader header;
u8 rssivalue; u8 value;
u8 rssifreq; u8 freq;
} __attribute__ ((packed));
struct mrvlietypes_snrthreshold {
struct mrvlietypesheader header;
u8 snrvalue;
u8 snrfreq;
} __attribute__ ((packed));
struct mrvlietypes_failurecount {
struct mrvlietypesheader header;
u8 failvalue;
u8 Failfreq;
} __attribute__ ((packed)); } __attribute__ ((packed));
struct mrvlietypes_beaconsmissed { struct mrvlietypes_beaconsmissed {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment