• Johannes Berg's avatar
    iwlwifi: pcie: rework RX buffer list init and freeing · c7df1f4b
    Johannes Berg authored
    The PCIe code has an array of buffer descriptors (RXBs) that have pages
    and DMA mappings attached. In regular use, the array isn't used and the
    buffers are either on the hardware receive queue or the rx_free/rx_used
    lists for recycling.
    
    Occasionally, during module unload, we'd see a warning from this:
    
    WARNING: at lib/list_debug.c:32 __list_add+0x91/0xa0()
    list_add corruption. prev->next should be next (c31c98cc), but was c31c80bc. (prev=c31c80bc).
    Pid: 519, comm: rmmod Tainted: G        W  O 3.4.24-dev #3
    Call Trace:
     [<c10335b2>] warn_slowpath_common+0x72/0xa0
     [<c1033683>] warn_slowpath_fmt+0x33/0x40
     [<c12e31d1>] __list_add+0x91/0xa0
     [<fdf2083c>] iwl_pcie_rxq_free_rbs+0xcc/0xe0 [iwlwifi]
     [<fdf21b3f>] iwl_pcie_rx_free+0x3f/0x210 [iwlwifi]
     [<fdf2dd7a>] iwl_trans_pcie_free+0x2a/0x90 [iwlwifi]
    
    The reason for this seems to be that in iwl_pcie_rxq_free_rbs() we use
    the array to free all buffers (the hardware receive queue isn't in use
    any more at this point). The function also adds all buffers to rx_used
    because it's also used during initialisation (when no freeing happens.)
    This can cause the warning because it may add entries to the list that
    are already on it. Luckily, this is harmless because it can only happen
    when the entire data structure is freed anyway, since during init both
    lists are initialized from scratch.
    
    Disentangle this code and treat init and free separately. During init
    we just need to put them onto the list after freeing all buffers (for
    switching between 4k/8k buffers); during free no list manipulations
    are necessary at all.
    Reviewed-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
    Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
    c7df1f4b
rx.c 39.4 KB