diff options
author | Holger Schurig <hs4233@mail.mn-solutions.de> | 2007-11-26 10:07:14 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 15:04:55 -0800 |
commit | 3a1886491710c196656a005fcc693172f5bb4c8a (patch) | |
tree | c33009fb8cacd0fdea6fe7b7fdb7b5269c3063e4 /drivers/net/wireless/libertas/debugfs.c | |
parent | 69f9032d9dfeb763b467fdbe8cf5938f5457083a (diff) |
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: Holger Schurig <hs4233@mail.mn-solutions.de>
Acked-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/libertas/debugfs.c')
-rw-r--r-- | drivers/net/wireless/libertas/debugfs.c | 1071 |
1 files changed, 185 insertions, 886 deletions
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index 2e1842474f8..de768de4584 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -384,524 +384,162 @@ out_unlock: 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"); - return -ENOMEM; - } - if (!(*response_buf = kmalloc(3000, GFP_KERNEL))) { - lbs_deb_debugfs("failed to allocate response buffer!\n"); - return -ENOMEM; - } - lbs_set_cmd_ctrl_node(priv, *cmdnode, 0, wait_option, NULL); - init_waitqueue_head(&(*cmdnode)->cmdwait_q); - (*cmdnode)->pdata_buf = *response_buf; - (*cmdnode)->cmdflags |= CMD_F_HOSTCMD; - (*cmdnode)->cmdwaitqwoken = 0; - *cmd = (struct cmd_ds_command *)(*cmdnode)->bufvirtualaddr; - (*cmd)->command = cpu_to_le16(CMD_802_11_SUBSCRIBE_EVENT); - (*cmd)->seqnum = cpu_to_le16(++priv->adapter->seqnum); - (*cmd)->result = 0; - return 0; -} - -static ssize_t lbs_lowrssi_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) +/* + * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might + * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the + * firmware. Here's an example: + * 04 01 02 00 00 00 05 01 02 00 00 00 06 01 02 00 + * 00 00 07 01 02 00 3c 00 00 00 00 00 00 00 03 03 + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * + * The 04 01 is the TLV type (here TLV_TYPE_RSSI_LOW), 02 00 is the length, + * 00 00 are the data bytes of this TLV. For this TLV, their meaning is + * defined in mrvlietypes_thresholds + * + * This function searches in this TLV data chunk for a given TLV type + * and returns a pointer to the first data byte of the TLV, or to NULL + * if the TLV hasn't been found. + */ +static void *lbs_tlv_find(u16 tlv_type, const u8 *tlv, u16 size) { - 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; + __le16 le_type = cpu_to_le16(tlv_type); 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_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; + struct mrvlietypesheader *tlv_h; + while (pos < size) { + u16 length; + tlv_h = (struct mrvlietypesheader *) tlv; + if (tlv_h->type == le_type) + return tlv_h; + if (tlv_h->len == 0) + return NULL; + length = le16_to_cpu(tlv_h->len) + + sizeof(struct mrvlietypesheader); + pos += length; + tlv += length; + } + return NULL; } + +/* + * 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) { - 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; - 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); + ssize_t res; - 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) { - lbs_pr_err("%s: fail, result=%d\n", __func__, - le16_to_cpu(pcmdptr->result)); - kfree(response_buf); - return 0; - } + res = lbs_prepare_and_send_command(priv, + CMD_802_11_SUBSCRIBE_EVENT, CMD_ACT_GET, + CMD_OPTION_WAITFORRSP, 0, events); - if (le16_to_cpu(pcmdptr->command) != CMD_RET(CMD_802_11_SUBSCRIBE_EVENT)) { - lbs_pr_err("command response incorrect!\n"); - kfree(response_buf); + if (res) { + kfree(events); return 0; } - - 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; + return le16_to_cpu(events->events); } -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))) { - 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_lowsnr_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) +static ssize_t lbs_threshold_read( + u16 tlv_type, u16 event_mask, + 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; + ssize_t res = 0; + size_t pos = 0; unsigned long addr = get_zeroed_page(GFP_KERNEL); char *buf = (char *)addr; + u8 value; + u8 freq; - 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); + struct cmd_ds_802_11_subscribe_event *events = kzalloc( + sizeof(struct cmd_ds_802_11_subscribe_event), + GFP_KERNEL); + struct mrvlietypes_thresholds *got; - 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 = lbs_prepare_and_send_command(priv, + CMD_802_11_SUBSCRIBE_EVENT, CMD_ACT_GET, + CMD_OPTION_WAITFORRSP, 0, events); + if (res) { + kfree(events); + return res; } - 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 *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; - } + got = lbs_tlv_find(tlv_type, events->tlv, sizeof(events->tlv)); + if (got) { + value = got->value; + freq = got->freq; } + 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); - 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); 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); - res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - free_page(addr); - return res; -} - -static ssize_t lbs_failcount_write(struct file *file, - const char __user *userbuf, - size_t count, loff_t *ppos) +static ssize_t lbs_threshold_write( + u16 tlv_type, u16 event_mask, + 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_failurecount *failcount; - void *response_buf; - u16 event_bitmap; - u8 *ptr; + int value, freq, curr_mask, new_mask; unsigned long addr = get_zeroed_page(GFP_KERNEL); char *buf = (char *)addr; + struct cmd_ds_802_11_subscribe_event *events; 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); + res = sscanf(buf, "%d %d %d", &value, &freq, &new_mask); if (res != 3) { res = -EFAULT; goto out_unlock; } + curr_mask = lbs_get_events_bitmap(priv); - 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_failurecount)); - cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event); - ptr = (u8*) pcmdptr+cmd_len; - failcount = (struct mrvlietypes_failurecount *)(ptr); - failcount->header.type = cpu_to_le16(TLV_TYPE_FAILCOUNT); - failcount->header.len = cpu_to_le16(2); - failcount->failvalue = value; - failcount->Failfreq = freq; - event_bitmap |= subscribed ? 0x0004 : 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 = (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; + if (new_mask) + new_mask = curr_mask | event_mask; + else + new_mask = curr_mask & ~event_mask; + + /* Now everything is set and we can send stuff down to the firmware */ + events = kzalloc( + sizeof(struct cmd_ds_802_11_subscribe_event), + GFP_KERNEL); + if (events) { + struct mrvlietypes_thresholds *tlv = + (struct mrvlietypes_thresholds *) events->tlv; + events->action = cpu_to_le16(CMD_ACT_SET); + events->events = cpu_to_le16(new_mask); + tlv->header.type = cpu_to_le16(tlv_type); + tlv->header.len = cpu_to_le16( + sizeof(struct mrvlietypes_thresholds) - + sizeof(struct mrvlietypesheader)); + tlv->value = value; + if (tlv_type != TLV_TYPE_BCNMISS) + tlv->freq = freq; + lbs_prepare_and_send_command(priv, + CMD_802_11_SUBSCRIBE_EVENT, CMD_ACT_SET, + CMD_OPTION_WAITFORRSP, 0, events); + kfree(events); } res = count; @@ -910,457 +548,119 @@ out_unlock: 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); - 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_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) +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; - 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_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; + return lbs_threshold_read(TLV_TYPE_RSSI_LOW, CMD_SUBSCRIBE_RSSI_LOW, + file, userbuf, count, ppos); } -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); - if (res < 0) { - free_page(addr); - return res; - } +static ssize_t lbs_lowrssi_write( + struct file *file, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + 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 */ - wait_event_interruptible(pcmdnode->cmdwait_q, - pcmdnode->cmdwaitqwoken); +static ssize_t lbs_lowsnr_read( + struct file *file, char __user *userbuf, + 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) { - lbs_pr_err("%s: fail, result=%d\n", __func__, - le16_to_cpu(pcmdptr->result)); - kfree(response_buf); - free_page(addr); - return 0; - } +static ssize_t lbs_lowsnr_write( + struct file *file, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + return lbs_threshold_write(TLV_TYPE_SNR_LOW, CMD_SUBSCRIBE_SNR_LOW, + 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); - 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 *Highrssi; - 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; - } - } +static ssize_t lbs_failcount_read( + struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + return lbs_threshold_read(TLV_TYPE_FAILCOUNT, CMD_SUBSCRIBE_FAILCOUNT, + file, userbuf, count, ppos); +} - kfree(response_buf); - res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - free_page(addr); - return res; +static ssize_t lbs_failcount_write( + struct file *file, const char __user *userbuf, + 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, - size_t count, loff_t *ppos) + +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; - 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; + return lbs_threshold_read(TLV_TYPE_RSSI_HIGH, CMD_SUBSCRIBE_RSSI_HIGH, + file, userbuf, count, ppos); +} - 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; - 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(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; - } +static ssize_t lbs_highsnr_read( + struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + return lbs_threshold_read(TLV_TYPE_SNR_HIGH, CMD_SUBSCRIBE_SNR_HIGH, + 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); - return 0; - } - res = count; -out_unlock: - free_page(addr); - return res; +static ssize_t lbs_highsnr_write( + struct file *file, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + 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, - size_t count, loff_t *ppos) +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)); - 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; - } - } + return lbs_threshold_read(TLV_TYPE_BCNMISS, CMD_SUBSCRIBE_BCNMISS, + file, userbuf, count, ppos); +} - 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) +{ + 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, size_t count, loff_t *ppos) @@ -1911,4 +1211,3 @@ static void lbs_debug_init(struct lbs_private *priv, struct net_device *dev) &lbs_debug_fops); } #endif - |