diff options
author | Holger Schurig <hs4233@mail.mn-solutions.de> | 2008-04-01 08:50:43 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-04-16 15:59:56 -0400 |
commit | 7919b89c8276d657976d4d4d6b7cb58ea1aa08c3 (patch) | |
tree | 31fc24e2f8b7d8eeee67347333e078591796d4b7 /drivers/net/wireless/libertas | |
parent | 98dd6a575928ed9c42130d208e6bfb0f7a914d5a (diff) |
libertas: convert libertas driver to use an event/cmdresp queue
This patch (co-developed by Dan Williams and Holger Schurig) uses a kfifo
object for events and a swapping buffer scheme for the command response to
preserve the zero-copy semantics of the CF driver and keep memory usage low.
The main thread should only ever touch the buffer indexed by priv->resp_idx,
while the interface code is free to write to the second buffer, then swap
priv->resp_idx under the driver spinlock. The firmware specs only permit
one in-flight command, so there will only ever be one command response to
process at a time.
Signed-off-by: Holger Schurig <hs4233@mail.mn-solutions.de>
Signed-off-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/libertas')
-rw-r--r-- | drivers/net/wireless/libertas/cmd.c | 25 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/cmdresp.c | 23 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/debugfs.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/decl.h | 10 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/defs.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/dev.h | 27 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_cs.c | 244 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_sdio.c | 65 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_usb.c | 71 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_usb.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/main.c | 158 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/rx.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/tx.c | 20 |
13 files changed, 269 insertions, 383 deletions
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 4a82f5114ca..49267ed7cea 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c | |||
@@ -4,6 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <net/iw_handler.h> | 6 | #include <net/iw_handler.h> |
7 | #include <linux/kfifo.h> | ||
7 | #include "host.h" | 8 | #include "host.h" |
8 | #include "hostcmd.h" | 9 | #include "hostcmd.h" |
9 | #include "decl.h" | 10 | #include "decl.h" |
@@ -1829,15 +1830,20 @@ static void lbs_send_confirmsleep(struct lbs_private *priv) | |||
1829 | 1830 | ||
1830 | ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep, | 1831 | ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep, |
1831 | sizeof(confirm_sleep)); | 1832 | sizeof(confirm_sleep)); |
1832 | |||
1833 | if (ret) { | 1833 | if (ret) { |
1834 | lbs_pr_alert("confirm_sleep failed\n"); | 1834 | lbs_pr_alert("confirm_sleep failed\n"); |
1835 | } else { | 1835 | goto out; |
1836 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
1837 | if (!priv->intcounter) | ||
1838 | priv->psstate = PS_STATE_SLEEP; | ||
1839 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
1840 | } | 1836 | } |
1837 | |||
1838 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
1839 | |||
1840 | /* If nothing to do, go back to sleep (?) */ | ||
1841 | if (!__kfifo_len(priv->event_fifo) && !priv->resp_len[priv->resp_idx]) | ||
1842 | priv->psstate = PS_STATE_SLEEP; | ||
1843 | |||
1844 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
1845 | |||
1846 | out: | ||
1841 | lbs_deb_leave(LBS_DEB_HOST); | 1847 | lbs_deb_leave(LBS_DEB_HOST); |
1842 | } | 1848 | } |
1843 | 1849 | ||
@@ -1899,13 +1905,16 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv) | |||
1899 | } | 1905 | } |
1900 | 1906 | ||
1901 | spin_lock_irqsave(&priv->driver_lock, flags); | 1907 | spin_lock_irqsave(&priv->driver_lock, flags); |
1908 | /* In-progress command? */ | ||
1902 | if (priv->cur_cmd) { | 1909 | if (priv->cur_cmd) { |
1903 | allowed = 0; | 1910 | allowed = 0; |
1904 | lbs_deb_host("cur_cmd was set\n"); | 1911 | lbs_deb_host("cur_cmd was set\n"); |
1905 | } | 1912 | } |
1906 | if (priv->intcounter > 0) { | 1913 | |
1914 | /* Pending events or command responses? */ | ||
1915 | if (__kfifo_len(priv->event_fifo) || priv->resp_len[priv->resp_idx]) { | ||
1907 | allowed = 0; | 1916 | allowed = 0; |
1908 | lbs_deb_host("intcounter %d\n", priv->intcounter); | 1917 | lbs_deb_host("pending events or command responses\n"); |
1909 | } | 1918 | } |
1910 | spin_unlock_irqrestore(&priv->driver_lock, flags); | 1919 | spin_unlock_irqrestore(&priv->driver_lock, flags); |
1911 | 1920 | ||
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 245d3c3a927..5abecb7673e 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c | |||
@@ -384,7 +384,7 @@ static inline int handle_cmd_response(struct lbs_private *priv, | |||
384 | return ret; | 384 | return ret; |
385 | } | 385 | } |
386 | 386 | ||
387 | int lbs_process_rx_command(struct lbs_private *priv) | 387 | int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) |
388 | { | 388 | { |
389 | uint16_t respcmd, curcmd; | 389 | uint16_t respcmd, curcmd; |
390 | struct cmd_header *resp; | 390 | struct cmd_header *resp; |
@@ -404,14 +404,14 @@ int lbs_process_rx_command(struct lbs_private *priv) | |||
404 | goto done; | 404 | goto done; |
405 | } | 405 | } |
406 | 406 | ||
407 | resp = (void *)priv->upld_buf; | 407 | resp = (void *)data; |
408 | curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command); | 408 | curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command); |
409 | respcmd = le16_to_cpu(resp->command); | 409 | respcmd = le16_to_cpu(resp->command); |
410 | result = le16_to_cpu(resp->result); | 410 | result = le16_to_cpu(resp->result); |
411 | 411 | ||
412 | lbs_deb_cmd("CMD_RESP: response 0x%04x, seq %d, size %d\n", | 412 | lbs_deb_cmd("CMD_RESP: response 0x%04x, seq %d, size %d\n", |
413 | respcmd, le16_to_cpu(resp->seqnum), priv->upld_len); | 413 | respcmd, le16_to_cpu(resp->seqnum), len); |
414 | lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, priv->upld_len); | 414 | lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, len); |
415 | 415 | ||
416 | if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) { | 416 | if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) { |
417 | lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n", | 417 | lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n", |
@@ -569,18 +569,13 @@ static int lbs_send_confirmwake(struct lbs_private *priv) | |||
569 | return ret; | 569 | return ret; |
570 | } | 570 | } |
571 | 571 | ||
572 | int lbs_process_event(struct lbs_private *priv) | 572 | int lbs_process_event(struct lbs_private *priv, u32 event) |
573 | { | 573 | { |
574 | int ret = 0; | 574 | int ret = 0; |
575 | u32 eventcause; | ||
576 | 575 | ||
577 | lbs_deb_enter(LBS_DEB_CMD); | 576 | lbs_deb_enter(LBS_DEB_CMD); |
578 | 577 | ||
579 | spin_lock_irq(&priv->driver_lock); | 578 | switch (event) { |
580 | eventcause = priv->eventcause >> SBI_EVENT_CAUSE_SHIFT; | ||
581 | spin_unlock_irq(&priv->driver_lock); | ||
582 | |||
583 | switch (eventcause) { | ||
584 | case MACREG_INT_CODE_LINK_SENSED: | 579 | case MACREG_INT_CODE_LINK_SENSED: |
585 | lbs_deb_cmd("EVENT: link sensed\n"); | 580 | lbs_deb_cmd("EVENT: link sensed\n"); |
586 | break; | 581 | break; |
@@ -696,14 +691,10 @@ int lbs_process_event(struct lbs_private *priv) | |||
696 | break; | 691 | break; |
697 | 692 | ||
698 | default: | 693 | default: |
699 | lbs_pr_alert("EVENT: unknown event id %d\n", eventcause); | 694 | lbs_pr_alert("EVENT: unknown event id %d\n", event); |
700 | break; | 695 | break; |
701 | } | 696 | } |
702 | 697 | ||
703 | spin_lock_irq(&priv->driver_lock); | ||
704 | priv->eventcause = 0; | ||
705 | spin_unlock_irq(&priv->driver_lock); | ||
706 | |||
707 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | 698 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); |
708 | return ret; | 699 | return ret; |
709 | } | 700 | } |
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index 7072e26b42d..ad2fabca911 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c | |||
@@ -824,7 +824,6 @@ struct debug_data { | |||
824 | /* To debug any member of struct lbs_private, simply add one line here. | 824 | /* To debug any member of struct lbs_private, simply add one line here. |
825 | */ | 825 | */ |
826 | static struct debug_data items[] = { | 826 | static struct debug_data items[] = { |
827 | {"intcounter", item_size(intcounter), item_addr(intcounter)}, | ||
828 | {"psmode", item_size(psmode), item_addr(psmode)}, | 827 | {"psmode", item_size(psmode), item_addr(psmode)}, |
829 | {"psstate", item_size(psstate), item_addr(psstate)}, | 828 | {"psstate", item_size(psstate), item_addr(psstate)}, |
830 | }; | 829 | }; |
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index 4aea421f07c..b652fa301e1 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h | |||
@@ -19,7 +19,7 @@ struct cmd_ds_command; | |||
19 | 19 | ||
20 | void lbs_set_mac_control(struct lbs_private *priv); | 20 | void lbs_set_mac_control(struct lbs_private *priv); |
21 | 21 | ||
22 | void lbs_send_tx_feedback(struct lbs_private *priv); | 22 | void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count); |
23 | 23 | ||
24 | int lbs_free_cmd_buffer(struct lbs_private *priv); | 24 | int lbs_free_cmd_buffer(struct lbs_private *priv); |
25 | 25 | ||
@@ -30,14 +30,16 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
30 | 30 | ||
31 | int lbs_allocate_cmd_buffer(struct lbs_private *priv); | 31 | int lbs_allocate_cmd_buffer(struct lbs_private *priv); |
32 | int lbs_execute_next_command(struct lbs_private *priv); | 32 | int lbs_execute_next_command(struct lbs_private *priv); |
33 | int lbs_process_event(struct lbs_private *priv); | 33 | int lbs_process_event(struct lbs_private *priv, u32 event); |
34 | void lbs_interrupt(struct lbs_private *priv); | 34 | void lbs_queue_event(struct lbs_private *priv, u32 event); |
35 | void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx); | ||
36 | |||
35 | int lbs_set_radio_control(struct lbs_private *priv); | 37 | int lbs_set_radio_control(struct lbs_private *priv); |
36 | u32 lbs_fw_index_to_data_rate(u8 index); | 38 | u32 lbs_fw_index_to_data_rate(u8 index); |
37 | u8 lbs_data_rate_to_fw_index(u32 rate); | 39 | u8 lbs_data_rate_to_fw_index(u32 rate); |
38 | 40 | ||
39 | /** The proc fs interface */ | 41 | /** The proc fs interface */ |
40 | int lbs_process_rx_command(struct lbs_private *priv); | 42 | int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len); |
41 | void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, | 43 | void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, |
42 | int result); | 44 | int result); |
43 | int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev); | 45 | int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev); |
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index 84e8de5e21d..d3952011106 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h | |||
@@ -177,8 +177,6 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in | |||
177 | #define MRVDRV_CMD_UPLD_RDY 0x0008 | 177 | #define MRVDRV_CMD_UPLD_RDY 0x0008 |
178 | #define MRVDRV_CARDEVENT 0x0010 | 178 | #define MRVDRV_CARDEVENT 0x0010 |
179 | 179 | ||
180 | #define SBI_EVENT_CAUSE_SHIFT 3 | ||
181 | |||
182 | /** TxPD status */ | 180 | /** TxPD status */ |
183 | 181 | ||
184 | /* Station firmware use TxPD status field to report final Tx transmit | 182 | /* Station firmware use TxPD status field to report final Tx transmit |
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 1e6bae80396..0d9edb9b11f 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -129,10 +129,6 @@ struct lbs_private { | |||
129 | u32 bbp_offset; | 129 | u32 bbp_offset; |
130 | u32 rf_offset; | 130 | u32 rf_offset; |
131 | 131 | ||
132 | /** Upload length */ | ||
133 | u32 upld_len; | ||
134 | /* Upload buffer */ | ||
135 | u8 upld_buf[LBS_UPLD_SIZE]; | ||
136 | /* Download sent: | 132 | /* Download sent: |
137 | bit0 1/0=data_sent/data_tx_done, | 133 | bit0 1/0=data_sent/data_tx_done, |
138 | bit1 1/0=cmd_sent/cmd_tx_done, | 134 | bit1 1/0=cmd_sent/cmd_tx_done, |
@@ -155,21 +151,16 @@ struct lbs_private { | |||
155 | 151 | ||
156 | /** Hardware access */ | 152 | /** Hardware access */ |
157 | int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); | 153 | int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); |
158 | int (*hw_get_int_status) (struct lbs_private *priv, u8 *); | ||
159 | int (*hw_read_event_cause) (struct lbs_private *); | ||
160 | 154 | ||
161 | /* Wake On LAN */ | 155 | /* Wake On LAN */ |
162 | uint32_t wol_criteria; | 156 | uint32_t wol_criteria; |
163 | uint8_t wol_gpio; | 157 | uint8_t wol_gpio; |
164 | uint8_t wol_gap; | 158 | uint8_t wol_gap; |
165 | 159 | ||
166 | /* was struct lbs_adapter from here... */ | ||
167 | |||
168 | /** Wlan adapter data structure*/ | 160 | /** Wlan adapter data structure*/ |
169 | /** STATUS variables */ | 161 | /** STATUS variables */ |
170 | u32 fwrelease; | 162 | u32 fwrelease; |
171 | u32 fwcapinfo; | 163 | u32 fwcapinfo; |
172 | /* protected with big lock */ | ||
173 | 164 | ||
174 | struct mutex lock; | 165 | struct mutex lock; |
175 | 166 | ||
@@ -181,7 +172,6 @@ struct lbs_private { | |||
181 | 172 | ||
182 | /** command-related variables */ | 173 | /** command-related variables */ |
183 | u16 seqnum; | 174 | u16 seqnum; |
184 | /* protected by big lock */ | ||
185 | 175 | ||
186 | struct cmd_ctrl_node *cmd_array; | 176 | struct cmd_ctrl_node *cmd_array; |
187 | /** Current command */ | 177 | /** Current command */ |
@@ -194,12 +184,17 @@ struct lbs_private { | |||
194 | struct list_head cmdpendingq; | 184 | struct list_head cmdpendingq; |
195 | 185 | ||
196 | wait_queue_head_t cmd_pending; | 186 | wait_queue_head_t cmd_pending; |
197 | /* command related variables protected by priv->driver_lock */ | ||
198 | 187 | ||
199 | /** Async and Sync Event variables */ | 188 | /* Command responses sent from the hardware to the driver */ |
200 | u32 intcounter; | 189 | u8 resp_idx; |
201 | u32 eventcause; | 190 | u8 resp_buf[2][LBS_UPLD_SIZE]; |
202 | u8 nodename[16]; /* nickname */ | 191 | u32 resp_len[2]; |
192 | |||
193 | /* Events sent from hardware to driver */ | ||
194 | struct kfifo *event_fifo; | ||
195 | |||
196 | /* nickname */ | ||
197 | u8 nodename[16]; | ||
203 | 198 | ||
204 | /** spin locks */ | 199 | /** spin locks */ |
205 | spinlock_t driver_lock; | 200 | spinlock_t driver_lock; |
@@ -209,8 +204,6 @@ struct lbs_private { | |||
209 | int nr_retries; | 204 | int nr_retries; |
210 | int cmd_timed_out; | 205 | int cmd_timed_out; |
211 | 206 | ||
212 | u8 hisregcpy; | ||
213 | |||
214 | /** current ssid/bssid related parameters*/ | 207 | /** current ssid/bssid related parameters*/ |
215 | struct current_bss_params curbssparams; | 208 | struct current_bss_params curbssparams; |
216 | 209 | ||
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 53afebac714..54280e292ea 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c | |||
@@ -83,14 +83,14 @@ static inline unsigned int if_cs_read8(struct if_cs_card *card, uint reg) | |||
83 | { | 83 | { |
84 | unsigned int val = ioread8(card->iobase + reg); | 84 | unsigned int val = ioread8(card->iobase + reg); |
85 | if (debug_output) | 85 | if (debug_output) |
86 | printk(KERN_INFO "##inb %08x<%02x\n", reg, val); | 86 | printk(KERN_INFO "inb %08x<%02x\n", reg, val); |
87 | return val; | 87 | return val; |
88 | } | 88 | } |
89 | static inline unsigned int if_cs_read16(struct if_cs_card *card, uint reg) | 89 | static inline unsigned int if_cs_read16(struct if_cs_card *card, uint reg) |
90 | { | 90 | { |
91 | unsigned int val = ioread16(card->iobase + reg); | 91 | unsigned int val = ioread16(card->iobase + reg); |
92 | if (debug_output) | 92 | if (debug_output) |
93 | printk(KERN_INFO "##inw %08x<%04x\n", reg, val); | 93 | printk(KERN_INFO "inw %08x<%04x\n", reg, val); |
94 | return val; | 94 | return val; |
95 | } | 95 | } |
96 | static inline void if_cs_read16_rep( | 96 | static inline void if_cs_read16_rep( |
@@ -100,7 +100,7 @@ static inline void if_cs_read16_rep( | |||
100 | unsigned long count) | 100 | unsigned long count) |
101 | { | 101 | { |
102 | if (debug_output) | 102 | if (debug_output) |
103 | printk(KERN_INFO "##insw %08x<(0x%lx words)\n", | 103 | printk(KERN_INFO "insw %08x<(0x%lx words)\n", |
104 | reg, count); | 104 | reg, count); |
105 | ioread16_rep(card->iobase + reg, buf, count); | 105 | ioread16_rep(card->iobase + reg, buf, count); |
106 | } | 106 | } |
@@ -108,14 +108,14 @@ static inline void if_cs_read16_rep( | |||
108 | static inline void if_cs_write8(struct if_cs_card *card, uint reg, u8 val) | 108 | static inline void if_cs_write8(struct if_cs_card *card, uint reg, u8 val) |
109 | { | 109 | { |
110 | if (debug_output) | 110 | if (debug_output) |
111 | printk(KERN_INFO "##outb %08x>%02x\n", reg, val); | 111 | printk(KERN_INFO "outb %08x>%02x\n", reg, val); |
112 | iowrite8(val, card->iobase + reg); | 112 | iowrite8(val, card->iobase + reg); |
113 | } | 113 | } |
114 | 114 | ||
115 | static inline void if_cs_write16(struct if_cs_card *card, uint reg, u16 val) | 115 | static inline void if_cs_write16(struct if_cs_card *card, uint reg, u16 val) |
116 | { | 116 | { |
117 | if (debug_output) | 117 | if (debug_output) |
118 | printk(KERN_INFO "##outw %08x>%04x\n", reg, val); | 118 | printk(KERN_INFO "outw %08x>%04x\n", reg, val); |
119 | iowrite16(val, card->iobase + reg); | 119 | iowrite16(val, card->iobase + reg); |
120 | } | 120 | } |
121 | 121 | ||
@@ -126,7 +126,7 @@ static inline void if_cs_write16_rep( | |||
126 | unsigned long count) | 126 | unsigned long count) |
127 | { | 127 | { |
128 | if (debug_output) | 128 | if (debug_output) |
129 | printk(KERN_INFO "##outsw %08x>(0x%lx words)\n", | 129 | printk(KERN_INFO "outsw %08x>(0x%lx words)\n", |
130 | reg, count); | 130 | reg, count); |
131 | iowrite16_rep(card->iobase + reg, buf, count); | 131 | iowrite16_rep(card->iobase + reg, buf, count); |
132 | } | 132 | } |
@@ -199,17 +199,6 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r | |||
199 | #define IF_CS_C_S_CARDEVENT 0x0010 | 199 | #define IF_CS_C_S_CARDEVENT 0x0010 |
200 | #define IF_CS_C_S_MASK 0x001f | 200 | #define IF_CS_C_S_MASK 0x001f |
201 | #define IF_CS_C_S_STATUS_MASK 0x7f00 | 201 | #define IF_CS_C_S_STATUS_MASK 0x7f00 |
202 | /* The following definitions should be the same as the MRVDRV_ ones */ | ||
203 | |||
204 | #if MRVDRV_CMD_DNLD_RDY != IF_CS_C_S_CMD_DNLD_RDY | ||
205 | #error MRVDRV_CMD_DNLD_RDY and IF_CS_C_S_CMD_DNLD_RDY not in sync | ||
206 | #endif | ||
207 | #if MRVDRV_CMD_UPLD_RDY != IF_CS_C_S_CMD_UPLD_RDY | ||
208 | #error MRVDRV_CMD_UPLD_RDY and IF_CS_C_S_CMD_UPLD_RDY not in sync | ||
209 | #endif | ||
210 | #if MRVDRV_CARDEVENT != IF_CS_C_S_CARDEVENT | ||
211 | #error MRVDRV_CARDEVENT and IF_CS_C_S_CARDEVENT not in sync | ||
212 | #endif | ||
213 | 202 | ||
214 | #define IF_CS_C_INT_CAUSE 0x00000022 | 203 | #define IF_CS_C_INT_CAUSE 0x00000022 |
215 | #define IF_CS_C_IC_MASK 0x001f | 204 | #define IF_CS_C_IC_MASK 0x001f |
@@ -226,55 +215,6 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r | |||
226 | 215 | ||
227 | 216 | ||
228 | /********************************************************************/ | 217 | /********************************************************************/ |
229 | /* Interrupts */ | ||
230 | /********************************************************************/ | ||
231 | |||
232 | static inline void if_cs_enable_ints(struct if_cs_card *card) | ||
233 | { | ||
234 | lbs_deb_enter(LBS_DEB_CS); | ||
235 | if_cs_write16(card, IF_CS_H_INT_MASK, 0); | ||
236 | } | ||
237 | |||
238 | static inline void if_cs_disable_ints(struct if_cs_card *card) | ||
239 | { | ||
240 | lbs_deb_enter(LBS_DEB_CS); | ||
241 | if_cs_write16(card, IF_CS_H_INT_MASK, IF_CS_H_IM_MASK); | ||
242 | } | ||
243 | |||
244 | static irqreturn_t if_cs_interrupt(int irq, void *data) | ||
245 | { | ||
246 | struct if_cs_card *card = data; | ||
247 | u16 int_cause; | ||
248 | |||
249 | lbs_deb_enter(LBS_DEB_CS); | ||
250 | |||
251 | int_cause = if_cs_read16(card, IF_CS_C_INT_CAUSE); | ||
252 | if (int_cause == 0x0) { | ||
253 | /* Not for us */ | ||
254 | return IRQ_NONE; | ||
255 | |||
256 | } else if (int_cause == 0xffff) { | ||
257 | /* Read in junk, the card has probably been removed */ | ||
258 | card->priv->surpriseremoved = 1; | ||
259 | return IRQ_HANDLED; | ||
260 | } else { | ||
261 | if (int_cause & IF_CS_H_IC_TX_OVER) | ||
262 | lbs_host_to_card_done(card->priv); | ||
263 | |||
264 | /* clear interrupt */ | ||
265 | if_cs_write16(card, IF_CS_C_INT_CAUSE, int_cause & IF_CS_C_IC_MASK); | ||
266 | } | ||
267 | spin_lock(&card->priv->driver_lock); | ||
268 | lbs_interrupt(card->priv); | ||
269 | spin_unlock(&card->priv->driver_lock); | ||
270 | |||
271 | return IRQ_HANDLED; | ||
272 | } | ||
273 | |||
274 | |||
275 | |||
276 | |||
277 | /********************************************************************/ | ||
278 | /* I/O */ | 218 | /* I/O */ |
279 | /********************************************************************/ | 219 | /********************************************************************/ |
280 | 220 | ||
@@ -351,6 +291,7 @@ static void if_cs_send_data(struct lbs_private *priv, u8 *buf, u16 nb) | |||
351 | */ | 291 | */ |
352 | static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len) | 292 | static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len) |
353 | { | 293 | { |
294 | unsigned long flags; | ||
354 | int ret = -1; | 295 | int ret = -1; |
355 | u16 val; | 296 | u16 val; |
356 | 297 | ||
@@ -378,6 +319,12 @@ static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len) | |||
378 | * bytes */ | 319 | * bytes */ |
379 | *len -= 8; | 320 | *len -= 8; |
380 | ret = 0; | 321 | ret = 0; |
322 | |||
323 | /* Clear this flag again */ | ||
324 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
325 | priv->dnld_sent = DNLD_RES_RECEIVED; | ||
326 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
327 | |||
381 | out: | 328 | out: |
382 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d, len %d", ret, *len); | 329 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d, len %d", ret, *len); |
383 | return ret; | 330 | return ret; |
@@ -396,11 +343,9 @@ static struct sk_buff *if_cs_receive_data(struct lbs_private *priv) | |||
396 | if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { | 343 | if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { |
397 | lbs_pr_err("card data buffer has invalid # of bytes (%d)\n", len); | 344 | lbs_pr_err("card data buffer has invalid # of bytes (%d)\n", len); |
398 | priv->stats.rx_dropped++; | 345 | priv->stats.rx_dropped++; |
399 | printk(KERN_INFO "##HS %s:%d TODO\n", __FUNCTION__, __LINE__); | ||
400 | goto dat_err; | 346 | goto dat_err; |
401 | } | 347 | } |
402 | 348 | ||
403 | //TODO: skb = dev_alloc_skb(len+ETH_FRAME_LEN+MRVDRV_SNAP_HEADER_LEN+EXTRA_LEN); | ||
404 | skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + 2); | 349 | skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + 2); |
405 | if (!skb) | 350 | if (!skb) |
406 | goto out; | 351 | goto out; |
@@ -425,6 +370,96 @@ out: | |||
425 | 370 | ||
426 | 371 | ||
427 | /********************************************************************/ | 372 | /********************************************************************/ |
373 | /* Interrupts */ | ||
374 | /********************************************************************/ | ||
375 | |||
376 | static inline void if_cs_enable_ints(struct if_cs_card *card) | ||
377 | { | ||
378 | lbs_deb_enter(LBS_DEB_CS); | ||
379 | if_cs_write16(card, IF_CS_H_INT_MASK, 0); | ||
380 | } | ||
381 | |||
382 | static inline void if_cs_disable_ints(struct if_cs_card *card) | ||
383 | { | ||
384 | lbs_deb_enter(LBS_DEB_CS); | ||
385 | if_cs_write16(card, IF_CS_H_INT_MASK, IF_CS_H_IM_MASK); | ||
386 | } | ||
387 | |||
388 | |||
389 | static irqreturn_t if_cs_interrupt(int irq, void *data) | ||
390 | { | ||
391 | struct if_cs_card *card = data; | ||
392 | struct lbs_private *priv = card->priv; | ||
393 | u16 cause; | ||
394 | |||
395 | lbs_deb_enter(LBS_DEB_CS); | ||
396 | |||
397 | cause = if_cs_read16(card, IF_CS_C_INT_CAUSE); | ||
398 | if_cs_write16(card, IF_CS_C_INT_CAUSE, cause & IF_CS_C_IC_MASK); | ||
399 | |||
400 | lbs_deb_cs("cause 0x%04x\n", cause); | ||
401 | if (cause == 0) { | ||
402 | /* Not for us */ | ||
403 | return IRQ_NONE; | ||
404 | } | ||
405 | |||
406 | if (cause == 0xffff) { | ||
407 | /* Read in junk, the card has probably been removed */ | ||
408 | card->priv->surpriseremoved = 1; | ||
409 | return IRQ_HANDLED; | ||
410 | } | ||
411 | |||
412 | /* TODO: I'm not sure what the best ordering is */ | ||
413 | |||
414 | cause = if_cs_read16(card, IF_CS_C_STATUS) & IF_CS_C_S_MASK; | ||
415 | |||
416 | if (cause & IF_CS_C_S_RX_UPLD_RDY) { | ||
417 | struct sk_buff *skb; | ||
418 | lbs_deb_cs("rx packet\n"); | ||
419 | skb = if_cs_receive_data(priv); | ||
420 | if (skb) | ||
421 | lbs_process_rxed_packet(priv, skb); | ||
422 | } | ||
423 | |||
424 | if (cause & IF_CS_H_IC_TX_OVER) { | ||
425 | lbs_deb_cs("tx over\n"); | ||
426 | lbs_host_to_card_done(priv); | ||
427 | } | ||
428 | |||
429 | if (cause & IF_CS_C_S_CMD_UPLD_RDY) { | ||
430 | unsigned long flags; | ||
431 | u8 i; | ||
432 | |||
433 | lbs_deb_cs("cmd upload ready\n"); | ||
434 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
435 | i = (priv->resp_idx == 0) ? 1 : 0; | ||
436 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
437 | |||
438 | BUG_ON(priv->resp_len[i]); | ||
439 | if_cs_receive_cmdres(priv, priv->resp_buf[i], | ||
440 | &priv->resp_len[i]); | ||
441 | |||
442 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
443 | lbs_notify_command_response(priv, i); | ||
444 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
445 | } | ||
446 | |||
447 | if (cause & IF_CS_H_IC_HOST_EVENT) { | ||
448 | u16 event = if_cs_read16(priv->card, IF_CS_C_STATUS) | ||
449 | & IF_CS_C_S_STATUS_MASK; | ||
450 | if_cs_write16(priv->card, IF_CS_H_INT_CAUSE, | ||
451 | IF_CS_H_IC_HOST_EVENT); | ||
452 | lbs_deb_cs("eventcause 0x%04x\n", event); | ||
453 | lbs_queue_event(priv, event >> 8 & 0xff); | ||
454 | } | ||
455 | |||
456 | return IRQ_HANDLED; | ||
457 | } | ||
458 | |||
459 | |||
460 | |||
461 | |||
462 | /********************************************************************/ | ||
428 | /* Firmware */ | 463 | /* Firmware */ |
429 | /********************************************************************/ | 464 | /********************************************************************/ |
430 | 465 | ||
@@ -476,8 +511,6 @@ static int if_cs_prog_helper(struct if_cs_card *card) | |||
476 | 511 | ||
477 | if (remain < count) | 512 | if (remain < count) |
478 | count = remain; | 513 | count = remain; |
479 | /* printk(KERN_INFO "//HS %d loading %d of %d bytes\n", | ||
480 | __LINE__, sent, fw->size); */ | ||
481 | 514 | ||
482 | /* "write the number of bytes to be sent to the I/O Command | 515 | /* "write the number of bytes to be sent to the I/O Command |
483 | * write length register" */ | 516 | * write length register" */ |
@@ -544,18 +577,12 @@ static int if_cs_prog_real(struct if_cs_card *card) | |||
544 | 577 | ||
545 | ret = if_cs_poll_while_fw_download(card, IF_CS_C_SQ_READ_LOW, IF_CS_C_SQ_HELPER_OK); | 578 | ret = if_cs_poll_while_fw_download(card, IF_CS_C_SQ_READ_LOW, IF_CS_C_SQ_HELPER_OK); |
546 | if (ret < 0) { | 579 | if (ret < 0) { |
547 | int i; | ||
548 | lbs_pr_err("helper firmware doesn't answer\n"); | 580 | lbs_pr_err("helper firmware doesn't answer\n"); |
549 | for (i = 0; i < 0x50; i += 2) | ||
550 | printk(KERN_INFO "## HS %02x: %04x\n", | ||
551 | i, if_cs_read16(card, i)); | ||
552 | goto err_release; | 581 | goto err_release; |
553 | } | 582 | } |
554 | 583 | ||
555 | for (sent = 0; sent < fw->size; sent += len) { | 584 | for (sent = 0; sent < fw->size; sent += len) { |
556 | len = if_cs_read16(card, IF_CS_C_SQ_READ_LOW); | 585 | len = if_cs_read16(card, IF_CS_C_SQ_READ_LOW); |
557 | /* printk(KERN_INFO "//HS %d loading %d of %d bytes\n", | ||
558 | __LINE__, sent, fw->size); */ | ||
559 | if (len & 1) { | 586 | if (len & 1) { |
560 | retry++; | 587 | retry++; |
561 | lbs_pr_info("odd, need to retry this firmware block\n"); | 588 | lbs_pr_info("odd, need to retry this firmware block\n"); |
@@ -642,64 +669,6 @@ static int if_cs_host_to_card(struct lbs_private *priv, | |||
642 | } | 669 | } |
643 | 670 | ||
644 | 671 | ||
645 | static int if_cs_get_int_status(struct lbs_private *priv, u8 *ireg) | ||
646 | { | ||
647 | struct if_cs_card *card = (struct if_cs_card *)priv->card; | ||
648 | int ret = 0; | ||
649 | u16 int_cause; | ||
650 | *ireg = 0; | ||
651 | |||
652 | lbs_deb_enter(LBS_DEB_CS); | ||
653 | |||
654 | if (priv->surpriseremoved) | ||
655 | goto out; | ||
656 | |||
657 | int_cause = if_cs_read16(card, IF_CS_C_INT_CAUSE) & IF_CS_C_IC_MASK; | ||
658 | if_cs_write16(card, IF_CS_C_INT_CAUSE, int_cause); | ||
659 | |||
660 | *ireg = if_cs_read16(card, IF_CS_C_STATUS) & IF_CS_C_S_MASK; | ||
661 | |||
662 | if (!*ireg) | ||
663 | goto sbi_get_int_status_exit; | ||
664 | |||
665 | sbi_get_int_status_exit: | ||
666 | |||
667 | /* is there a data packet for us? */ | ||
668 | if (*ireg & IF_CS_C_S_RX_UPLD_RDY) { | ||
669 | struct sk_buff *skb = if_cs_receive_data(priv); | ||
670 | lbs_process_rxed_packet(priv, skb); | ||
671 | *ireg &= ~IF_CS_C_S_RX_UPLD_RDY; | ||
672 | } | ||
673 | |||
674 | if (*ireg & IF_CS_C_S_TX_DNLD_RDY) { | ||
675 | priv->dnld_sent = DNLD_RES_RECEIVED; | ||
676 | } | ||
677 | |||
678 | /* Card has a command result for us */ | ||
679 | if (*ireg & IF_CS_C_S_CMD_UPLD_RDY) { | ||
680 | ret = if_cs_receive_cmdres(priv, priv->upld_buf, &priv->upld_len); | ||
681 | if (ret < 0) | ||
682 | lbs_pr_err("could not receive cmd from card\n"); | ||
683 | } | ||
684 | |||
685 | out: | ||
686 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d, ireg 0x%x, hisregcpy 0x%x", ret, *ireg, priv->hisregcpy); | ||
687 | return ret; | ||
688 | } | ||
689 | |||
690 | |||
691 | static int if_cs_read_event_cause(struct lbs_private *priv) | ||
692 | { | ||
693 | lbs_deb_enter(LBS_DEB_CS); | ||
694 | |||
695 | priv->eventcause = (if_cs_read16(priv->card, IF_CS_C_STATUS) & IF_CS_C_S_STATUS_MASK) >> 5; | ||
696 | if_cs_write16(priv->card, IF_CS_H_INT_CAUSE, IF_CS_H_IC_HOST_EVENT); | ||
697 | |||
698 | return 0; | ||
699 | } | ||
700 | |||
701 | |||
702 | |||
703 | /********************************************************************/ | 672 | /********************************************************************/ |
704 | /* Card Services */ | 673 | /* Card Services */ |
705 | /********************************************************************/ | 674 | /********************************************************************/ |
@@ -852,13 +821,10 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
852 | goto out2; | 821 | goto out2; |
853 | } | 822 | } |
854 | 823 | ||
855 | /* Store pointers to our call-back functions */ | 824 | /* Finish setting up fields in lbs_private */ |
856 | card->priv = priv; | 825 | card->priv = priv; |
857 | priv->card = card; | 826 | priv->card = card; |
858 | priv->hw_host_to_card = if_cs_host_to_card; | 827 | priv->hw_host_to_card = if_cs_host_to_card; |
859 | priv->hw_get_int_status = if_cs_get_int_status; | ||
860 | priv->hw_read_event_cause = if_cs_read_event_cause; | ||
861 | |||
862 | priv->fw_ready = 1; | 828 | priv->fw_ready = 1; |
863 | 829 | ||
864 | /* Now actually get the IRQ */ | 830 | /* Now actually get the IRQ */ |
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index eed73204bcc..51f664bbee9 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
@@ -91,8 +91,6 @@ struct if_sdio_card { | |||
91 | const char *firmware; | 91 | const char *firmware; |
92 | 92 | ||
93 | u8 buffer[65536]; | 93 | u8 buffer[65536]; |
94 | u8 int_cause; | ||
95 | u32 event; | ||
96 | 94 | ||
97 | spinlock_t lock; | 95 | spinlock_t lock; |
98 | struct if_sdio_packet *packets; | 96 | struct if_sdio_packet *packets; |
@@ -129,13 +127,13 @@ static u16 if_sdio_read_scratch(struct if_sdio_card *card, int *err) | |||
129 | static int if_sdio_handle_cmd(struct if_sdio_card *card, | 127 | static int if_sdio_handle_cmd(struct if_sdio_card *card, |
130 | u8 *buffer, unsigned size) | 128 | u8 *buffer, unsigned size) |
131 | { | 129 | { |
130 | struct lbs_private *priv = card->priv; | ||
132 | int ret; | 131 | int ret; |
133 | unsigned long flags; | 132 | unsigned long flags; |
133 | u8 i; | ||
134 | 134 | ||
135 | lbs_deb_enter(LBS_DEB_SDIO); | 135 | lbs_deb_enter(LBS_DEB_SDIO); |
136 | 136 | ||
137 | spin_lock_irqsave(&card->priv->driver_lock, flags); | ||
138 | |||
139 | if (size > LBS_CMD_BUFFER_SIZE) { | 137 | if (size > LBS_CMD_BUFFER_SIZE) { |
140 | lbs_deb_sdio("response packet too large (%d bytes)\n", | 138 | lbs_deb_sdio("response packet too large (%d bytes)\n", |
141 | (int)size); | 139 | (int)size); |
@@ -143,20 +141,20 @@ static int if_sdio_handle_cmd(struct if_sdio_card *card, | |||
143 | goto out; | 141 | goto out; |
144 | } | 142 | } |
145 | 143 | ||
146 | memcpy(card->priv->upld_buf, buffer, size); | 144 | spin_lock_irqsave(&priv->driver_lock, flags); |
147 | card->priv->upld_len = size; | ||
148 | 145 | ||
149 | card->int_cause |= MRVDRV_CMD_UPLD_RDY; | 146 | i = (priv->resp_idx == 0) ? 1 : 0; |
147 | BUG_ON(priv->resp_len[i]); | ||
148 | priv->resp_len[i] = size; | ||
149 | memcpy(priv->resp_buf[i], buffer, size); | ||
150 | lbs_notify_command_response(priv, i); | ||
150 | 151 | ||
151 | lbs_interrupt(card->priv); | 152 | spin_unlock_irqrestore(&card->priv->driver_lock, flags); |
152 | 153 | ||
153 | ret = 0; | 154 | ret = 0; |
154 | 155 | ||
155 | out: | 156 | out: |
156 | spin_unlock_irqrestore(&card->priv->driver_lock, flags); | ||
157 | |||
158 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | 157 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); |
159 | |||
160 | return ret; | 158 | return ret; |
161 | } | 159 | } |
162 | 160 | ||
@@ -202,7 +200,6 @@ static int if_sdio_handle_event(struct if_sdio_card *card, | |||
202 | u8 *buffer, unsigned size) | 200 | u8 *buffer, unsigned size) |
203 | { | 201 | { |
204 | int ret; | 202 | int ret; |
205 | unsigned long flags; | ||
206 | u32 event; | 203 | u32 event; |
207 | 204 | ||
208 | lbs_deb_enter(LBS_DEB_SDIO); | 205 | lbs_deb_enter(LBS_DEB_SDIO); |
@@ -222,18 +219,9 @@ static int if_sdio_handle_event(struct if_sdio_card *card, | |||
222 | event |= buffer[2] << 16; | 219 | event |= buffer[2] << 16; |
223 | event |= buffer[1] << 8; | 220 | event |= buffer[1] << 8; |
224 | event |= buffer[0] << 0; | 221 | event |= buffer[0] << 0; |
225 | event <<= SBI_EVENT_CAUSE_SHIFT; | ||
226 | } | 222 | } |
227 | 223 | ||
228 | spin_lock_irqsave(&card->priv->driver_lock, flags); | 224 | lbs_queue_event(card->priv, event & 0xFF); |
229 | |||
230 | card->event = event; | ||
231 | card->int_cause |= MRVDRV_CARDEVENT; | ||
232 | |||
233 | lbs_interrupt(card->priv); | ||
234 | |||
235 | spin_unlock_irqrestore(&card->priv->driver_lock, flags); | ||
236 | |||
237 | ret = 0; | 225 | ret = 0; |
238 | 226 | ||
239 | out: | 227 | out: |
@@ -770,37 +758,6 @@ out: | |||
770 | return ret; | 758 | return ret; |
771 | } | 759 | } |
772 | 760 | ||
773 | static int if_sdio_get_int_status(struct lbs_private *priv, u8 *ireg) | ||
774 | { | ||
775 | struct if_sdio_card *card; | ||
776 | |||
777 | lbs_deb_enter(LBS_DEB_SDIO); | ||
778 | |||
779 | card = priv->card; | ||
780 | |||
781 | *ireg = card->int_cause; | ||
782 | card->int_cause = 0; | ||
783 | |||
784 | lbs_deb_leave(LBS_DEB_SDIO); | ||
785 | |||
786 | return 0; | ||
787 | } | ||
788 | |||
789 | static int if_sdio_read_event_cause(struct lbs_private *priv) | ||
790 | { | ||
791 | struct if_sdio_card *card; | ||
792 | |||
793 | lbs_deb_enter(LBS_DEB_SDIO); | ||
794 | |||
795 | card = priv->card; | ||
796 | |||
797 | priv->eventcause = card->event; | ||
798 | |||
799 | lbs_deb_leave(LBS_DEB_SDIO); | ||
800 | |||
801 | return 0; | ||
802 | } | ||
803 | |||
804 | /*******************************************************************/ | 761 | /*******************************************************************/ |
805 | /* SDIO callbacks */ | 762 | /* SDIO callbacks */ |
806 | /*******************************************************************/ | 763 | /*******************************************************************/ |
@@ -953,8 +910,6 @@ static int if_sdio_probe(struct sdio_func *func, | |||
953 | 910 | ||
954 | priv->card = card; | 911 | priv->card = card; |
955 | priv->hw_host_to_card = if_sdio_host_to_card; | 912 | priv->hw_host_to_card = if_sdio_host_to_card; |
956 | priv->hw_get_int_status = if_sdio_get_int_status; | ||
957 | priv->hw_read_event_cause = if_sdio_read_event_cause; | ||
958 | 913 | ||
959 | priv->fw_ready = 1; | 914 | priv->fw_ready = 1; |
960 | 915 | ||
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 75aed9d0736..8032df72aaa 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c | |||
@@ -38,8 +38,6 @@ static void if_usb_receive_fwload(struct urb *urb); | |||
38 | static int if_usb_prog_firmware(struct if_usb_card *cardp); | 38 | static int if_usb_prog_firmware(struct if_usb_card *cardp); |
39 | static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, | 39 | static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, |
40 | uint8_t *payload, uint16_t nb); | 40 | uint8_t *payload, uint16_t nb); |
41 | static int if_usb_get_int_status(struct lbs_private *priv, uint8_t *); | ||
42 | static int if_usb_read_event_cause(struct lbs_private *); | ||
43 | static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, | 41 | static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, |
44 | uint16_t nb); | 42 | uint16_t nb); |
45 | static void if_usb_free(struct if_usb_card *cardp); | 43 | static void if_usb_free(struct if_usb_card *cardp); |
@@ -233,8 +231,6 @@ static int if_usb_probe(struct usb_interface *intf, | |||
233 | cardp->priv->fw_ready = 1; | 231 | cardp->priv->fw_ready = 1; |
234 | 232 | ||
235 | priv->hw_host_to_card = if_usb_host_to_card; | 233 | priv->hw_host_to_card = if_usb_host_to_card; |
236 | priv->hw_get_int_status = if_usb_get_int_status; | ||
237 | priv->hw_read_event_cause = if_usb_read_event_cause; | ||
238 | cardp->boot2_version = udev->descriptor.bcdDevice; | 234 | cardp->boot2_version = udev->descriptor.bcdDevice; |
239 | 235 | ||
240 | if_usb_submit_rx_urb(cardp); | 236 | if_usb_submit_rx_urb(cardp); |
@@ -582,7 +578,6 @@ static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb, | |||
582 | skb_pull(skb, MESSAGE_HEADER_LEN); | 578 | skb_pull(skb, MESSAGE_HEADER_LEN); |
583 | 579 | ||
584 | lbs_process_rxed_packet(priv, skb); | 580 | lbs_process_rxed_packet(priv, skb); |
585 | priv->upld_len = (recvlength - MESSAGE_HEADER_LEN); | ||
586 | } | 581 | } |
587 | 582 | ||
588 | static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, | 583 | static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, |
@@ -590,6 +585,8 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, | |||
590 | struct if_usb_card *cardp, | 585 | struct if_usb_card *cardp, |
591 | struct lbs_private *priv) | 586 | struct lbs_private *priv) |
592 | { | 587 | { |
588 | u8 i; | ||
589 | |||
593 | if (recvlength > LBS_CMD_BUFFER_SIZE) { | 590 | if (recvlength > LBS_CMD_BUFFER_SIZE) { |
594 | lbs_deb_usbd(&cardp->udev->dev, | 591 | lbs_deb_usbd(&cardp->udev->dev, |
595 | "The receive buffer is too large\n"); | 592 | "The receive buffer is too large\n"); |
@@ -601,12 +598,15 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, | |||
601 | BUG(); | 598 | BUG(); |
602 | 599 | ||
603 | spin_lock(&priv->driver_lock); | 600 | spin_lock(&priv->driver_lock); |
604 | cardp->usb_int_cause |= MRVDRV_CMD_UPLD_RDY; | ||
605 | priv->upld_len = (recvlength - MESSAGE_HEADER_LEN); | ||
606 | memcpy(priv->upld_buf, recvbuff + MESSAGE_HEADER_LEN, priv->upld_len); | ||
607 | 601 | ||
602 | i = (priv->resp_idx == 0) ? 1 : 0; | ||
603 | BUG_ON(priv->resp_len[i]); | ||
604 | priv->resp_len[i] = (recvlength - MESSAGE_HEADER_LEN); | ||
605 | memcpy(priv->resp_buf[i], recvbuff + MESSAGE_HEADER_LEN, | ||
606 | priv->resp_len[i]); | ||
608 | kfree_skb(skb); | 607 | kfree_skb(skb); |
609 | lbs_interrupt(priv); | 608 | lbs_notify_command_response(priv, i); |
609 | |||
610 | spin_unlock(&priv->driver_lock); | 610 | spin_unlock(&priv->driver_lock); |
611 | 611 | ||
612 | lbs_deb_usbd(&cardp->udev->dev, | 612 | lbs_deb_usbd(&cardp->udev->dev, |
@@ -629,6 +629,7 @@ static void if_usb_receive(struct urb *urb) | |||
629 | uint8_t *recvbuff = NULL; | 629 | uint8_t *recvbuff = NULL; |
630 | uint32_t recvtype = 0; | 630 | uint32_t recvtype = 0; |
631 | __le32 *pkt = (__le32 *)(skb->data + IPFIELD_ALIGN_OFFSET); | 631 | __le32 *pkt = (__le32 *)(skb->data + IPFIELD_ALIGN_OFFSET); |
632 | uint32_t event; | ||
632 | 633 | ||
633 | lbs_deb_enter(LBS_DEB_USB); | 634 | lbs_deb_enter(LBS_DEB_USB); |
634 | 635 | ||
@@ -660,26 +661,20 @@ static void if_usb_receive(struct urb *urb) | |||
660 | break; | 661 | break; |
661 | 662 | ||
662 | case CMD_TYPE_INDICATION: | 663 | case CMD_TYPE_INDICATION: |
663 | /* Event cause handling */ | 664 | /* Event handling */ |
664 | spin_lock(&priv->driver_lock); | 665 | event = le32_to_cpu(pkt[1]); |
666 | lbs_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", event); | ||
667 | kfree_skb(skb); | ||
665 | 668 | ||
666 | cardp->usb_event_cause = le32_to_cpu(pkt[1]); | 669 | /* Icky undocumented magic special case */ |
670 | if (event & 0xffff0000) { | ||
671 | u32 trycount = (event & 0xffff0000) >> 16; | ||
667 | 672 | ||
668 | lbs_deb_usbd(&cardp->udev->dev,"**EVENT** 0x%X\n", | 673 | lbs_send_tx_feedback(priv, trycount); |
669 | cardp->usb_event_cause); | 674 | } else |
675 | lbs_queue_event(priv, event & 0xFF); | ||
676 | break; | ||
670 | 677 | ||
671 | /* Icky undocumented magic special case */ | ||
672 | if (cardp->usb_event_cause & 0xffff0000) { | ||
673 | lbs_send_tx_feedback(priv); | ||
674 | spin_unlock(&priv->driver_lock); | ||
675 | break; | ||
676 | } | ||
677 | cardp->usb_event_cause <<= 3; | ||
678 | cardp->usb_int_cause |= MRVDRV_CARDEVENT; | ||
679 | kfree_skb(skb); | ||
680 | lbs_interrupt(priv); | ||
681 | spin_unlock(&priv->driver_lock); | ||
682 | goto rx_exit; | ||
683 | default: | 678 | default: |
684 | lbs_deb_usbd(&cardp->udev->dev, "Unknown command type 0x%X\n", | 679 | lbs_deb_usbd(&cardp->udev->dev, "Unknown command type 0x%X\n", |
685 | recvtype); | 680 | recvtype); |
@@ -722,30 +717,6 @@ static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, | |||
722 | return usb_tx_block(cardp, cardp->ep_out_buf, nb + MESSAGE_HEADER_LEN); | 717 | return usb_tx_block(cardp, cardp->ep_out_buf, nb + MESSAGE_HEADER_LEN); |
723 | } | 718 | } |
724 | 719 | ||
725 | /* called with priv->driver_lock held */ | ||
726 | static int if_usb_get_int_status(struct lbs_private *priv, uint8_t *ireg) | ||
727 | { | ||
728 | struct if_usb_card *cardp = priv->card; | ||
729 | |||
730 | *ireg = cardp->usb_int_cause; | ||
731 | cardp->usb_int_cause = 0; | ||
732 | |||
733 | lbs_deb_usbd(&cardp->udev->dev, "Int cause is 0x%X\n", *ireg); | ||
734 | |||
735 | return 0; | ||
736 | } | ||
737 | |||
738 | static int if_usb_read_event_cause(struct lbs_private *priv) | ||
739 | { | ||
740 | struct if_usb_card *cardp = priv->card; | ||
741 | |||
742 | priv->eventcause = cardp->usb_event_cause; | ||
743 | /* Re-submit rx urb here to avoid event lost issue */ | ||
744 | if_usb_submit_rx_urb(cardp); | ||
745 | |||
746 | return 0; | ||
747 | } | ||
748 | |||
749 | /** | 720 | /** |
750 | * @brief This function issues Boot command to the Boot2 code | 721 | * @brief This function issues Boot command to the Boot2 code |
751 | * @param ivalue 1:Boot from FW by USB-Download | 722 | * @param ivalue 1:Boot from FW by USB-Download |
diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h index e4829a391eb..5771a83a43f 100644 --- a/drivers/net/wireless/libertas/if_usb.h +++ b/drivers/net/wireless/libertas/if_usb.h | |||
@@ -46,8 +46,6 @@ struct if_usb_card { | |||
46 | struct lbs_private *priv; | 46 | struct lbs_private *priv; |
47 | 47 | ||
48 | struct sk_buff *rx_skb; | 48 | struct sk_buff *rx_skb; |
49 | uint32_t usb_event_cause; | ||
50 | uint8_t usb_int_cause; | ||
51 | 49 | ||
52 | uint8_t ep_in; | 50 | uint8_t ep_in; |
53 | uint8_t ep_out; | 51 | uint8_t ep_out; |
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 8f112261097..406f54d4095 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/netdevice.h> | 10 | #include <linux/netdevice.h> |
11 | #include <linux/if_arp.h> | 11 | #include <linux/if_arp.h> |
12 | #include <linux/kthread.h> | 12 | #include <linux/kthread.h> |
13 | #include <linux/kfifo.h> | ||
13 | 14 | ||
14 | #include <net/iw_handler.h> | 15 | #include <net/iw_handler.h> |
15 | #include <net/ieee80211.h> | 16 | #include <net/ieee80211.h> |
@@ -480,10 +481,9 @@ static void lbs_tx_timeout(struct net_device *dev) | |||
480 | 481 | ||
481 | dev->trans_start = jiffies; | 482 | dev->trans_start = jiffies; |
482 | 483 | ||
483 | if (priv->currenttxskb) { | 484 | if (priv->currenttxskb) |
484 | priv->eventcause = 0x01000000; | 485 | lbs_send_tx_feedback(priv, 0); |
485 | lbs_send_tx_feedback(priv); | 486 | |
486 | } | ||
487 | /* XX: Shouldn't we also call into the hw-specific driver | 487 | /* XX: Shouldn't we also call into the hw-specific driver |
488 | to kick it somehow? */ | 488 | to kick it somehow? */ |
489 | lbs_host_to_card_done(priv); | 489 | lbs_host_to_card_done(priv); |
@@ -659,7 +659,6 @@ static int lbs_thread(void *data) | |||
659 | struct net_device *dev = data; | 659 | struct net_device *dev = data; |
660 | struct lbs_private *priv = dev->priv; | 660 | struct lbs_private *priv = dev->priv; |
661 | wait_queue_t wait; | 661 | wait_queue_t wait; |
662 | u8 ireg = 0; | ||
663 | 662 | ||
664 | lbs_deb_enter(LBS_DEB_THREAD); | 663 | lbs_deb_enter(LBS_DEB_THREAD); |
665 | 664 | ||
@@ -667,9 +666,10 @@ static int lbs_thread(void *data) | |||
667 | 666 | ||
668 | for (;;) { | 667 | for (;;) { |
669 | int shouldsleep; | 668 | int shouldsleep; |
669 | u8 resp_idx; | ||
670 | 670 | ||
671 | lbs_deb_thread( "main-thread 111: intcounter=%d currenttxskb=%p dnld_sent=%d\n", | 671 | lbs_deb_thread("1: currenttxskb %p, dnld_sent %d\n", |
672 | priv->intcounter, priv->currenttxskb, priv->dnld_sent); | 672 | priv->currenttxskb, priv->dnld_sent); |
673 | 673 | ||
674 | add_wait_queue(&priv->waitq, &wait); | 674 | add_wait_queue(&priv->waitq, &wait); |
675 | set_current_state(TASK_INTERRUPTIBLE); | 675 | set_current_state(TASK_INTERRUPTIBLE); |
@@ -681,8 +681,6 @@ static int lbs_thread(void *data) | |||
681 | shouldsleep = 1; /* We need to wait until we're _told_ to die */ | 681 | shouldsleep = 1; /* We need to wait until we're _told_ to die */ |
682 | else if (priv->psstate == PS_STATE_SLEEP) | 682 | else if (priv->psstate == PS_STATE_SLEEP) |
683 | shouldsleep = 1; /* Sleep mode. Nothing we can do till it wakes */ | 683 | shouldsleep = 1; /* Sleep mode. Nothing we can do till it wakes */ |
684 | else if (priv->intcounter) | ||
685 | shouldsleep = 0; /* Interrupt pending. Deal with it now */ | ||
686 | else if (priv->cmd_timed_out) | 684 | else if (priv->cmd_timed_out) |
687 | shouldsleep = 0; /* Command timed out. Recover */ | 685 | shouldsleep = 0; /* Command timed out. Recover */ |
688 | else if (!priv->fw_ready) | 686 | else if (!priv->fw_ready) |
@@ -695,29 +693,34 @@ static int lbs_thread(void *data) | |||
695 | shouldsleep = 1; /* Can't send a command; one already running */ | 693 | shouldsleep = 1; /* Can't send a command; one already running */ |
696 | else if (!list_empty(&priv->cmdpendingq)) | 694 | else if (!list_empty(&priv->cmdpendingq)) |
697 | shouldsleep = 0; /* We have a command to send */ | 695 | shouldsleep = 0; /* We have a command to send */ |
696 | else if (__kfifo_len(priv->event_fifo)) | ||
697 | shouldsleep = 0; /* We have an event to process */ | ||
698 | else if (priv->resp_len[priv->resp_idx]) | ||
699 | shouldsleep = 0; /* We have a command response */ | ||
698 | else | 700 | else |
699 | shouldsleep = 1; /* No command */ | 701 | shouldsleep = 1; /* No command */ |
700 | 702 | ||
701 | if (shouldsleep) { | 703 | if (shouldsleep) { |
702 | lbs_deb_thread("main-thread sleeping... Conn=%d IntC=%d PS_mode=%d PS_State=%d\n", | 704 | lbs_deb_thread("sleeping, connect_status %d, " |
703 | priv->connect_status, priv->intcounter, | 705 | "ps_mode %d, ps_state %d\n", |
704 | priv->psmode, priv->psstate); | 706 | priv->connect_status, |
707 | priv->psmode, priv->psstate); | ||
705 | spin_unlock_irq(&priv->driver_lock); | 708 | spin_unlock_irq(&priv->driver_lock); |
706 | schedule(); | 709 | schedule(); |
707 | } else | 710 | } else |
708 | spin_unlock_irq(&priv->driver_lock); | 711 | spin_unlock_irq(&priv->driver_lock); |
709 | 712 | ||
710 | lbs_deb_thread("main-thread 222 (waking up): intcounter=%d currenttxskb=%p dnld_sent=%d\n", | 713 | lbs_deb_thread("2: currenttxskb %p, dnld_send %d\n", |
711 | priv->intcounter, priv->currenttxskb, priv->dnld_sent); | 714 | priv->currenttxskb, priv->dnld_sent); |
712 | 715 | ||
713 | set_current_state(TASK_RUNNING); | 716 | set_current_state(TASK_RUNNING); |
714 | remove_wait_queue(&priv->waitq, &wait); | 717 | remove_wait_queue(&priv->waitq, &wait); |
715 | 718 | ||
716 | lbs_deb_thread("main-thread 333: intcounter=%d currenttxskb=%p dnld_sent=%d\n", | 719 | lbs_deb_thread("3: currenttxskb %p, dnld_sent %d\n", |
717 | priv->intcounter, priv->currenttxskb, priv->dnld_sent); | 720 | priv->currenttxskb, priv->dnld_sent); |
718 | 721 | ||
719 | if (kthread_should_stop()) { | 722 | if (kthread_should_stop()) { |
720 | lbs_deb_thread("main-thread: break from main thread\n"); | 723 | lbs_deb_thread("break from main thread\n"); |
721 | break; | 724 | break; |
722 | } | 725 | } |
723 | 726 | ||
@@ -726,35 +729,23 @@ static int lbs_thread(void *data) | |||
726 | continue; | 729 | continue; |
727 | } | 730 | } |
728 | 731 | ||
729 | spin_lock_irq(&priv->driver_lock); | 732 | lbs_deb_thread("4: currenttxskb %p, dnld_sent %d\n", |
730 | 733 | priv->currenttxskb, priv->dnld_sent); | |
731 | if (priv->intcounter) { | ||
732 | u8 int_status; | ||
733 | 734 | ||
734 | priv->intcounter = 0; | 735 | spin_lock_irq(&priv->driver_lock); |
735 | int_status = priv->hw_get_int_status(priv, &ireg); | 736 | /* Process any pending command response */ |
736 | 737 | resp_idx = priv->resp_idx; | |
737 | if (int_status) { | 738 | if (priv->resp_len[resp_idx]) { |
738 | lbs_deb_thread("main-thread: reading HOST_INT_STATUS_REG failed\n"); | ||
739 | spin_unlock_irq(&priv->driver_lock); | ||
740 | continue; | ||
741 | } | ||
742 | priv->hisregcpy |= ireg; | ||
743 | } | ||
744 | |||
745 | lbs_deb_thread("main-thread 444: intcounter=%d currenttxskb=%p dnld_sent=%d\n", | ||
746 | priv->intcounter, priv->currenttxskb, priv->dnld_sent); | ||
747 | |||
748 | /* command response? */ | ||
749 | if (priv->hisregcpy & MRVDRV_CMD_UPLD_RDY) { | ||
750 | lbs_deb_thread("main-thread: cmd response ready\n"); | ||
751 | |||
752 | priv->hisregcpy &= ~MRVDRV_CMD_UPLD_RDY; | ||
753 | spin_unlock_irq(&priv->driver_lock); | 739 | spin_unlock_irq(&priv->driver_lock); |
754 | lbs_process_rx_command(priv); | 740 | lbs_process_command_response(priv, |
741 | priv->resp_buf[resp_idx], | ||
742 | priv->resp_len[resp_idx]); | ||
755 | spin_lock_irq(&priv->driver_lock); | 743 | spin_lock_irq(&priv->driver_lock); |
744 | priv->resp_len[resp_idx] = 0; | ||
756 | } | 745 | } |
746 | spin_unlock_irq(&priv->driver_lock); | ||
757 | 747 | ||
748 | /* command timeout stuff */ | ||
758 | if (priv->cmd_timed_out && priv->cur_cmd) { | 749 | if (priv->cmd_timed_out && priv->cur_cmd) { |
759 | struct cmd_ctrl_node *cmdnode = priv->cur_cmd; | 750 | struct cmd_ctrl_node *cmdnode = priv->cur_cmd; |
760 | 751 | ||
@@ -775,21 +766,18 @@ static int lbs_thread(void *data) | |||
775 | } | 766 | } |
776 | priv->cmd_timed_out = 0; | 767 | priv->cmd_timed_out = 0; |
777 | 768 | ||
778 | /* Any Card Event */ | 769 | /* Process hardware events, e.g. card removed, link lost */ |
779 | if (priv->hisregcpy & MRVDRV_CARDEVENT) { | 770 | spin_lock_irq(&priv->driver_lock); |
780 | lbs_deb_thread("main-thread: Card Event Activity\n"); | 771 | while (__kfifo_len(priv->event_fifo)) { |
781 | 772 | u32 event; | |
782 | priv->hisregcpy &= ~MRVDRV_CARDEVENT; | ||
783 | 773 | ||
784 | if (priv->hw_read_event_cause(priv)) { | 774 | __kfifo_get(priv->event_fifo, (unsigned char *) &event, |
785 | lbs_pr_alert("main-thread: hw_read_event_cause failed\n"); | 775 | sizeof(event)); |
786 | spin_unlock_irq(&priv->driver_lock); | ||
787 | continue; | ||
788 | } | ||
789 | spin_unlock_irq(&priv->driver_lock); | ||
790 | lbs_process_event(priv); | ||
791 | } else | ||
792 | spin_unlock_irq(&priv->driver_lock); | 776 | spin_unlock_irq(&priv->driver_lock); |
777 | lbs_process_event(priv, event); | ||
778 | spin_lock_irq(&priv->driver_lock); | ||
779 | } | ||
780 | spin_unlock_irq(&priv->driver_lock); | ||
793 | 781 | ||
794 | if (!priv->fw_ready) | 782 | if (!priv->fw_ready) |
795 | continue; | 783 | continue; |
@@ -798,8 +786,10 @@ static int lbs_thread(void *data) | |||
798 | if (priv->psstate == PS_STATE_PRE_SLEEP && | 786 | if (priv->psstate == PS_STATE_PRE_SLEEP && |
799 | !priv->dnld_sent && !priv->cur_cmd) { | 787 | !priv->dnld_sent && !priv->cur_cmd) { |
800 | if (priv->connect_status == LBS_CONNECTED) { | 788 | if (priv->connect_status == LBS_CONNECTED) { |
801 | lbs_deb_thread("main_thread: PRE_SLEEP--intcounter=%d currenttxskb=%p dnld_sent=%d cur_cmd=%p, confirm now\n", | 789 | lbs_deb_thread("pre-sleep, currenttxskb %p, " |
802 | priv->intcounter, priv->currenttxskb, priv->dnld_sent, priv->cur_cmd); | 790 | "dnld_sent %d, cur_cmd %p\n", |
791 | priv->currenttxskb, priv->dnld_sent, | ||
792 | priv->cur_cmd); | ||
803 | 793 | ||
804 | lbs_ps_confirm_sleep(priv); | 794 | lbs_ps_confirm_sleep(priv); |
805 | } else { | 795 | } else { |
@@ -809,7 +799,8 @@ static int lbs_thread(void *data) | |||
809 | * after firmware fixes it | 799 | * after firmware fixes it |
810 | */ | 800 | */ |
811 | priv->psstate = PS_STATE_AWAKE; | 801 | priv->psstate = PS_STATE_AWAKE; |
812 | lbs_pr_alert("main-thread: ignore PS_SleepConfirm in non-connected state\n"); | 802 | lbs_pr_alert("ignore PS_SleepConfirm in " |
803 | "non-connected state\n"); | ||
813 | } | 804 | } |
814 | } | 805 | } |
815 | 806 | ||
@@ -1046,7 +1037,18 @@ static int lbs_init_adapter(struct lbs_private *priv) | |||
1046 | /* Allocate the command buffers */ | 1037 | /* Allocate the command buffers */ |
1047 | if (lbs_allocate_cmd_buffer(priv)) { | 1038 | if (lbs_allocate_cmd_buffer(priv)) { |
1048 | lbs_pr_err("Out of memory allocating command buffers\n"); | 1039 | lbs_pr_err("Out of memory allocating command buffers\n"); |
1049 | ret = -1; | 1040 | ret = -ENOMEM; |
1041 | goto out; | ||
1042 | } | ||
1043 | priv->resp_idx = 0; | ||
1044 | priv->resp_len[0] = priv->resp_len[1] = 0; | ||
1045 | |||
1046 | /* Create the event FIFO */ | ||
1047 | priv->event_fifo = kfifo_alloc(sizeof(u32) * 16, GFP_KERNEL, NULL); | ||
1048 | if (IS_ERR(priv->event_fifo)) { | ||
1049 | lbs_pr_err("Out of memory allocating event FIFO buffer\n"); | ||
1050 | ret = -ENOMEM; | ||
1051 | goto out; | ||
1050 | } | 1052 | } |
1051 | 1053 | ||
1052 | out: | 1054 | out: |
@@ -1060,6 +1062,8 @@ static void lbs_free_adapter(struct lbs_private *priv) | |||
1060 | lbs_deb_enter(LBS_DEB_MAIN); | 1062 | lbs_deb_enter(LBS_DEB_MAIN); |
1061 | 1063 | ||
1062 | lbs_free_cmd_buffer(priv); | 1064 | lbs_free_cmd_buffer(priv); |
1065 | if (priv->event_fifo) | ||
1066 | kfifo_free(priv->event_fifo); | ||
1063 | del_timer(&priv->command_timer); | 1067 | del_timer(&priv->command_timer); |
1064 | kfree(priv->networks); | 1068 | kfree(priv->networks); |
1065 | priv->networks = NULL; | 1069 | priv->networks = NULL; |
@@ -1434,27 +1438,41 @@ out: | |||
1434 | return ret; | 1438 | return ret; |
1435 | } | 1439 | } |
1436 | 1440 | ||
1437 | /** | 1441 | void lbs_queue_event(struct lbs_private *priv, u32 event) |
1438 | * @brief This function handles the interrupt. it will change PS | 1442 | { |
1439 | * state if applicable. it will wake up main_thread to handle | 1443 | unsigned long flags; |
1440 | * the interrupt event as well. | 1444 | |
1441 | * | 1445 | lbs_deb_enter(LBS_DEB_THREAD); |
1442 | * @param dev A pointer to net_device structure | 1446 | spin_lock_irqsave(&priv->driver_lock, flags); |
1443 | * @return n/a | 1447 | |
1444 | */ | 1448 | if (priv->psstate == PS_STATE_SLEEP) |
1445 | void lbs_interrupt(struct lbs_private *priv) | 1449 | priv->psstate = PS_STATE_AWAKE; |
1450 | |||
1451 | __kfifo_put(priv->event_fifo, (unsigned char *) &event, sizeof(u32)); | ||
1452 | |||
1453 | wake_up_interruptible(&priv->waitq); | ||
1454 | |||
1455 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
1456 | lbs_deb_leave(LBS_DEB_THREAD); | ||
1457 | } | ||
1458 | EXPORT_SYMBOL_GPL(lbs_queue_event); | ||
1459 | |||
1460 | void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx) | ||
1446 | { | 1461 | { |
1447 | lbs_deb_enter(LBS_DEB_THREAD); | 1462 | lbs_deb_enter(LBS_DEB_THREAD); |
1448 | 1463 | ||
1449 | lbs_deb_thread("lbs_interrupt: intcounter=%d\n", priv->intcounter); | ||
1450 | priv->intcounter++; | ||
1451 | if (priv->psstate == PS_STATE_SLEEP) | 1464 | if (priv->psstate == PS_STATE_SLEEP) |
1452 | priv->psstate = PS_STATE_AWAKE; | 1465 | priv->psstate = PS_STATE_AWAKE; |
1466 | |||
1467 | /* Swap buffers by flipping the response index */ | ||
1468 | BUG_ON(resp_idx > 1); | ||
1469 | priv->resp_idx = resp_idx; | ||
1470 | |||
1453 | wake_up_interruptible(&priv->waitq); | 1471 | wake_up_interruptible(&priv->waitq); |
1454 | 1472 | ||
1455 | lbs_deb_leave(LBS_DEB_THREAD); | 1473 | lbs_deb_leave(LBS_DEB_THREAD); |
1456 | } | 1474 | } |
1457 | EXPORT_SYMBOL_GPL(lbs_interrupt); | 1475 | EXPORT_SYMBOL_GPL(lbs_notify_command_response); |
1458 | 1476 | ||
1459 | static int __init lbs_init_module(void) | 1477 | static int __init lbs_init_module(void) |
1460 | { | 1478 | { |
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 09f023089ea..05af7316f69 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c | |||
@@ -145,14 +145,14 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) | |||
145 | struct net_device *dev = priv->dev; | 145 | struct net_device *dev = priv->dev; |
146 | struct rxpackethdr *p_rx_pkt; | 146 | struct rxpackethdr *p_rx_pkt; |
147 | struct rxpd *p_rx_pd; | 147 | struct rxpd *p_rx_pd; |
148 | |||
149 | int hdrchop; | 148 | int hdrchop; |
150 | struct ethhdr *p_ethhdr; | 149 | struct ethhdr *p_ethhdr; |
151 | |||
152 | const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; | 150 | const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; |
153 | 151 | ||
154 | lbs_deb_enter(LBS_DEB_RX); | 152 | lbs_deb_enter(LBS_DEB_RX); |
155 | 153 | ||
154 | BUG_ON(!skb); | ||
155 | |||
156 | skb->ip_summed = CHECKSUM_NONE; | 156 | skb->ip_summed = CHECKSUM_NONE; |
157 | 157 | ||
158 | if (priv->monitormode) | 158 | if (priv->monitormode) |
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index 77f1f9525b8..a4972fed294 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c | |||
@@ -179,31 +179,17 @@ int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
179 | * | 179 | * |
180 | * @returns void | 180 | * @returns void |
181 | */ | 181 | */ |
182 | void lbs_send_tx_feedback(struct lbs_private *priv) | 182 | void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count) |
183 | { | 183 | { |
184 | struct tx_radiotap_hdr *radiotap_hdr; | 184 | struct tx_radiotap_hdr *radiotap_hdr; |
185 | u32 status = priv->eventcause; | ||
186 | int txfail; | ||
187 | int try_count; | ||
188 | 185 | ||
189 | if (!priv->monitormode || priv->currenttxskb == NULL) | 186 | if (!priv->monitormode || priv->currenttxskb == NULL) |
190 | return; | 187 | return; |
191 | 188 | ||
192 | radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data; | 189 | radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data; |
193 | 190 | ||
194 | txfail = (status >> 24); | 191 | radiotap_hdr->data_retries = try_count ? |
195 | 192 | (1 + priv->txretrycount - try_count) : 0; | |
196 | #if 0 | ||
197 | /* The version of roofnet that we've tested does not use this yet | ||
198 | * But it may be used in the future. | ||
199 | */ | ||
200 | if (txfail) | ||
201 | radiotap_hdr->flags &= IEEE80211_RADIOTAP_F_TX_FAIL; | ||
202 | #endif | ||
203 | try_count = (status >> 16) & 0xff; | ||
204 | radiotap_hdr->data_retries = (try_count) ? | ||
205 | (1 + priv->txretrycount - try_count) : 0; | ||
206 | |||
207 | 193 | ||
208 | priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb, | 194 | priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb, |
209 | priv->rtap_net_dev); | 195 | priv->rtap_net_dev); |