diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2011-07-07 07:59:02 -0700 |
---|---|---|
committer | Wey-Yi Guy <wey-yi.w.guy@intel.com> | 2011-07-16 07:37:06 -0700 |
commit | 1ab9f6c11b003d086ae4890ea202cc3c66f5a17a (patch) | |
tree | 36296b54edf0e3d8ee2b2c671d730b4de1f215e0 /drivers/net/wireless/iwlwifi/iwl-rx.c | |
parent | a27367d25da06c24e0379ad4489542016ff11dbb (diff) |
iwlagn: move the Rx dispatching to the upper layer
The upper layer receives a pointer to an iwl_rx_mem_buffer. I would prefer the
upper layer to receive a pointer to an iwl_rx_packet, but this is impossible
since the Rx path needs to add the address of the page to the skb.
I may find a solution later.
All the pre_rx_handler and notification code has been moved to the upper layer.
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-rx.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-rx.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index f3f3efe38ce..c5eb379246f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -1105,3 +1105,49 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) /* Set up hardware specific Rx handlers */ priv->cfg->ops->lib->rx_handler_setup(priv); } + +void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + + /* + * Do the notification wait before RX handlers so + * even if the RX handler consumes the RXB we have + * access to it in the notification wait entry. + */ + if (!list_empty(&priv->_agn.notif_waits)) { + struct iwl_notification_wait *w; + + spin_lock(&priv->_agn.notif_wait_lock); + list_for_each_entry(w, &priv->_agn.notif_waits, list) { + if (w->cmd != pkt->hdr.cmd) + continue; + IWL_DEBUG_RX(priv, + "Notif: %s, 0x%02x - wake the callers up\n", + get_cmd_string(pkt->hdr.cmd), + pkt->hdr.cmd); + w->triggered = true; + if (w->fn) + w->fn(priv, pkt, w->fn_data); + } + spin_unlock(&priv->_agn.notif_wait_lock); + + wake_up_all(&priv->_agn.notif_waitq); + } + + if (priv->pre_rx_handler) + priv->pre_rx_handler(priv, rxb); + + /* Based on type of command response or notification, + * handle those that need handling via function in + * rx_handlers table. See iwl_setup_rx_handlers() */ + if (priv->rx_handlers[pkt->hdr.cmd]) { + priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; + priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); + } else { + /* No handling needed */ + IWL_DEBUG_RX(priv, + "No handler needed for %s, 0x%02x\n", + get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); + } +} |