]> Git Repo - linux.git/commitdiff
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
authorLinus Torvalds <[email protected]>
Fri, 3 Mar 2023 22:41:50 +0000 (14:41 -0800)
committerLinus Torvalds <[email protected]>
Fri, 3 Mar 2023 22:41:50 +0000 (14:41 -0800)
Pull more SCSI updates from James Bottomley:
 "Updates that missed the first pull, mostly because of needing more
  soak time.

  Driver updates (zfcp, ufs, mpi3mr, plus two ipr bug fixes), an
  enclosure services (ses) update (mostly bug fixes) and other minor bug
  fixes and changes"

* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (32 commits)
  scsi: zfcp: Trace when request remove fails after qdio send fails
  scsi: zfcp: Change the type of all fsf request id fields and variables to u64
  scsi: zfcp: Make the type for accessing request hashtable buckets size_t
  scsi: ufs: core: Simplify ufshcd_execute_start_stop()
  scsi: ufs: core: Rely on the block layer for setting RQF_PM
  scsi: core: Extend struct scsi_exec_args
  scsi: lpfc: Fix double word in comments
  scsi: core: Remove the /proc/scsi/${proc_name} directory earlier
  scsi: core: Fix a source code comment
  scsi: cxgbi: Remove unneeded version.h include
  scsi: qedi: Remove unneeded version.h include
  scsi: mpi3mr: Remove unneeded version.h include
  scsi: mpi3mr: Fix missing mrioc->evtack_cmds initialization
  scsi: mpi3mr: Use number of bits to manage bitmap sizes
  scsi: mpi3mr: Remove unnecessary memcpy() to alltgt_info->dmi
  scsi: mpi3mr: Fix issues in mpi3mr_get_all_tgt_info()
  scsi: mpi3mr: Fix an issue found by KASAN
  scsi: mpi3mr: Replace 1-element array with flex-array
  scsi: ipr: Work around fortify-string warning
  scsi: ipr: Make ipr_probe_ioa_part2() return void
  ...

1  2 
drivers/scsi/ipr.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/mpi3mr/mpi3mr_fw.c
drivers/scsi/sd.c
drivers/ufs/core/ufshcd.c
include/ufs/ufshcd.h

diff --combined drivers/scsi/ipr.c
index 198d3f20d682887cf550b2d6bfadcc95b4db7cb1,b9f6a16cc1c68885b7fcba6eecc8ea5e5d053cd2..c74053f0b72f464d2cae1cf694a116d932d22501
@@@ -1516,23 -1516,22 +1516,22 @@@ static void ipr_process_ccn(struct ipr_
  }
  
  /**
-  * strip_and_pad_whitespace - Strip and pad trailing whitespace.
-  * @i:                index into buffer
-  * @buf:              string to modify
+  * strip_whitespace - Strip and pad trailing whitespace.
+  * @i:                size of buffer
+  * @buf:      string to modify
   *
-  * This function will strip all trailing whitespace, pad the end
-  * of the string with a single space, and NULL terminate the string.
+  * This function will strip all trailing whitespace and
+  * NUL terminate the string.
   *
-  * Return value:
-  *    new length of string
   **/
- static int strip_and_pad_whitespace(int i, char *buf)
+ static void strip_whitespace(int i, char *buf)
  {
+       if (i < 1)
+               return;
+       i--;
        while (i && buf[i] == ' ')
                i--;
-       buf[i+1] = ' ';
-       buf[i+2] = '\0';
-       return i + 2;
+       buf[i+1] = '\0';
  }
  
  /**
  static void ipr_log_vpd_compact(char *prefix, struct ipr_hostrcb *hostrcb,
                                struct ipr_vpd *vpd)
  {
-       char buffer[IPR_VENDOR_ID_LEN + IPR_PROD_ID_LEN + IPR_SERIAL_NUM_LEN + 3];
-       int i = 0;
+       char vendor_id[IPR_VENDOR_ID_LEN + 1];
+       char product_id[IPR_PROD_ID_LEN + 1];
+       char sn[IPR_SERIAL_NUM_LEN + 1];
  
-       memcpy(buffer, vpd->vpids.vendor_id, IPR_VENDOR_ID_LEN);
-       i = strip_and_pad_whitespace(IPR_VENDOR_ID_LEN - 1, buffer);
+       memcpy(vendor_id, vpd->vpids.vendor_id, IPR_VENDOR_ID_LEN);
+       strip_whitespace(IPR_VENDOR_ID_LEN, vendor_id);
  
-       memcpy(&buffer[i], vpd->vpids.product_id, IPR_PROD_ID_LEN);
-       i = strip_and_pad_whitespace(i + IPR_PROD_ID_LEN - 1, buffer);
+       memcpy(product_id, vpd->vpids.product_id, IPR_PROD_ID_LEN);
+       strip_whitespace(IPR_PROD_ID_LEN, product_id);
  
-       memcpy(&buffer[i], vpd->sn, IPR_SERIAL_NUM_LEN);
-       buffer[IPR_SERIAL_NUM_LEN + i] = '\0';
+       memcpy(sn, vpd->sn, IPR_SERIAL_NUM_LEN);
+       strip_whitespace(IPR_SERIAL_NUM_LEN, sn);
  
-       ipr_hcam_err(hostrcb, "%s VPID/SN: %s\n", prefix, buffer);
+       ipr_hcam_err(hostrcb, "%s VPID/SN: %s %s %s\n", prefix,
+                    vendor_id, product_id, sn);
  }
  
  /**
@@@ -5365,9 -5366,9 +5366,9 @@@ static int __ipr_eh_dev_reset(struct sc
                                        continue;
  
                                ipr_cmd->done = ipr_sata_eh_done;
 -                              if (!(ipr_cmd->qc->flags & ATA_QCFLAG_FAILED)) {
 +                              if (!(ipr_cmd->qc->flags & ATA_QCFLAG_EH)) {
                                        ipr_cmd->qc->err_mask |= AC_ERR_TIMEOUT;
 -                                      ipr_cmd->qc->flags |= ATA_QCFLAG_FAILED;
 +                                      ipr_cmd->qc->flags |= ATA_QCFLAG_EH;
                                }
                        }
                }
@@@ -7137,8 -7138,11 +7138,8 @@@ static unsigned int ipr_qc_issue(struc
  /**
   * ipr_qc_fill_rtf - Read result TF
   * @qc: ATA queued command
 - *
 - * Return value:
 - *    true
   **/
 -static bool ipr_qc_fill_rtf(struct ata_queued_cmd *qc)
 +static void ipr_qc_fill_rtf(struct ata_queued_cmd *qc)
  {
        struct ipr_sata_port *sata_port = qc->ap->private_data;
        struct ipr_ioasa_gata *g = &sata_port->ioasa;
        tf->hob_lbal = g->hob_lbal;
        tf->hob_lbam = g->hob_lbam;
        tf->hob_lbah = g->hob_lbah;
 -
 -      return true;
  }
  
  static struct ata_port_operations ipr_sata_ops = {
@@@ -9495,11 -9501,10 +9496,10 @@@ static pci_ers_result_t ipr_pci_error_d
   * This function takes care of initilizing the adapter to the point
   * where it can accept new commands.
   * Return value:
-  *    0 on success / -EIO on failure
+  *     none
   **/
- static int ipr_probe_ioa_part2(struct ipr_ioa_cfg *ioa_cfg)
+ static void ipr_probe_ioa_part2(struct ipr_ioa_cfg *ioa_cfg)
  {
-       int rc = 0;
        unsigned long host_lock_flags = 0;
  
        ENTER;
        spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags);
  
        LEAVE;
-       return rc;
  }
  
  /**
@@@ -10558,12 -10562,7 +10557,7 @@@ static int ipr_probe(struct pci_dev *pd
                return rc;
  
        ioa_cfg = pci_get_drvdata(pdev);
-       rc = ipr_probe_ioa_part2(ioa_cfg);
-       if (rc) {
-               __ipr_remove(pdev);
-               return rc;
-       }
+       ipr_probe_ioa_part2(ioa_cfg);
  
        rc = scsi_add_host(ioa_cfg->host, &pdev->dev);
  
index 6eb4085a3a222d9b295f0311fc4dd658cc11561f,75737088d0116e59cc99c7bd08eab972e2672cf7..61958a24a43d9f765bef60d9f2af17bc2e20634b
@@@ -30,7 -30,6 +30,7 @@@
  #include <linux/kthread.h>
  #include <linux/pci.h>
  #include <linux/spinlock.h>
 +#include <linux/sched/clock.h>
  #include <linux/ctype.h>
  #include <linux/aer.h>
  #include <linux/slab.h>
@@@ -5502,7 -5501,7 +5502,7 @@@ lpfc_sli4_async_link_evt(struct lpfc_hb
        bf_set(lpfc_mbx_read_top_link_spd, la,
               (bf_get(lpfc_acqe_link_speed, acqe_link)));
  
-       /* Fake the the following irrelvant fields */
+       /* Fake the following irrelevant fields */
        bf_set(lpfc_mbx_read_top_topology, la, LPFC_TOPOLOGY_PT_PT);
        bf_set(lpfc_mbx_read_top_alpa_granted, la, 0);
        bf_set(lpfc_mbx_read_top_il, la, 0);
@@@ -12549,7 -12548,7 +12549,7 @@@ lpfc_cpu_affinity_check(struct lpfc_hb
                        /* Mark CPU as IRQ not assigned by the kernel */
                        cpup->flag |= LPFC_CPU_MAP_UNASSIGN;
  
-                       /* If so, find a new_cpup thats on the the SAME
+                       /* If so, find a new_cpup that is on the SAME
                         * phys_id as cpup. start_cpu will start where we
                         * left off so all unassigned entries don't get assgined
                         * the IRQ of the first entry.
index 286a44506578b40665e1a45e0e0c88da9267b3b3,1e4467ea8472a1ad92a0da5cd54a2e0f3ffb0bd3..758f7ca9e0ee803bad899d35fef7bbd04b222f69
@@@ -1128,7 -1128,6 +1128,6 @@@ static int mpi3mr_issue_and_process_mur
  static int
  mpi3mr_revalidate_factsdata(struct mpi3mr_ioc *mrioc)
  {
-       u16 dev_handle_bitmap_sz;
        void *removepend_bitmap;
  
        if (mrioc->facts.reply_sz > mrioc->reply_sz) {
                    "\tcontroller while sas transport support is enabled at the\n"
                    "\tdriver, please reboot the system or reload the driver\n");
  
-       dev_handle_bitmap_sz = mrioc->facts.max_devhandle / 8;
-       if (mrioc->facts.max_devhandle % 8)
-               dev_handle_bitmap_sz++;
-       if (dev_handle_bitmap_sz > mrioc->dev_handle_bitmap_sz) {
-               removepend_bitmap = krealloc(mrioc->removepend_bitmap,
-                   dev_handle_bitmap_sz, GFP_KERNEL);
+       if (mrioc->facts.max_devhandle > mrioc->dev_handle_bitmap_bits) {
+               removepend_bitmap = bitmap_zalloc(mrioc->facts.max_devhandle,
+                                                 GFP_KERNEL);
                if (!removepend_bitmap) {
                        ioc_err(mrioc,
-                           "failed to increase removepend_bitmap sz from: %d to %d\n",
-                           mrioc->dev_handle_bitmap_sz, dev_handle_bitmap_sz);
+                               "failed to increase removepend_bitmap bits from %d to %d\n",
+                               mrioc->dev_handle_bitmap_bits,
+                               mrioc->facts.max_devhandle);
                        return -EPERM;
                }
-               memset(removepend_bitmap + mrioc->dev_handle_bitmap_sz, 0,
-                   dev_handle_bitmap_sz - mrioc->dev_handle_bitmap_sz);
+               bitmap_free(mrioc->removepend_bitmap);
                mrioc->removepend_bitmap = removepend_bitmap;
                ioc_info(mrioc,
-                   "increased dev_handle_bitmap_sz from %d to %d\n",
-                   mrioc->dev_handle_bitmap_sz, dev_handle_bitmap_sz);
-               mrioc->dev_handle_bitmap_sz = dev_handle_bitmap_sz;
+                        "increased bits of dev_handle_bitmap from %d to %d\n",
+                        mrioc->dev_handle_bitmap_bits,
+                        mrioc->facts.max_devhandle);
+               mrioc->dev_handle_bitmap_bits = mrioc->facts.max_devhandle;
        }
  
        return 0;
@@@ -2957,27 -2954,18 +2954,18 @@@ static int mpi3mr_alloc_reply_sense_buf
        if (!mrioc->pel_abort_cmd.reply)
                goto out_failed;
  
-       mrioc->dev_handle_bitmap_sz = mrioc->facts.max_devhandle / 8;
-       if (mrioc->facts.max_devhandle % 8)
-               mrioc->dev_handle_bitmap_sz++;
-       mrioc->removepend_bitmap = kzalloc(mrioc->dev_handle_bitmap_sz,
-           GFP_KERNEL);
+       mrioc->dev_handle_bitmap_bits = mrioc->facts.max_devhandle;
+       mrioc->removepend_bitmap = bitmap_zalloc(mrioc->dev_handle_bitmap_bits,
+                                                GFP_KERNEL);
        if (!mrioc->removepend_bitmap)
                goto out_failed;
  
-       mrioc->devrem_bitmap_sz = MPI3MR_NUM_DEVRMCMD / 8;
-       if (MPI3MR_NUM_DEVRMCMD % 8)
-               mrioc->devrem_bitmap_sz++;
-       mrioc->devrem_bitmap = kzalloc(mrioc->devrem_bitmap_sz,
-           GFP_KERNEL);
+       mrioc->devrem_bitmap = bitmap_zalloc(MPI3MR_NUM_DEVRMCMD, GFP_KERNEL);
        if (!mrioc->devrem_bitmap)
                goto out_failed;
  
-       mrioc->evtack_cmds_bitmap_sz = MPI3MR_NUM_EVTACKCMD / 8;
-       if (MPI3MR_NUM_EVTACKCMD % 8)
-               mrioc->evtack_cmds_bitmap_sz++;
-       mrioc->evtack_cmds_bitmap = kzalloc(mrioc->evtack_cmds_bitmap_sz,
-           GFP_KERNEL);
+       mrioc->evtack_cmds_bitmap = bitmap_zalloc(MPI3MR_NUM_EVTACKCMD,
+                                                 GFP_KERNEL);
        if (!mrioc->evtack_cmds_bitmap)
                goto out_failed;
  
@@@ -3415,10 -3403,7 +3403,7 @@@ static int mpi3mr_alloc_chain_bufs(stru
                if (!mrioc->chain_sgl_list[i].addr)
                        goto out_failed;
        }
-       mrioc->chain_bitmap_sz = num_chains / 8;
-       if (num_chains % 8)
-               mrioc->chain_bitmap_sz++;
-       mrioc->chain_bitmap = kzalloc(mrioc->chain_bitmap_sz, GFP_KERNEL);
+       mrioc->chain_bitmap = bitmap_zalloc(num_chains, GFP_KERNEL);
        if (!mrioc->chain_bitmap)
                goto out_failed;
        return retval;
@@@ -3633,7 -3618,8 +3618,7 @@@ int mpi3mr_setup_resources(struct mpi3m
        int i, retval = 0, capb = 0;
        u16 message_control;
        u64 dma_mask = mrioc->dma_mask ? mrioc->dma_mask :
 -          (((dma_get_required_mask(&pdev->dev) > DMA_BIT_MASK(32)) &&
 -          (sizeof(dma_addr_t) > 4)) ? DMA_BIT_MASK(64) : DMA_BIT_MASK(32));
 +          ((sizeof(dma_addr_t) > 4) ? DMA_BIT_MASK(64) : DMA_BIT_MASK(32));
  
        if (pci_enable_device_mem(pdev)) {
                ioc_err(mrioc, "pci_enable_device_mem: failed\n");
@@@ -4189,10 -4175,11 +4174,11 @@@ void mpi3mr_memset_buffers(struct mpi3m
                for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++)
                        memset(mrioc->evtack_cmds[i].reply, 0,
                            sizeof(*mrioc->evtack_cmds[i].reply));
-               memset(mrioc->removepend_bitmap, 0, mrioc->dev_handle_bitmap_sz);
-               memset(mrioc->devrem_bitmap, 0, mrioc->devrem_bitmap_sz);
-               memset(mrioc->evtack_cmds_bitmap, 0,
-                   mrioc->evtack_cmds_bitmap_sz);
+               bitmap_clear(mrioc->removepend_bitmap, 0,
+                            mrioc->dev_handle_bitmap_bits);
+               bitmap_clear(mrioc->devrem_bitmap, 0, MPI3MR_NUM_DEVRMCMD);
+               bitmap_clear(mrioc->evtack_cmds_bitmap, 0,
+                            MPI3MR_NUM_EVTACKCMD);
        }
  
        for (i = 0; i < mrioc->num_queues; i++) {
@@@ -4318,16 -4305,16 +4304,16 @@@ void mpi3mr_free_mem(struct mpi3mr_ioc 
                mrioc->evtack_cmds[i].reply = NULL;
        }
  
-       kfree(mrioc->removepend_bitmap);
+       bitmap_free(mrioc->removepend_bitmap);
        mrioc->removepend_bitmap = NULL;
  
-       kfree(mrioc->devrem_bitmap);
+       bitmap_free(mrioc->devrem_bitmap);
        mrioc->devrem_bitmap = NULL;
  
-       kfree(mrioc->evtack_cmds_bitmap);
+       bitmap_free(mrioc->evtack_cmds_bitmap);
        mrioc->evtack_cmds_bitmap = NULL;
  
-       kfree(mrioc->chain_bitmap);
+       bitmap_free(mrioc->chain_bitmap);
        mrioc->chain_bitmap = NULL;
  
        kfree(mrioc->transport_cmds.reply);
@@@ -4886,9 -4873,10 +4872,10 @@@ int mpi3mr_soft_reset_handler(struct mp
  
        mpi3mr_flush_delayed_cmd_lists(mrioc);
        mpi3mr_flush_drv_cmds(mrioc);
-       memset(mrioc->devrem_bitmap, 0, mrioc->devrem_bitmap_sz);
-       memset(mrioc->removepend_bitmap, 0, mrioc->dev_handle_bitmap_sz);
-       memset(mrioc->evtack_cmds_bitmap, 0, mrioc->evtack_cmds_bitmap_sz);
+       bitmap_clear(mrioc->devrem_bitmap, 0, MPI3MR_NUM_DEVRMCMD);
+       bitmap_clear(mrioc->removepend_bitmap, 0,
+                    mrioc->dev_handle_bitmap_bits);
+       bitmap_clear(mrioc->evtack_cmds_bitmap, 0, MPI3MR_NUM_EVTACKCMD);
        mpi3mr_flush_host_io(mrioc);
        mpi3mr_cleanup_fwevt_list(mrioc);
        mpi3mr_invalidate_devhandles(mrioc);
diff --combined drivers/scsi/sd.c
index a38c71511bc94b7a8637eb4a2d81471edc3b2ce3,2f9b7c8f6bd0b40aac37fd033db9f35a4f5bdd9f..4f28dd617ecadaa5636adde4b892834df7cfb1a1
@@@ -121,7 -121,6 +121,6 @@@ static void scsi_disk_release(struct de
  
  static DEFINE_IDA(sd_index_ida);
  
- static struct kmem_cache *sd_cdb_cache;
  static mempool_t *sd_page_pool;
  static struct lock_class_key sd_bio_compl_lkclass;
  
@@@ -834,19 -833,6 +833,19 @@@ static void sd_config_discard(struct sc
        blk_queue_max_discard_sectors(q, max_blocks * (logical_block_size >> 9));
  }
  
 +static void *sd_set_special_bvec(struct request *rq, unsigned int data_len)
 +{
 +      struct page *page;
 +
 +      page = mempool_alloc(sd_page_pool, GFP_ATOMIC);
 +      if (!page)
 +              return NULL;
 +      clear_highpage(page);
 +      bvec_set_page(&rq->special_vec, page, data_len, 0);
 +      rq->rq_flags |= RQF_SPECIAL_PAYLOAD;
 +      return bvec_virt(&rq->special_vec);
 +}
 +
  static blk_status_t sd_setup_unmap_cmnd(struct scsi_cmnd *cmd)
  {
        struct scsi_device *sdp = cmd->device;
        unsigned int data_len = 24;
        char *buf;
  
 -      rq->special_vec.bv_page = mempool_alloc(sd_page_pool, GFP_ATOMIC);
 -      if (!rq->special_vec.bv_page)
 +      buf = sd_set_special_bvec(rq, data_len);
 +      if (!buf)
                return BLK_STS_RESOURCE;
 -      clear_highpage(rq->special_vec.bv_page);
 -      rq->special_vec.bv_offset = 0;
 -      rq->special_vec.bv_len = data_len;
 -      rq->rq_flags |= RQF_SPECIAL_PAYLOAD;
  
        cmd->cmd_len = 10;
        cmd->cmnd[0] = UNMAP;
        cmd->cmnd[8] = 24;
  
 -      buf = bvec_virt(&rq->special_vec);
        put_unaligned_be16(6 + 16, &buf[0]);
        put_unaligned_be16(16, &buf[2]);
        put_unaligned_be64(lba, &buf[8]);
@@@ -887,8 -878,13 +886,8 @@@ static blk_status_t sd_setup_write_same
        u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq));
        u32 data_len = sdp->sector_size;
  
 -      rq->special_vec.bv_page = mempool_alloc(sd_page_pool, GFP_ATOMIC);
 -      if (!rq->special_vec.bv_page)
 +      if (!sd_set_special_bvec(rq, data_len))
                return BLK_STS_RESOURCE;
 -      clear_highpage(rq->special_vec.bv_page);
 -      rq->special_vec.bv_offset = 0;
 -      rq->special_vec.bv_len = data_len;
 -      rq->rq_flags |= RQF_SPECIAL_PAYLOAD;
  
        cmd->cmd_len = 16;
        cmd->cmnd[0] = WRITE_SAME_16;
@@@ -914,8 -910,13 +913,8 @@@ static blk_status_t sd_setup_write_same
        u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq));
        u32 data_len = sdp->sector_size;
  
 -      rq->special_vec.bv_page = mempool_alloc(sd_page_pool, GFP_ATOMIC);
 -      if (!rq->special_vec.bv_page)
 +      if (!sd_set_special_bvec(rq, data_len))
                return BLK_STS_RESOURCE;
 -      clear_highpage(rq->special_vec.bv_page);
 -      rq->special_vec.bv_offset = 0;
 -      rq->special_vec.bv_len = data_len;
 -      rq->rq_flags |= RQF_SPECIAL_PAYLOAD;
  
        cmd->cmd_len = 10;
        cmd->cmnd[0] = WRITE_SAME;
@@@ -2252,23 -2253,20 +2251,20 @@@ static void sd_config_protection(struc
  {
        struct scsi_device *sdp = sdkp->device;
  
-       if (!sdkp->first_scan)
-               return;
        sd_dif_config_host(sdkp);
  
        if (!sdkp->protection_type)
                return;
  
        if (!scsi_host_dif_capable(sdp->host, sdkp->protection_type)) {
-               sd_printk(KERN_NOTICE, sdkp,
-                         "Disabling DIF Type %u protection\n",
-                         sdkp->protection_type);
+               sd_first_printk(KERN_NOTICE, sdkp,
+                               "Disabling DIF Type %u protection\n",
+                               sdkp->protection_type);
                sdkp->protection_type = 0;
        }
  
-       sd_printk(KERN_NOTICE, sdkp, "Enabling DIF Type %u protection\n",
-                 sdkp->protection_type);
+       sd_first_printk(KERN_NOTICE, sdkp, "Enabling DIF Type %u protection\n",
+                       sdkp->protection_type);
  }
  
  static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp,
@@@ -3851,19 -3849,11 +3847,11 @@@ static int __init init_sd(void
        if (err)
                goto err_out;
  
-       sd_cdb_cache = kmem_cache_create("sd_ext_cdb", SD_EXT_CDB_SIZE,
-                                        0, 0, NULL);
-       if (!sd_cdb_cache) {
-               printk(KERN_ERR "sd: can't init extended cdb cache\n");
-               err = -ENOMEM;
-               goto err_out_class;
-       }
        sd_page_pool = mempool_create_page_pool(SD_MEMPOOL_SIZE, 0);
        if (!sd_page_pool) {
                printk(KERN_ERR "sd: can't init discard page pool\n");
                err = -ENOMEM;
-               goto err_out_cache;
+               goto err_out_class;
        }
  
        err = scsi_register_driver(&sd_template.gendrv);
  
  err_out_driver:
        mempool_destroy(sd_page_pool);
- err_out_cache:
-       kmem_cache_destroy(sd_cdb_cache);
  err_out_class:
        class_unregister(&sd_disk_class);
  err_out:
@@@ -3899,7 -3885,6 +3883,6 @@@ static void __exit exit_sd(void
  
        scsi_unregister_driver(&sd_template.gendrv);
        mempool_destroy(sd_page_pool);
-       kmem_cache_destroy(sd_cdb_cache);
  
        class_unregister(&sd_disk_class);
  
index 276a82b2e5ee3e691bbf0c327ab5f49387824ae6,629442c6bc9cc7ce5730551364231f69c996c6b4..172d25fef740d354a73f156acdbc37a1febb9b00
@@@ -1286,14 -1286,12 +1286,14 @@@ static int ufshcd_clock_scaling_prepare
         * clock scaling is in progress
         */
        ufshcd_scsi_block_requests(hba);
 +      mutex_lock(&hba->wb_mutex);
        down_write(&hba->clk_scaling_lock);
  
        if (!hba->clk_scaling.is_allowed ||
            ufshcd_wait_for_doorbell_clr(hba, timeout_us)) {
                ret = -EBUSY;
                up_write(&hba->clk_scaling_lock);
 +              mutex_unlock(&hba->wb_mutex);
                ufshcd_scsi_unblock_requests(hba);
                goto out;
        }
        return ret;
  }
  
 -static void ufshcd_clock_scaling_unprepare(struct ufs_hba *hba, bool writelock)
 +static void ufshcd_clock_scaling_unprepare(struct ufs_hba *hba, int err, bool scale_up)
  {
 -      if (writelock)
 -              up_write(&hba->clk_scaling_lock);
 -      else
 -              up_read(&hba->clk_scaling_lock);
 +      up_write(&hba->clk_scaling_lock);
 +
 +      /* Enable Write Booster if we have scaled up else disable it */
 +      if (ufshcd_enable_wb_if_scaling_up(hba) && !err)
 +              ufshcd_wb_toggle(hba, scale_up);
 +
 +      mutex_unlock(&hba->wb_mutex);
 +
        ufshcd_scsi_unblock_requests(hba);
        ufshcd_release(hba);
  }
  static int ufshcd_devfreq_scale(struct ufs_hba *hba, bool scale_up)
  {
        int ret = 0;
 -      bool is_writelock = true;
  
        ret = ufshcd_clock_scaling_prepare(hba, 1 * USEC_PER_SEC);
        if (ret)
                }
        }
  
 -      /* Enable Write Booster if we have scaled up else disable it */
 -      if (ufshcd_enable_wb_if_scaling_up(hba)) {
 -              downgrade_write(&hba->clk_scaling_lock);
 -              is_writelock = false;
 -              ufshcd_wb_toggle(hba, scale_up);
 -      }
 -
  out_unprepare:
 -      ufshcd_clock_scaling_unprepare(hba, is_writelock);
 +      ufshcd_clock_scaling_unprepare(hba, ret, scale_up);
        return ret;
  }
  
@@@ -1409,6 -1411,13 +1409,13 @@@ static int ufshcd_devfreq_target(struc
        struct ufs_clk_info *clki;
        unsigned long irq_flags;
  
+       /*
+        * Skip devfreq if UFS initialization is not finished.
+        * Otherwise ufs could be in a inconsistent state.
+        */
+       if (!smp_load_acquire(&hba->logical_unit_scan_finished))
+               return 0;
        if (!ufshcd_is_clkscaling_supported(hba))
                return -EINVAL;
  
@@@ -6163,21 -6172,11 +6170,21 @@@ void ufshcd_schedule_eh_work(struct ufs
        }
  }
  
 +static void ufshcd_force_error_recovery(struct ufs_hba *hba)
 +{
 +      spin_lock_irq(hba->host->host_lock);
 +      hba->force_reset = true;
 +      ufshcd_schedule_eh_work(hba);
 +      spin_unlock_irq(hba->host->host_lock);
 +}
 +
  static void ufshcd_clk_scaling_allow(struct ufs_hba *hba, bool allow)
  {
 +      mutex_lock(&hba->wb_mutex);
        down_write(&hba->clk_scaling_lock);
        hba->clk_scaling.is_allowed = allow;
        up_write(&hba->clk_scaling_lock);
 +      mutex_unlock(&hba->wb_mutex);
  }
  
  static void ufshcd_clk_scaling_suspend(struct ufs_hba *hba, bool suspend)
@@@ -8392,22 -8391,6 +8399,6 @@@ static int ufshcd_add_lus(struct ufs_hb
        if (ret)
                goto out;
  
-       /* Initialize devfreq after UFS device is detected */
-       if (ufshcd_is_clkscaling_supported(hba)) {
-               memcpy(&hba->clk_scaling.saved_pwr_info.info,
-                       &hba->pwr_info,
-                       sizeof(struct ufs_pa_layer_attr));
-               hba->clk_scaling.saved_pwr_info.is_valid = true;
-               hba->clk_scaling.is_allowed = true;
-               ret = ufshcd_devfreq_init(hba);
-               if (ret)
-                       goto out;
-               hba->clk_scaling.is_enabled = true;
-               ufshcd_init_clk_scaling_sysfs(hba);
-       }
        ufs_bsg_probe(hba);
        ufshpb_init(hba);
        scsi_scan_host(hba->host);
@@@ -8538,7 -8521,9 +8529,9 @@@ static int ufshcd_device_init(struct uf
                        return ret;
                if (is_mcq_supported(hba) && !hba->scsi_host_added) {
                        ret = ufshcd_alloc_mcq(hba);
-                       if (ret) {
+                       if (!ret) {
+                               ufshcd_config_mcq(hba);
+                       } else {
                                /* Continue with SDB mode */
                                use_mcq_mode = false;
                                dev_err(hba->dev, "MCQ mode is disabled, err=%d\n",
                                return ret;
                        }
                        hba->scsi_host_added = true;
-               }
-               /* MCQ may be disabled if ufshcd_alloc_mcq() fails */
-               if (is_mcq_supported(hba) && use_mcq_mode)
+               } else if (is_mcq_supported(hba)) {
+                       /* UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH is set */
                        ufshcd_config_mcq(hba);
+               }
        }
  
        ufshcd_tune_unipro_params(hba);
        if (ret) {
                pm_runtime_put_sync(hba->dev);
                ufshcd_hba_exit(hba);
+       } else {
+               /*
+                * Make sure that when reader code sees UFS initialization has finished,
+                * all initialization steps have really been executed.
+                */
+               smp_store_release(&hba->logical_unit_scan_finished, true);
        }
  }
  
@@@ -9143,34 -9134,15 +9142,15 @@@ static int ufshcd_execute_start_stop(st
                                     enum ufs_dev_pwr_mode pwr_mode,
                                     struct scsi_sense_hdr *sshdr)
  {
-       unsigned char cdb[6] = { START_STOP, 0, 0, 0, pwr_mode << 4, 0 };
-       struct request *req;
-       struct scsi_cmnd *scmd;
-       int ret;
-       req = scsi_alloc_request(sdev->request_queue, REQ_OP_DRV_IN,
-                                BLK_MQ_REQ_PM);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
-       scmd = blk_mq_rq_to_pdu(req);
-       scmd->cmd_len = COMMAND_SIZE(cdb[0]);
-       memcpy(scmd->cmnd, cdb, scmd->cmd_len);
-       scmd->allowed = 0/*retries*/;
-       scmd->flags |= SCMD_FAIL_IF_RECOVERING;
-       req->timeout = 1 * HZ;
-       req->rq_flags |= RQF_PM | RQF_QUIET;
-       blk_execute_rq(req, /*at_head=*/true);
-       if (sshdr)
-               scsi_normalize_sense(scmd->sense_buffer, scmd->sense_len,
-                                    sshdr);
-       ret = scmd->result;
-       blk_mq_free_request(req);
+       const unsigned char cdb[6] = { START_STOP, 0, 0, 0, pwr_mode << 4, 0 };
+       const struct scsi_exec_args args = {
+               .sshdr = sshdr,
+               .req_flags = BLK_MQ_REQ_PM,
+               .scmd_flags = SCMD_FAIL_IF_RECOVERING,
+       };
  
-       return ret;
+       return scsi_execute_cmd(sdev, cdb, REQ_OP_DRV_IN, /*buffer=*/NULL,
+                       /*bufflen=*/0, /*timeout=*/HZ, /*retries=*/0, &args);
  }
  
  /**
@@@ -9477,15 -9449,6 +9457,15 @@@ static int __ufshcd_wl_suspend(struct u
  
                if (!hba->dev_info.b_rpm_dev_flush_capable) {
                        ret = ufshcd_set_dev_pwr_mode(hba, req_dev_pwr_mode);
 +                      if (ret && pm_op != UFS_SHUTDOWN_PM) {
 +                              /*
 +                               * If return err in suspend flow, IO will hang.
 +                               * Trigger error handler and break suspend for
 +                               * error recovery.
 +                               */
 +                              ufshcd_force_error_recovery(hba);
 +                              ret = -EBUSY;
 +                      }
                        if (ret)
                                goto enable_scaling;
                }
         */
        check_for_bkops = !ufshcd_is_ufs_dev_deepsleep(hba);
        ret = ufshcd_link_state_transition(hba, req_link_state, check_for_bkops);
 +      if (ret && pm_op != UFS_SHUTDOWN_PM) {
 +              /*
 +               * If return err in suspend flow, IO will hang.
 +               * Trigger error handler and break suspend for
 +               * error recovery.
 +               */
 +              ufshcd_force_error_recovery(hba);
 +              ret = -EBUSY;
 +      }
        if (ret)
                goto set_dev_active;
  
@@@ -10231,7 -10185,6 +10211,7 @@@ int ufshcd_init(struct ufs_hba *hba, vo
        /* Initialize mutex for exception event control */
        mutex_init(&hba->ee_ctrl_mutex);
  
 +      mutex_init(&hba->wb_mutex);
        init_rwsem(&hba->clk_scaling_lock);
  
        ufshcd_init_clk_gating(hba);
         */
        ufshcd_set_ufs_dev_active(hba);
  
+       /* Initialize devfreq */
+       if (ufshcd_is_clkscaling_supported(hba)) {
+               memcpy(&hba->clk_scaling.saved_pwr_info.info,
+                       &hba->pwr_info,
+                       sizeof(struct ufs_pa_layer_attr));
+               hba->clk_scaling.saved_pwr_info.is_valid = true;
+               hba->clk_scaling.is_allowed = true;
+               err = ufshcd_devfreq_init(hba);
+               if (err)
+                       goto rpm_put_sync;
+               hba->clk_scaling.is_enabled = true;
+               ufshcd_init_clk_scaling_sysfs(hba);
+       }
        async_schedule(ufshcd_async_scan, hba);
        ufs_sysfs_add_nodes(hba->dev);
  
        device_enable_async_suspend(dev);
        return 0;
  
+ rpm_put_sync:
+       pm_runtime_put_sync(dev);
  free_tmf_queue:
        blk_mq_destroy_queue(hba->tmf_queue);
        blk_put_queue(hba->tmf_queue);
diff --combined include/ufs/ufshcd.h
index 431c3afb2ce0f2048d6a50e77d90121ad8557239,05e416414e41dcda44915f5d78af3e8bf134b58c..25aab8ec4f86be11780176b250c915ca73865b98
@@@ -878,7 -878,6 +878,7 @@@ enum ufshcd_mcq_opr 
   * @urgent_bkops_lvl: keeps track of urgent bkops level for device
   * @is_urgent_bkops_lvl_checked: keeps track if the urgent bkops level for
   *  device is known or not.
 + * @wb_mutex: used to serialize devfreq and sysfs write booster toggling
   * @clk_scaling_lock: used to serialize device commands and clock scaling
   * @desc_size: descriptor sizes reported by device
   * @scsi_block_reqs_cnt: reference counting for scsi block requests
@@@ -979,6 -978,7 +979,7 @@@ struct ufs_hba 
        struct completion *uic_async_done;
  
        enum ufshcd_state ufshcd_state;
+       bool logical_unit_scan_finished;
        u32 eh_flags;
        u32 intr_mask;
        u16 ee_ctrl_mask;
        enum bkops_status urgent_bkops_lvl;
        bool is_urgent_bkops_lvl_checked;
  
 +      struct mutex wb_mutex;
        struct rw_semaphore clk_scaling_lock;
        atomic_t scsi_block_reqs_cnt;
  
This page took 0.113661 seconds and 4 git commands to generate.