summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/if_sdio.c
diff options
context:
space:
mode:
authorHolger Schurig <hs4233@mail.mn-solutions.de>2008-04-01 14:50:43 +0200
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)
downloadblackbird-op-linux-7919b89c8276d657976d4d4d6b7cb58ea1aa08c3.tar.gz
blackbird-op-linux-7919b89c8276d657976d4d4d6b7cb58ea1aa08c3.zip
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 {
const char *firmware;
u8 buffer[65536];
- u8 int_cause;
- u32 event;
spinlock_t lock;
struct if_sdio_packet *packets;
@@ -129,13 +127,13 @@ static u16 if_sdio_read_scratch(struct if_sdio_card *card, int *err)
static int if_sdio_handle_cmd(struct if_sdio_card *card,
u8 *buffer, unsigned size)
{
+ struct lbs_private *priv = card->priv;
int ret;
unsigned long flags;
+ u8 i;
lbs_deb_enter(LBS_DEB_SDIO);
- spin_lock_irqsave(&card->priv->driver_lock, flags);
-
if (size > LBS_CMD_BUFFER_SIZE) {
lbs_deb_sdio("response packet too large (%d bytes)\n",
(int)size);
@@ -143,20 +141,20 @@ static int if_sdio_handle_cmd(struct if_sdio_card *card,
goto out;
}
- memcpy(card->priv->upld_buf, buffer, size);
- card->priv->upld_len = size;
+ spin_lock_irqsave(&priv->driver_lock, flags);
- card->int_cause |= MRVDRV_CMD_UPLD_RDY;
+ i = (priv->resp_idx == 0) ? 1 : 0;
+ BUG_ON(priv->resp_len[i]);
+ priv->resp_len[i] = size;
+ memcpy(priv->resp_buf[i], buffer, size);
+ lbs_notify_command_response(priv, i);
- lbs_interrupt(card->priv);
+ spin_unlock_irqrestore(&card->priv->driver_lock, flags);
ret = 0;
out:
- spin_unlock_irqrestore(&card->priv->driver_lock, flags);
-
lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
-
return ret;
}
@@ -202,7 +200,6 @@ static int if_sdio_handle_event(struct if_sdio_card *card,
u8 *buffer, unsigned size)
{
int ret;
- unsigned long flags;
u32 event;
lbs_deb_enter(LBS_DEB_SDIO);
@@ -222,18 +219,9 @@ static int if_sdio_handle_event(struct if_sdio_card *card,
event |= buffer[2] << 16;
event |= buffer[1] << 8;
event |= buffer[0] << 0;
- event <<= SBI_EVENT_CAUSE_SHIFT;
}
- spin_lock_irqsave(&card->priv->driver_lock, flags);
-
- card->event = event;
- card->int_cause |= MRVDRV_CARDEVENT;
-
- lbs_interrupt(card->priv);
-
- spin_unlock_irqrestore(&card->priv->driver_lock, flags);
-
+ lbs_queue_event(card->priv, event & 0xFF);
ret = 0;
out:
@@ -770,37 +758,6 @@ out:
return ret;
}
-static int if_sdio_get_int_status(struct lbs_private *priv, u8 *ireg)
-{
- struct if_sdio_card *card;
-
- lbs_deb_enter(LBS_DEB_SDIO);
-
- card = priv->card;
-
- *ireg = card->int_cause;
- card->int_cause = 0;
-
- lbs_deb_leave(LBS_DEB_SDIO);
-
- return 0;
-}
-
-static int if_sdio_read_event_cause(struct lbs_private *priv)
-{
- struct if_sdio_card *card;
-
- lbs_deb_enter(LBS_DEB_SDIO);
-
- card = priv->card;
-
- priv->eventcause = card->event;
-
- lbs_deb_leave(LBS_DEB_SDIO);
-
- return 0;
-}
-
/*******************************************************************/
/* SDIO callbacks */
/*******************************************************************/
@@ -953,8 +910,6 @@ static int if_sdio_probe(struct sdio_func *func,
priv->card = card;
priv->hw_host_to_card = if_sdio_host_to_card;
- priv->hw_get_int_status = if_sdio_get_int_status;
- priv->hw_read_event_cause = if_sdio_read_event_cause;
priv->fw_ready = 1;
OpenPOWER on IntegriCloud