RE: Re: [PATCH v26 4/4] scsi: ufs: Add HPB 2.0 support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]

  Powered by Linux