Signed-off-by: Aneesh Kumar K.V <aneesh.ku...@linux.vnet.ibm.com>
---
 arch/powerpc/platforms/pseries/lpar.c | 40 ++++++++++++++++++++++++++++-------
 1 file changed, 32 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/lpar.c 
b/arch/powerpc/platforms/pseries/lpar.c
index 4ea9224cbeb6..6dffdf654a28 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -684,19 +684,43 @@ static void pSeries_lpar_flush_hash_range(unsigned long 
number, int local)
        for (i = 0; i < number; i++) {
                vpn = batch->vpn[i];
                pte_iterate_hashed_subpages(vpn, psize, index, shift) {
-                       long slot;
-
-                       slot = pSeries_lpar_hpte_find(vpn, psize, ssize);
-                       if (slot < 0)
-                               continue;
-                       pix = plpar_bluk_remove(param, pix, slot, vpn,
-                                               psize, ssize, local);
+                       if (!firmware_has_feature(FW_FEATURE_HASH_API)) {
+                               long slot;
+
+                               slot = pSeries_lpar_hpte_find(vpn, psize, 
ssize);
+                               if (slot < 0)
+                                       continue;
+                               pix = plpar_bluk_remove(param, pix, slot, vpn,
+                                                         psize, ssize, local);
+                       } else {
+                               unsigned long hash;
+                               hash = hpt_hash(vpn, 
mmu_psize_defs[psize].shift, ssize);
+                               /* trim the top bits, we overload them below */
+                               hash &= MAX_HTAB_MASK;
+                               param[pix] = HBR_REQUEST | HBR_AVPN | hash;
+                               param[pix+1] = hpte_encode_avpn(vpn, psize, 
ssize);
+                               pix += 2;
+                               if (pix == 8) {
+                                       rc = plpar_hcall9(H_HASH_BULK_REMOVE, 
param,
+                                                         param[0], param[1], 
param[2],
+                                                         param[3], param[4], 
param[5],
+                                                         param[6], param[7]);
+                                       BUG_ON(rc != H_SUCCESS);
+                                       pix = 0;
+                               }
+                       }
                } pte_iterate_hashed_end();
        }
        if (pix) {
+               unsigned long hcall;
+
                /* We have a flush pending */
                param[pix] = HBR_END;
-               rc = plpar_hcall9(H_BULK_REMOVE, param, param[0], param[1],
+               if (!firmware_has_feature(FW_FEATURE_HASH_API))
+                       hcall = H_BULK_REMOVE;
+               else
+                       hcall = H_HASH_BULK_REMOVE;
+               rc = plpar_hcall9(hcall, param, param[0], param[1],
                                  param[2], param[3], param[4], param[5],
                                  param[6], param[7]);
                BUG_ON(rc != H_SUCCESS);
-- 
2.13.6

Reply via email to