diff options
author | Gaurav Batra <gbatra@linux.vnet.ibm.com> | 2023-05-25 17:34:54 +0300 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2023-05-30 09:33:10 +0300 |
commit | 9d2ccf00bddc268045e3d65a8108d61ada0e4b4e (patch) | |
tree | c5910fc79f5efb0cc11c2a285f34dc4d1092cc95 /arch/powerpc/platforms/pseries | |
parent | 81d358b118dc364bd147432db569d4d400a5a4f2 (diff) | |
download | linux-9d2ccf00bddc268045e3d65a8108d61ada0e4b4e.tar.xz |
powerpc/iommu: Limit number of TCEs to 512 for H_STUFF_TCE hcall
Currently in tce_freemulti_pSeriesLP() there is no limit on how many
TCEs are passed to the H_STUFF_TCE hcall. This has not caused an issue
until now, but newer firmware releases have started enforcing a limit of
512 TCEs per call.
The limit is correct per the specification (PAPR v2.12 ยง 14.5.4.2.3).
The code has been in it's current form since it was initially merged.
Cc: stable@vger.kernel.org
Signed-off-by: Gaurav Batra <gbatra@linux.vnet.ibm.com>
Reviewed-by: Brian King <brking@linux.vnet.ibm.com>
[mpe: Tweak change log wording & add PAPR reference]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20230525143454.56878-1-gbatra@linux.vnet.ibm.com
Diffstat (limited to 'arch/powerpc/platforms/pseries')
-rw-r--r-- | arch/powerpc/platforms/pseries/iommu.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 918f511837db..d59e8a98a200 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -317,13 +317,22 @@ static void tce_free_pSeriesLP(unsigned long liobn, long tcenum, long tceshift, static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages) { u64 rc; + long rpages = npages; + unsigned long limit; if (!firmware_has_feature(FW_FEATURE_STUFF_TCE)) return tce_free_pSeriesLP(tbl->it_index, tcenum, tbl->it_page_shift, npages); - rc = plpar_tce_stuff((u64)tbl->it_index, - (u64)tcenum << tbl->it_page_shift, 0, npages); + do { + limit = min_t(unsigned long, rpages, 512); + + rc = plpar_tce_stuff((u64)tbl->it_index, + (u64)tcenum << tbl->it_page_shift, 0, limit); + + rpages -= limit; + tcenum += limit; + } while (rpages > 0 && !rc); if (rc && printk_ratelimit()) { printk("tce_freemulti_pSeriesLP: plpar_tce_stuff failed\n"); |