Commit 499b1883 authored by Tomas Winkler's avatar Tomas Winkler Committed by John W. Linville

iwlwifi: fix TX cmd dma unmapping

This patch:
1. fixes command DMA unmapping, this might be visible only
	on platforms where DMA unmapping is no noop such as PPC64 (not tested)
2. attaches correctly high memory part of the host command buffer
3. changes structure of TFD TB
	instead of describing transmit buffer (TB) tuple it describes single
	TB and makes code more readable on price of one unaligned access
4. eliminates using of IWL_GET/SET_BITs for TFD handling
5. renames TFD structures to mach the HW spec
6. reduces iwl_tx_info size by reserving first TB to the host command

This patch should not have any visible effect on x86 32

This patch is rework of
iwlwifi: fix DMA code and bugs from
Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarTomas Winkler <tomas.winkler@intel.com>
Cc: Johannes Berg <johannes@sipsolutions.net>
Reviewed-by: default avatarZhu Yi <yi.zhu@intel.com>
Signed-off-by: default avatarReinette Chatre <reinette.chatre@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 76eff18b
...@@ -822,94 +822,62 @@ enum { ...@@ -822,94 +822,62 @@ enum {
#define IWL49_NUM_QUEUES 16 #define IWL49_NUM_QUEUES 16
#define IWL49_NUM_AMPDU_QUEUES 8 #define IWL49_NUM_AMPDU_QUEUES 8
#define IWL_TX_DMA_MASK (DMA_BIT_MASK(36) & ~0x3)
#define IWL_NUM_OF_TBS 20
static inline u8 iwl_get_dma_hi_addr(dma_addr_t addr)
{
return (sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0) & 0xF;
}
/** /**
* struct iwl_tfd_frame_data * struct iwl_tfd_tb transmit buffer descriptor within transmit frame descriptor
* *
* Describes up to 2 buffers containing (contiguous) portions of a Tx frame. * This structure contains dma address and length of transmission address
* Each buffer must be on dword boundary.
* Up to 10 iwl_tfd_frame_data structures, describing up to 20 buffers,
* may be filled within a TFD (iwl_tfd_frame).
* *
* Bit fields in tb1_addr: * @lo: low [31:0] portion of the dma address of TX buffer
* 31- 0: Tx buffer 1 address bits [31:0] * every even is unaligned on 16 bit boundary
* * @hi_n_len 0-3 [35:32] portion of dma
* Bit fields in val1: * 4-16 length of the tx buffer
* 31-16: Tx buffer 2 address bits [15:0]
* 15- 4: Tx buffer 1 length (bytes)
* 3- 0: Tx buffer 1 address bits [32:32]
*
* Bit fields in val2:
* 31-20: Tx buffer 2 length (bytes)
* 19- 0: Tx buffer 2 address bits [35:16]
*/ */
struct iwl_tfd_frame_data { struct iwl_tfd_tb {
__le32 tb1_addr; __le32 lo;
__le16 hi_n_len;
__le32 val1; } __attribute__((packed));
/* __le32 ptb1_32_35:4; */
#define IWL_tb1_addr_hi_POS 0
#define IWL_tb1_addr_hi_LEN 4
#define IWL_tb1_addr_hi_SYM val1
/* __le32 tb_len1:12; */
#define IWL_tb1_len_POS 4
#define IWL_tb1_len_LEN 12
#define IWL_tb1_len_SYM val1
/* __le32 ptb2_0_15:16; */
#define IWL_tb2_addr_lo16_POS 16
#define IWL_tb2_addr_lo16_LEN 16
#define IWL_tb2_addr_lo16_SYM val1
__le32 val2;
/* __le32 ptb2_16_35:20; */
#define IWL_tb2_addr_hi20_POS 0
#define IWL_tb2_addr_hi20_LEN 20
#define IWL_tb2_addr_hi20_SYM val2
/* __le32 tb_len2:12; */
#define IWL_tb2_len_POS 20
#define IWL_tb2_len_LEN 12
#define IWL_tb2_len_SYM val2
} __attribute__ ((packed));
/** /**
* struct iwl_tfd_frame * struct iwl_tfd
* *
* Transmit Frame Descriptor (TFD) * Transmit Frame Descriptor (TFD)
* *
* 4965 supports up to 16 Tx queues resident in host DRAM. * @ __reserved1[3] reserved
* @ num_tbs 0-5 number of active tbs
* 6-7 padding (not used)
* @ tbs[20] transmit frame buffer descriptors
* @ __pad padding
*
* Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM. * Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM.
* Both driver and device share these circular buffers, each of which must be * Both driver and device share these circular buffers, each of which must be
* contiguous 256 TFDs x 128 bytes-per-TFD = 32 KBytes for 4965. * contiguous 256 TFDs x 128 bytes-per-TFD = 32 KBytes
* *
* Driver must indicate the physical address of the base of each * Driver must indicate the physical address of the base of each
* circular buffer via the 4965's FH_MEM_CBBC_QUEUE registers. * circular buffer via the FH_MEM_CBBC_QUEUE registers.
* *
* Each TFD contains pointer/size information for up to 20 data buffers * Each TFD contains pointer/size information for up to 20 data buffers
* in host DRAM. These buffers collectively contain the (one) frame described * in host DRAM. These buffers collectively contain the (one) frame described
* by the TFD. Each buffer must be a single contiguous block of memory within * by the TFD. Each buffer must be a single contiguous block of memory within
* itself, but buffers may be scattered in host DRAM. Each buffer has max size * itself, but buffers may be scattered in host DRAM. Each buffer has max size
* of (4K - 4). The 4965 concatenates all of a TFD's buffers into a single * of (4K - 4). The concatenates all of a TFD's buffers into a single
* Tx frame, up to 8 KBytes in size. * Tx frame, up to 8 KBytes in size.
* *
* Bit fields in the control dword (val0):
* 31-30: # dwords (0-3) of padding required at end of frame for 16-byte bound
* 29: reserved
* 28-24: # Transmit Buffer Descriptors in TFD
* 23- 0: reserved
*
* A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx. * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx.
*
* Bit fields in the control dword (val0):
*/ */
struct iwl_tfd_frame { struct iwl_tfd {
__le32 val0; u8 __reserved1[3];
/* __le32 rsvd1:24; */ u8 num_tbs;
/* __le32 num_tbs:5; */ struct iwl_tfd_tb tbs[IWL_NUM_OF_TBS];
#define IWL_num_tbs_POS 24 __le32 __pad;
#define IWL_num_tbs_LEN 5
#define IWL_num_tbs_SYM val0
/* __le32 rsvd2:1; */
/* __le32 padding:2; */
struct iwl_tfd_frame_data pa[10];
__le32 reserved;
} __attribute__ ((packed)); } __attribute__ ((packed));
......
...@@ -536,7 +536,7 @@ static int iwl5000_load_section(struct iwl_priv *priv, ...@@ -536,7 +536,7 @@ static int iwl5000_load_section(struct iwl_priv *priv,
iwl_write_direct32(priv, iwl_write_direct32(priv,
FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL),
(iwl_get_dma_hi_address(phy_addr) (iwl_get_dma_hi_addr(phy_addr)
<< FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt);
iwl_write_direct32(priv, iwl_write_direct32(priv,
......
...@@ -112,11 +112,9 @@ struct iwl_queue { ...@@ -112,11 +112,9 @@ struct iwl_queue {
* space less than this */ * space less than this */
} __attribute__ ((packed)); } __attribute__ ((packed));
#define MAX_NUM_OF_TBS (20)
/* One for each TFD */ /* One for each TFD */
struct iwl_tx_info { struct iwl_tx_info {
struct sk_buff *skb[MAX_NUM_OF_TBS]; struct sk_buff *skb[IWL_NUM_OF_TBS - 1];
}; };
/** /**
...@@ -134,7 +132,7 @@ struct iwl_tx_info { ...@@ -134,7 +132,7 @@ struct iwl_tx_info {
*/ */
struct iwl_tx_queue { struct iwl_tx_queue {
struct iwl_queue q; struct iwl_queue q;
struct iwl_tfd_frame *bd; struct iwl_tfd *tfds;
struct iwl_cmd *cmd[TFD_TX_CMD_SLOTS]; struct iwl_cmd *cmd[TFD_TX_CMD_SLOTS];
struct iwl_tx_info *txb; struct iwl_tx_info *txb;
int need_update; int need_update;
...@@ -252,7 +250,8 @@ struct iwl_cmd_meta { ...@@ -252,7 +250,8 @@ struct iwl_cmd_meta {
/* The CMD_SIZE_HUGE flag bit indicates that the command /* The CMD_SIZE_HUGE flag bit indicates that the command
* structure is stored at the end of the shared queue memory. */ * structure is stored at the end of the shared queue memory. */
u32 flags; u32 flags;
DECLARE_PCI_UNMAP_ADDR(mapping)
DECLARE_PCI_UNMAP_LEN(len)
} __attribute__ ((packed)); } __attribute__ ((packed));
#define IWL_CMD_MAX_PAYLOAD 320 #define IWL_CMD_MAX_PAYLOAD 320
......
...@@ -159,11 +159,6 @@ static inline unsigned long elapsed_jiffies(unsigned long start, ...@@ -159,11 +159,6 @@ static inline unsigned long elapsed_jiffies(unsigned long start,
return end + (MAX_JIFFY_OFFSET - start) + 1; return end + (MAX_JIFFY_OFFSET - start) + 1;
} }
static inline u8 iwl_get_dma_hi_address(dma_addr_t addr)
{
return sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0;
}
/** /**
* iwl_queue_inc_wrap - increment queue index, wrap back to beginning * iwl_queue_inc_wrap - increment queue index, wrap back to beginning
* @index -- current index * @index -- current index
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment