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/if_sdio.c | |
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/if_sdio.c')
-rw-r--r-- | drivers/net/wireless/libertas/if_sdio.c | 65 |
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) | |||
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 | ||