Re: [PATCH v4 20/31] scsi: pm8001: Fix tag values handling

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

 



On Thu, Feb 17, 2022 at 2:30 PM Damien Le Moal
<damien.lemoal@xxxxxxxxxxxxxxxxxx> wrote:
>
> The function pm8001_tag_alloc() determines free tags using the function
> find_first_zero_bit() which can return 0 when the first bit of the
> bitmap being inspected is 0. As such, tag 0 is a valid tag value that
> should not be dismissed as invalid. Fix the functions pm8001_work_fn(),
> mpi_sata_completion(), pm8001_mpi_task_abort_resp() and
> pm8001_open_reject_retry() to not dismiss 0 tags as invalid.
>
> The value 0xffffffff is used for invalid tags for unused ccb
> information structures. Add the macro definition PM8001_INVALID_TAG to
> define this value.
>
> Signed-off-by: Damien Le Moal <damien.lemoal@xxxxxxxxxxxxxxxxxx>
Reviewed-by: Jack Wang <jinpu.wang@xxxxxxxxx>
> ---
>  drivers/scsi/pm8001/pm8001_hwi.c  | 52 +++++++++++--------------------
>  drivers/scsi/pm8001/pm8001_init.c |  3 +-
>  drivers/scsi/pm8001/pm8001_sas.c  | 13 ++++----
>  drivers/scsi/pm8001/pm8001_sas.h  |  2 ++
>  drivers/scsi/pm8001/pm80xx_hwi.c  |  5 ---
>  5 files changed, 28 insertions(+), 47 deletions(-)
>
> diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
> index 5cad5504301e..3dc628b0384d 100644
> --- a/drivers/scsi/pm8001/pm8001_hwi.c
> +++ b/drivers/scsi/pm8001/pm8001_hwi.c
> @@ -1522,7 +1522,6 @@ void pm8001_work_fn(struct work_struct *work)
>         case IO_XFER_ERROR_BREAK:
>         {       /* This one stashes the sas_task instead */
>                 struct sas_task *t = (struct sas_task *)pm8001_dev;
> -               u32 tag;
>                 struct pm8001_ccb_info *ccb;
>                 struct pm8001_hba_info *pm8001_ha = pw->pm8001_ha;
>                 unsigned long flags, flags1;
> @@ -1544,8 +1543,8 @@ void pm8001_work_fn(struct work_struct *work)
>                 /* Search for a possible ccb that matches the task */
>                 for (i = 0; ccb = NULL, i < PM8001_MAX_CCB; i++) {
>                         ccb = &pm8001_ha->ccb_info[i];
> -                       tag = ccb->ccb_tag;
> -                       if ((tag != 0xFFFFFFFF) && (ccb->task == t))
> +                       if ((ccb->ccb_tag != PM8001_INVALID_TAG) &&
> +                           (ccb->task == t))
>                                 break;
>                 }
>                 if (!ccb) {
> @@ -1566,11 +1565,11 @@ void pm8001_work_fn(struct work_struct *work)
>                         spin_unlock_irqrestore(&t->task_state_lock, flags1);
>                         pm8001_dbg(pm8001_ha, FAIL, "task 0x%p done with event 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
>                                    t, pw->handler, ts->resp, ts->stat);
> -                       pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
> +                       pm8001_ccb_task_free(pm8001_ha, t, ccb, ccb->ccb_tag);
>                         spin_unlock_irqrestore(&pm8001_ha->lock, flags);
>                 } else {
>                         spin_unlock_irqrestore(&t->task_state_lock, flags1);
> -                       pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
> +                       pm8001_ccb_task_free(pm8001_ha, t, ccb, ccb->ccb_tag);
>                         mb();/* in order to force CPU ordering */
>                         spin_unlock_irqrestore(&pm8001_ha->lock, flags);
>                         t->task_done(t);
> @@ -1579,7 +1578,6 @@ void pm8001_work_fn(struct work_struct *work)
>         case IO_XFER_OPEN_RETRY_TIMEOUT:
>         {       /* This one stashes the sas_task instead */
>                 struct sas_task *t = (struct sas_task *)pm8001_dev;
> -               u32 tag;
>                 struct pm8001_ccb_info *ccb;
>                 struct pm8001_hba_info *pm8001_ha = pw->pm8001_ha;
>                 unsigned long flags, flags1;
> @@ -1613,8 +1611,8 @@ void pm8001_work_fn(struct work_struct *work)
>                 /* Search for a possible ccb that matches the task */
>                 for (i = 0; ccb = NULL, i < PM8001_MAX_CCB; i++) {
>                         ccb = &pm8001_ha->ccb_info[i];
> -                       tag = ccb->ccb_tag;
> -                       if ((tag != 0xFFFFFFFF) && (ccb->task == t))
> +                       if ((ccb->ccb_tag != PM8001_INVALID_TAG) &&
> +                           (ccb->task == t))
>                                 break;
>                 }
>                 if (!ccb) {
> @@ -1685,19 +1683,13 @@ void pm8001_work_fn(struct work_struct *work)
>                 struct task_status_struct *ts;
>                 struct sas_task *task;
>                 int i;
> -               u32 tag, device_id;
> +               u32 device_id;
>
>                 for (i = 0; ccb = NULL, i < PM8001_MAX_CCB; i++) {
>                         ccb = &pm8001_ha->ccb_info[i];
>                         task = ccb->task;
>                         ts = &task->task_status;
> -                       tag = ccb->ccb_tag;
> -                       /* check if tag is NULL */
> -                       if (!tag) {
> -                               pm8001_dbg(pm8001_ha, FAIL,
> -                                       "tag Null\n");
> -                               continue;
> -                       }
> +
>                         if (task != NULL) {
>                                 dev = task->dev;
>                                 if (!dev) {
> @@ -1706,10 +1698,11 @@ void pm8001_work_fn(struct work_struct *work)
>                                         continue;
>                                 }
>                                 /*complete sas task and update to top layer */
> -                               pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
> +                               pm8001_ccb_task_free(pm8001_ha, task, ccb,
> +                                                    ccb->ccb_tag);
>                                 ts->resp = SAS_TASK_COMPLETE;
>                                 task->task_done(task);
> -                       } else if (tag != 0xFFFFFFFF) {
> +                       } else if (ccb->ccb_tag != PM8001_INVALID_TAG) {
>                                 /* complete the internal commands/non-sas task */
>                                 pm8001_dev = ccb->device;
>                                 if (pm8001_dev->dcompletion) {
> @@ -1717,7 +1710,7 @@ void pm8001_work_fn(struct work_struct *work)
>                                         pm8001_dev->dcompletion = NULL;
>                                 }
>                                 complete(pm8001_ha->nvmd_completion);
> -                               pm8001_tag_free(pm8001_ha, tag);
> +                               pm8001_tag_free(pm8001_ha, ccb->ccb_tag);
>                         }
>                 }
>                 /* Deregister all the device ids  */
> @@ -2313,11 +2306,6 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
>         param = le32_to_cpu(psataPayload->param);
>         tag = le32_to_cpu(psataPayload->tag);
>
> -       if (!tag) {
> -               pm8001_dbg(pm8001_ha, FAIL, "tag null\n");
> -               return;
> -       }
> -
>         ccb = &pm8001_ha->ccb_info[tag];
>         t = ccb->task;
>         pm8001_dev = ccb->device;
> @@ -3051,7 +3039,7 @@ void pm8001_mpi_set_dev_state_resp(struct pm8001_hba_info *pm8001_ha,
>                    device_id, pds, nds, status);
>         complete(pm8001_dev->setds_completion);
>         ccb->task = NULL;
> -       ccb->ccb_tag = 0xFFFFFFFF;
> +       ccb->ccb_tag = PM8001_INVALID_TAG;
>         pm8001_tag_free(pm8001_ha, tag);
>  }
>
> @@ -3069,7 +3057,7 @@ void pm8001_mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                                 dlen_status);
>         }
>         ccb->task = NULL;
> -       ccb->ccb_tag = 0xFFFFFFFF;
> +       ccb->ccb_tag = PM8001_INVALID_TAG;
>         pm8001_tag_free(pm8001_ha, tag);
>  }
>
> @@ -3096,7 +3084,7 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
>                  * freed by requesting path anywhere.
>                  */
>                 ccb->task = NULL;
> -               ccb->ccb_tag = 0xFFFFFFFF;
> +               ccb->ccb_tag = PM8001_INVALID_TAG;
>                 pm8001_tag_free(pm8001_ha, tag);
>                 return;
>         }
> @@ -3142,7 +3130,7 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
>         complete(pm8001_ha->nvmd_completion);
>         pm8001_dbg(pm8001_ha, MSG, "Get nvmd data complete!\n");
>         ccb->task = NULL;
> -       ccb->ccb_tag = 0xFFFFFFFF;
> +       ccb->ccb_tag = PM8001_INVALID_TAG;
>         pm8001_tag_free(pm8001_ha, tag);
>  }
>
> @@ -3555,7 +3543,7 @@ int pm8001_mpi_reg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
>         }
>         complete(pm8001_dev->dcompletion);
>         ccb->task = NULL;
> -       ccb->ccb_tag = 0xFFFFFFFF;
> +       ccb->ccb_tag = PM8001_INVALID_TAG;
>         pm8001_tag_free(pm8001_ha, htag);
>         return 0;
>  }
> @@ -3627,7 +3615,7 @@ int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha,
>         }
>         kfree(ccb->fw_control_context);
>         ccb->task = NULL;
> -       ccb->ccb_tag = 0xFFFFFFFF;
> +       ccb->ccb_tag = PM8001_INVALID_TAG;
>         pm8001_tag_free(pm8001_ha, tag);
>         complete(pm8001_ha->nvmd_completion);
>         return 0;
> @@ -3663,10 +3651,6 @@ int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
>
>         status = le32_to_cpu(pPayload->status);
>         tag = le32_to_cpu(pPayload->tag);
> -       if (!tag) {
> -               pm8001_dbg(pm8001_ha, FAIL, " TAG NULL. RETURNING !!!\n");
> -               return -1;
> -       }
>
>         scp = le32_to_cpu(pPayload->scp);
>         ccb = &pm8001_ha->ccb_info[tag];
> diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
> index 4b9a26f008a9..8f44be8364dc 100644
> --- a/drivers/scsi/pm8001/pm8001_init.c
> +++ b/drivers/scsi/pm8001/pm8001_init.c
> @@ -1216,10 +1216,11 @@ pm8001_init_ccb_tag(struct pm8001_hba_info *pm8001_ha, struct Scsi_Host *shost,
>                         goto err_out;
>                 }
>                 pm8001_ha->ccb_info[i].task = NULL;
> -               pm8001_ha->ccb_info[i].ccb_tag = 0xffffffff;
> +               pm8001_ha->ccb_info[i].ccb_tag = PM8001_INVALID_TAG;
>                 pm8001_ha->ccb_info[i].device = NULL;
>                 ++pm8001_ha->tags_num;
>         }
> +
>         return 0;
>
>  err_out_noccb:
> diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
> index 4ab0ea9483f2..d0f5feb4f2d3 100644
> --- a/drivers/scsi/pm8001/pm8001_sas.c
> +++ b/drivers/scsi/pm8001/pm8001_sas.c
> @@ -563,7 +563,7 @@ void pm8001_ccb_task_free(struct pm8001_hba_info *pm8001_ha,
>
>         task->lldd_task = NULL;
>         ccb->task = NULL;
> -       ccb->ccb_tag = 0xFFFFFFFF;
> +       ccb->ccb_tag = PM8001_INVALID_TAG;
>         ccb->open_retry = 0;
>         pm8001_tag_free(pm8001_ha, ccb_idx);
>  }
> @@ -948,9 +948,11 @@ void pm8001_open_reject_retry(
>                 struct task_status_struct *ts;
>                 struct pm8001_device *pm8001_dev;
>                 unsigned long flags1;
> -               u32 tag;
>                 struct pm8001_ccb_info *ccb = &pm8001_ha->ccb_info[i];
>
> +               if (ccb->ccb_tag == PM8001_INVALID_TAG)
> +                       continue;
> +
>                 pm8001_dev = ccb->device;
>                 if (!pm8001_dev || (pm8001_dev->dev_type == SAS_PHY_UNUSED))
>                         continue;
> @@ -962,9 +964,6 @@ void pm8001_open_reject_retry(
>                                 continue;
>                 } else if (pm8001_dev != device_to_close)
>                         continue;
> -               tag = ccb->ccb_tag;
> -               if (!tag || (tag == 0xFFFFFFFF))
> -                       continue;
>                 task = ccb->task;
>                 if (!task || !task->task_done)
>                         continue;
> @@ -984,11 +983,11 @@ void pm8001_open_reject_retry(
>                                 & SAS_TASK_STATE_ABORTED))) {
>                         spin_unlock_irqrestore(&task->task_state_lock,
>                                 flags1);
> -                       pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
> +                       pm8001_ccb_task_free(pm8001_ha, task, ccb, ccb->ccb_tag);
>                 } else {
>                         spin_unlock_irqrestore(&task->task_state_lock,
>                                 flags1);
> -                       pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
> +                       pm8001_ccb_task_free(pm8001_ha, task, ccb, ccb->ccb_tag);
>                         mb();/* in order to force CPU ordering */
>                         spin_unlock_irqrestore(&pm8001_ha->lock, flags);
>                         task->task_done(task);
> diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
> index a17da1cebce1..1791cdf30276 100644
> --- a/drivers/scsi/pm8001/pm8001_sas.h
> +++ b/drivers/scsi/pm8001/pm8001_sas.h
> @@ -738,6 +738,8 @@ void pm8001_free_dev(struct pm8001_device *pm8001_dev);
>  /* ctl shared API */
>  extern const struct attribute_group *pm8001_host_groups[];
>
> +#define PM8001_INVALID_TAG     ((u32)-1)
> +
>  static inline void
>  pm8001_ccb_task_free_done(struct pm8001_hba_info *pm8001_ha,
>                         struct sas_task *task, struct pm8001_ccb_info *ccb,
> diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
> index a5a99d23cfbe..4419fdb0db78 100644
> --- a/drivers/scsi/pm8001/pm80xx_hwi.c
> +++ b/drivers/scsi/pm8001/pm80xx_hwi.c
> @@ -2402,11 +2402,6 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha,
>         param = le32_to_cpu(psataPayload->param);
>         tag = le32_to_cpu(psataPayload->tag);
>
> -       if (!tag) {
> -               pm8001_dbg(pm8001_ha, FAIL, "tag null\n");
> -               return;
> -       }
> -
>         ccb = &pm8001_ha->ccb_info[tag];
>         t = ccb->task;
>         pm8001_dev = ccb->device;
> --
> 2.34.1
>



[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