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>
This commit is contained in:
committed by
John W. Linville
parent
98dd6a5759
commit
7919b89c82
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
#include <net/iw_handler.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include "host.h"
|
||||
#include "hostcmd.h"
|
||||
#include "decl.h"
|
||||
@@ -1829,15 +1830,20 @@ static void lbs_send_confirmsleep(struct lbs_private *priv)
|
||||
|
||||
ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep,
|
||||
sizeof(confirm_sleep));
|
||||
|
||||
if (ret) {
|
||||
lbs_pr_alert("confirm_sleep failed\n");
|
||||
} else {
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
if (!priv->intcounter)
|
||||
priv->psstate = PS_STATE_SLEEP;
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
|
||||
/* If nothing to do, go back to sleep (?) */
|
||||
if (!__kfifo_len(priv->event_fifo) && !priv->resp_len[priv->resp_idx])
|
||||
priv->psstate = PS_STATE_SLEEP;
|
||||
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
|
||||
out:
|
||||
lbs_deb_leave(LBS_DEB_HOST);
|
||||
}
|
||||
|
||||
@@ -1899,13 +1905,16 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv)
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
/* In-progress command? */
|
||||
if (priv->cur_cmd) {
|
||||
allowed = 0;
|
||||
lbs_deb_host("cur_cmd was set\n");
|
||||
}
|
||||
if (priv->intcounter > 0) {
|
||||
|
||||
/* Pending events or command responses? */
|
||||
if (__kfifo_len(priv->event_fifo) || priv->resp_len[priv->resp_idx]) {
|
||||
allowed = 0;
|
||||
lbs_deb_host("intcounter %d\n", priv->intcounter);
|
||||
lbs_deb_host("pending events or command responses\n");
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
|
||||
|
Reference in New Issue
Block a user