lkml.org 
[lkml]   [2012]   [Jan]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[17/49] iwlagn: fix (remove) use of PAGE_SIZE
    3.2-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Johannes Berg <johannes.berg@intel.com>

    commit 106671369e6d046c0b3e1e72b18ad6dd9cb298b0 upstream.

    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>
    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>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

    ---
    drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | 2
    drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 77 +++++++++-------------
    2 files changed, 33 insertions(+), 46 deletions(-)

    --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
    +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
    @@ -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;
    --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
    +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
    @@ -1136,7 +1136,11 @@ void iwl_irq_tasklet(struct iwl_trans *t
    * 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)
    @@ -1144,21 +1148,19 @@ void iwl_free_isr_ict(struct iwl_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)
    @@ -1166,36 +1168,26 @@ int iwl_alloc_isr_ict(struct iwl_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);
    -
    - 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));
    -
    - 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));
    + /* 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\n",
    + (unsigned long long)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 */
    @@ -1213,23 +1205,20 @@ int iwl_reset_ict(struct iwl_trans *tran
    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;



    \
     
     \ /
      Last update: 2012-01-11 00:15    [W:3.272 / U:0.324 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site