mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 17:30:02 +00:00
iwlagn: fix (remove) use of PAGE_SIZE
The ICT code erroneously uses PAGE_SIZE. The bug is that PAGE_SIZE isn't necessarily 4096, so on such platforms this code will not work correctly as we'll try to attempt to read an index in the table that the device never wrote, it always has 4096-byte pages. Additionally, the manual alignment code here is unnecessary -- Documentation/DMA-API-HOWTO.txt states: The cpu return address and the DMA bus master address are both guaranteed to be aligned to the smallest PAGE_SIZE order which is greater than or equal to the requested size. This invariant exists (for example) to guarantee that if you allocate a chunk which is smaller than or equal to 64 kilobytes, the extent of the buffer you receive will not cross a 64K boundary. Just use appropriate new constants and get rid of the alignment code. Cc: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Cc: stable@vger.kernel.org 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>
This commit is contained in:
parent
3ac44670ad
commit
106671369e
2 changed files with 31 additions and 44 deletions
|
@ -219,9 +219,7 @@ struct iwl_trans_pcie {
|
|||
|
||||
/* INT ICT Table */
|
||||
__le32 *ict_tbl;
|
||||
void *ict_tbl_vir;
|
||||
dma_addr_t ict_tbl_dma;
|
||||
dma_addr_t aligned_ict_tbl_dma;
|
||||
int ict_index;
|
||||
u32 inta;
|
||||
bool use_ict;
|
||||
|
|
|
@ -1151,7 +1151,11 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
|
|||
* ICT functions
|
||||
*
|
||||
******************************************************************************/
|
||||
#define ICT_COUNT (PAGE_SIZE/sizeof(u32))
|
||||
|
||||
/* a device (PCI-E) page is 4096 bytes long */
|
||||
#define ICT_SHIFT 12
|
||||
#define ICT_SIZE (1 << ICT_SHIFT)
|
||||
#define ICT_COUNT (ICT_SIZE / sizeof(u32))
|
||||
|
||||
/* Free dram table */
|
||||
void iwl_free_isr_ict(struct iwl_trans *trans)
|
||||
|
@ -1159,21 +1163,19 @@ void iwl_free_isr_ict(struct iwl_trans *trans)
|
|||
struct iwl_trans_pcie *trans_pcie =
|
||||
IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
if (trans_pcie->ict_tbl_vir) {
|
||||
dma_free_coherent(bus(trans)->dev,
|
||||
(sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
|
||||
trans_pcie->ict_tbl_vir,
|
||||
if (trans_pcie->ict_tbl) {
|
||||
dma_free_coherent(bus(trans)->dev, ICT_SIZE,
|
||||
trans_pcie->ict_tbl,
|
||||
trans_pcie->ict_tbl_dma);
|
||||
trans_pcie->ict_tbl_vir = NULL;
|
||||
memset(&trans_pcie->ict_tbl_dma, 0,
|
||||
sizeof(trans_pcie->ict_tbl_dma));
|
||||
memset(&trans_pcie->aligned_ict_tbl_dma, 0,
|
||||
sizeof(trans_pcie->aligned_ict_tbl_dma));
|
||||
trans_pcie->ict_tbl = NULL;
|
||||
trans_pcie->ict_tbl_dma = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* allocate dram shared table it is a PAGE_SIZE aligned
|
||||
/*
|
||||
* allocate dram shared table, it is an aligned memory
|
||||
* block of ICT_SIZE.
|
||||
* also reset all data related to ICT table interrupt.
|
||||
*/
|
||||
int iwl_alloc_isr_ict(struct iwl_trans *trans)
|
||||
|
@ -1181,36 +1183,26 @@ int iwl_alloc_isr_ict(struct iwl_trans *trans)
|
|||
struct iwl_trans_pcie *trans_pcie =
|
||||
IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
/* allocate shrared data table */
|
||||
trans_pcie->ict_tbl_vir =
|
||||
dma_alloc_coherent(bus(trans)->dev,
|
||||
(sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
|
||||
&trans_pcie->ict_tbl_dma, GFP_KERNEL);
|
||||
if (!trans_pcie->ict_tbl_vir)
|
||||
trans_pcie->ict_tbl =
|
||||
dma_alloc_coherent(bus(trans)->dev, ICT_SIZE,
|
||||
&trans_pcie->ict_tbl_dma,
|
||||
GFP_KERNEL);
|
||||
if (!trans_pcie->ict_tbl)
|
||||
return -ENOMEM;
|
||||
|
||||
/* align table to PAGE_SIZE boundary */
|
||||
trans_pcie->aligned_ict_tbl_dma =
|
||||
ALIGN(trans_pcie->ict_tbl_dma, PAGE_SIZE);
|
||||
/* just an API sanity check ... it is guaranteed to be aligned */
|
||||
if (WARN_ON(trans_pcie->ict_tbl_dma & (ICT_SIZE - 1))) {
|
||||
iwl_free_isr_ict(trans);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
IWL_DEBUG_ISR(trans, "ict dma addr %Lx dma aligned %Lx diff %d\n",
|
||||
(unsigned long long)trans_pcie->ict_tbl_dma,
|
||||
(unsigned long long)trans_pcie->aligned_ict_tbl_dma,
|
||||
(int)(trans_pcie->aligned_ict_tbl_dma -
|
||||
trans_pcie->ict_tbl_dma));
|
||||
IWL_DEBUG_ISR(trans, "ict dma addr %Lx\n",
|
||||
(unsigned long long)trans_pcie->ict_tbl_dma);
|
||||
|
||||
trans_pcie->ict_tbl = trans_pcie->ict_tbl_vir +
|
||||
(trans_pcie->aligned_ict_tbl_dma -
|
||||
trans_pcie->ict_tbl_dma);
|
||||
|
||||
IWL_DEBUG_ISR(trans, "ict vir addr %p vir aligned %p diff %d\n",
|
||||
trans_pcie->ict_tbl, trans_pcie->ict_tbl_vir,
|
||||
(int)(trans_pcie->aligned_ict_tbl_dma -
|
||||
trans_pcie->ict_tbl_dma));
|
||||
IWL_DEBUG_ISR(trans, "ict vir addr %p\n", trans_pcie->ict_tbl);
|
||||
|
||||
/* reset table and index to all 0 */
|
||||
memset(trans_pcie->ict_tbl_vir, 0,
|
||||
(sizeof(u32) * ICT_COUNT) + PAGE_SIZE);
|
||||
memset(trans_pcie->ict_tbl, 0, ICT_SIZE);
|
||||
trans_pcie->ict_index = 0;
|
||||
|
||||
/* add periodic RX interrupt */
|
||||
|
@ -1228,23 +1220,20 @@ int iwl_reset_ict(struct iwl_trans *trans)
|
|||
struct iwl_trans_pcie *trans_pcie =
|
||||
IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
if (!trans_pcie->ict_tbl_vir)
|
||||
if (!trans_pcie->ict_tbl)
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&trans->shrd->lock, flags);
|
||||
iwl_disable_interrupts(trans);
|
||||
|
||||
memset(&trans_pcie->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT);
|
||||
memset(trans_pcie->ict_tbl, 0, ICT_SIZE);
|
||||
|
||||
val = trans_pcie->aligned_ict_tbl_dma >> PAGE_SHIFT;
|
||||
val = trans_pcie->ict_tbl_dma >> ICT_SHIFT;
|
||||
|
||||
val |= CSR_DRAM_INT_TBL_ENABLE;
|
||||
val |= CSR_DRAM_INIT_TBL_WRAP_CHECK;
|
||||
|
||||
IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%X "
|
||||
"aligned dma address %Lx\n",
|
||||
val,
|
||||
(unsigned long long)trans_pcie->aligned_ict_tbl_dma);
|
||||
IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%x\n", val);
|
||||
|
||||
iwl_write32(bus(trans), CSR_DRAM_INT_TBL_REG, val);
|
||||
trans_pcie->use_ict = true;
|
||||
|
|
Loading…
Reference in a new issue