• Dan Williams's avatar
    acpi, nfit: Fix Address Range Scrub completion tracking · d3abaf43
    Dan Williams authored
    The Address Range Scrub implementation tried to skip running scrubs
    against ranges that were already scrubbed by the BIOS. Unfortunately
    that support also resulted in early scrub completions as evidenced by
    this debug output from nfit_test:
    
        nd_region region9: ARS: range 1 short complete
        nd_region region3: ARS: range 1 short complete
        nd_region region4: ARS: range 2 ARS start (0)
        nd_region region4: ARS: range 2 short complete
    
    ...i.e. completions without any indications that the scrub was started.
    
    This state of affairs was hard to see in the code due to the
    proliferation of state bits and mistakenly trying to track done state
    per-range when the completion is a global property of the bus.
    
    So, kill the four ARS state bits (ARS_REQ, ARS_REQ_REDO, ARS_DONE, and
    ARS_SHORT), and replace them with just 2 request flags ARS_REQ_SHORT and
    ARS_REQ_LONG. The implementation will still complete and reap the
    results of BIOS initiated ARS, but it will not attempt to use that
    information to affect the completion status of scrubbing the ranges from
    a Linux perspective.
    
    Instead, try to synchronously run a short ARS per range at init time and
    schedule a long scrub in the background. If ARS is busy with an ARS
    request, schedule both a short and a long scrub for when ARS returns to
    idle. This logic also satisfies the intent of what ARS_REQ_REDO was
    trying to achieve. The new rule is that the REQ flag stays set until the
    next successful ars_start() for that range.
    
    With the new policy that the REQ flags are not cleared until the next
    start, the implementation no longer loses requests as can be seen from
    the following log:
    
        nd_region region3: ARS: range 1 ARS start short (0)
        nd_region region9: ARS: range 1 ARS start short (0)
        nd_region region3: ARS: range 1 complete
        nd_region region4: ARS: range 2 ARS start short (0)
        nd_region region9: ARS: range 1 complete
        nd_region region9: ARS: range 1 ARS start long (0)
        nd_region region4: ARS: range 2 complete
        nd_region region3: ARS: range 1 ARS start long (0)
        nd_region region9: ARS: range 1 complete
        nd_region region3: ARS: range 1 complete
        nd_region region4: ARS: range 2 ARS start long (0)
        nd_region region4: ARS: range 2 complete
    
    ...note that the nfit_test emulated driver provides 2 buses, that is why
    some of the range indices are duplicated. Notice that each range
    now successfully completes a short and long scrub.
    
    Cc: <stable@vger.kernel.org>
    Fixes: 14c73f99 ("nfit, address-range-scrub: introduce nfit_spa->ars_state")
    Fixes: cc3d3458 ("acpi/nfit: queue issuing of ars when an uc error...")
    Reported-by: default avatarJacek Zloch <jacek.zloch@intel.com>
    Reported-by: default avatarKrzysztof Rusocki <krzysztof.rusocki@intel.com>
    Reviewed-by: default avatarDave Jiang <dave.jiang@intel.com>
    Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
    d3abaf43
nfit.h 7.97 KB