From 7919b89c8276d657976d4d4d6b7cb58ea1aa08c3 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Tue, 1 Apr 2008 14:50:43 +0200 Subject: 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 Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_usb.c | 71 ++++++++++------------------------ 1 file changed, 21 insertions(+), 50 deletions(-) (limited to 'drivers/net/wireless/libertas/if_usb.c') 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); static int if_usb_prog_firmware(struct if_usb_card *cardp); static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, uint8_t *payload, uint16_t nb); -static int if_usb_get_int_status(struct lbs_private *priv, uint8_t *); -static int if_usb_read_event_cause(struct lbs_private *); static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb); static void if_usb_free(struct if_usb_card *cardp); @@ -233,8 +231,6 @@ static int if_usb_probe(struct usb_interface *intf, cardp->priv->fw_ready = 1; priv->hw_host_to_card = if_usb_host_to_card; - priv->hw_get_int_status = if_usb_get_int_status; - priv->hw_read_event_cause = if_usb_read_event_cause; cardp->boot2_version = udev->descriptor.bcdDevice; if_usb_submit_rx_urb(cardp); @@ -582,7 +578,6 @@ static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb, skb_pull(skb, MESSAGE_HEADER_LEN); lbs_process_rxed_packet(priv, skb); - priv->upld_len = (recvlength - MESSAGE_HEADER_LEN); } static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, @@ -590,6 +585,8 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, struct if_usb_card *cardp, struct lbs_private *priv) { + u8 i; + if (recvlength > LBS_CMD_BUFFER_SIZE) { lbs_deb_usbd(&cardp->udev->dev, "The receive buffer is too large\n"); @@ -601,12 +598,15 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, BUG(); spin_lock(&priv->driver_lock); - cardp->usb_int_cause |= MRVDRV_CMD_UPLD_RDY; - priv->upld_len = (recvlength - MESSAGE_HEADER_LEN); - memcpy(priv->upld_buf, recvbuff + MESSAGE_HEADER_LEN, priv->upld_len); + i = (priv->resp_idx == 0) ? 1 : 0; + BUG_ON(priv->resp_len[i]); + priv->resp_len[i] = (recvlength - MESSAGE_HEADER_LEN); + memcpy(priv->resp_buf[i], recvbuff + MESSAGE_HEADER_LEN, + priv->resp_len[i]); kfree_skb(skb); - lbs_interrupt(priv); + lbs_notify_command_response(priv, i); + spin_unlock(&priv->driver_lock); lbs_deb_usbd(&cardp->udev->dev, @@ -629,6 +629,7 @@ static void if_usb_receive(struct urb *urb) uint8_t *recvbuff = NULL; uint32_t recvtype = 0; __le32 *pkt = (__le32 *)(skb->data + IPFIELD_ALIGN_OFFSET); + uint32_t event; lbs_deb_enter(LBS_DEB_USB); @@ -660,26 +661,20 @@ static void if_usb_receive(struct urb *urb) break; case CMD_TYPE_INDICATION: - /* Event cause handling */ - spin_lock(&priv->driver_lock); + /* Event handling */ + event = le32_to_cpu(pkt[1]); + lbs_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", event); + kfree_skb(skb); - cardp->usb_event_cause = le32_to_cpu(pkt[1]); + /* Icky undocumented magic special case */ + if (event & 0xffff0000) { + u32 trycount = (event & 0xffff0000) >> 16; - lbs_deb_usbd(&cardp->udev->dev,"**EVENT** 0x%X\n", - cardp->usb_event_cause); + lbs_send_tx_feedback(priv, trycount); + } else + lbs_queue_event(priv, event & 0xFF); + break; - /* Icky undocumented magic special case */ - if (cardp->usb_event_cause & 0xffff0000) { - lbs_send_tx_feedback(priv); - spin_unlock(&priv->driver_lock); - break; - } - cardp->usb_event_cause <<= 3; - cardp->usb_int_cause |= MRVDRV_CARDEVENT; - kfree_skb(skb); - lbs_interrupt(priv); - spin_unlock(&priv->driver_lock); - goto rx_exit; default: lbs_deb_usbd(&cardp->udev->dev, "Unknown command type 0x%X\n", recvtype); @@ -722,30 +717,6 @@ static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, return usb_tx_block(cardp, cardp->ep_out_buf, nb + MESSAGE_HEADER_LEN); } -/* called with priv->driver_lock held */ -static int if_usb_get_int_status(struct lbs_private *priv, uint8_t *ireg) -{ - struct if_usb_card *cardp = priv->card; - - *ireg = cardp->usb_int_cause; - cardp->usb_int_cause = 0; - - lbs_deb_usbd(&cardp->udev->dev, "Int cause is 0x%X\n", *ireg); - - return 0; -} - -static int if_usb_read_event_cause(struct lbs_private *priv) -{ - struct if_usb_card *cardp = priv->card; - - priv->eventcause = cardp->usb_event_cause; - /* Re-submit rx urb here to avoid event lost issue */ - if_usb_submit_rx_urb(cardp); - - return 0; -} - /** * @brief This function issues Boot command to the Boot2 code * @param ivalue 1:Boot from FW by USB-Download -- cgit v1.2.3