In host mode, eviction is considered an extreme measure.
verify that the entering region has enough reads, and the exiting
region has much less reads.

Signed-off-by: Avri Altman <avri.alt...@wdc.com>
---
 drivers/scsi/ufs/ufshpb.c | 44 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 41 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/ufs/ufshpb.c b/drivers/scsi/ufs/ufshpb.c
index 51c3607166bc..a16c0f2d5fac 100644
--- a/drivers/scsi/ufs/ufshpb.c
+++ b/drivers/scsi/ufs/ufshpb.c
@@ -18,6 +18,7 @@
 
 #define WORK_PENDING 0
 #define ACTIVATION_THRSHLD 4 /* 4 IOs */
+#define EVICTION_THRSHLD (ACTIVATION_THRSHLD << 6) /* 256 IOs */
 
 /* memory management */
 static struct kmem_cache *ufshpb_mctx_cache;
@@ -639,6 +640,14 @@ static struct ufshpb_region *ufshpb_victim_lru_info(struct 
ufshpb_lu *hpb)
                if (ufshpb_check_srgns_issue_state(hpb, rgn))
                        continue;
 
+               /*
+                * in host control mode, verify that the exiting region
+                * has less reads
+                */
+               if (ufshpb_mode == HPB_HOST_CONTROL &&
+                   atomic64_read(&rgn->reads) > (EVICTION_THRSHLD >> 1))
+                       continue;
+
                victim_rgn = rgn;
                break;
        }
@@ -789,7 +798,7 @@ static int ufshpb_issue_map_req(struct ufshpb_lu *hpb,
 
 static int ufshpb_add_region(struct ufshpb_lu *hpb, struct ufshpb_region *rgn)
 {
-       struct ufshpb_region *victim_rgn;
+       struct ufshpb_region *victim_rgn = NULL;
        struct victim_select_info *lru_info = &hpb->lru_info;
        unsigned long flags;
        int ret = 0;
@@ -817,6 +826,17 @@ static int ufshpb_add_region(struct ufshpb_lu *hpb, struct 
ufshpb_region *rgn)
                         * because the device could detect this region
                         * by not issuing HPB_READ
                         */
+
+                       /*
+                        * in host control mode, verify that the entering
+                        * region has enough reads
+                        */
+                       if (ufshpb_mode == HPB_HOST_CONTROL &&
+                           atomic64_read(&rgn->reads) < EVICTION_THRSHLD) {
+                               ret = -EACCES;
+                               goto out;
+                       }
+
                        victim_rgn = ufshpb_victim_lru_info(hpb);
                        if (!victim_rgn) {
                                dev_warn(&hpb->sdev_ufs_lu->sdev_dev,
@@ -1024,8 +1044,13 @@ static void ufshpb_run_active_subregion_list(struct 
ufshpb_lu *hpb)
 
                rgn = hpb->rgn_tbl + srgn->rgn_idx;
                ret = ufshpb_add_region(hpb, rgn);
-               if (ret)
-                       goto active_failed;
+               if (ret) {
+                       if (ret == -EACCES) {
+                               spin_lock_irqsave(&hpb->rsp_list_lock, flags);
+                               continue;
+                       }
+                       goto add_region_failed;
+               }
 
                ret = ufshpb_issue_map_req(hpb, rgn, srgn);
                if (ret) {
@@ -1039,9 +1064,22 @@ static void ufshpb_run_active_subregion_list(struct 
ufshpb_lu *hpb)
        spin_unlock_irqrestore(&hpb->rsp_list_lock, flags);
        return;
 
+add_region_failed:
+       if (ufshpb_mode == HPB_HOST_CONTROL) {
+               /*
+                * In host control mode, it is common that eviction trials
+                * fail, either because the entering region didn't have enough
+                * reads, or a poor-performing exiting region wasn't found.
+                * No need to re-insert those regions to the "to-be-activated"
+                * list.
+                */
+               return;
+       }
+
 active_failed:
        dev_err(&hpb->sdev_ufs_lu->sdev_dev, "failed to activate region %d - 
%d, will retry\n",
                   rgn->rgn_idx, srgn->srgn_idx);
+
        spin_lock_irqsave(&hpb->rsp_list_lock, flags);
        ufshpb_add_active_list(hpb, rgn, srgn);
        spin_unlock_irqrestore(&hpb->rsp_list_lock, flags);
-- 
2.25.1

Reply via email to