aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorHolger Schurig <hs4233@mail.mn-solutions.de>2008-04-01 08:50:43 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-04-16 15:59:56 -0400
commit7919b89c8276d657976d4d4d6b7cb58ea1aa08c3 (patch)
tree31fc24e2f8b7d8eeee67347333e078591796d4b7 /drivers/net
parent98dd6a575928ed9c42130d208e6bfb0f7a914d5a (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')
-rw-r--r--drivers/net/wireless/libertas/cmd.c25
-rw-r--r--drivers/net/wireless/libertas/cmdresp.c23
-rw-r--r--drivers/net/wireless/libertas/debugfs.c1
-rw-r--r--drivers/net/wireless/libertas/decl.h10
-rw-r--r--drivers/net/wireless/libertas/defs.h2
-rw-r--r--drivers/net/wireless/libertas/dev.h27
-rw-r--r--drivers/net/wireless/libertas/if_cs.c244
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c65
-rw-r--r--drivers/net/wireless/libertas/if_usb.c71
-rw-r--r--drivers/net/wireless/libertas/if_usb.h2
-rw-r--r--drivers/net/wireless/libertas/main.c158
-rw-r--r--drivers/net/wireless/libertas/rx.c4
-rw-r--r--drivers/net/wireless/libertas/tx.c20
13 files changed, 269 insertions, 383 deletions
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 4a82f5114ca0..49267ed7cea3 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
1846out:
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 245d3c3a9274..5abecb7673e6 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
387int lbs_process_rx_command(struct lbs_private *priv) 387int 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
572int lbs_process_event(struct lbs_private *priv) 572int 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 7072e26b42d9..ad2fabca9116 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 */
826static struct debug_data items[] = { 826static 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 4aea421f07ce..b652fa301e19 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
20void lbs_set_mac_control(struct lbs_private *priv); 20void lbs_set_mac_control(struct lbs_private *priv);
21 21
22void lbs_send_tx_feedback(struct lbs_private *priv); 22void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count);
23 23
24int lbs_free_cmd_buffer(struct lbs_private *priv); 24int 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
31int lbs_allocate_cmd_buffer(struct lbs_private *priv); 31int lbs_allocate_cmd_buffer(struct lbs_private *priv);
32int lbs_execute_next_command(struct lbs_private *priv); 32int lbs_execute_next_command(struct lbs_private *priv);
33int lbs_process_event(struct lbs_private *priv); 33int lbs_process_event(struct lbs_private *priv, u32 event);
34void lbs_interrupt(struct lbs_private *priv); 34void lbs_queue_event(struct lbs_private *priv, u32 event);
35void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
36
35int lbs_set_radio_control(struct lbs_private *priv); 37int lbs_set_radio_control(struct lbs_private *priv);
36u32 lbs_fw_index_to_data_rate(u8 index); 38u32 lbs_fw_index_to_data_rate(u8 index);
37u8 lbs_data_rate_to_fw_index(u32 rate); 39u8 lbs_data_rate_to_fw_index(u32 rate);
38 40
39/** The proc fs interface */ 41/** The proc fs interface */
40int lbs_process_rx_command(struct lbs_private *priv); 42int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len);
41void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, 43void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
42 int result); 44 int result);
43int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev); 45int 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 84e8de5e21da..d39520111062 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 1e6bae80396b..0d9edb9b11f5 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 53afebac7146..54280e292ea5 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}
89static inline unsigned int if_cs_read16(struct if_cs_card *card, uint reg) 89static 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}
96static inline void if_cs_read16_rep( 96static 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(
108static inline void if_cs_write8(struct if_cs_card *card, uint reg, u8 val) 108static 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
115static inline void if_cs_write16(struct if_cs_card *card, uint reg, u16 val) 115static 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
232static 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
238static 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
244static 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 */
352static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len) 292static 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
381out: 328out:
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
376static 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
382static 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
389static 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
645static 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
665sbi_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
685out:
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
691static 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 eed73204bcc9..51f664bbee9d 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)
129static int if_sdio_handle_cmd(struct if_sdio_card *card, 127static 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
155out: 156out:
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
239out: 227out:
@@ -770,37 +758,6 @@ out:
770 return ret; 758 return ret;
771} 759}
772 760
773static 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
789static 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 75aed9d07367..8032df72aaab 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);
38static int if_usb_prog_firmware(struct if_usb_card *cardp); 38static int if_usb_prog_firmware(struct if_usb_card *cardp);
39static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, 39static 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);
41static int if_usb_get_int_status(struct lbs_private *priv, uint8_t *);
42static int if_usb_read_event_cause(struct lbs_private *);
43static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, 41static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
44 uint16_t nb); 42 uint16_t nb);
45static void if_usb_free(struct if_usb_card *cardp); 43static 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
588static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, 583static 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 */
726static 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
738static 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 e4829a391eb9..5771a83a43f0 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 8f1122610974..406f54d40956 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
1052out: 1054out:
@@ -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/** 1441void 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)
1445void 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}
1458EXPORT_SYMBOL_GPL(lbs_queue_event);
1459
1460void 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}
1457EXPORT_SYMBOL_GPL(lbs_interrupt); 1475EXPORT_SYMBOL_GPL(lbs_notify_command_response);
1458 1476
1459static int __init lbs_init_module(void) 1477static 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 09f023089ea4..05af7316f698 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 77f1f9525b81..a4972fed2941 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 */
182void lbs_send_tx_feedback(struct lbs_private *priv) 182void 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);