iwlwifi: pcie: allocate smaller dev_cmd for TX headers
As noted in the previous commit, due to the way we allocate the dev_cmd headers with 324 byte size, and 4/8 byte alignment, the part we use of them (bytes 20..40-68) could still cross a page and thus 2^32 boundary. Address this by using alignment to ensure that the allocation cannot cross a page boundary, on hardware that's affected. To make that not cause more memory consumption, reduce the size of the allocations to the necessary size - we go from 324 bytes in each allocation to 60/68 on gen2 depending on family, and ~120 or so on gen1 (so on gen1 it's a pure reduction in size, since we don't need alignment there). To avoid size and clearing issues, add a new structure that's just the header, and use kmem_cache_zalloc(). Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
This commit is contained in:

committed by
Luca Coelho

parent
c5a4e8eb68
commit
a89c72ffd0
@@ -193,6 +193,18 @@ struct iwl_device_cmd {
|
||||
};
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_device_tx_cmd - buffer for TX command
|
||||
* @hdr: the header
|
||||
* @payload: the payload placeholder
|
||||
*
|
||||
* The actual structure is sized dynamically according to need.
|
||||
*/
|
||||
struct iwl_device_tx_cmd {
|
||||
struct iwl_cmd_header hdr;
|
||||
u8 payload[];
|
||||
} __packed;
|
||||
|
||||
#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd))
|
||||
|
||||
/*
|
||||
@@ -544,7 +556,7 @@ struct iwl_trans_ops {
|
||||
int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
|
||||
|
||||
int (*tx)(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
struct iwl_device_cmd *dev_cmd, int queue);
|
||||
struct iwl_device_tx_cmd *dev_cmd, int queue);
|
||||
void (*reclaim)(struct iwl_trans *trans, int queue, int ssn,
|
||||
struct sk_buff_head *skbs);
|
||||
|
||||
@@ -948,22 +960,22 @@ iwl_trans_dump_data(struct iwl_trans *trans, u32 dump_mask)
|
||||
return trans->ops->dump_data(trans, dump_mask);
|
||||
}
|
||||
|
||||
static inline struct iwl_device_cmd *
|
||||
static inline struct iwl_device_tx_cmd *
|
||||
iwl_trans_alloc_tx_cmd(struct iwl_trans *trans)
|
||||
{
|
||||
return kmem_cache_alloc(trans->dev_cmd_pool, GFP_ATOMIC);
|
||||
return kmem_cache_zalloc(trans->dev_cmd_pool, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
|
||||
|
||||
static inline void iwl_trans_free_tx_cmd(struct iwl_trans *trans,
|
||||
struct iwl_device_cmd *dev_cmd)
|
||||
struct iwl_device_tx_cmd *dev_cmd)
|
||||
{
|
||||
kmem_cache_free(trans->dev_cmd_pool, dev_cmd);
|
||||
}
|
||||
|
||||
static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
struct iwl_device_cmd *dev_cmd, int queue)
|
||||
struct iwl_device_tx_cmd *dev_cmd, int queue)
|
||||
{
|
||||
if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status)))
|
||||
return -EIO;
|
||||
@@ -1271,7 +1283,9 @@ static inline bool iwl_trans_dbg_ini_valid(struct iwl_trans *trans)
|
||||
*****************************************************/
|
||||
struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
|
||||
struct device *dev,
|
||||
const struct iwl_trans_ops *ops);
|
||||
const struct iwl_trans_ops *ops,
|
||||
unsigned int cmd_pool_size,
|
||||
unsigned int cmd_pool_align);
|
||||
void iwl_trans_free(struct iwl_trans *trans);
|
||||
|
||||
/*****************************************************
|
||||
|
Reference in New Issue
Block a user