aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/if_sdio.c
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/wireless/libertas/if_sdio.c
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/wireless/libertas/if_sdio.c')
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c65
1 files changed, 10 insertions, 55 deletions
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