aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-trans.h
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-03-15 16:26:43 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-04-09 16:37:14 -0400
commit0c19744c344cf1bfda04f681ff4e1e46455577bd (patch)
treed6351ac483da68ca9bfe46df5642dccef313f17a /drivers/net/wireless/iwlwifi/iwl-trans.h
parent88f10a176c7364a700c8638732e2b3110beaceb6 (diff)
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 {
162 162
163 163
164#define FH_RSCSR_FRAME_SIZE_MSK 0x00003FFF /* bits 0-13 */ 164#define FH_RSCSR_FRAME_SIZE_MSK 0x00003FFF /* bits 0-13 */
165#define FH_RSCSR_FRAME_INVALID 0x55550000
166#define FH_RSCSR_FRAME_ALIGN 0x40
165 167
166struct iwl_rx_packet { 168struct iwl_rx_packet {
167 /* 169 /*
@@ -260,18 +262,25 @@ static inline void iwl_free_resp(struct iwl_host_cmd *cmd)
260 262
261struct iwl_rx_cmd_buffer { 263struct iwl_rx_cmd_buffer {
262 struct page *_page; 264 struct page *_page;
265 int _offset;
266 bool _page_stolen;
263}; 267};
264 268
265static inline void *rxb_addr(struct iwl_rx_cmd_buffer *r) 269static inline void *rxb_addr(struct iwl_rx_cmd_buffer *r)
266{ 270{
267 return page_address(r->_page); 271 return (void *)((unsigned long)page_address(r->_page) + r->_offset);
272}
273
274static inline int rxb_offset(struct iwl_rx_cmd_buffer *r)
275{
276 return r->_offset;
268} 277}
269 278
270static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r) 279static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r)
271{ 280{
272 struct page *p = r->_page; 281 r->_page_stolen = true;
273 r->_page = NULL; 282 get_page(r->_page);
274 return p; 283 return r->_page;
275} 284}
276 285
277#define MAX_NO_RECLAIM_CMDS 6 286#define MAX_NO_RECLAIM_CMDS 6