lkml.org 
[lkml]   [2021]   [Mar]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    SubjectRE: Re: [PATCH v26 4/4] scsi: ufs: Add HPB 2.0 support
    From
    Date
    Hi Bean,

    > > +
    > > +static inline int ufshpb_get_read_id(struct ufshpb_lu *hpb)
    > > +{
    > > + if (++hpb->cur_read_id >= MAX_HPB_READ_ID)
    > > + hpb->cur_read_id = 0;
    > > + return hpb->cur_read_id;
    > > +}
    > > +
    > > +static int ufshpb_execute_pre_req(struct ufshpb_lu *hpb, struct
    > > scsi_cmnd *cmd,
    > > + struct ufshpb_req *pre_req, int
    > > read_id)
    > > +{
    > > + struct scsi_device *sdev = cmd->device;
    > > + struct request_queue *q = sdev->request_queue;
    > > + struct request *req;
    > > + struct scsi_request *rq;
    > > + struct bio *bio = pre_req->bio;
    > > +
    > > + pre_req->hpb = hpb;
    > > + pre_req->wb.lpn = sectors_to_logical(cmd->device,
    > > + blk_rq_pos(cmd-
    > > >request));
    > > + pre_req->wb.len = sectors_to_logical(cmd->device,
    > > + blk_rq_sectors(cmd-
    > > >request));
    > > + if (ufshpb_pre_req_add_bio_page(hpb, q, pre_req))
    > > + return -ENOMEM;
    > > +
    > > + req = pre_req->req;
    > > +
    > > + /* 1. request setup */
    > > + blk_rq_append_bio(req, &bio);
    > > + req->rq_disk = NULL;
    > > + req->end_io_data = (void *)pre_req;
    > > + req->end_io = ufshpb_pre_req_compl_fn;
    > > +
    > > + /* 2. scsi_request setup */
    > > + rq = scsi_req(req);
    > > + rq->retries = 1;
    > > +
    > > + ufshpb_set_write_buf_cmd(rq->cmd, pre_req->wb.lpn, pre_req-
    > > >wb.len,
    > > + read_id);
    > > + rq->cmd_len = scsi_command_size(rq->cmd);
    > > +
    > > + if (blk_insert_cloned_request(q, req) != BLK_STS_OK)
    > > + return -EAGAIN;
    > > +
    > > + hpb->stats.pre_req_cnt++;
    > > +
    > > + return 0;
    > > +}
    > > +
    > > +static int ufshpb_issue_pre_req(struct ufshpb_lu *hpb, struct
    > > scsi_cmnd *cmd,
    > > + int *read_id)
    > > +{
    > > + struct ufshpb_req *pre_req;
    > > + struct request *req = NULL;
    > > + struct bio *bio = NULL;
    > > + unsigned long flags;
    > > + int _read_id;
    > > + int ret = 0;
    > > +
    > > + req = blk_get_request(cmd->device->request_queue,
    > > + REQ_OP_SCSI_OUT | REQ_SYNC,
    > > BLK_MQ_REQ_NOWAIT);
    > > + if (IS_ERR(req))
    > > + return -EAGAIN;
    > > +
    > > + bio = bio_alloc(GFP_ATOMIC, 1);
    > > + if (!bio) {
    > > + blk_put_request(req);
    > > + return -EAGAIN;
    > > + }
    > > +
    > > + spin_lock_irqsave(&hpb->rgn_state_lock, flags);
    > > + pre_req = ufshpb_get_pre_req(hpb);
    > > + if (!pre_req) {
    > > + ret = -EAGAIN;
    > > + goto unlock_out;
    > > + }
    > > + _read_id = ufshpb_get_read_id(hpb);
    > > + spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
    > > +
    > > + pre_req->req = req;
    > > + pre_req->bio = bio;
    > > +
    > > + ret = ufshpb_execute_pre_req(hpb, cmd, pre_req, _read_id);
    > > + if (ret)
    > > + goto free_pre_req;
    > > +
    > > + *read_id = _read_id;
    > > +
    > > + return ret;
    > > +free_pre_req:
    > > + spin_lock_irqsave(&hpb->rgn_state_lock, flags);
    > > + ufshpb_put_pre_req(hpb, pre_req);
    > > +unlock_out:
    > > + spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
    > > + bio_put(bio);
    > > + blk_put_request(req);
    > > + return ret;
    > > +}
    > > +
    > > /*
    > > * This function will set up HPB read command using host-side L2P
    > > map data.
    > > - * In HPB v1.0, maximum size of HPB read command is 4KB.
    > > */
    > > -void ufshpb_prep(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
    > > +int ufshpb_prep(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
    > > {
    > > struct ufshpb_lu *hpb;
    > > struct ufshpb_region *rgn;
    > > @@ -291,26 +560,27 @@ void ufshpb_prep(struct ufs_hba *hba, struct
    > > ufshcd_lrb *lrbp)
    > > u64 ppn;
    > > unsigned long flags;
    > > int transfer_len, rgn_idx, srgn_idx, srgn_offset;
    > > + int read_id = 0;
    > > int err = 0;
    > >
    > > hpb = ufshpb_get_hpb_data(cmd->device);
    > > if (!hpb)
    > > - return;
    > > + return -ENODEV;
    > >
    > > if (ufshpb_get_state(hpb) != HPB_PRESENT) {
    > > dev_notice(&hpb->sdev_ufs_lu->sdev_dev,
    > > "%s: ufshpb state is not PRESENT",
    > > __func__);
    > > - return;
    > > + return -ENODEV;
    > > }
    > >
    > > if (!ufshpb_is_write_or_discard_cmd(cmd) &&
    > > !ufshpb_is_read_cmd(cmd))
    > > - return;
    > > + return 0;
    > >
    > > transfer_len = sectors_to_logical(cmd->device,
    > > blk_rq_sectors(cmd-
    > > >request));
    > > if (unlikely(!transfer_len))
    > > - return;
    > > + return 0;
    > >
    > > lpn = sectors_to_logical(cmd->device, blk_rq_pos(cmd-
    > > >request));
    > > ufshpb_get_pos_from_lpn(hpb, lpn, &rgn_idx, &srgn_idx,
    > > &srgn_offset);
    > > @@ -323,18 +593,19 @@ void ufshpb_prep(struct ufs_hba *hba, struct
    > > ufshcd_lrb *lrbp)
    > > ufshpb_set_ppn_dirty(hpb, rgn_idx, srgn_idx,
    > > srgn_offset,
    > > transfer_len);
    > > spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
    > > - return;
    > > + return 0;
    > > }
    > >
    > > - if (!ufshpb_is_support_chunk(transfer_len))
    > > - return;
    > > + if (!ufshpb_is_support_chunk(hpb, transfer_len) &&
    > > + (ufshpb_is_legacy(hba) && (transfer_len !=
    > > HPB_LEGACY_CHUNK_HIGH)))
    > > + return 0;
    > >
    > > spin_lock_irqsave(&hpb->rgn_state_lock, flags);
    > > if (ufshpb_test_ppn_dirty(hpb, rgn_idx, srgn_idx,
    > > srgn_offset,
    > > transfer_len)) {
    > > hpb->stats.miss_cnt++;
    > > spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
    > > - return;
    > > + return 0;
    > > }
    > >
    > > err = ufshpb_fill_ppn_from_page(hpb, srgn->mctx, srgn_offset,
    > > 1, &ppn);
    > > @@ -347,28 +618,46 @@ void ufshpb_prep(struct ufs_hba *hba, struct
    > > ufshcd_lrb *lrbp)
    > > * active state.
    > > */
    > > dev_err(hba->dev, "get ppn failed. err %d\n", err);
    > > - return;
    > > + return err;
    > > + }
    > > +
    > > + if (!ufshpb_is_legacy(hba) &&
    > > + ufshpb_is_required_wb(hpb, transfer_len)) {
    > > + err = ufshpb_issue_pre_req(hpb, cmd, &read_id);
    > > + if (err) {
    > > + unsigned long timeout;
    > > +
    > > + timeout = cmd->jiffies_at_alloc +
    > > msecs_to_jiffies(
    > > + hpb->params.requeue_timeout_ms);
    > > +
    > > + if (time_before(jiffies, timeout))
    > > + return -EAGAIN;
    > > +
    > > + hpb->stats.miss_cnt++;
    > > + return 0;
    > > + }
    > > }
    > >
    > > - ufshpb_set_hpb_read_to_upiu(hpb, lrbp, lpn, ppn,
    > > transfer_len);
    > > + ufshpb_set_hpb_read_to_upiu(hpb, lrbp, lpn, ppn,
    > > transfer_len, read_id);
    > >
    > > hpb->stats.hit_cnt++;
    > > + return 0;
    > > }
    >
    >
    >
    > BUG!!!
    >
    >
    > Please read HPB 2.0 Spec carefully, and check how to correctly use HPB
    > READ ID. you are assigning 0 for HPB write buffer. how can you expect
    > the HPB READ be paired???
    >
    I fixed as follows,

    static inline int ufshpb_get_read_id(struct ufshpb_lu *hpb)
    {
    if (hpb->cur_read_id >= MAX_HPB_READ_ID)
    hpb->cur_read_id = 0;
    return ++hpb->cur_read_id;
    }

    Thanks for comments, I will check carefully.

    Thanks,
    Daejun

    \
     
     \ /
      Last update: 2021-03-05 01:36    [W:6.612 / U:0.080 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site