summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-trans.h
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-03-15 21:26:43 +0100
committerJohn W. Linville <linville@tuxdriver.com>2012-04-09 22:37:14 +0200
commit0c19744c344cf1bfda04f681ff4e1e46455577bd (patch)
treed6351ac483da68ca9bfe46df5642dccef313f17a /drivers/net/wireless/iwlwifi/iwl-trans.h
parentiwlwifi: remove un-needed parameter (diff)
downloadlinux-0c19744c344cf1bfda04f681ff4e1e46455577bd.tar.xz
linux-0c19744c344cf1bfda04f681ff4e1e46455577bd.zip
iwlwifi: process multiple frames per RXB
The flow handler (hardware) can put multiple frames into a single RX buffer. To handle this, walk the RX buffer and check if there are multiple valid packets in it. To let the upper layer handle this correctly introduce rxb_offset() which is needed when we pass pages to mac80211 -- we need to know the offset into the page there. Also change the page handling scheme to use refcounting. Anyone who needs a page will "steal" it, which marks it as having been used & refcounts it. The RX handler then has to free its own reference and must not reuse the page. Finally, do not set the bit asking the FH to give us each packet in a single buffer. This really enables the feature. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-trans.h')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h17
1 files changed, 13 insertions, 4 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 0c81cbaa8088..57d8ae7b7ba9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -162,6 +162,8 @@ struct iwl_cmd_header {
#define FH_RSCSR_FRAME_SIZE_MSK 0x00003FFF /* bits 0-13 */
+#define FH_RSCSR_FRAME_INVALID 0x55550000
+#define FH_RSCSR_FRAME_ALIGN 0x40
struct iwl_rx_packet {
/*
@@ -260,18 +262,25 @@ static inline void iwl_free_resp(struct iwl_host_cmd *cmd)
struct iwl_rx_cmd_buffer {
struct page *_page;
+ int _offset;
+ bool _page_stolen;
};
static inline void *rxb_addr(struct iwl_rx_cmd_buffer *r)
{
- return page_address(r->_page);
+ return (void *)((unsigned long)page_address(r->_page) + r->_offset);
+}
+
+static inline int rxb_offset(struct iwl_rx_cmd_buffer *r)
+{
+ return r->_offset;
}
static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r)
{
- struct page *p = r->_page;
- r->_page = NULL;
- return p;
+ r->_page_stolen = true;
+ get_page(r->_page);
+ return r->_page;
}
#define MAX_NO_RECLAIM_CMDS 6