summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-02-12 15:43:02 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2026-02-12 15:43:02 -0800
commitd4a379a52c3c2dc44366c4f6722c063a7d0de179 (patch)
tree3b705036e2c5d2135f2b51ec43404da288c0db77
parent041c16acbafbdd8c089cc077c78e060322dde18c (diff)
parent1982257570b84dc33753d536dd969fd357a014e9 (diff)
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley: "Usual driver updates (qla2xxx, mpi3mr, mpt3sas, ufs) plus assorted cleanups and fixes. The biggest core change is the massive code motion in the sd driver to remove forward declarations and the most significant change is to enumify the queuecommand return" * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (78 commits) scsi: csiostor: Fix dereference of null pointer rn scsi: buslogic: Reduce stack usage scsi: ufs: host: mediatek: Require CONFIG_PM scsi: ufs: mediatek: Fix page faults in ufs_mtk_clk_scale() trace event scsi: smartpqi: Fix memory leak in pqi_report_phys_luns() scsi: mpi3mr: Make driver probing asynchronous scsi: ufs: core: Flush exception handling work when RPM level is zero scsi: efct: Use IRQF_ONESHOT and default primary handler scsi: ufs: core: Use a host-wide tagset in SDB mode scsi: qla2xxx: target: Add WQ_PERCPU to alloc_workqueue() users scsi: qla2xxx: Add WQ_PERCPU to alloc_workqueue() users scsi: qla4xxx: Add WQ_PERCPU to alloc_workqueue() users scsi: mpi3mr: Driver version update to 8.17.0.3.50 scsi: mpi3mr: Fixed the W=1 compilation warning scsi: mpi3mr: Record and report controller firmware faults scsi: mpi3mr: Update MPI Headers to revision 39 scsi: mpi3mr: Use negotiated link rate from DevicePage0 scsi: mpi3mr: Avoid redundant diag-fault resets scsi: mpi3mr: Rename log data save helper to reflect threaded/BH context scsi: mpi3mr: Add module parameter to control threaded IRQ polling ...
-rw-r--r--Documentation/devicetree/bindings/ufs/qcom,sa8255p-ufshc.yaml56
-rw-r--r--Documentation/scsi/scsi_mid_low_api.rst3
-rw-r--r--MAINTAINERS2
-rw-r--r--drivers/ata/libata-scsi.c8
-rw-r--r--drivers/ata/libata.h3
-rw-r--r--drivers/base/transport_class.c8
-rw-r--r--drivers/firewire/sbp2.c7
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c3
-rw-r--r--drivers/message/fusion/mptfc.c7
-rw-r--r--drivers/message/fusion/mptsas.c4
-rw-r--r--drivers/message/fusion/mptscsih.c3
-rw-r--r--drivers/message/fusion/mptscsih.h2
-rw-r--r--drivers/message/fusion/mptspi.c4
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c4
-rw-r--r--drivers/scsi/3w-9xxx.c2
-rw-r--r--drivers/scsi/3w-sas.c8
-rw-r--r--drivers/scsi/3w-xxxx.c2
-rw-r--r--drivers/scsi/53c700.c6
-rw-r--r--drivers/scsi/BusLogic.c8
-rw-r--r--drivers/scsi/BusLogic.h3
-rw-r--r--drivers/scsi/NCR5380.c4
-rw-r--r--drivers/scsi/a100u2w.c2
-rw-r--r--drivers/scsi/aacraid/linit.c4
-rw-r--r--drivers/scsi/advansys.c5
-rw-r--r--drivers/scsi/aha152x.c8
-rw-r--r--drivers/scsi/aha1542.c3
-rw-r--r--drivers/scsi/aha1740.c2
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c12
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c4
-rw-r--r--drivers/scsi/arcmsr/arcmsr_hba.c5
-rw-r--r--drivers/scsi/arm/acornscsi.c2
-rw-r--r--drivers/scsi/arm/fas216.c11
-rw-r--r--drivers/scsi/arm/fas216.h11
-rw-r--r--drivers/scsi/atp870u.c2
-rw-r--r--drivers/scsi/bfa/bfad_im.c5
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc.h3
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_io.c4
-rw-r--r--drivers/scsi/ch.c18
-rw-r--r--drivers/scsi/csiostor/csio_scsi.c7
-rw-r--r--drivers/scsi/dc395x.c2
-rw-r--r--drivers/scsi/esas2r/esas2r.h3
-rw-r--r--drivers/scsi/esas2r/esas2r_main.c3
-rw-r--r--drivers/scsi/esp_scsi.c2
-rw-r--r--drivers/scsi/fdomain.c3
-rw-r--r--drivers/scsi/fnic/fnic.h3
-rw-r--r--drivers/scsi/fnic/fnic_scsi.c3
-rw-r--r--drivers/scsi/hosts.c5
-rw-r--r--drivers/scsi/hpsa.c6
-rw-r--r--drivers/scsi/hptiop.c2
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c3
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c9
-rw-r--r--drivers/scsi/imm.c2
-rw-r--r--drivers/scsi/initio.c2
-rw-r--r--drivers/scsi/ipr.c4
-rw-r--r--drivers/scsi/ips.c4
-rw-r--r--drivers/scsi/libfc/fc_fcp.c3
-rw-r--r--drivers/scsi/libiscsi.c3
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c3
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c40
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c7
-rw-r--r--drivers/scsi/lpfc/lpfc_disc.h7
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c57
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c1
-rw-r--r--drivers/scsi/lpfc/lpfc_hw4.h11
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c5
-rw-r--r--drivers/scsi/lpfc/lpfc_logmsg.h3
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c8
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c62
-rw-r--r--drivers/scsi/lpfc/lpfc_sli4.h4
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h2
-rw-r--r--drivers/scsi/mac53c94.c2
-rw-r--r--drivers/scsi/megaraid.c17
-rw-r--r--drivers/scsi/megaraid.h6
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.c23
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c4
-rw-r--r--drivers/scsi/mesh.c2
-rw-r--r--drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h92
-rw-r--r--drivers/scsi/mpi3mr/mpi/mpi30_image.h102
-rw-r--r--drivers/scsi/mpi3mr/mpi/mpi30_init.h2
-rw-r--r--drivers/scsi/mpi3mr/mpi/mpi30_ioc.h1
-rw-r--r--drivers/scsi/mpi3mr/mpi/mpi30_pci.h2
-rw-r--r--drivers/scsi/mpi3mr/mpi/mpi30_sas.h2
-rw-r--r--drivers/scsi/mpi3mr/mpi/mpi30_tool.h6
-rw-r--r--drivers/scsi/mpi3mr/mpi/mpi30_transport.h4
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr.h18
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_app.c28
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_fw.c136
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_os.c111
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_transport.c30
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.c17
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.h10
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_scsih.c1336
-rw-r--r--drivers/scsi/mvumi.c4
-rw-r--r--drivers/scsi/myrb.c12
-rw-r--r--drivers/scsi/myrs.c4
-rw-r--r--drivers/scsi/ncr53c8xx.c2
-rw-r--r--drivers/scsi/nsp32.c5
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.c2
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.h3
-rw-r--r--drivers/scsi/pcmcia/sym53c500_cs.c2
-rw-r--r--drivers/scsi/pmcraid.c4
-rw-r--r--drivers/scsi/ppa.c2
-rw-r--r--drivers/scsi/ps3rom.c2
-rw-r--r--drivers/scsi/qedf/qedf.h4
-rw-r--r--drivers/scsi/qedf/qedf_io.c4
-rw-r--r--drivers/scsi/qla1280.c18
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.c147
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.h12
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h30
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h5
-rw-r--r--drivers/scsi/qla2xxx/qla_gs.c41
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c232
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c19
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c88
-rw-r--r--drivers/scsi/qla2xxx/qla_nx.h1
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c16
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c29
-rw-r--r--drivers/scsi/qla2xxx/qla_target.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h8
-rw-r--r--drivers/scsi/qla2xxx/tcm_qla2xxx.c2
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c8
-rw-r--r--drivers/scsi/qlogicfas408.c2
-rw-r--r--drivers/scsi/qlogicfas408.h3
-rw-r--r--drivers/scsi/qlogicpti.c2
-rw-r--r--drivers/scsi/scsi_debug.c127
-rw-r--r--drivers/scsi/scsi_lib.c11
-rw-r--r--drivers/scsi/scsi_priv.h3
-rw-r--r--drivers/scsi/scsi_sysfs.c77
-rw-r--r--drivers/scsi/scsi_transport_fc.c42
-rw-r--r--drivers/scsi/sd.c295
-rw-r--r--drivers/scsi/ses.c15
-rw-r--r--drivers/scsi/smartpqi/smartpqi_init.c16
-rw-r--r--drivers/scsi/snic/snic.h3
-rw-r--r--drivers/scsi/snic/snic_scsi.c4
-rw-r--r--drivers/scsi/sr.c21
-rw-r--r--drivers/scsi/st.c22
-rw-r--r--drivers/scsi/stex.c2
-rw-r--r--drivers/scsi/storvsc_drv.c3
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c2
-rw-r--r--drivers/scsi/virtio_scsi.c4
-rw-r--r--drivers/scsi/vmw_pvscsi.c2
-rw-r--r--drivers/scsi/wd33c93.c2
-rw-r--r--drivers/scsi/wd33c93.h3
-rw-r--r--drivers/scsi/wd719x.c3
-rw-r--r--drivers/scsi/xen-scsifront.c4
-rw-r--r--drivers/target/loopback/tcm_loop.c3
-rw-r--r--drivers/target/target_core_configfs.c68
-rw-r--r--drivers/target/target_core_fabric_configfs.c30
-rw-r--r--drivers/target/target_core_spc.c86
-rw-r--r--drivers/ufs/core/ufs-mcq.c5
-rw-r--r--drivers/ufs/core/ufs-sysfs.c6
-rw-r--r--drivers/ufs/core/ufshcd-priv.h7
-rw-r--r--drivers/ufs/core/ufshcd.c38
-rw-r--r--drivers/ufs/host/Kconfig1
-rw-r--r--drivers/ufs/host/ufs-exynos.c10
-rw-r--r--drivers/ufs/host/ufs-mediatek-trace.h6
-rw-r--r--drivers/ufs/host/ufs-mediatek.c12
-rw-r--r--drivers/ufs/host/ufs-qcom.c156
-rw-r--r--drivers/ufs/host/ufs-qcom.h1
-rw-r--r--drivers/usb/image/microtek.c6
-rw-r--r--drivers/usb/storage/scsiglue.c2
-rw-r--r--drivers/usb/storage/uas.c2
-rw-r--r--include/linux/libata.h3
-rw-r--r--include/linux/transport_class.h1
-rw-r--r--include/scsi/libfc.h3
-rw-r--r--include/scsi/libiscsi.h3
-rw-r--r--include/scsi/libsas.h3
-rw-r--r--include/scsi/scsi.h13
-rw-r--r--include/scsi/scsi_driver.h7
-rw-r--r--include/scsi/scsi_host.h12
-rw-r--r--include/scsi/scsi_transport_fc.h12
-rw-r--r--include/target/target_core_base.h4
-rw-r--r--include/uapi/scsi/scsi_bsg_ufs.h17
-rw-r--r--include/ufs/ufs.h5
-rw-r--r--include/ufs/ufshcd.h6
-rw-r--r--include/ufs/ufshci.h1
176 files changed, 3616 insertions, 767 deletions
diff --git a/Documentation/devicetree/bindings/ufs/qcom,sa8255p-ufshc.yaml b/Documentation/devicetree/bindings/ufs/qcom,sa8255p-ufshc.yaml
new file mode 100644
index 000000000000..75fae9f1eba7
--- /dev/null
+++ b/Documentation/devicetree/bindings/ufs/qcom,sa8255p-ufshc.yaml
@@ -0,0 +1,56 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/ufs/qcom,sa8255p-ufshc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SA8255P UFS Host Controller
+
+maintainers:
+ - Ram Kumar Dwivedi <ram.dwivedi@oss.qualcomm.com>
+
+properties:
+ compatible:
+ const: qcom,sa8255p-ufshc
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ iommus:
+ maxItems: 1
+
+ dma-coherent: true
+
+ power-domains:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - power-domains
+ - iommus
+ - dma-coherent
+
+allOf:
+ - $ref: ufs-common.yaml
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ ufshc@1d84000 {
+ compatible = "qcom,sa8255p-ufshc";
+ reg = <0x01d84000 0x3000>;
+ interrupts = <GIC_SPI 265 IRQ_TYPE_LEVEL_HIGH>;
+ lanes-per-direction = <2>;
+
+ iommus = <&apps_smmu 0x100 0x0>;
+ power-domains = <&scmi3_pd 0>;
+ dma-coherent;
+ };
diff --git a/Documentation/scsi/scsi_mid_low_api.rst b/Documentation/scsi/scsi_mid_low_api.rst
index 634f5c28a849..7f59dff43eb5 100644
--- a/Documentation/scsi/scsi_mid_low_api.rst
+++ b/Documentation/scsi/scsi_mid_low_api.rst
@@ -903,7 +903,8 @@ Details::
*
* Defined in: LLD
**/
- int queuecommand(struct Scsi_Host *shost, struct scsi_cmnd * scp)
+ enum scsi_qc_status queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *scp)
/**
diff --git a/MAINTAINERS b/MAINTAINERS
index 16710c66b775..398045c00495 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -27063,7 +27063,7 @@ M: Manivannan Sadhasivam <mani@kernel.org>
L: linux-arm-msm@vger.kernel.org
L: linux-scsi@vger.kernel.org
S: Maintained
-F: Documentation/devicetree/bindings/ufs/qcom,ufs.yaml
+F: Documentation/devicetree/bindings/ufs/qcom*
F: drivers/ufs/host/ufs-qcom*
UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER RENESAS HOOKS
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 721d3f270c8e..2967a2900317 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -4309,7 +4309,8 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
return NULL;
}
-int __ata_scsi_queuecmd(struct scsi_cmnd *scmd, struct ata_device *dev)
+enum scsi_qc_status __ata_scsi_queuecmd(struct scsi_cmnd *scmd,
+ struct ata_device *dev)
{
struct ata_port *ap = dev->link->ap;
u8 scsi_op = scmd->cmnd[0];
@@ -4383,12 +4384,13 @@ int __ata_scsi_queuecmd(struct scsi_cmnd *scmd, struct ata_device *dev)
* Return value from __ata_scsi_queuecmd() if @cmd can be queued,
* 0 otherwise.
*/
-int ata_scsi_queuecmd(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
+enum scsi_qc_status ata_scsi_queuecmd(struct Scsi_Host *shost,
+ struct scsi_cmnd *cmd)
{
struct ata_port *ap;
struct ata_device *dev;
struct scsi_device *scsidev = cmd->device;
- int rc = 0;
+ enum scsi_qc_status rc = 0;
unsigned long irq_flags;
ap = ata_shost_to_port(shost);
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 0e7ecac73680..0e48bd1c0c20 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -164,7 +164,8 @@ extern int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
void ata_scsi_sdev_config(struct scsi_device *sdev);
int ata_scsi_dev_config(struct scsi_device *sdev, struct queue_limits *lim,
struct ata_device *dev);
-int __ata_scsi_queuecmd(struct scsi_cmnd *scmd, struct ata_device *dev);
+enum scsi_qc_status __ata_scsi_queuecmd(struct scsi_cmnd *scmd,
+ struct ata_device *dev);
/* libata-eh.c */
extern unsigned int ata_internal_cmd_timeout(struct ata_device *dev, u8 cmd);
diff --git a/drivers/base/transport_class.c b/drivers/base/transport_class.c
index 4b1e8820e764..416e9f819df5 100644
--- a/drivers/base/transport_class.c
+++ b/drivers/base/transport_class.c
@@ -165,6 +165,12 @@ static int transport_add_class_device(struct attribute_container *cont,
goto err_del;
}
+ if (tcont->encryption) {
+ error = sysfs_create_group(&classdev->kobj, tcont->encryption);
+ if (error)
+ goto err_del;
+ }
+
return 0;
err_del:
@@ -240,6 +246,8 @@ static int transport_remove_classdev(struct attribute_container *cont,
if (tclass->remove != anon_transport_dummy_function) {
if (tcont->statistics)
sysfs_remove_group(&classdev->kobj, tcont->statistics);
+ if (tcont->encryption)
+ sysfs_remove_group(&classdev->kobj, tcont->encryption);
attribute_container_class_device_del(classdev);
}
diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c
index 1a19828114cf..bb1a510b6423 100644
--- a/drivers/firewire/sbp2.c
+++ b/drivers/firewire/sbp2.c
@@ -1440,13 +1440,14 @@ static int sbp2_map_scatterlist(struct sbp2_command_orb *orb,
/* SCSI stack integration */
-static int sbp2_scsi_queuecommand(struct Scsi_Host *shost,
- struct scsi_cmnd *cmd)
+static enum scsi_qc_status sbp2_scsi_queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *cmd)
{
struct sbp2_logical_unit *lu = cmd->device->hostdata;
struct fw_device *device = target_parent_device(lu->tgt);
+ enum scsi_qc_status retval = SCSI_MLQUEUE_HOST_BUSY;
struct sbp2_command_orb *orb;
- int generation, retval = SCSI_MLQUEUE_HOST_BUSY;
+ int generation;
orb = kzalloc(sizeof(*orb), GFP_ATOMIC);
if (orb == NULL)
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 2012ba22a7af..510f16004ecd 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -2149,7 +2149,8 @@ static void srp_handle_qp_err(struct ib_cq *cq, struct ib_wc *wc,
target->qp_in_error = true;
}
-static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
+static enum scsi_qc_status srp_queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *scmnd)
{
struct request *rq = scsi_cmd_to_rq(scmnd);
struct srp_target_port *target = host_to_target(shost);
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index 8f587c0efd9d..cd52db6fe76c 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -97,7 +97,8 @@ static u8 mptfcInternalCtx = MPT_MAX_PROTOCOL_DRIVERS;
static int mptfc_target_alloc(struct scsi_target *starget);
static int mptfc_sdev_init(struct scsi_device *sdev);
-static int mptfc_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *SCpnt);
+static enum scsi_qc_status mptfc_qcmd(struct Scsi_Host *shost,
+ struct scsi_cmnd *SCpnt);
static void mptfc_target_destroy(struct scsi_target *starget);
static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);
static void mptfc_remove(struct pci_dev *pdev);
@@ -676,8 +677,8 @@ mptfc_sdev_init(struct scsi_device *sdev)
return 0;
}
-static int
-mptfc_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *SCpnt)
+static enum scsi_qc_status mptfc_qcmd(struct Scsi_Host *shost,
+ struct scsi_cmnd *SCpnt)
{
struct mptfc_rport_info *ri;
struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 185c08eab4ca..5276bdb7acc2 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -1920,8 +1920,8 @@ mptsas_sdev_init(struct scsi_device *sdev)
return 0;
}
-static int
-mptsas_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *SCpnt)
+static enum scsi_qc_status mptsas_qcmd(struct Scsi_Host *shost,
+ struct scsi_cmnd *SCpnt)
{
MPT_SCSI_HOST *hd;
MPT_ADAPTER *ioc;
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 3304f8824cf7..ec6edcc4ef56 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -1309,8 +1309,7 @@ int mptscsih_show_info(struct seq_file *m, struct Scsi_Host *host)
*
* Returns 0. (rtn value discarded by linux scsi mid-layer)
*/
-int
-mptscsih_qcmd(struct scsi_cmnd *SCpnt)
+enum scsi_qc_status mptscsih_qcmd(struct scsi_cmnd *SCpnt)
{
MPT_SCSI_HOST *hd;
MPT_FRAME_HDR *mf;
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index f9678d48100c..ac3f56801c92 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -113,7 +113,7 @@ extern int mptscsih_resume(struct pci_dev *pdev);
#endif
extern int mptscsih_show_info(struct seq_file *, struct Scsi_Host *);
extern const char * mptscsih_info(struct Scsi_Host *SChost);
-extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt);
+extern enum scsi_qc_status mptscsih_qcmd(struct scsi_cmnd *SCpnt);
extern int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel,
u8 id, u64 lun, int ctx2abort, ulong timeout);
extern void mptscsih_sdev_destroy(struct scsi_device *device);
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index a3901fbfac4f..14707d19fbbd 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -774,8 +774,8 @@ static int mptspi_sdev_configure(struct scsi_device *sdev,
return 0;
}
-static int
-mptspi_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *SCpnt)
+static enum scsi_qc_status mptspi_qcmd(struct Scsi_Host *shost,
+ struct scsi_cmnd *SCpnt)
{
struct _MPT_SCSI_HOST *hd = shost_priv(shost);
VirtDevice *vdevice = SCpnt->device->hostdata;
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 141476ea21bb..634bd8dceedd 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -63,8 +63,8 @@ static void zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result)
scsi_done(scpnt);
}
-static
-int zfcp_scsi_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scpnt)
+static enum scsi_qc_status zfcp_scsi_queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *scpnt)
{
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
struct fc_rport *rport = starget_to_rport(scsi_target(scpnt->device));
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index a377a6f6900a..e64a9a18ec6e 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -1746,7 +1746,7 @@ out:
} /* End twa_scsi_eh_reset() */
/* This is the main scsi queue function to handle scsi opcodes */
-static int twa_scsi_queue_lck(struct scsi_cmnd *SCpnt)
+static enum scsi_qc_status twa_scsi_queue_lck(struct scsi_cmnd *SCpnt)
{
void (*done)(struct scsi_cmnd *) = scsi_done;
int request_id, retval;
diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c
index e319be7d369c..fde12475b712 100644
--- a/drivers/scsi/3w-sas.c
+++ b/drivers/scsi/3w-sas.c
@@ -1453,11 +1453,13 @@ out:
} /* End twl_scsi_eh_reset() */
/* This is the main scsi queue function to handle scsi opcodes */
-static int twl_scsi_queue_lck(struct scsi_cmnd *SCpnt)
+static enum scsi_qc_status twl_scsi_queue_lck(struct scsi_cmnd *SCpnt)
{
+ TW_Device_Extension *tw_dev =
+ (TW_Device_Extension *)SCpnt->device->host->hostdata;
void (*done)(struct scsi_cmnd *) = scsi_done;
- int request_id, retval;
- TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
+ enum scsi_qc_status retval;
+ int request_id;
/* If we are resetting due to timed out ioctl, report as busy */
if (test_bit(TW_IN_RESET, &tw_dev->flags)) {
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 0306a228c702..c68678fa72c1 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -1920,7 +1920,7 @@ static int tw_scsiop_test_unit_ready_complete(TW_Device_Extension *tw_dev, int r
} /* End tw_scsiop_test_unit_ready_complete() */
/* This is the main scsi queue function to handle scsi opcodes */
-static int tw_scsi_queue_lck(struct scsi_cmnd *SCpnt)
+static enum scsi_qc_status tw_scsi_queue_lck(struct scsi_cmnd *SCpnt)
{
void (*done)(struct scsi_cmnd *) = scsi_done;
unsigned char *command = SCpnt->cmnd;
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index 71b7ac027f48..860538c6f8cb 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -152,8 +152,8 @@ MODULE_LICENSE("GPL");
/* This is the script */
#include "53c700_d.h"
-
-STATIC int NCR_700_queuecommand(struct Scsi_Host *h, struct scsi_cmnd *);
+STATIC enum scsi_qc_status NCR_700_queuecommand(struct Scsi_Host *h,
+ struct scsi_cmnd *);
STATIC int NCR_700_abort(struct scsi_cmnd * SCpnt);
STATIC int NCR_700_host_reset(struct scsi_cmnd * SCpnt);
STATIC void NCR_700_chip_setup(struct Scsi_Host *host);
@@ -1751,7 +1751,7 @@ NCR_700_intr(int irq, void *dev_id)
return IRQ_RETVAL(handled);
}
-static int NCR_700_queuecommand_lck(struct scsi_cmnd *SCp)
+static enum scsi_qc_status NCR_700_queuecommand_lck(struct scsi_cmnd *SCp)
{
struct NCR_700_Host_Parameters *hostdata =
(struct NCR_700_Host_Parameters *)SCp->device->host->hostdata[0];
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index a86d780d1ba4..49929d0339fa 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -920,7 +920,8 @@ static int __init blogic_init_fp_probeinfo(struct blogic_adapter *adapter)
a particular probe order.
*/
-static void __init blogic_init_probeinfo_list(struct blogic_adapter *adapter)
+static noinline_for_stack void __init
+blogic_init_probeinfo_list(struct blogic_adapter *adapter)
{
/*
If a PCI BIOS is present, interrogate it for MultiMaster and
@@ -1690,7 +1691,8 @@ common:
blogic_reportconfig reports the configuration of Host Adapter.
*/
-static bool __init blogic_reportconfig(struct blogic_adapter *adapter)
+static noinline_for_stack bool __init
+blogic_reportconfig(struct blogic_adapter *adapter)
{
unsigned short alltgt_mask = (1 << adapter->maxdev) - 1;
unsigned short sync_ok, fast_ok;
@@ -2877,7 +2879,7 @@ static int blogic_hostreset(struct scsi_cmnd *SCpnt)
Outgoing Mailbox for execution by the associated Host Adapter.
*/
-static int blogic_qcmd_lck(struct scsi_cmnd *command)
+static enum scsi_qc_status blogic_qcmd_lck(struct scsi_cmnd *command)
{
void (*comp_cb)(struct scsi_cmnd *) = scsi_done;
struct blogic_adapter *adapter =
diff --git a/drivers/scsi/BusLogic.h b/drivers/scsi/BusLogic.h
index 79de815e33b0..24697a5bedc8 100644
--- a/drivers/scsi/BusLogic.h
+++ b/drivers/scsi/BusLogic.h
@@ -1272,7 +1272,8 @@ static inline void blogic_incszbucket(unsigned int *cmdsz_buckets,
*/
static const char *blogic_drvr_info(struct Scsi_Host *);
-static int blogic_qcmd(struct Scsi_Host *h, struct scsi_cmnd *);
+static enum scsi_qc_status blogic_qcmd(struct Scsi_Host *h,
+ struct scsi_cmnd *command);
static int blogic_diskparam(struct scsi_device *, struct gendisk *, sector_t, int *);
static int blogic_sdev_configure(struct scsi_device *,
struct queue_limits *lim);
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index 0e10502660de..006dcf981218 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -555,8 +555,8 @@ static void complete_cmd(struct Scsi_Host *instance,
* main coroutine is not running, it is restarted.
*/
-static int NCR5380_queue_command(struct Scsi_Host *instance,
- struct scsi_cmnd *cmd)
+static enum scsi_qc_status NCR5380_queue_command(struct Scsi_Host *instance,
+ struct scsi_cmnd *cmd)
{
struct NCR5380_hostdata *hostdata = shost_priv(instance);
struct NCR5380_cmd *ncmd = NCR5380_to_ncmd(cmd);
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index a8979f9e30ff..4365b896f5c4 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -909,7 +909,7 @@ static int inia100_build_scb(struct orc_host * host, struct orc_scb * scb, struc
* block, build the host specific scb structures and if there is room
* queue the command down to the controller
*/
-static int inia100_queue_lck(struct scsi_cmnd *cmd)
+static enum scsi_qc_status inia100_queue_lck(struct scsi_cmnd *cmd)
{
struct orc_scb *scb;
struct orc_host *host; /* Point to Host adapter control block */
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 82c6e7c7cdaf..ea468666159a 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -237,8 +237,8 @@ static struct aac_driver_ident aac_drivers[] = {
* TODO: unify with aac_scsi_cmd().
*/
-static int aac_queuecommand(struct Scsi_Host *shost,
- struct scsi_cmnd *cmd)
+static enum scsi_qc_status aac_queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *cmd)
{
aac_priv(cmd)->owner = AAC_OWNER_LOWLEVEL;
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 06223b5ee6da..08bddac49757 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -8462,10 +8462,11 @@ static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp)
* This function always returns 0. Command return status is saved
* in the 'scp' result field.
*/
-static int advansys_queuecommand_lck(struct scsi_cmnd *scp)
+static enum scsi_qc_status advansys_queuecommand_lck(struct scsi_cmnd *scp)
{
struct Scsi_Host *shost = scp->device->host;
- int asc_res, result = 0;
+ enum scsi_qc_status result = 0;
+ int asc_res;
ASC_STATS(shost, queuecommand);
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index 182aa80ec4c6..e3ccb6bb62c0 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -924,7 +924,7 @@ static int setup_expected_interrupts(struct Scsi_Host *shpnt)
/*
* Queue a command and setup interrupts for a free bus.
*/
-static int aha152x_internal_queue(struct scsi_cmnd *SCpnt,
+static enum scsi_qc_status aha152x_internal_queue(struct scsi_cmnd *SCpnt,
struct completion *complete, int phase)
{
struct aha152x_cmd_priv *acp = aha152x_priv(SCpnt);
@@ -939,13 +939,13 @@ static int aha152x_internal_queue(struct scsi_cmnd *SCpnt,
if (acp->phase & (resetting | check_condition)) {
if (!SCpnt->host_scribble || SCSEM(SCpnt) || SCNEXT(SCpnt)) {
scmd_printk(KERN_ERR, SCpnt, "cannot reuse command\n");
- return FAILED;
+ return SCSI_MLQUEUE_HOST_BUSY;
}
} else {
SCpnt->host_scribble = kmalloc(sizeof(struct aha152x_scdata), GFP_ATOMIC);
if(!SCpnt->host_scribble) {
scmd_printk(KERN_ERR, SCpnt, "allocation failed\n");
- return FAILED;
+ return SCSI_MLQUEUE_HOST_BUSY;
}
}
@@ -995,7 +995,7 @@ static int aha152x_internal_queue(struct scsi_cmnd *SCpnt,
* queue a command
*
*/
-static int aha152x_queue_lck(struct scsi_cmnd *SCpnt)
+static enum scsi_qc_status aha152x_queue_lck(struct scsi_cmnd *SCpnt)
{
return aha152x_internal_queue(SCpnt, NULL, 0);
}
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index 371e8300f029..fd766282d4a4 100644
--- a/drivers/scsi/aha1542.c
+++ b/drivers/scsi/aha1542.c
@@ -411,7 +411,8 @@ static irqreturn_t aha1542_interrupt(int irq, void *dev_id)
}
}
-static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
+static enum scsi_qc_status aha1542_queuecommand(struct Scsi_Host *sh,
+ struct scsi_cmnd *cmd)
{
struct aha1542_cmd *acmd = scsi_cmd_priv(cmd);
struct aha1542_hostdata *aha1542 = shost_priv(sh);
diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c
index b234621f6b37..c435769359f2 100644
--- a/drivers/scsi/aha1740.c
+++ b/drivers/scsi/aha1740.c
@@ -319,7 +319,7 @@ static irqreturn_t aha1740_intr_handle(int irq, void *dev_id)
return IRQ_RETVAL(handled);
}
-static int aha1740_queuecommand_lck(struct scsi_cmnd *SCpnt)
+static enum scsi_qc_status aha1740_queuecommand_lck(struct scsi_cmnd *SCpnt)
{
void (*done)(struct scsi_cmnd *) = scsi_done;
unchar direction;
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index c3d1b9dd24ae..c8b6dc48300a 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -359,7 +359,7 @@ static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd);
static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd,
struct ahd_devinfo *devinfo);
static void ahd_linux_device_queue_depth(struct scsi_device *);
-static int ahd_linux_run_command(struct ahd_softc*,
+static enum scsi_qc_status ahd_linux_run_command(struct ahd_softc*,
struct ahd_linux_device *,
struct scsi_cmnd *);
static void ahd_linux_setup_tag_info_global(char *p);
@@ -577,11 +577,11 @@ ahd_linux_info(struct Scsi_Host *host)
/*
* Queue an SCB to the controller.
*/
-static int ahd_linux_queue_lck(struct scsi_cmnd *cmd)
+static enum scsi_qc_status ahd_linux_queue_lck(struct scsi_cmnd *cmd)
{
- struct ahd_softc *ahd;
- struct ahd_linux_device *dev = scsi_transport_device_data(cmd->device);
- int rtn = SCSI_MLQUEUE_HOST_BUSY;
+ struct ahd_linux_device *dev = scsi_transport_device_data(cmd->device);
+ enum scsi_qc_status rtn = SCSI_MLQUEUE_HOST_BUSY;
+ struct ahd_softc *ahd;
ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
@@ -1535,7 +1535,7 @@ ahd_linux_device_queue_depth(struct scsi_device *sdev)
}
}
-static int
+static enum scsi_qc_status
ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
struct scsi_cmnd *cmd)
{
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index 8b2b98666d61..c71f80f8fa34 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -519,11 +519,11 @@ ahc_linux_info(struct Scsi_Host *host)
/*
* Queue an SCB to the controller.
*/
-static int ahc_linux_queue_lck(struct scsi_cmnd *cmd)
+static enum scsi_qc_status ahc_linux_queue_lck(struct scsi_cmnd *cmd)
{
struct ahc_softc *ahc;
struct ahc_linux_device *dev = scsi_transport_device_data(cmd->device);
- int rtn = SCSI_MLQUEUE_HOST_BUSY;
+ enum scsi_qc_status rtn = SCSI_MLQUEUE_HOST_BUSY;
unsigned long flags;
ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index f0c5a30ce51b..8aa948f06cac 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -113,7 +113,8 @@ static int arcmsr_abort(struct scsi_cmnd *);
static int arcmsr_bus_reset(struct scsi_cmnd *);
static int arcmsr_bios_param(struct scsi_device *sdev,
struct gendisk *disk, sector_t capacity, int *info);
-static int arcmsr_queue_command(struct Scsi_Host *h, struct scsi_cmnd *cmd);
+static enum scsi_qc_status arcmsr_queue_command(struct Scsi_Host *h,
+ struct scsi_cmnd *cmd);
static int arcmsr_probe(struct pci_dev *pdev,
const struct pci_device_id *id);
static int __maybe_unused arcmsr_suspend(struct device *dev);
@@ -3312,7 +3313,7 @@ static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb,
}
}
-static int arcmsr_queue_command_lck(struct scsi_cmnd *cmd)
+static enum scsi_qc_status arcmsr_queue_command_lck(struct scsi_cmnd *cmd)
{
struct Scsi_Host *host = cmd->device->host;
struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c
index ef21b85cf014..79d7d7336b6a 100644
--- a/drivers/scsi/arm/acornscsi.c
+++ b/drivers/scsi/arm/acornscsi.c
@@ -2408,7 +2408,7 @@ acornscsi_intr(int irq, void *dev_id)
* Params : cmd - SCSI command
* Returns : 0, or < 0 on error.
*/
-static int acornscsi_queuecmd_lck(struct scsi_cmnd *SCpnt)
+static enum scsi_qc_status acornscsi_queuecmd_lck(struct scsi_cmnd *SCpnt)
{
struct scsi_pointer *scsi_pointer = arm_scsi_pointer(SCpnt);
void (*done)(struct scsi_cmnd *) = scsi_done;
diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
index b1a749ab18f8..fccfacaaf1d5 100644
--- a/drivers/scsi/arm/fas216.c
+++ b/drivers/scsi/arm/fas216.c
@@ -2202,11 +2202,12 @@ no_command:
* Returns: 0 on success, else error.
* Notes: io_request_lock is held, interrupts are disabled.
*/
-static int fas216_queue_command_internal(struct scsi_cmnd *SCpnt,
- void (*done)(struct scsi_cmnd *))
+static enum scsi_qc_status
+fas216_queue_command_internal(struct scsi_cmnd *SCpnt,
+ void (*done)(struct scsi_cmnd *))
{
FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
- int result;
+ enum scsi_qc_status result;
fas216_checkmagic(info);
@@ -2243,7 +2244,7 @@ static int fas216_queue_command_internal(struct scsi_cmnd *SCpnt,
return result;
}
-static int fas216_queue_command_lck(struct scsi_cmnd *SCpnt)
+static enum scsi_qc_status fas216_queue_command_lck(struct scsi_cmnd *SCpnt)
{
return fas216_queue_command_internal(SCpnt, scsi_done);
}
@@ -2273,7 +2274,7 @@ static void fas216_internal_done(struct scsi_cmnd *SCpnt)
* Returns: scsi result code.
* Notes: io_request_lock is held, interrupts are disabled.
*/
-static int fas216_noqueue_command_lck(struct scsi_cmnd *SCpnt)
+static enum scsi_qc_status fas216_noqueue_command_lck(struct scsi_cmnd *SCpnt)
{
FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
diff --git a/drivers/scsi/arm/fas216.h b/drivers/scsi/arm/fas216.h
index 08113277a2a9..29f710f9cb51 100644
--- a/drivers/scsi/arm/fas216.h
+++ b/drivers/scsi/arm/fas216.h
@@ -338,21 +338,24 @@ extern int fas216_init (struct Scsi_Host *instance);
*/
extern int fas216_add (struct Scsi_Host *instance, struct device *dev);
-/* Function: int fas216_queue_command(struct Scsi_Host *h, struct scsi_cmnd *SCpnt)
+/* Function: enum scsi_qc_status fas216_queue_command(struct Scsi_Host *h, struct scsi_cmnd *SCpnt)
* Purpose : queue a command for adapter to process.
* Params : h - host adapter
* : SCpnt - Command to queue
* Returns : 0 - success, else error
*/
-extern int fas216_queue_command(struct Scsi_Host *h, struct scsi_cmnd *SCpnt);
+extern enum scsi_qc_status fas216_queue_command(struct Scsi_Host *h,
+ struct scsi_cmnd *SCpnt);
-/* Function: int fas216_noqueue_command(struct Scsi_Host *h, struct scsi_cmnd *SCpnt)
+/* Function: enum scsi_qc_status fas216_noqueue_command(struct Scsi_Host *h,
+ * struct scsi_cmnd *SCpnt)
* Purpose : queue a command for adapter to process, and process it to completion.
* Params : h - host adapter
* : SCpnt - Command to queue
* Returns : 0 - success, else error
*/
-extern int fas216_noqueue_command(struct Scsi_Host *, struct scsi_cmnd *);
+extern enum scsi_qc_status fas216_noqueue_command(struct Scsi_Host *h,
+ struct scsi_cmnd *SCpnt);
/* Function: irqreturn_t fas216_intr (FAS216_Info *info)
* Purpose : handle interrupts from the interface to progress a command
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index df6f40b51deb..67459d81f479 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -617,7 +617,7 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id)
*
* Queue a command to the ATP queue. Called with the host lock held.
*/
-static int atp870u_queuecommand_lck(struct scsi_cmnd *req_p)
+static enum scsi_qc_status atp870u_queuecommand_lck(struct scsi_cmnd *req_p)
{
void (*done)(struct scsi_cmnd *) = scsi_done;
unsigned char c;
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c
index f56e008ee52b..6c84982c4726 100644
--- a/drivers/scsi/bfa/bfad_im.c
+++ b/drivers/scsi/bfa/bfad_im.c
@@ -24,7 +24,8 @@ DEFINE_IDR(bfad_im_port_index);
struct scsi_transport_template *bfad_im_scsi_transport_template;
struct scsi_transport_template *bfad_im_scsi_vport_transport_template;
static void bfad_im_itnim_work_handler(struct work_struct *work);
-static int bfad_im_queuecommand(struct Scsi_Host *h, struct scsi_cmnd *cmnd);
+static enum scsi_qc_status bfad_im_queuecommand(struct Scsi_Host *h,
+ struct scsi_cmnd *cmnd);
static int bfad_im_sdev_init(struct scsi_device *sdev);
static void bfad_im_fc_rport_add(struct bfad_im_port_s *im_port,
struct bfad_itnim_s *itnim);
@@ -1199,7 +1200,7 @@ bfad_im_itnim_work_handler(struct work_struct *work)
/*
* Scsi_Host template entry, queue a SCSI command to the BFAD.
*/
-static int bfad_im_queuecommand_lck(struct scsi_cmnd *cmnd)
+static enum scsi_qc_status bfad_im_queuecommand_lck(struct scsi_cmnd *cmnd)
{
void (*done)(struct scsi_cmnd *) = scsi_done;
struct bfad_im_port_s *im_port =
diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h
index 6d47a4d8eed6..8c8968ec8cb4 100644
--- a/drivers/scsi/bnx2fc/bnx2fc.h
+++ b/drivers/scsi/bnx2fc/bnx2fc.h
@@ -498,7 +498,8 @@ static inline struct bnx2fc_priv *bnx2fc_priv(struct scsi_cmnd *cmd)
struct bnx2fc_cmd *bnx2fc_cmd_alloc(struct bnx2fc_rport *tgt);
struct bnx2fc_cmd *bnx2fc_elstm_alloc(struct bnx2fc_rport *tgt, int type);
void bnx2fc_cmd_release(struct kref *ref);
-int bnx2fc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc_cmd);
+enum scsi_qc_status bnx2fc_queuecommand(struct Scsi_Host *host,
+ struct scsi_cmnd *sc_cmd);
int bnx2fc_send_fw_fcoe_init_msg(struct bnx2fc_hba *hba);
int bnx2fc_send_fw_fcoe_destroy_msg(struct bnx2fc_hba *hba);
int bnx2fc_send_session_ofld_req(struct fcoe_port *port,
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c
index 33057908f147..90b2b54c549a 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_io.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_io.c
@@ -1836,8 +1836,8 @@ static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req,
*
* This is the IO strategy routine, called by SCSI-ML
**/
-int bnx2fc_queuecommand(struct Scsi_Host *host,
- struct scsi_cmnd *sc_cmd)
+enum scsi_qc_status bnx2fc_queuecommand(struct Scsi_Host *host,
+ struct scsi_cmnd *sc_cmd)
{
struct fc_lport *lport = shost_priv(host);
struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index fa07a6f54003..b6ca23a29ef5 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -894,9 +894,9 @@ static long ch_ioctl(struct file *file,
/* ------------------------------------------------------------------------ */
-static int ch_probe(struct device *dev)
+static int ch_probe(struct scsi_device *sd)
{
- struct scsi_device *sd = to_scsi_device(dev);
+ struct device *dev = &sd->sdev_gendev;
struct device *class_dev;
int ret;
scsi_changer *ch;
@@ -967,8 +967,9 @@ free_ch:
return ret;
}
-static int ch_remove(struct device *dev)
+static void ch_remove(struct scsi_device *sd)
{
+ struct device *dev = &sd->sdev_gendev;
scsi_changer *ch = dev_get_drvdata(dev);
spin_lock(&ch_index_lock);
@@ -979,15 +980,14 @@ static int ch_remove(struct device *dev)
device_destroy(&ch_sysfs_class, MKDEV(SCSI_CHANGER_MAJOR, ch->minor));
scsi_device_put(ch->device);
kref_put(&ch->ref, ch_destroy);
- return 0;
}
static struct scsi_driver ch_template = {
- .gendrv = {
+ .probe = ch_probe,
+ .remove = ch_remove,
+ .gendrv = {
.name = "ch",
.owner = THIS_MODULE,
- .probe = ch_probe,
- .remove = ch_remove,
},
};
@@ -1014,7 +1014,7 @@ static int __init init_ch_module(void)
SCSI_CHANGER_MAJOR);
goto fail1;
}
- rc = scsi_register_driver(&ch_template.gendrv);
+ rc = scsi_register_driver(&ch_template);
if (rc < 0)
goto fail2;
return 0;
@@ -1028,7 +1028,7 @@ static int __init init_ch_module(void)
static void __exit exit_ch_module(void)
{
- scsi_unregister_driver(&ch_template.gendrv);
+ scsi_unregister_driver(&ch_template);
unregister_chrdev(SCSI_CHANGER_MAJOR, "ch");
class_unregister(&ch_sysfs_class);
idr_destroy(&ch_index_idr);
diff --git a/drivers/scsi/csiostor/csio_scsi.c b/drivers/scsi/csiostor/csio_scsi.c
index 34bde6650fae..05137784f369 100644
--- a/drivers/scsi/csiostor/csio_scsi.c
+++ b/drivers/scsi/csiostor/csio_scsi.c
@@ -1775,8 +1775,8 @@ csio_scsi_cbfn(struct csio_hw *hw, struct csio_ioreq *req)
* - Kicks off the SCSI state machine for this IO.
* - Returns busy status on error.
*/
-static int
-csio_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmnd)
+static enum scsi_qc_status csio_queuecommand(struct Scsi_Host *host,
+ struct scsi_cmnd *cmnd)
{
struct csio_lnode *ln = shost_priv(host);
struct csio_hw *hw = csio_lnode_to_hw(ln);
@@ -2074,7 +2074,7 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd)
struct csio_scsi_level_data sld;
if (!rn)
- goto fail;
+ goto fail_ret;
csio_dbg(hw, "Request to reset LUN:%llu (ssni:0x%x tgtid:%d)\n",
cmnd->device->lun, rn->flowid, rn->scsi_id);
@@ -2220,6 +2220,7 @@ fail_ret_ioreq:
csio_put_scsi_ioreq_lock(hw, scsim, ioreq);
fail:
CSIO_INC_STATS(rn, n_lun_rst_fail);
+fail_ret:
return FAILED;
}
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index 386c8359e1cc..9dc499c89d3e 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -873,7 +873,7 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
* and is expected to be held on return.
*
*/
-static int dc395x_queue_command_lck(struct scsi_cmnd *cmd)
+static enum scsi_qc_status dc395x_queue_command_lck(struct scsi_cmnd *cmd)
{
void (*done)(struct scsi_cmnd *) = scsi_done;
struct DeviceCtlBlk *dcb;
diff --git a/drivers/scsi/esas2r/esas2r.h b/drivers/scsi/esas2r/esas2r.h
index c48275d53aef..a763edd05fe4 100644
--- a/drivers/scsi/esas2r/esas2r.h
+++ b/drivers/scsi/esas2r/esas2r.h
@@ -968,7 +968,8 @@ int esas2r_ioctl_handler(void *hostdata, unsigned int cmd, void __user *arg);
int esas2r_ioctl(struct scsi_device *dev, unsigned int cmd, void __user *arg);
u8 handle_hba_ioctl(struct esas2r_adapter *a,
struct atto_ioctl *ioctl_hba);
-int esas2r_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd);
+enum scsi_qc_status esas2r_queuecommand(struct Scsi_Host *host,
+ struct scsi_cmnd *cmd);
int esas2r_show_info(struct seq_file *m, struct Scsi_Host *sh);
long esas2r_proc_ioctl(struct file *fp, unsigned int cmd, unsigned long arg);
diff --git a/drivers/scsi/esas2r/esas2r_main.c b/drivers/scsi/esas2r/esas2r_main.c
index be6bf518eb7c..fdcffc871d19 100644
--- a/drivers/scsi/esas2r/esas2r_main.c
+++ b/drivers/scsi/esas2r/esas2r_main.c
@@ -818,7 +818,8 @@ static u32 get_physaddr_from_sgc(struct esas2r_sg_context *sgc, u64 *addr)
return len;
}
-int esas2r_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
+enum scsi_qc_status esas2r_queuecommand(struct Scsi_Host *host,
+ struct scsi_cmnd *cmd)
{
struct esas2r_adapter *a =
(struct esas2r_adapter *)cmd->device->host->hostdata;
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index 802718ffad84..05647ccc3c8a 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -952,7 +952,7 @@ static void esp_event_queue_full(struct esp *esp, struct esp_cmd_entry *ent)
scsi_track_queue_full(dev, lp->num_tagged - 1);
}
-static int esp_queuecommand_lck(struct scsi_cmnd *cmd)
+static enum scsi_qc_status esp_queuecommand_lck(struct scsi_cmnd *cmd)
{
struct scsi_device *dev = cmd->device;
struct esp *esp = shost_priv(dev->host);
diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
index c0b2a980db34..22fbb0222f07 100644
--- a/drivers/scsi/fdomain.c
+++ b/drivers/scsi/fdomain.c
@@ -402,7 +402,8 @@ static irqreturn_t fdomain_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int fdomain_queue(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
+static enum scsi_qc_status fdomain_queue(struct Scsi_Host *sh,
+ struct scsi_cmnd *cmd)
{
struct scsi_pointer *scsi_pointer = fdomain_scsi_pointer(cmd);
struct fdomain *fd = shost_priv(cmd->device->host);
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
index 1199d701c3f5..42237eb3222f 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -503,7 +503,8 @@ void fnic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf);
void fnic_flush_tx(struct work_struct *work);
void fnic_update_mac_locked(struct fnic *, u8 *new);
-int fnic_queuecommand(struct Scsi_Host *, struct scsi_cmnd *);
+enum scsi_qc_status fnic_queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *sc);
int fnic_abort_cmd(struct scsi_cmnd *);
int fnic_device_reset(struct scsi_cmnd *);
int fnic_eh_host_reset_handler(struct scsi_cmnd *sc);
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
index 75b29a018d1f..29d7aca06958 100644
--- a/drivers/scsi/fnic/fnic_scsi.c
+++ b/drivers/scsi/fnic/fnic_scsi.c
@@ -454,7 +454,8 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
return 0;
}
-int fnic_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc)
+enum scsi_qc_status fnic_queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *sc)
{
struct request *const rq = scsi_cmd_to_rq(sc);
uint32_t mqtag = 0;
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 1b3fbd328277..e047747d4ecf 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -626,9 +626,8 @@ int scsi_host_busy(struct Scsi_Host *shost)
{
int cnt = 0;
- if (shost->tag_set.ops)
- blk_mq_tagset_busy_iter(&shost->tag_set,
- scsi_host_check_in_flight, &cnt);
+ blk_mq_tagset_busy_iter(&shost->tag_set,
+ scsi_host_check_in_flight, &cnt);
return cnt;
}
EXPORT_SYMBOL(scsi_host_busy);
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 3654b12c5d5a..3e235dbfb67a 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -276,7 +276,8 @@ static void hpsa_free_cmd_pool(struct ctlr_info *h);
#define VPD_PAGE (1 << 8)
#define HPSA_SIMPLE_ERROR_BITS 0x03
-static int hpsa_scsi_queue_command(struct Scsi_Host *h, struct scsi_cmnd *cmd);
+static enum scsi_qc_status hpsa_scsi_queue_command(struct Scsi_Host *h,
+ struct scsi_cmnd *cmd);
static void hpsa_scan_start(struct Scsi_Host *);
static int hpsa_scan_finished(struct Scsi_Host *sh,
unsigned long elapsed_time);
@@ -5667,7 +5668,8 @@ static void hpsa_command_resubmit_worker(struct work_struct *work)
}
/* Running in struct Scsi_Host->host_lock less mode */
-static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
+static enum scsi_qc_status hpsa_scsi_queue_command(struct Scsi_Host *sh,
+ struct scsi_cmnd *cmd)
{
struct ctlr_info *h;
struct hpsa_scsi_dev_t *dev;
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
index 21f1d9871a33..7083c14c5302 100644
--- a/drivers/scsi/hptiop.c
+++ b/drivers/scsi/hptiop.c
@@ -993,7 +993,7 @@ static int hptiop_reset_comm_mvfrey(struct hptiop_hba *hba)
return 0;
}
-static int hptiop_queuecommand_lck(struct scsi_cmnd *scp)
+static enum scsi_qc_status hptiop_queuecommand_lck(struct scsi_cmnd *scp)
{
struct Scsi_Host *host = scp->device->host;
struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 228daffb286d..1c370d11b6dd 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -1960,7 +1960,8 @@ static struct ibmvfc_cmd *ibmvfc_init_vfc_cmd(struct ibmvfc_event *evt, struct s
* Returns:
* 0 on success / other on failure
**/
-static int ibmvfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
+static enum scsi_qc_status ibmvfc_queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *cmnd)
{
struct ibmvfc_host *vhost = shost_priv(shost);
struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 3d65a498b701..200debd6f7e8 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -868,9 +868,10 @@ static void ibmvscsi_timeout(struct timer_list *t)
* Returns the value returned from ibmvscsi_send_crq(). (Zero for success)
* Note that this routine assumes that host_lock is held for synchronization
*/
-static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
- struct ibmvscsi_host_data *hostdata,
- unsigned long timeout)
+static enum scsi_qc_status
+ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
+ struct ibmvscsi_host_data *hostdata,
+ unsigned long timeout)
{
__be64 *crq_as_u64 = (__be64 *)&evt_struct->crq;
int request_status = 0;
@@ -1040,7 +1041,7 @@ static inline u16 lun_from_dev(struct scsi_device *dev)
* @cmnd: struct scsi_cmnd to be executed
* @done: Callback function to be called when cmd is completed
*/
-static int ibmvscsi_queuecommand_lck(struct scsi_cmnd *cmnd)
+static enum scsi_qc_status ibmvscsi_queuecommand_lck(struct scsi_cmnd *cmnd)
{
void (*done)(struct scsi_cmnd *) = scsi_done;
struct srp_cmd *srp_cmd;
diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c
index 45b0e33293a5..da7aaac10a73 100644
--- a/drivers/scsi/imm.c
+++ b/drivers/scsi/imm.c
@@ -925,7 +925,7 @@ static int imm_engine(imm_struct *dev, struct scsi_cmnd *const cmd)
return 0;
}
-static int imm_queuecommand_lck(struct scsi_cmnd *cmd)
+static enum scsi_qc_status imm_queuecommand_lck(struct scsi_cmnd *cmd)
{
imm_struct *dev = imm_dev(cmd->device->host);
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index ed34ad92c807..06fbe85dccfa 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -2606,7 +2606,7 @@ static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * c
* zero if successful or indicate a host busy condition if not (which
* will cause the mid layer to call us again later with the command)
*/
-static int i91u_queuecommand_lck(struct scsi_cmnd *cmd)
+static enum scsi_qc_status i91u_queuecommand_lck(struct scsi_cmnd *cmd)
{
struct initio_host *host = (struct initio_host *) cmd->device->host->hostdata;
struct scsi_ctrl_blk *cmnd;
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index dbd58a7e7bc1..c0487ce38d8d 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -6242,8 +6242,8 @@ static void ipr_scsi_done(struct ipr_cmnd *ipr_cmd)
* SCSI_MLQUEUE_DEVICE_BUSY if device is busy
* SCSI_MLQUEUE_HOST_BUSY if host is busy
**/
-static int ipr_queuecommand(struct Scsi_Host *shost,
- struct scsi_cmnd *scsi_cmd)
+static enum scsi_qc_status ipr_queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *scsi_cmd)
{
struct ipr_ioa_cfg *ioa_cfg;
struct ipr_resource_entry *res;
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index 40af961382dc..0089b17ed288 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -231,7 +231,7 @@ module_param(ips, charp, 0);
*/
static int ips_eh_abort(struct scsi_cmnd *);
static int ips_eh_reset(struct scsi_cmnd *);
-static int ips_queue(struct Scsi_Host *, struct scsi_cmnd *);
+static enum scsi_qc_status ips_queue(struct Scsi_Host *, struct scsi_cmnd *);
static const char *ips_info(struct Scsi_Host *);
static irqreturn_t do_ipsintr(int, void *);
static int ips_hainit(ips_ha_t *);
@@ -1018,7 +1018,7 @@ static int ips_eh_reset(struct scsi_cmnd *SC)
/* Linux obtains io_request_lock before calling this function */
/* */
/****************************************************************************/
-static int ips_queue_lck(struct scsi_cmnd *SC)
+static enum scsi_qc_status ips_queue_lck(struct scsi_cmnd *SC)
{
void (*done)(struct scsi_cmnd *) = scsi_done;
ips_ha_t *ha;
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 31d08c115521..2f93f6c65a86 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -1854,7 +1854,8 @@ static inline int fc_fcp_lport_queue_ready(struct fc_lport *lport)
*
* This is the i/o strategy routine, called by the SCSI layer.
*/
-int fc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc_cmd)
+enum scsi_qc_status fc_queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *sc_cmd)
{
struct fc_lport *lport = shost_priv(shost);
struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index c9f410c50978..25857d6ed6e8 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1747,7 +1747,8 @@ enum {
FAILURE_SESSION_NOT_READY,
};
-int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc)
+enum scsi_qc_status iscsi_queuecommand(struct Scsi_Host *host,
+ struct scsi_cmnd *sc)
{
struct iscsi_cls_session *cls_session;
struct iscsi_host *ihost;
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index da02457f0b09..c83282733ec4 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -158,7 +158,8 @@ static struct sas_task *sas_create_task(struct scsi_cmnd *cmd,
return task;
}
-int sas_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
+enum scsi_qc_status sas_queuecommand(struct Scsi_Host *host,
+ struct scsi_cmnd *cmd)
{
struct sas_internal *i = to_sas_internal(host->transportt);
struct domain_device *dev = cmd_to_domain_dev(cmd);
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 33582d48ec09..4af5c069635a 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -6979,6 +6979,42 @@ lpfc_reset_stats(struct Scsi_Host *shost)
return;
}
+/**
+ * lpfc_get_enc_info - Return encryption information about the session for
+ * a given remote port.
+ * @rport: ptr to fc_rport from scsi transport fc
+ *
+ * Given an rport object, iterate through the fc_nodes list to find node
+ * corresponding with rport. Pass the encryption information from the node to
+ * rport's encryption attribute for reporting to upper layers. Information is
+ * passed through nlp_enc_info struct which contains encryption status.
+ *
+ * Returns:
+ * - Address of rport's fc_encryption_info struct
+ * - NULL when not found
+ **/
+static struct fc_encryption_info *
+lpfc_get_enc_info(struct fc_rport *rport)
+{
+ struct Scsi_Host *shost = rport_to_shost(rport);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct fc_encryption_info *ef = NULL;
+ struct lpfc_nodelist *ndlp, *next_ndlp;
+ unsigned long iflags;
+
+ spin_lock_irqsave(&vport->fc_nodes_list_lock, iflags);
+ list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
+ if (ndlp->rport && ndlp->rport == rport) {
+ ef = &rport->enc_info;
+ ef->status = ndlp->nlp_enc_info.status;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&vport->fc_nodes_list_lock, iflags);
+ return ef;
+}
+
+
/*
* The LPFC driver treats linkdown handling as target loss events so there
* are no sysfs handlers for link_down_tmo.
@@ -7196,6 +7232,8 @@ struct fc_function_template lpfc_transport_functions = {
.get_fc_host_stats = lpfc_get_stats,
.reset_fc_host_stats = lpfc_reset_stats,
+ .get_fc_rport_enc_info = lpfc_get_enc_info,
+
.dd_fcrport_size = sizeof(struct lpfc_rport_data),
.show_rport_maxframe_size = 1,
.show_rport_supported_classes = 1,
@@ -7265,6 +7303,8 @@ struct fc_function_template lpfc_vport_transport_functions = {
.get_fc_host_stats = lpfc_get_stats,
.reset_fc_host_stats = lpfc_reset_stats,
+ .get_fc_rport_enc_info = lpfc_get_enc_info,
+
.dd_fcrport_size = sizeof(struct lpfc_rport_data),
.show_rport_maxframe_size = 1,
.show_rport_supported_classes = 1,
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index 92b5b2dbe847..646f88c776f5 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -872,6 +872,13 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
ndlp->nlp_rpi);
len += scnprintf(buf+len, size-len, "flag:x%08lx ",
ndlp->nlp_flag);
+ if (ndlp->nlp_enc_info.status) {
+ len += scnprintf(buf + len,
+ size - len, "ENCRYPTED");
+ len += scnprintf(buf + len, size - len,
+ ndlp->nlp_enc_info.level
+ ? "(CNSA2.0) " : "(CNSA1.0) ");
+ }
if (!ndlp->nlp_type)
len += scnprintf(buf+len, size-len, "UNKNOWN_TYPE ");
if (ndlp->nlp_type & NLP_FC_NODE)
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
index 51cb8571c049..de0adeecf668 100644
--- a/drivers/scsi/lpfc/lpfc_disc.h
+++ b/drivers/scsi/lpfc/lpfc_disc.h
@@ -77,6 +77,11 @@ struct lpfc_node_rrqs {
unsigned long xri_bitmap[XRI_BITMAP_ULONGS];
};
+struct lpfc_enc_info {
+ u8 status; /* encryption status for session */
+ u8 level; /* CNSA encryption level */
+};
+
enum lpfc_fc4_xpt_flags {
NLP_XPT_REGD = 0x1,
SCSI_XPT_REGD = 0x2,
@@ -138,6 +143,8 @@ struct lpfc_nodelist {
uint8_t vmid_support; /* destination VMID support */
#define NLP_NVME_NSLER 0x1 /* NVME NSLER device */
+ struct lpfc_enc_info nlp_enc_info; /* Encryption information struct */
+
struct timer_list nlp_delayfunc; /* Used for delayed ELS cmds */
struct lpfc_hba *phba;
struct fc_rport *rport; /* scsi_transport_fc port structure */
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 02b6d31b9ad9..32da3c23c7f4 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -2014,6 +2014,58 @@ lpfc_cmpl_els_rrq(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_nlp_put(ndlp);
return;
}
+
+/**
+ * lpfc_check_encryption - Reports an ndlp's encryption information
+ * @phba: pointer to lpfc hba data structure.
+ * @ndlp: pointer to a node-list data structure.
+ * @cmdiocb: pointer to lpfc command iocbq data structure.
+ * @rspiocb: pointer to lpfc response iocbq data structure.
+ *
+ * This routine is called in the completion callback function for issuing
+ * or receiving a Port Login (PLOGI) command. In a PLOGI completion, if FEDIF
+ * is supported, encryption information will be provided in completion status
+ * data. If @phba supports FEDIF, a log message containing encryption
+ * information will be logged. Encryption status is also saved for encryption
+ * reporting with upper layer through the rport encryption attribute.
+ **/
+static void
+lpfc_check_encryption(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+ struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb)
+{
+ struct lpfc_vport *vport = cmdiocb->vport;
+ u32 did = ndlp->nlp_DID;
+ struct lpfc_enc_info *nlp_enc_info = &ndlp->nlp_enc_info;
+ char enc_status[FC_RPORT_ENCRYPTION_STATUS_MAX_LEN] = {0};
+ char enc_level[8] = "N/A";
+ u8 encryption;
+
+ if (phba->sli4_hba.encryption_support &&
+ ((did & Fabric_DID_MASK) != Fabric_DID_MASK)) {
+ encryption = bf_get(lpfc_wcqe_c_enc,
+ &rspiocb->wcqe_cmpl);
+ nlp_enc_info->status = encryption;
+
+ strscpy(enc_status, encryption ? "Encrypted" : "Unencrypted",
+ sizeof(enc_status));
+
+ if (encryption) {
+ nlp_enc_info->level = bf_get(lpfc_wcqe_c_enc_lvl,
+ &rspiocb->wcqe_cmpl);
+ strscpy(enc_level, nlp_enc_info->level ? "CNSA2.0" :
+ "CNSA1.0",
+ sizeof(enc_level));
+ }
+
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ENCRYPTION,
+ "0924 DID:x%06x %s Session "
+ "Established, Encryption Level:%s "
+ "rpi:x%x\n",
+ ndlp->nlp_DID, enc_status, enc_level,
+ ndlp->nlp_rpi);
+ }
+}
+
/**
* lpfc_cmpl_els_plogi - Completion callback function for plogi
* @phba: pointer to lpfc hba data structure.
@@ -2153,6 +2205,8 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
goto out;
ndlp = lpfc_plogi_confirm_nport(phba, prsp->virt, ndlp);
+ lpfc_check_encryption(phba, ndlp, cmdiocb, rspiocb);
+
sp = (struct serv_parm *)((u8 *)prsp->virt +
sizeof(u32));
@@ -5407,6 +5461,9 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
goto out;
}
+ if (!ulp_status && test_bit(NLP_RCV_PLOGI, &ndlp->nlp_flag))
+ lpfc_check_encryption(phba, ndlp, cmdiocb, rspiocb);
+
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
"ELS rsp cmpl: status:x%x/x%x did:x%x",
ulp_status, ulp_word4, did);
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index bb803f32bc1b..1aeebdc08073 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -5340,6 +5340,7 @@ out:
clear_bit(NLP_NPR_ADISC, &ndlp->nlp_flag);
if (acc_plogi)
clear_bit(NLP_LOGO_ACC, &ndlp->nlp_flag);
+ memset(&ndlp->nlp_enc_info, 0, sizeof(ndlp->nlp_enc_info));
return 1;
}
clear_bit(NLP_LOGO_ACC, &ndlp->nlp_flag);
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index a7f7ed86d2b0..c000474c3066 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -437,6 +437,12 @@ struct lpfc_wcqe_complete {
#define lpfc_wcqe_c_cmf_bw_MASK 0x0FFFFFFF
#define lpfc_wcqe_c_cmf_bw_WORD total_data_placed
uint32_t parameter;
+#define lpfc_wcqe_c_enc_SHIFT 31
+#define lpfc_wcqe_c_enc_MASK 0x00000001
+#define lpfc_wcqe_c_enc_WORD parameter
+#define lpfc_wcqe_c_enc_lvl_SHIFT 30
+#define lpfc_wcqe_c_enc_lvl_MASK 0x00000001
+#define lpfc_wcqe_c_enc_lvl_WORD parameter
#define lpfc_wcqe_c_bg_edir_SHIFT 5
#define lpfc_wcqe_c_bg_edir_MASK 0x00000001
#define lpfc_wcqe_c_bg_edir_WORD parameter
@@ -2942,7 +2948,10 @@ struct lpfc_mbx_read_config {
#define lpfc_mbx_rd_conf_topology_SHIFT 24
#define lpfc_mbx_rd_conf_topology_MASK 0x000000FF
#define lpfc_mbx_rd_conf_topology_WORD word2
- uint32_t rsvd_3;
+ uint32_t word3;
+#define lpfc_mbx_rd_conf_fedif_SHIFT 6
+#define lpfc_mbx_rd_conf_fedif_MASK 0x00000001
+#define lpfc_mbx_rd_conf_fedif_WORD word3
uint32_t word4;
#define lpfc_mbx_rd_conf_e_d_tov_SHIFT 0
#define lpfc_mbx_rd_conf_e_d_tov_MASK 0x0000FFFF
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index b1460b16dd91..a116a16c4a6f 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -9999,6 +9999,11 @@ lpfc_sli4_read_config(struct lpfc_hba *phba)
(phba->sli4_hba.max_cfg_param.max_vpi - 1) : 0;
phba->max_vports = phba->max_vpi;
+ if (bf_get(lpfc_mbx_rd_conf_fedif, rd_config))
+ phba->sli4_hba.encryption_support = true;
+ else
+ phba->sli4_hba.encryption_support = false;
+
/* Next decide on FPIN or Signal E2E CGN support
* For congestion alarms and warnings valid combination are:
* 1. FPIN alarms / FPIN warnings
diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h
index 59bd2bafc73f..e00d101d548c 100644
--- a/drivers/scsi/lpfc/lpfc_logmsg.h
+++ b/drivers/scsi/lpfc/lpfc_logmsg.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2023 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2009 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -47,6 +47,7 @@
#define LOG_RSVD1 0x01000000 /* Reserved */
#define LOG_RSVD2 0x02000000 /* Reserved */
#define LOG_CGN_MGMT 0x04000000 /* Congestion Mgmt events */
+#define LOG_ENCRYPTION 0x40000000 /* EDIF Encryption events. */
#define LOG_TRACE_EVENT 0x80000000 /* Dmp the DBG log on this err */
#define LOG_ALL_MSG 0x7fffffff /* LOG all messages */
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 6d9d8c196936..df64948e55ee 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -5233,8 +5233,8 @@ static char *lpfc_is_command_vm_io(struct scsi_cmnd *cmd)
* 0 - Success
* SCSI_MLQUEUE_HOST_BUSY - Block all devices served by this host temporarily.
**/
-static int
-lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
+static enum scsi_qc_status lpfc_queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *cmnd)
{
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
struct lpfc_hba *phba = vport->phba;
@@ -6743,8 +6743,8 @@ lpfc_disable_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn,
return false;
}
-static int
-lpfc_no_command(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
+static enum scsi_qc_status lpfc_no_command(struct Scsi_Host *shost,
+ struct scsi_cmnd *cmnd)
{
return SCSI_MLQUEUE_HOST_BUSY;
}
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 73d77cfab5f8..734af3d039f8 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -20432,62 +20432,36 @@ lpfc_check_next_fcf_pri_level(struct lpfc_hba *phba)
uint16_t
lpfc_sli4_fcf_rr_next_index_get(struct lpfc_hba *phba)
{
- uint16_t next_fcf_index;
+ uint16_t next;
-initial_priority:
- /* Search start from next bit of currently registered FCF index */
- next_fcf_index = phba->fcf.current_rec.fcf_indx;
-
-next_priority:
- /* Determine the next fcf index to check */
- next_fcf_index = (next_fcf_index + 1) % LPFC_SLI4_FCF_TBL_INDX_MAX;
- next_fcf_index = find_next_bit(phba->fcf.fcf_rr_bmask,
- LPFC_SLI4_FCF_TBL_INDX_MAX,
- next_fcf_index);
+ do {
+ for_each_set_bit_wrap(next, phba->fcf.fcf_rr_bmask,
+ LPFC_SLI4_FCF_TBL_INDX_MAX, phba->fcf.current_rec.fcf_indx) {
+ if (next == phba->fcf.current_rec.fcf_indx)
+ continue;
- /* Wrap around condition on phba->fcf.fcf_rr_bmask */
- if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX) {
- /*
- * If we have wrapped then we need to clear the bits that
- * have been tested so that we can detect when we should
- * change the priority level.
- */
- next_fcf_index = find_first_bit(phba->fcf.fcf_rr_bmask,
- LPFC_SLI4_FCF_TBL_INDX_MAX);
- }
+ if (!(phba->fcf.fcf_pri[next].fcf_rec.flag & LPFC_FCF_FLOGI_FAILED)) {
+ lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
+ "2845 Get next roundrobin failover FCF (x%x)\n", next);
+ return next;
+ }
+ if (list_is_singular(&phba->fcf.fcf_pri_list))
+ return LPFC_FCOE_FCF_NEXT_NONE;
+ }
- /* Check roundrobin failover list empty condition */
- if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX ||
- next_fcf_index == phba->fcf.current_rec.fcf_indx) {
/*
* If next fcf index is not found check if there are lower
* Priority level fcf's in the fcf_priority list.
* Set up the rr_bmask with all of the avaiable fcf bits
* at that level and continue the selection process.
*/
- if (lpfc_check_next_fcf_pri_level(phba))
- goto initial_priority;
- lpfc_printf_log(phba, KERN_WARNING, LOG_FIP,
- "2844 No roundrobin failover FCF available\n");
-
- return LPFC_FCOE_FCF_NEXT_NONE;
- }
-
- if (next_fcf_index < LPFC_SLI4_FCF_TBL_INDX_MAX &&
- phba->fcf.fcf_pri[next_fcf_index].fcf_rec.flag &
- LPFC_FCF_FLOGI_FAILED) {
- if (list_is_singular(&phba->fcf.fcf_pri_list))
- return LPFC_FCOE_FCF_NEXT_NONE;
+ } while (lpfc_check_next_fcf_pri_level(phba));
- goto next_priority;
- }
-
- lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
- "2845 Get next roundrobin failover FCF (x%x)\n",
- next_fcf_index);
+ lpfc_printf_log(phba, KERN_WARNING, LOG_FIP,
+ "2844 No roundrobin failover FCF available\n");
- return next_fcf_index;
+ return LPFC_FCOE_FCF_NEXT_NONE;
}
/**
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index fd6dab157887..ee58383492b2 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -888,6 +888,10 @@ struct lpfc_sli4_hba {
#define LPFC_FP_EQ_MAX_INTR_SEC 10000
uint32_t intr_enable;
+
+ /* Indicates whether SLI Port supports FEDIF */
+ bool encryption_support;
+
struct lpfc_bmbx bmbx;
struct lpfc_max_cfg_param max_cfg_param;
uint16_t extents_in_use; /* must allocate resource extents. */
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index f3dada5bf7c1..c4ca8bf5843a 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -20,7 +20,7 @@
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "14.4.0.12"
+#define LPFC_DRIVER_VERSION "14.4.0.13"
#define LPFC_DRIVER_NAME "lpfc"
/* Used for SLI 2/3 */
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c
index 377dcab32cd8..49f856be2e51 100644
--- a/drivers/scsi/mac53c94.c
+++ b/drivers/scsi/mac53c94.c
@@ -66,7 +66,7 @@ static irqreturn_t do_mac53c94_interrupt(int, void *);
static void cmd_done(struct fsc_state *, int result);
static void set_dma_cmds(struct fsc_state *, struct scsi_cmnd *);
-static int mac53c94_queue_lck(struct scsi_cmnd *cmd)
+static enum scsi_qc_status mac53c94_queue_lck(struct scsi_cmnd *cmd)
{
struct fsc_state *state;
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index a00622c0c526..6b088bb049cc 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -372,11 +372,11 @@ mega_runpendq(adapter_t *adapter)
*
* The command queuing entry point for the mid-layer.
*/
-static int megaraid_queue_lck(struct scsi_cmnd *scmd)
+static enum scsi_qc_status megaraid_queue_lck(struct scsi_cmnd *scmd)
{
adapter_t *adapter;
scb_t *scb;
- int busy=0;
+ enum scsi_qc_status busy = 0;
unsigned long flags;
adapter = (adapter_t *)scmd->device->host->hostdata;
@@ -518,7 +518,8 @@ mega_get_ldrv_num(adapter_t *adapter, struct scsi_cmnd *cmd, int channel)
* boot settings.
*/
static scb_t *
-mega_build_cmd(adapter_t *adapter, struct scsi_cmnd *cmd, int *busy)
+mega_build_cmd(adapter_t *adapter, struct scsi_cmnd *cmd,
+ enum scsi_qc_status *busy)
{
mega_passthru *pthru;
scb_t *scb;
@@ -640,7 +641,7 @@ mega_build_cmd(adapter_t *adapter, struct scsi_cmnd *cmd, int *busy)
}
if(!(scb = mega_allocate_scb(adapter, cmd))) {
- *busy = 1;
+ *busy = SCSI_MLQUEUE_HOST_BUSY;
return NULL;
}
@@ -688,7 +689,7 @@ mega_build_cmd(adapter_t *adapter, struct scsi_cmnd *cmd, int *busy)
/* Allocate a SCB and initialize passthru */
if(!(scb = mega_allocate_scb(adapter, cmd))) {
- *busy = 1;
+ *busy = SCSI_MLQUEUE_HOST_BUSY;
return NULL;
}
pthru = scb->pthru;
@@ -730,7 +731,7 @@ mega_build_cmd(adapter_t *adapter, struct scsi_cmnd *cmd, int *busy)
/* Allocate a SCB and initialize mailbox */
if(!(scb = mega_allocate_scb(adapter, cmd))) {
- *busy = 1;
+ *busy = SCSI_MLQUEUE_HOST_BUSY;
return NULL;
}
mbox = (mbox_t *)scb->raw_mbox;
@@ -870,7 +871,7 @@ mega_build_cmd(adapter_t *adapter, struct scsi_cmnd *cmd, int *busy)
/* Allocate a SCB and initialize mailbox */
if(!(scb = mega_allocate_scb(adapter, cmd))) {
- *busy = 1;
+ *busy = SCSI_MLQUEUE_HOST_BUSY;
return NULL;
}
@@ -898,7 +899,7 @@ mega_build_cmd(adapter_t *adapter, struct scsi_cmnd *cmd, int *busy)
else {
/* Allocate a SCB and initialize passthru */
if(!(scb = mega_allocate_scb(adapter, cmd))) {
- *busy = 1;
+ *busy = SCSI_MLQUEUE_HOST_BUSY;
return NULL;
}
diff --git a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h
index d6bfd26a8843..ecbaa0a0ab51 100644
--- a/drivers/scsi/megaraid.h
+++ b/drivers/scsi/megaraid.h
@@ -962,8 +962,10 @@ static int mega_query_adapter(adapter_t *);
static int issue_scb(adapter_t *, scb_t *);
static int mega_setup_mailbox(adapter_t *);
-static int megaraid_queue (struct Scsi_Host *, struct scsi_cmnd *);
-static scb_t * mega_build_cmd(adapter_t *, struct scsi_cmnd *, int *);
+static enum scsi_qc_status megaraid_queue(struct Scsi_Host *,
+ struct scsi_cmnd *);
+static scb_t *mega_build_cmd(adapter_t *, struct scsi_cmnd *,
+ enum scsi_qc_status *);
static void __mega_runpendq(adapter_t *);
static int issue_scb_block(adapter_t *, u_char *);
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index b610cad83321..b6a32bb0bd19 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -109,8 +109,10 @@ static int megaraid_mbox_fire_sync_cmd(adapter_t *);
static void megaraid_mbox_display_scb(adapter_t *, scb_t *);
static void megaraid_mbox_setup_device_map(adapter_t *);
-static int megaraid_queue_command(struct Scsi_Host *, struct scsi_cmnd *);
-static scb_t *megaraid_mbox_build_cmd(adapter_t *, struct scsi_cmnd *, int *);
+static enum scsi_qc_status megaraid_queue_command(struct Scsi_Host *,
+ struct scsi_cmnd *);
+static scb_t *megaraid_mbox_build_cmd(adapter_t *, struct scsi_cmnd *,
+ enum scsi_qc_status *);
static void megaraid_mbox_runpendq(adapter_t *, scb_t *);
static void megaraid_mbox_prepare_pthru(adapter_t *, scb_t *,
struct scsi_cmnd *);
@@ -1434,12 +1436,12 @@ mbox_post_cmd(adapter_t *adapter, scb_t *scb)
*
* Queue entry point for mailbox based controllers.
*/
-static int megaraid_queue_command_lck(struct scsi_cmnd *scp)
+static enum scsi_qc_status megaraid_queue_command_lck(struct scsi_cmnd *scp)
{
void (*done)(struct scsi_cmnd *) = scsi_done;
adapter_t *adapter;
scb_t *scb;
- int if_busy;
+ enum scsi_qc_status if_busy;
adapter = SCP2ADAPTER(scp);
scp->result = 0;
@@ -1477,7 +1479,8 @@ static DEF_SCSI_QCMD(megaraid_queue_command)
* firmware. We also complete certain commands without sending them to firmware.
*/
static scb_t *
-megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy)
+megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp,
+ enum scsi_qc_status *busy)
{
mraid_device_t *rdev = ADAP2RAIDDEV(adapter);
int channel;
@@ -1516,7 +1519,7 @@ megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy)
if (!(scb = megaraid_alloc_scb(adapter, scp))) {
scp->result = (DID_ERROR << 16);
- *busy = 1;
+ *busy = SCSI_MLQUEUE_HOST_BUSY;
return NULL;
}
@@ -1599,7 +1602,7 @@ megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy)
/* Allocate a SCB and initialize passthru */
if (!(scb = megaraid_alloc_scb(adapter, scp))) {
scp->result = (DID_ERROR << 16);
- *busy = 1;
+ *busy = SCSI_MLQUEUE_HOST_BUSY;
return NULL;
}
@@ -1644,7 +1647,7 @@ megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy)
*/
if (!(scb = megaraid_alloc_scb(adapter, scp))) {
scp->result = (DID_ERROR << 16);
- *busy = 1;
+ *busy = SCSI_MLQUEUE_HOST_BUSY;
return NULL;
}
ccb = (mbox_ccb_t *)scb->ccb;
@@ -1740,7 +1743,7 @@ megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy)
*/
if (!(scb = megaraid_alloc_scb(adapter, scp))) {
scp->result = (DID_ERROR << 16);
- *busy = 1;
+ *busy = SCSI_MLQUEUE_HOST_BUSY;
return NULL;
}
@@ -1808,7 +1811,7 @@ megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy)
// Allocate a SCB and initialize passthru
if (!(scb = megaraid_alloc_scb(adapter, scp))) {
scp->result = (DID_ERROR << 16);
- *busy = 1;
+ *busy = SCSI_MLQUEUE_HOST_BUSY;
return NULL;
}
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index abbbc4b36cd1..52894e892a92 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -1781,8 +1781,8 @@ out_return_cmd:
* @shost: adapter SCSI host
* @scmd: SCSI command to be queued
*/
-static int
-megasas_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
+static enum scsi_qc_status megasas_queue_command(struct Scsi_Host *shost,
+ struct scsi_cmnd *scmd)
{
struct megasas_instance *instance;
struct MR_PRIV_DEVICE *mr_device_priv_data;
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
index 768b85eecc8f..dc1402b321da 100644
--- a/drivers/scsi/mesh.c
+++ b/drivers/scsi/mesh.c
@@ -1625,7 +1625,7 @@ static void cmd_complete(struct mesh_state *ms)
* Called by midlayer with host locked to queue a new
* request
*/
-static int mesh_queue_lck(struct scsi_cmnd *cmd)
+static enum scsi_qc_status mesh_queue_lck(struct scsi_cmnd *cmd)
{
struct mesh_state *ms;
diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h b/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h
index 8c8bfbbdd34e..33dd303c97bb 100644
--- a/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h
+++ b/drivers/scsi/mpi3mr/mpi/mpi30_cnfg.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
- * Copyright 2017-2023 Broadcom Inc. All rights reserved.
+ * Copyright 2017-2026 Broadcom Inc. All rights reserved.
*/
#ifndef MPI30_CNFG_H
#define MPI30_CNFG_H 1
@@ -1037,6 +1037,7 @@ struct mpi3_io_unit_page5 {
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SATA_SSD_SHIFT (2)
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SAS_SSD_MASK (0x0003)
#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SAS_SSD_SHIFT (0)
+#define MPI3_IOUNIT5_DEVICE_SHUTDOWN_HDD_SPINDOWN_ENABLE (0x8000)
#define MPI3_IOUNIT5_FLAGS_SATAPUIS_MASK (0x0c)
#define MPI3_IOUNIT5_FLAGS_SATAPUIS_NOT_SUPPORTED (0x00)
#define MPI3_IOUNIT5_FLAGS_SATAPUIS_OS_CONTROLLED (0x04)
@@ -1074,7 +1075,8 @@ struct mpi3_io_unit_page8 {
u8 current_key_encryption_algo;
u8 key_digest_hash_algo;
union mpi3_version_union current_svn;
- __le32 reserved14;
+ __le16 pending_svn_time;
+ __le16 reserved16;
__le32 current_key[128];
union mpi3_iounit8_digest digest[MPI3_IOUNIT8_DIGEST_MAX];
};
@@ -1406,6 +1408,7 @@ struct mpi3_driver_page1 {
};
#define MPI3_DRIVER1_PAGEVERSION (0x00)
+#define MPI3_DRIVER1_FLAGS_DEVICE_SHUTDOWN_ON_UNLOAD_DISABLE (0x0001)
#ifndef MPI3_DRIVER2_TRIGGER_MAX
#define MPI3_DRIVER2_TRIGGER_MAX (1)
#endif
@@ -1561,7 +1564,9 @@ struct mpi3_security1_key_record {
u8 consumer;
__le16 key_data_size;
__le32 additional_key_data;
- __le32 reserved08[2];
+ u8 library_version;
+ u8 reserved09[3];
+ __le32 reserved0c;
union mpi3_security1_key_data key_data;
};
@@ -1614,6 +1619,85 @@ struct mpi3_security_page2 {
u8 reserved9d[3];
struct mpi3_security2_trusted_root trusted_root[MPI3_SECURITY2_TRUSTED_ROOT_MAX];
};
+
+struct mpi3_security_page3 {
+ struct mpi3_config_page_header header;
+ __le16 key_data_length;
+ __le16 reserved0a;
+ u8 key_number;
+ u8 reserved0d[3];
+ union mpi3_security_mac mac;
+ union mpi3_security_nonce nonce;
+ __le32 reserved90[12];
+ u8 flags;
+ u8 consumer;
+ __le16 key_data_size;
+ __le32 additional_key_data;
+ u8 library_version;
+ u8 reserved_c9[3];
+ __le32 reserved_cc;
+ u8 key_data[];
+};
+
+#define MPI3_SECURITY3_PAGEVERSION (0x00)
+#define MPI3_SECURITY3_FLAGS_TYPE_MASK (0x0f)
+#define MPI3_SECURITY3_FLAGS_TYPE_SHIFT (0)
+#define MPI3_SECURITY3_FLAGS_TYPE_NOT_VALID (0)
+#define MPI3_SECURITY3_FLAGS_TYPE_MLDSA_PRIVATE (1)
+#define MPI3_SECURITY3_FLAGS_TYPE_MLDSA_PUBLIC (2)
+struct mpi3_security_page10 {
+ struct mpi3_config_page_header header;
+ __le32 reserved08[2];
+ union mpi3_security_mac mac;
+ union mpi3_security_nonce nonce;
+ __le64 current_token_nonce;
+ __le64 previous_token_nonce;
+ __le32 reserved_a0[8];
+ u8 diagnostic_auth_id[64];
+};
+#define MPI3_SECURITY10_PAGEVERSION (0x00)
+
+struct mpi3_security_page11 {
+ struct mpi3_config_page_header header;
+ u8 flags;
+ u8 reserved09[3];
+ __le32 reserved0c;
+ __le32 diagnostic_token_length;
+ __le32 reserved14[3];
+ u8 diagnostic_token[];
+};
+#define MPI3_SECURITY11_PAGEVERSION (0x00)
+#define MPI3_SECURITY11_FLAGS_TOKEN_ENABLED (0x01)
+
+struct mpi3_security12_diag_feature {
+ __le32 feature_identifier;
+ u8 feature_size;
+ u8 feature_type;
+ __le16 reserved06;
+ u8 status;
+ u8 section;
+ __le16 reserved0a;
+ __le32 reserved0c;
+ u8 feature_data[64];
+};
+#define MPI3_SECURITY12_DIAG_FEATURE_STATUS_MASK (0x03)
+#define MPI3_SECURITY12_DIAG_FEATURE_STATUS_SHIFT (0)
+#define MPI3_SECURITY12_DIAG_FEATURE_STATUS_UNKNOWN (0x00)
+#define MPI3_SECURITY12_DIAG_FEATURE_STATUS_DISABLED (0x01)
+#define MPI3_SECURITY12_DIAG_FEATURE_STATUS_ENABLED (0x02)
+#define MPI3_SECURITY12_DIAG_FEATURE_SECTION_PROTECTED (0x00)
+#define MPI3_SECURITY12_DIAG_FEATURE_SECTION_UNPROTECTED (0x01)
+#define MPI3_SECURITY12_DIAG_FEATURE_SECTION_PAYLOAD (0x02)
+#define MPI3_SECURITY12_DIAG_FEATURE_SECTION_SIGNATURE (0x03)
+struct mpi3_security_page12 {
+ struct mpi3_config_page_header header;
+ __le32 reserved08[2];
+ u8 num_diag_features;
+ u8 reserved11[3];
+ __le32 reserved14[3];
+ struct mpi3_security12_diag_feature diag_feature[];
+};
+
#define MPI3_SECURITY2_PAGEVERSION (0x00)
struct mpi3_sas_io_unit0_phy_data {
u8 io_unit_port;
@@ -2314,6 +2398,8 @@ struct mpi3_device0_sas_sata_format {
u8 attached_phy_identifier;
u8 max_port_connections;
u8 zone_group;
+ u8 reserved10[3];
+ u8 negotiated_link_rate;
};
#define MPI3_DEVICE0_SASSATA_FLAGS_WRITE_SAME_UNMAP_NCQ (0x0400)
diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_image.h b/drivers/scsi/mpi3mr/mpi/mpi30_image.h
index 8d824107a678..62ddf094d46c 100644
--- a/drivers/scsi/mpi3mr/mpi/mpi30_image.h
+++ b/drivers/scsi/mpi3mr/mpi/mpi30_image.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
- * Copyright 2018-2023 Broadcom Inc. All rights reserved.
+ * Copyright 2018-2026 Broadcom Inc. All rights reserved.
*/
#ifndef MPI30_IMAGE_H
#define MPI30_IMAGE_H 1
@@ -135,7 +135,7 @@ struct mpi3_ci_manifest_mpi {
__le32 package_version_string_offset;
__le32 package_build_date_string_offset;
__le32 package_build_time_string_offset;
- __le32 reserved4c;
+ __le32 diag_authorization_key_offset;
__le32 diag_authorization_identifier[16];
struct mpi3_ci_manifest_mpi_comp_image_ref component_image_ref[MPI3_CI_MANIFEST_MPI_MAX];
};
@@ -148,16 +148,112 @@ struct mpi3_ci_manifest_mpi {
#define MPI3_CI_MANIFEST_MPI_RELEASE_LEVEL_GCA (0x50)
#define MPI3_CI_MANIFEST_MPI_RELEASE_LEVEL_POINT (0x60)
#define MPI3_CI_MANIFEST_MPI_FLAGS_DIAG_AUTHORIZATION (0x01)
+#define MPI3_CI_MANIFEST_MPI_FLAGS_DIAG_AUTH_ANCHOR_MASK (0x06)
+#define MPI3_CI_MANIFEST_MPI_FLAGS_DIAG_AUTH_ANCHOR_SHIFT (1)
+#define MPI3_CI_MANIFEST_MPI_FLAGS_DIAG_AUTH_ANCHOR_IDENTIFIER (0x00)
+#define MPI3_CI_MANIFEST_MPI_FLAGS_DIAG_AUTH_ANCHOR_KEY_OFFSET (0x02)
#define MPI3_CI_MANIFEST_MPI_SUBSYSTEMID_IGNORED (0xffff)
#define MPI3_CI_MANIFEST_MPI_PKG_VER_STR_OFF_UNSPECIFIED (0x00000000)
#define MPI3_CI_MANIFEST_MPI_PKG_BUILD_DATE_STR_OFF_UNSPECIFIED (0x00000000)
#define MPI3_CI_MANIFEST_MPI_PKG_BUILD_TIME_STR_OFF_UNSPECIFIED (0x00000000)
+
+struct mpi3_sb_manifest_ci_digest {
+ __le32 signature1;
+ __le32 reserved04[2];
+ u8 hash_algorithm;
+ u8 reserved09[3];
+ struct mpi3_comp_image_version component_image_version;
+ __le32 component_image_version_string_offset;
+ __le32 digest[16];
+};
+
+struct mpi3_sb_manifest_ci_ref_element {
+ u8 num_ci_digests;
+ u8 reserved01[3];
+ struct mpi3_sb_manifest_ci_digest ci_digest[];
+};
+
+struct mpi3_sb_manifest_embedded_key_element {
+ __le32 reserved00[3];
+ u8 key_algorithm;
+ u8 flags;
+ __le16 public_key_size;
+ __le32 start_tag;
+ __le32 public_key[];
+};
+
+#define MPI3_SB_MANIFEST_EMBEDDED_KEY_FLAGS_KEYINDEX_MASK (0x03)
+#define MPI3_SB_MANIFEST_EMBEDDED_KEY_FLAGS_KEYINDEX_STRT (0x00)
+#define MPI3_SB_MANIFEST_EMBEDDED_KEY_FLAGS_KEYINDEX_K2GO (0x01)
+#define MPI3_SB_MANIFEST_EMBEDDED_KEY_STARTTAG_STRT (0x54525453)
+#define MPI3_SB_MANIFEST_EMBEDDED_KEY_STARTTAG_K2GO (0x4f47324b)
+#define MPI3_SB_MANIFEST_EMBEDDED_KEY_ENDTAG_STOP (0x504f5453)
+#define MPI3_SB_MANIFEST_EMBEDDED_KEY_ENDTAG_K2ST (0x5453324b)
+
+struct mpi3_sb_manifest_diag_key_element {
+ __le32 reserved00[3];
+ u8 key_algorithm;
+ u8 flags;
+ __le16 public_key_size;
+ __le32 public_key[];
+};
+
+#define MPI3_SB_MANIFEST_DIAG_KEY_FLAGS_KEYINDEX_MASK (0x03)
+#define MPI3_SB_MANIFEST_DIAG_KEY_FLAGS_KEYSELECT_FW_KEY (0x04)
+union mpi3_sb_manifest_element_data {
+ struct mpi3_sb_manifest_ci_ref_element ci_ref;
+ struct mpi3_sb_manifest_embedded_key_element embed_key;
+ struct mpi3_sb_manifest_diag_key_element diag_key;
+ __le32 dword;
+};
+struct mpi3_sb_manifest_element {
+ u8 manifest_element_form;
+ u8 reserved01[3];
+ union mpi3_sb_manifest_element_data form_specific[];
+};
+#define MPI3_SB_MANIFEST_ELEMENT_FORM_CI_REFS (0x01)
+#define MPI3_SB_MANIFEST_ELEMENT_FORM_EMBED_KEY (0x02)
+#define MPI3_SB_MANIFEST_ELEMENT_FORM_DIAG_KEY (0x03)
+struct mpi3_sb_manifest_mpi {
+ u8 manifest_type;
+ u8 reserved01[3];
+ __le32 reserved04[3];
+ u8 reserved10;
+ u8 release_level;
+ __le16 reserved12;
+ __le16 reserved14;
+ __le16 flags;
+ __le32 reserved18[2];
+ __le16 vendor_id;
+ __le16 device_id;
+ __le16 subsystem_vendor_id;
+ __le16 subsystem_id;
+ __le32 reserved28[2];
+ union mpi3_version_union package_security_version;
+ __le32 reserved34;
+ struct mpi3_comp_image_version package_version;
+ __le32 package_version_string_offset;
+ __le32 package_build_date_string_offset;
+ __le32 package_build_time_string_offset;
+ __le32 component_image_references_offset;
+ __le32 embedded_key0offset;
+ __le32 embedded_key1offset;
+ __le32 diag_authorization_key_offset;
+ __le32 reserved5c[9];
+ struct mpi3_sb_manifest_element manifest_elements[];
+};
+
union mpi3_ci_manifest {
struct mpi3_ci_manifest_mpi mpi;
+ struct mpi3_sb_manifest_mpi sb_mpi;
__le32 dword[1];
};
-#define MPI3_CI_MANIFEST_TYPE_MPI (0x00)
+#define MPI3_SB_MANIFEST_APU_IMMEDIATE_DEFER_APU_ENABLE (0x01)
+
+#define MPI3_CI_MANIFEST_TYPE_MPI (0x00)
+#define MPI3_CI_MANIFEST_TYPE_SB (0x01)
+
struct mpi3_extended_image_header {
u8 image_type;
u8 reserved01[3];
diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_init.h b/drivers/scsi/mpi3mr/mpi/mpi30_init.h
index bbef5bac92ed..745e1101ebf4 100644
--- a/drivers/scsi/mpi3mr/mpi/mpi30_init.h
+++ b/drivers/scsi/mpi3mr/mpi/mpi30_init.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
- * Copyright 2016-2023 Broadcom Inc. All rights reserved.
+ * Copyright 2016-2026 Broadcom Inc. All rights reserved.
*/
#ifndef MPI30_INIT_H
#define MPI30_INIT_H 1
diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h b/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h
index 6561f98c3cb2..68efa0d51345 100644
--- a/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h
+++ b/drivers/scsi/mpi3mr/mpi/mpi30_ioc.h
@@ -662,6 +662,7 @@ struct mpi3_event_data_diag_buffer_status_change {
#define MPI3_EVENT_DIAG_BUFFER_STATUS_CHANGE_RC_RELEASED (0x01)
#define MPI3_EVENT_DIAG_BUFFER_STATUS_CHANGE_RC_PAUSED (0x02)
#define MPI3_EVENT_DIAG_BUFFER_STATUS_CHANGE_RC_RESUMED (0x03)
+#define MPI3_EVENT_DIAG_BUFFER_STATUS_CHANGE_RC_CLEARED (0x04)
#define MPI3_PEL_LOCALE_FLAGS_NON_BLOCKING_BOOT_EVENT (0x0200)
#define MPI3_PEL_LOCALE_FLAGS_BLOCKING_BOOT_EVENT (0x0100)
#define MPI3_PEL_LOCALE_FLAGS_PCIE (0x0080)
diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_pci.h b/drivers/scsi/mpi3mr/mpi/mpi30_pci.h
index 4eeb11c3c73e..3092dfe6d952 100644
--- a/drivers/scsi/mpi3mr/mpi/mpi30_pci.h
+++ b/drivers/scsi/mpi3mr/mpi/mpi30_pci.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
- * Copyright 2016-2023 Broadcom Inc. All rights reserved.
+ * Copyright 2016-2026 Broadcom Inc. All rights reserved.
*
*/
#ifndef MPI30_PCI_H
diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_sas.h b/drivers/scsi/mpi3mr/mpi/mpi30_sas.h
index 190b06508b00..f86da445df1e 100644
--- a/drivers/scsi/mpi3mr/mpi/mpi30_sas.h
+++ b/drivers/scsi/mpi3mr/mpi/mpi30_sas.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
- * Copyright 2016-2023 Broadcom Inc. All rights reserved.
+ * Copyright 2016-2026 Broadcom Inc. All rights reserved.
*/
#ifndef MPI30_SAS_H
#define MPI30_SAS_H 1
diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_tool.h b/drivers/scsi/mpi3mr/mpi/mpi30_tool.h
index 50a65b16a818..72d3e6bc52ec 100644
--- a/drivers/scsi/mpi3mr/mpi/mpi30_tool.h
+++ b/drivers/scsi/mpi3mr/mpi/mpi30_tool.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
- * Copyright 2016-2024 Broadcom Inc. All rights reserved.
+ * Copyright 2016-2026 Broadcom Inc. All rights reserved.
*/
#ifndef MPI30_TOOL_H
#define MPI30_TOOL_H 1
@@ -8,6 +8,10 @@
#define MPI3_DIAG_BUFFER_TYPE_TRACE (0x01)
#define MPI3_DIAG_BUFFER_TYPE_FW (0x02)
#define MPI3_DIAG_BUFFER_ACTION_RELEASE (0x01)
+#define MPI3_DIAG_BUFFER_ACTION_PAUSE (0x02)
+#define MPI3_DIAG_BUFFER_ACTION_RESUME (0x03)
+#define MPI3_DIAG_BUFFER_ACTION_CLEAR (0x04)
+
#define MPI3_DIAG_BUFFER_POST_MSGFLAGS_SEGMENTED (0x01)
struct mpi3_diag_buffer_post_request {
diff --git a/drivers/scsi/mpi3mr/mpi/mpi30_transport.h b/drivers/scsi/mpi3mr/mpi/mpi30_transport.h
index 28ab2efb3baa..290a1f5c2924 100644
--- a/drivers/scsi/mpi3mr/mpi/mpi30_transport.h
+++ b/drivers/scsi/mpi3mr/mpi/mpi30_transport.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
- * Copyright 2016-2023 Broadcom Inc. All rights reserved.
+ * Copyright 2016-2026 Broadcom Inc. All rights reserved.
*/
#ifndef MPI30_TRANSPORT_H
#define MPI30_TRANSPORT_H 1
@@ -18,7 +18,7 @@ union mpi3_version_union {
#define MPI3_VERSION_MAJOR (3)
#define MPI3_VERSION_MINOR (0)
-#define MPI3_VERSION_UNIT (37)
+#define MPI3_VERSION_UNIT (39)
#define MPI3_VERSION_DEV (0)
#define MPI3_DEVHANDLE_INVALID (0xffff)
struct mpi3_sysif_oper_queue_indexes {
diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h
index 31d68c151b20..6e962092577d 100644
--- a/drivers/scsi/mpi3mr/mpi3mr.h
+++ b/drivers/scsi/mpi3mr/mpi3mr.h
@@ -56,8 +56,8 @@ extern struct list_head mrioc_list;
extern int prot_mask;
extern atomic64_t event_counter;
-#define MPI3MR_DRIVER_VERSION "8.15.0.5.51"
-#define MPI3MR_DRIVER_RELDATE "18-November-2025"
+#define MPI3MR_DRIVER_VERSION "8.17.0.3.50"
+#define MPI3MR_DRIVER_RELDATE "09-January-2026"
#define MPI3MR_DRIVER_NAME "mpi3mr"
#define MPI3MR_DRIVER_LICENSE "GPL"
@@ -643,6 +643,7 @@ struct mpi3mr_enclosure_node {
* @dev_info: Device information bits
* @phy_id: Phy identifier provided in device page 0
* @attached_phy_id: Attached phy identifier provided in device page 0
+ * @negotiated_link_rate: Negotiated link rate from device page 0
* @sas_transport_attached: Is this device exposed to transport
* @pend_sas_rphy_add: Flag to check device is in process of add
* @hba_port: HBA port entry
@@ -654,6 +655,7 @@ struct tgt_dev_sas_sata {
u16 dev_info;
u8 phy_id;
u8 attached_phy_id;
+ u8 negotiated_link_rate;
u8 sas_transport_attached;
u8 pend_sas_rphy_add;
struct mpi3mr_hba_port *hba_port;
@@ -1076,7 +1078,6 @@ struct scmd_priv {
* @fwevt_worker_thread: Firmware event worker thread
* @fwevt_lock: Firmware event lock
* @fwevt_list: Firmware event list
- * @watchdog_work_q_name: Fault watchdog worker thread name
* @watchdog_work_q: Fault watchdog worker thread
* @watchdog_work: Fault watchdog work
* @watchdog_lock: Fault watchdog lock
@@ -1135,6 +1136,10 @@ struct scmd_priv {
* @default_qcount: Total Default queues
* @active_poll_qcount: Currently active poll queue count
* @requested_poll_qcount: User requested poll queue count
+ * @fault_during_init: Indicates a firmware fault occurred during initialization
+ * @saved_fault_code: Firmware fault code captured at the time of failure
+ * @saved_fault_info: Additional firmware-provided fault information
+ * @fwfault_counter: Count of firmware faults detected by the driver
* @bsg_dev: BSG device structure
* @bsg_queue: Request queue for BSG device
* @stop_bsgs: Stop BSG request flag
@@ -1265,7 +1270,6 @@ struct mpi3mr_ioc {
spinlock_t fwevt_lock;
struct list_head fwevt_list;
- char watchdog_work_q_name[50];
struct workqueue_struct *watchdog_work_q;
struct delayed_work watchdog_work;
spinlock_t watchdog_lock;
@@ -1338,6 +1342,10 @@ struct mpi3mr_ioc {
u16 default_qcount;
u16 active_poll_qcount;
u16 requested_poll_qcount;
+ u8 fault_during_init;
+ u32 saved_fault_code;
+ u32 saved_fault_info[3];
+ u64 fwfault_counter;
struct device bsg_dev;
struct request_queue *bsg_queue;
@@ -1508,7 +1516,7 @@ void mpi3mr_pel_get_seqnum_complete(struct mpi3mr_ioc *mrioc,
struct mpi3mr_drv_cmd *drv_cmd);
int mpi3mr_pel_get_seqnum_post(struct mpi3mr_ioc *mrioc,
struct mpi3mr_drv_cmd *drv_cmd);
-void mpi3mr_app_save_logdata(struct mpi3mr_ioc *mrioc, char *event_data,
+void mpi3mr_app_save_logdata_th(struct mpi3mr_ioc *mrioc, char *event_data,
u16 event_data_size);
struct mpi3mr_enclosure_node *mpi3mr_enclosure_find_by_handle(
struct mpi3mr_ioc *mrioc, u16 handle);
diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c
index 0e5478d62580..1353a8ff9c85 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_app.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_app.c
@@ -2920,7 +2920,7 @@ out:
}
/**
- * mpi3mr_app_save_logdata - Save Log Data events
+ * mpi3mr_app_save_logdata_th - Save Log Data events
* @mrioc: Adapter instance reference
* @event_data: event data associated with log data event
* @event_data_size: event data size to copy
@@ -2932,7 +2932,7 @@ out:
*
* Return:Nothing
*/
-void mpi3mr_app_save_logdata(struct mpi3mr_ioc *mrioc, char *event_data,
+void mpi3mr_app_save_logdata_th(struct mpi3mr_ioc *mrioc, char *event_data,
u16 event_data_size)
{
u32 index = mrioc->logdata_buf_idx, sz;
@@ -3255,6 +3255,29 @@ adp_state_show(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR_RO(adp_state);
+/**
+ * fwfault_count_show() - SysFS callback to show firmware fault count
+ * @dev: class device
+ * @attr: Device attribute
+ * @buf: Buffer to copy data into
+ *
+ * Displays the total number of firmware faults detected by the driver
+ * since the controller was initialized.
+ *
+ * Return: Number of bytes written to @buf
+ */
+
+static ssize_t
+fwfault_count_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct mpi3mr_ioc *mrioc = shost_priv(shost);
+
+ return snprintf(buf, PAGE_SIZE, "%llu\n", mrioc->fwfault_counter);
+}
+static DEVICE_ATTR_RO(fwfault_count);
+
static struct attribute *mpi3mr_host_attrs[] = {
&dev_attr_version_fw.attr,
&dev_attr_fw_queue_depth.attr,
@@ -3263,6 +3286,7 @@ static struct attribute *mpi3mr_host_attrs[] = {
&dev_attr_reply_qfull_count.attr,
&dev_attr_logging_level.attr,
&dev_attr_adp_state.attr,
+ &dev_attr_fwfault_count.attr,
NULL,
};
diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c
index 8c4bb7169a87..df984e9b5197 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_fw.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c
@@ -21,6 +21,10 @@ static int mpi3mr_check_op_admin_proc(struct mpi3mr_ioc *mrioc);
static int poll_queues;
module_param(poll_queues, int, 0444);
MODULE_PARM_DESC(poll_queues, "Number of queues for io_uring poll mode. (Range 1 - 126)");
+static bool threaded_isr_poll = true;
+module_param(threaded_isr_poll, bool, 0444);
+MODULE_PARM_DESC(threaded_isr_poll,
+ "Enablement of IRQ polling thread (default=true)");
#if defined(writeq) && defined(CONFIG_64BIT)
static inline void mpi3mr_writeq(__u64 b, void __iomem *addr,
@@ -595,7 +599,8 @@ int mpi3mr_process_op_reply_q(struct mpi3mr_ioc *mrioc,
* Exit completion loop to avoid CPU lockup
* Ensure remaining completion happens from threaded ISR.
*/
- if (num_op_reply > mrioc->max_host_ios) {
+ if ((num_op_reply > mrioc->max_host_ios) &&
+ (threaded_isr_poll == true)) {
op_reply_q->enable_irq_poll = true;
break;
}
@@ -692,7 +697,7 @@ static irqreturn_t mpi3mr_isr(int irq, void *privdata)
* If more IOs are expected, schedule IRQ polling thread.
* Otherwise exit from ISR.
*/
- if (!intr_info->op_reply_q)
+ if ((threaded_isr_poll == false) || !intr_info->op_reply_q)
return ret;
if (!intr_info->op_reply_q->enable_irq_poll ||
@@ -771,8 +776,8 @@ static inline int mpi3mr_request_irq(struct mpi3mr_ioc *mrioc, u16 index)
intr_info->msix_index = index;
intr_info->op_reply_q = NULL;
- snprintf(intr_info->name, MPI3MR_NAME_LENGTH, "%s%d-msix%d",
- mrioc->driver_name, mrioc->id, index);
+ scnprintf(intr_info->name, MPI3MR_NAME_LENGTH,
+ "%.32s%d-msix%u", mrioc->driver_name, mrioc->id, index);
#ifndef CONFIG_PREEMPT_RT
retval = request_threaded_irq(pci_irq_vector(pdev, index), mpi3mr_isr,
@@ -1104,6 +1109,31 @@ void mpi3mr_print_fault_info(struct mpi3mr_ioc *mrioc)
}
/**
+ * mpi3mr_save_fault_info - Save fault information
+ * @mrioc: Adapter instance reference
+ *
+ * Save the controller fault information if there is a
+ * controller fault.
+ *
+ * Return: Nothing.
+ */
+static void mpi3mr_save_fault_info(struct mpi3mr_ioc *mrioc)
+{
+ u32 ioc_status, i;
+
+ ioc_status = readl(&mrioc->sysif_regs->ioc_status);
+
+ if (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT) {
+ mrioc->saved_fault_code = readl(&mrioc->sysif_regs->fault) &
+ MPI3_SYSIF_FAULT_CODE_MASK;
+ for (i = 0; i < 3; i++) {
+ mrioc->saved_fault_info[i] =
+ readl(&mrioc->sysif_regs->fault_info[i]);
+ }
+ }
+}
+
+/**
* mpi3mr_get_iocstate - Get IOC State
* @mrioc: Adapter instance reference
*
@@ -1245,6 +1275,60 @@ out_failed:
}
/**
+ * mpi3mr_fault_uevent_emit - Emit uevent for any controller
+ * fault
+ * @mrioc: Pointer to the mpi3mr_ioc structure for the controller instance
+ *
+ * This function is invoked when the controller undergoes any
+ * type of fault.
+ */
+
+static void mpi3mr_fault_uevent_emit(struct mpi3mr_ioc *mrioc)
+{
+ struct kobj_uevent_env *env;
+ int ret;
+
+ env = kzalloc(sizeof(*env), GFP_KERNEL);
+ if (!env)
+ return;
+
+ ret = add_uevent_var(env, "DRIVER=%s", mrioc->driver_name);
+ if (ret)
+ goto out_free;
+
+ ret = add_uevent_var(env, "IOC_ID=%u", mrioc->id);
+ if (ret)
+ goto out_free;
+
+ ret = add_uevent_var(env, "FAULT_CODE=0x%08x",
+ mrioc->saved_fault_code);
+ if (ret)
+ goto out_free;
+
+ ret = add_uevent_var(env, "FAULT_INFO0=0x%08x",
+ mrioc->saved_fault_info[0]);
+ if (ret)
+ goto out_free;
+
+ ret = add_uevent_var(env, "FAULT_INFO1=0x%08x",
+ mrioc->saved_fault_info[1]);
+ if (ret)
+ goto out_free;
+
+ ret = add_uevent_var(env, "FAULT_INFO2=0x%08x",
+ mrioc->saved_fault_info[2]);
+ if (ret)
+ goto out_free;
+
+ kobject_uevent_env(&mrioc->shost->shost_gendev.kobj,
+ KOBJ_CHANGE, env->envp);
+
+out_free:
+ kfree(env);
+
+}
+
+/**
* mpi3mr_clear_reset_history - clear reset history
* @mrioc: Adapter instance reference
*
@@ -1475,6 +1559,10 @@ retry_bring_ioc_ready:
if (ioc_state == MRIOC_STATE_FAULT) {
timeout = MPI3_SYSIF_DIAG_SAVE_TIMEOUT * 10;
mpi3mr_print_fault_info(mrioc);
+ mpi3mr_save_fault_info(mrioc);
+ mrioc->fault_during_init = 1;
+ mrioc->fwfault_counter++;
+
do {
host_diagnostic =
readl(&mrioc->sysif_regs->host_diagnostic);
@@ -1701,7 +1789,9 @@ static int mpi3mr_issue_reset(struct mpi3mr_ioc *mrioc, u16 reset_type,
scratch_pad0 = ((MPI3MR_RESET_REASON_OSTYPE_LINUX <<
MPI3MR_RESET_REASON_OSTYPE_SHIFT) | (mrioc->facts.ioc_num <<
MPI3MR_RESET_REASON_IOCNUM_SHIFT) | reset_reason);
- writel(reset_reason, &mrioc->sysif_regs->scratchpad[0]);
+ writel(scratch_pad0, &mrioc->sysif_regs->scratchpad[0]);
+ if (reset_type == MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT)
+ mpi3mr_set_diagsave(mrioc);
writel(host_diagnostic | reset_type,
&mrioc->sysif_regs->host_diagnostic);
switch (reset_type) {
@@ -2570,6 +2660,9 @@ void mpi3mr_check_rh_fault_ioc(struct mpi3mr_ioc *mrioc, u32 reason_code)
mpi3mr_set_trigger_data_in_all_hdb(mrioc,
MPI3MR_HDB_TRIGGER_TYPE_FAULT, &trigger_data, 0);
mpi3mr_print_fault_info(mrioc);
+ mpi3mr_save_fault_info(mrioc);
+ mrioc->fault_during_init = 1;
+ mrioc->fwfault_counter++;
return;
}
@@ -2587,6 +2680,10 @@ void mpi3mr_check_rh_fault_ioc(struct mpi3mr_ioc *mrioc, u32 reason_code)
break;
msleep(100);
} while (--timeout);
+
+ mpi3mr_save_fault_info(mrioc);
+ mrioc->fault_during_init = 1;
+ mrioc->fwfault_counter++;
}
/**
@@ -2763,6 +2860,11 @@ static void mpi3mr_watchdog_work(struct work_struct *work)
union mpi3mr_trigger_data trigger_data;
u16 reset_reason = MPI3MR_RESET_FROM_FAULT_WATCH;
+ if (mrioc->fault_during_init) {
+ mpi3mr_fault_uevent_emit(mrioc);
+ mrioc->fault_during_init = 0;
+ }
+
if (mrioc->reset_in_progress || mrioc->pci_err_recovery)
return;
@@ -2835,6 +2937,10 @@ static void mpi3mr_watchdog_work(struct work_struct *work)
goto schedule_work;
}
+ mpi3mr_save_fault_info(mrioc);
+ mpi3mr_fault_uevent_emit(mrioc);
+ mrioc->fwfault_counter++;
+
switch (trigger_data.fault) {
case MPI3_SYSIF_FAULT_CODE_COMPLETE_RESET_NEEDED:
case MPI3_SYSIF_FAULT_CODE_POWER_CYCLE_REQUIRED:
@@ -2878,11 +2984,8 @@ void mpi3mr_start_watchdog(struct mpi3mr_ioc *mrioc)
return;
INIT_DELAYED_WORK(&mrioc->watchdog_work, mpi3mr_watchdog_work);
- snprintf(mrioc->watchdog_work_q_name,
- sizeof(mrioc->watchdog_work_q_name), "watchdog_%s%d", mrioc->name,
- mrioc->id);
mrioc->watchdog_work_q = alloc_ordered_workqueue(
- "%s", WQ_MEM_RECLAIM, mrioc->watchdog_work_q_name);
+ "watchdog_%s%d", WQ_MEM_RECLAIM, mrioc->name, mrioc->id);
if (!mrioc->watchdog_work_q) {
ioc_err(mrioc, "%s: failed (line=%d)\n", __func__, __LINE__);
return;
@@ -5401,6 +5504,7 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc,
{
int retval = 0, i;
unsigned long flags;
+ enum mpi3mr_iocstate ioc_state;
u32 host_diagnostic, timeout = MPI3_SYSIF_DIAG_SAVE_TIMEOUT * 10;
union mpi3mr_trigger_data trigger_data;
@@ -5459,7 +5563,6 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc,
mrioc->io_admin_reset_sync = 1;
if (snapdump) {
- mpi3mr_set_diagsave(mrioc);
retval = mpi3mr_issue_reset(mrioc,
MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, reset_reason);
if (!retval) {
@@ -5473,6 +5576,10 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc,
break;
msleep(100);
} while (--timeout);
+
+ mpi3mr_save_fault_info(mrioc);
+ mpi3mr_fault_uevent_emit(mrioc);
+ mrioc->fwfault_counter++;
mpi3mr_set_trigger_data_in_all_hdb(mrioc,
MPI3MR_HDB_TRIGGER_TYPE_FAULT, &trigger_data, 0);
}
@@ -5561,8 +5668,13 @@ out:
if (mrioc->pel_enabled)
atomic64_inc(&event_counter);
} else {
- mpi3mr_issue_reset(mrioc,
- MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, reset_reason);
+ dprint_reset(mrioc,
+ "soft_reset_handler failed, marking controller as unrecoverable\n");
+ ioc_state = mpi3mr_get_iocstate(mrioc);
+
+ if (ioc_state != MRIOC_STATE_FAULT)
+ mpi3mr_issue_reset(mrioc,
+ MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, reset_reason);
mrioc->device_refresh_on = 0;
mrioc->unrecoverable = 1;
mrioc->reset_in_progress = 0;
diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c
index d4ca878d0886..8e5abf620718 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_os.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_os.c
@@ -1139,6 +1139,89 @@ static void mpi3mr_refresh_tgtdevs(struct mpi3mr_ioc *mrioc)
}
/**
+ * mpi3mr_debug_dump_devpg0 - Dump device page0
+ * @mrioc: Adapter instance reference
+ * @dev_pg0: Device page 0.
+ *
+ * Prints pertinent details of the device page 0.
+ *
+ * Return: Nothing.
+ */
+static void
+mpi3mr_debug_dump_devpg0(struct mpi3mr_ioc *mrioc, struct mpi3_device_page0 *dev_pg0)
+{
+ ioc_info(mrioc,
+ "device_pg0: handle(0x%04x), perst_id(%d), wwid(0x%016llx), encl_handle(0x%04x), slot(%d)\n",
+ le16_to_cpu(dev_pg0->dev_handle),
+ le16_to_cpu(dev_pg0->persistent_id),
+ le64_to_cpu(dev_pg0->wwid), le16_to_cpu(dev_pg0->enclosure_handle),
+ le16_to_cpu(dev_pg0->slot));
+ ioc_info(mrioc, "device_pg0: access_status(0x%02x), flags(0x%04x), device_form(0x%02x), queue_depth(%d)\n",
+ dev_pg0->access_status, le16_to_cpu(dev_pg0->flags),
+ dev_pg0->device_form, le16_to_cpu(dev_pg0->queue_depth));
+ ioc_info(mrioc, "device_pg0: parent_handle(0x%04x), iounit_port(%d)\n",
+ le16_to_cpu(dev_pg0->parent_dev_handle), dev_pg0->io_unit_port);
+
+ switch (dev_pg0->device_form) {
+ case MPI3_DEVICE_DEVFORM_SAS_SATA:
+ {
+
+ struct mpi3_device0_sas_sata_format *sasinf =
+ &dev_pg0->device_specific.sas_sata_format;
+ ioc_info(mrioc,
+ "device_pg0: sas_sata: sas_address(0x%016llx),flags(0x%04x),\n"
+ "device_info(0x%04x), phy_num(%d), attached_phy_id(%d),negotiated_link_rate(0x%02x)\n",
+ le64_to_cpu(sasinf->sas_address),
+ le16_to_cpu(sasinf->flags),
+ le16_to_cpu(sasinf->device_info), sasinf->phy_num,
+ sasinf->attached_phy_identifier, sasinf->negotiated_link_rate);
+ break;
+ }
+ case MPI3_DEVICE_DEVFORM_PCIE:
+ {
+
+ struct mpi3_device0_pcie_format *pcieinf =
+ &dev_pg0->device_specific.pcie_format;
+ ioc_info(mrioc,
+ "device_pg0: pcie: port_num(%d), device_info(0x%04x), mdts(%d), page_sz(0x%02x)\n",
+ pcieinf->port_num, le16_to_cpu(pcieinf->device_info),
+ le32_to_cpu(pcieinf->maximum_data_transfer_size),
+ pcieinf->page_size);
+ ioc_info(mrioc,
+ "device_pg0: pcie: abort_timeout(%d), reset_timeout(%d) capabilities (0x%08x)\n",
+ pcieinf->nvme_abort_to, pcieinf->controller_reset_to,
+ le32_to_cpu(pcieinf->capabilities));
+ break;
+ }
+ case MPI3_DEVICE_DEVFORM_VD:
+ {
+
+ struct mpi3_device0_vd_format *vdinf =
+ &dev_pg0->device_specific.vd_format;
+
+ ioc_info(mrioc,
+ "device_pg0: vd: state(0x%02x), raid_level(%d), flags(0x%04x),\n"
+ "device_info(0x%04x) abort_timeout(%d), reset_timeout(%d)\n",
+ vdinf->vd_state, vdinf->raid_level,
+ le16_to_cpu(vdinf->flags),
+ le16_to_cpu(vdinf->device_info),
+ vdinf->vd_abort_to, vdinf->vd_reset_to);
+ ioc_info(mrioc,
+ "device_pg0: vd: tg_id(%d), high(%dMiB), low(%dMiB), qd_reduction_factor(%d)\n",
+ vdinf->io_throttle_group,
+ le16_to_cpu(vdinf->io_throttle_group_high),
+ le16_to_cpu(vdinf->io_throttle_group_low),
+ ((le16_to_cpu(vdinf->flags) &
+ MPI3_DEVICE0_VD_FLAGS_IO_THROTTLE_GROUP_QD_MASK) >> 12));
+ break;
+
+ }
+ default:
+ break;
+ }
+}
+
+/**
* mpi3mr_update_tgtdev - DevStatusChange evt bottomhalf
* @mrioc: Adapter instance reference
* @tgtdev: Target device internal structure
@@ -1159,6 +1242,10 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc,
struct mpi3mr_enclosure_node *enclosure_dev = NULL;
u8 prot_mask = 0;
+ if (mrioc->logging_level &
+ (MPI3_DEBUG_EVENT | MPI3_DEBUG_EVENT_WORK_TASK))
+ mpi3mr_debug_dump_devpg0(mrioc, dev_pg0);
+
tgtdev->perst_id = le16_to_cpu(dev_pg0->persistent_id);
tgtdev->dev_handle = le16_to_cpu(dev_pg0->dev_handle);
tgtdev->dev_type = dev_pg0->device_form;
@@ -1237,6 +1324,8 @@ static void mpi3mr_update_tgtdev(struct mpi3mr_ioc *mrioc,
tgtdev->dev_spec.sas_sata_inf.phy_id = sasinf->phy_num;
tgtdev->dev_spec.sas_sata_inf.attached_phy_id =
sasinf->attached_phy_identifier;
+ tgtdev->dev_spec.sas_sata_inf.negotiated_link_rate =
+ sasinf->negotiated_link_rate;
if ((dev_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) !=
MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_END_DEVICE)
tgtdev->is_hidden = 1;
@@ -1962,7 +2051,7 @@ static void mpi3mr_pcietopochg_evt_bh(struct mpi3mr_ioc *mrioc,
static void mpi3mr_logdata_evt_bh(struct mpi3mr_ioc *mrioc,
struct mpi3mr_fwevt *fwevt)
{
- mpi3mr_app_save_logdata(mrioc, fwevt->event_data,
+ mpi3mr_app_save_logdata_th(mrioc, fwevt->event_data,
fwevt->event_data_size);
}
@@ -3058,6 +3147,11 @@ void mpi3mr_os_handle_events(struct mpi3mr_ioc *mrioc,
}
case MPI3_EVENT_DEVICE_INFO_CHANGED:
case MPI3_EVENT_LOG_DATA:
+
+ sz = event_reply->event_data_length * 4;
+ mpi3mr_app_save_logdata_th(mrioc,
+ (char *)event_reply->event_data, sz);
+ break;
case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE:
case MPI3_EVENT_ENCL_DEVICE_ADDED:
{
@@ -5029,8 +5123,8 @@ inline bool mpi3mr_allow_scmd_to_fw(struct scsi_cmnd *scmd)
* SCSI_MLQUEUE_DEVICE_BUSY when the device is busy.
* SCSI_MLQUEUE_HOST_BUSY when the host queue is full.
*/
-static int mpi3mr_qcmd(struct Scsi_Host *shost,
- struct scsi_cmnd *scmd)
+static enum scsi_qc_status mpi3mr_qcmd(struct Scsi_Host *shost,
+ struct scsi_cmnd *scmd)
{
struct mpi3mr_ioc *mrioc = shost_priv(shost);
struct mpi3mr_stgt_priv_data *stgt_priv_data;
@@ -5381,8 +5475,10 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (retval < 0)
goto id_alloc_failed;
mrioc->id = (u8)retval;
- sprintf(mrioc->driver_name, "%s", MPI3MR_DRIVER_NAME);
- sprintf(mrioc->name, "%s%d", mrioc->driver_name, mrioc->id);
+ strscpy(mrioc->driver_name, MPI3MR_DRIVER_NAME,
+ sizeof(mrioc->driver_name));
+ scnprintf(mrioc->name, sizeof(mrioc->name),
+ "%s%u", mrioc->driver_name, mrioc->id);
INIT_LIST_HEAD(&mrioc->list);
spin_lock(&mrioc_list_lock);
list_add_tail(&mrioc->list, &mrioc_list);
@@ -5983,7 +6079,10 @@ static struct pci_driver mpi3mr_pci_driver = {
.remove = mpi3mr_remove,
.shutdown = mpi3mr_shutdown,
.err_handler = &mpi3mr_err_handler,
- .driver.pm = &mpi3mr_pm_ops,
+ .driver = {
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+ .pm = &mpi3mr_pm_ops,
+ },
};
static ssize_t event_counter_show(struct device_driver *dd, char *buf)
diff --git a/drivers/scsi/mpi3mr/mpi3mr_transport.c b/drivers/scsi/mpi3mr/mpi3mr_transport.c
index d70f002d6487..101161554ef1 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_transport.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_transport.c
@@ -2284,11 +2284,11 @@ void mpi3mr_expander_remove(struct mpi3mr_ioc *mrioc, u64 sas_address,
* @mrioc: Adapter instance reference
* @tgtdev: Target device
*
- * This function identifies whether the target device is
- * attached directly or through expander and issues sas phy
- * page0 or expander phy page1 and gets the link rate, if there
- * is any failure in reading the pages then this returns link
- * rate of 1.5.
+ * This function first tries to use the link rate from DevicePage0
+ * (populated by firmware during device discovery). If the cached
+ * value is not available or invalid, it falls back to reading from
+ * sas phy page0 or expander phy page1.
+ *
*
* Return: logical link rate.
*/
@@ -2301,6 +2301,14 @@ static u8 mpi3mr_get_sas_negotiated_logical_linkrate(struct mpi3mr_ioc *mrioc,
u32 phynum_handle;
u16 ioc_status;
+ /* First, try to use link rate from DevicePage0 (populated by firmware) */
+ if (tgtdev->dev_spec.sas_sata_inf.negotiated_link_rate >=
+ MPI3_SAS_NEG_LINK_RATE_1_5) {
+ link_rate = tgtdev->dev_spec.sas_sata_inf.negotiated_link_rate;
+ goto out;
+ }
+
+ /* Fallback to reading from phy pages if DevicePage0 value not available */
phy_number = tgtdev->dev_spec.sas_sata_inf.phy_id;
if (!(tgtdev->devpg0_flag & MPI3_DEVICE0_FLAGS_ATT_METHOD_DIR_ATTACHED)) {
phynum_handle = ((phy_number<<MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT)
@@ -2318,9 +2326,7 @@ static u8 mpi3mr_get_sas_negotiated_logical_linkrate(struct mpi3mr_ioc *mrioc,
__FILE__, __LINE__, __func__);
goto out;
}
- link_rate = (expander_pg1.negotiated_link_rate &
- MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
- MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
+ link_rate = expander_pg1.negotiated_link_rate;
goto out;
}
if (mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0,
@@ -2335,11 +2341,11 @@ static u8 mpi3mr_get_sas_negotiated_logical_linkrate(struct mpi3mr_ioc *mrioc,
__FILE__, __LINE__, __func__);
goto out;
}
- link_rate = (phy_pg0.negotiated_link_rate &
- MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
- MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
+ link_rate = phy_pg0.negotiated_link_rate;
+
out:
- return link_rate;
+ return ((link_rate & MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
+ MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT);
}
/**
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 0d652db8fe24..2f2183f405c9 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -843,11 +843,8 @@ mpt3sas_base_start_watchdog(struct MPT3SAS_ADAPTER *ioc)
/* initialize fault polling */
INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work);
- snprintf(ioc->fault_reset_work_q_name,
- sizeof(ioc->fault_reset_work_q_name), "poll_%s%d_status",
- ioc->driver_name, ioc->id);
ioc->fault_reset_work_q = alloc_ordered_workqueue(
- "%s", WQ_MEM_RECLAIM, ioc->fault_reset_work_q_name);
+ "poll_%s%d_status", WQ_MEM_RECLAIM, ioc->driver_name, ioc->id);
if (!ioc->fault_reset_work_q) {
ioc_err(ioc, "%s: failed (line=%d)\n", __func__, __LINE__);
return;
@@ -1564,6 +1561,8 @@ _base_get_cb_idx(struct MPT3SAS_ADAPTER *ioc, u16 smid)
int i;
u16 ctl_smid = ioc->scsiio_depth - INTERNAL_SCSIIO_CMDS_COUNT + 1;
u8 cb_idx = 0xFF;
+ u16 discovery_smid =
+ ioc->shost->can_queue + INTERNAL_SCSIIO_FOR_DISCOVERY;
if (smid < ioc->hi_priority_smid) {
struct scsiio_tracker *st;
@@ -1572,8 +1571,10 @@ _base_get_cb_idx(struct MPT3SAS_ADAPTER *ioc, u16 smid)
st = _get_st_from_smid(ioc, smid);
if (st)
cb_idx = st->cb_idx;
- } else if (smid == ctl_smid)
+ } else if (smid < discovery_smid)
cb_idx = ioc->ctl_cb_idx;
+ else
+ cb_idx = ioc->scsih_cb_idx;
} else if (smid < ioc->internal_smid) {
i = smid - ioc->hi_priority_smid;
cb_idx = ioc->hpr_lookup[i].cb_idx;
@@ -3174,7 +3175,7 @@ _base_request_irq(struct MPT3SAS_ADAPTER *ioc, u8 index)
if (index >= ioc->iopoll_q_start_index) {
qid = index - ioc->iopoll_q_start_index;
- snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d-mq-poll%d",
+ scnprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d-mq-poll%d",
ioc->driver_name, ioc->id, qid);
reply_q->is_iouring_poll_q = 1;
ioc->io_uring_poll_queues[qid].reply_q = reply_q;
@@ -3183,10 +3184,10 @@ _base_request_irq(struct MPT3SAS_ADAPTER *ioc, u8 index)
if (ioc->msix_enable)
- snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d-msix%d",
+ scnprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d-msix%d",
ioc->driver_name, ioc->id, index);
else
- snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d",
+ scnprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d",
ioc->driver_name, ioc->id);
r = request_irq(pci_irq_vector(pdev, index), _base_interrupt,
IRQF_SHARED, reply_q->name, reply_q);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
index e6a6f21d309b..d4597d058705 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -147,6 +147,7 @@
#define INTERNAL_CMDS_COUNT 10 /* reserved cmds */
/* reserved for issuing internally framed scsi io cmds */
#define INTERNAL_SCSIIO_CMDS_COUNT 3
+#define INTERNAL_SCSIIO_FOR_DISCOVERY 2
#define MPI3_HIM_MASK 0xFFFFFFFF /* mask every bit*/
@@ -480,6 +481,7 @@ struct MPT3SAS_DEVICE {
u32 flags;
u8 configured_lun;
u8 block;
+ u8 deleted;
u8 tlr_snoop_check;
u8 ignore_delay_remove;
/* Iopriority Command Handling */
@@ -577,7 +579,9 @@ struct _sas_device {
u8 chassis_slot;
u8 is_chassis_slot_valid;
u8 connector_name[5];
+ u8 ssd_device;
struct kref refcount;
+
u8 port_type;
struct hba_port *port;
struct sas_rphy *rphy;
@@ -1159,9 +1163,8 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
* @mask_interrupts: ignore interrupt
* @pci_access_mutex: Mutex to synchronize ioctl, sysfs show path and
* pci resource handling
- * @fault_reset_work_q_name: fw fault work queue
- * @fault_reset_work_q: ""
- * @fault_reset_work: ""
+ * @fault_reset_work_q: fw fault workqueue
+ * @fault_reset_work: fw fault work
* @firmware_event_thread: fw event work queue
* @fw_event_lock:
* @fw_event_list: list of fw events
@@ -1345,7 +1348,6 @@ struct MPT3SAS_ADAPTER {
u8 mask_interrupts;
/* fw fault handler */
- char fault_reset_work_q_name[20];
struct workqueue_struct *fault_reset_work_q;
struct delayed_work fault_reset_work;
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 7092d0debef3..26a13b622c95 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -61,6 +61,8 @@
#define PCIE_CHANNEL 2
+#define MPT3_MAX_LUNS (255)
+
/* forward proto's */
static void _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc,
struct _sas_node *sas_expander);
@@ -70,13 +72,24 @@ static void _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc,
struct _sas_device *sas_device);
static int _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle,
u8 retry_count, u8 is_pd);
-static int _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle);
+static int _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle,
+ u8 retry_count);
static void _scsih_pcie_device_remove_from_sml(struct MPT3SAS_ADAPTER *ioc,
struct _pcie_device *pcie_device);
static void
_scsih_pcie_check_device(struct MPT3SAS_ADAPTER *ioc, u16 handle);
static u8 _scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid);
static void _scsih_complete_devices_scanning(struct MPT3SAS_ADAPTER *ioc);
+static enum device_responsive_state
+_scsih_wait_for_target_to_become_ready(struct MPT3SAS_ADAPTER *ioc, u16 handle,
+ u8 retry_count, u8 is_pd, u8 tr_timeout, u8 tr_method);
+static enum device_responsive_state
+_scsih_ata_pass_thru_idd(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 *is_ssd_device,
+ u8 tr_timeout, u8 tr_method);
+static enum device_responsive_state
+_scsih_wait_for_device_to_become_ready(struct MPT3SAS_ADAPTER *ioc, u16 handle,
+ u8 retry_count, u8 is_pd, int lun, u8 tr_timeout, u8 tr_method);
+static void _firmware_event_work_delayed(struct work_struct *work);
/* global parameters */
LIST_HEAD(mpt3sas_ioc_list);
@@ -159,6 +172,15 @@ module_param(enable_sdev_max_qd, bool, 0444);
MODULE_PARM_DESC(enable_sdev_max_qd,
"Enable sdev max qd as can_queue, def=disabled(0)");
+/*
+ * permit overriding the SCSI command issuing capability of
+ * the driver to bring the drive to READY state
+ */
+static int issue_scsi_cmd_to_bringup_drive = 1;
+module_param(issue_scsi_cmd_to_bringup_drive, int, 0444);
+MODULE_PARM_DESC(issue_scsi_cmd_to_bringup_drive, "allow host driver to\n"
+ "issue SCSI commands to bring the drive to READY state, default=1 ");
+
static int multipath_on_hba = -1;
module_param(multipath_on_hba, int, 0);
MODULE_PARM_DESC(multipath_on_hba,
@@ -173,10 +195,33 @@ module_param(host_tagset_enable, int, 0444);
MODULE_PARM_DESC(host_tagset_enable,
"Shared host tagset enable/disable Default: enable(1)");
+static int command_retry_count = 144;
+module_param(command_retry_count, int, 0444);
+MODULE_PARM_DESC(command_retry_count, "Device discovery TUR command retry\n"
+ "count: (default=144)");
+
/* raid transport support */
static struct raid_template *mpt3sas_raid_template;
static struct raid_template *mpt2sas_raid_template;
+/**
+ * enum device_responsive_state - responsive state
+ * @DEVICE_READY: device is ready to be added
+ * @DEVICE_RETRY: device can be retried later
+ * @DEVICE_RETRY_UA: retry unit attentions
+ * @DEVICE_START_UNIT: requires start unit
+ * @DEVICE_STOP_UNIT: requires stop unit
+ * @DEVICE_ERROR: device reported some fatal error
+ *
+ */
+enum device_responsive_state {
+ DEVICE_READY,
+ DEVICE_RETRY,
+ DEVICE_RETRY_UA,
+ DEVICE_START_UNIT,
+ DEVICE_STOP_UNIT,
+ DEVICE_ERROR,
+};
/**
* struct sense_info - common structure for obtaining sense keys
@@ -205,6 +250,9 @@ struct sense_info {
/**
* struct fw_event_work - firmware event struct
+ * @retries: retry count for processing the event
+ * @delayed_work_active: flag indicating if delayed work is active
+ * @delayed_work: delayed work item for deferred event handling
* @list: link list framework
* @work: work object (ioc->fault_reset_work_q)
* @ioc: per adapter object
@@ -219,6 +267,9 @@ struct sense_info {
* This object stored on ioc->fw_event_list.
*/
struct fw_event_work {
+ u8 *retries;
+ u8 delayed_work_active;
+ struct delayed_work delayed_work;
struct list_head list;
struct work_struct work;
@@ -230,11 +281,16 @@ struct fw_event_work {
u16 event;
struct kref refcount;
char event_data[] __aligned(4);
+
};
static void fw_event_work_free(struct kref *r)
{
- kfree(container_of(r, struct fw_event_work, refcount));
+ struct fw_event_work *fw_work;
+
+ fw_work = container_of(r, struct fw_event_work, refcount);
+ kfree(fw_work->retries);
+ kfree(fw_work);
}
static void fw_event_work_get(struct fw_event_work *fw_work)
@@ -955,6 +1011,7 @@ _scsih_sas_device_remove(struct MPT3SAS_ADAPTER *ioc,
sas_device_put(sas_device);
}
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
}
/**
@@ -2528,6 +2585,8 @@ scsih_sdev_configure(struct scsi_device *sdev, struct queue_limits *lim)
char *r_level = "";
u16 handle, volume_handle = 0;
u64 volume_wwid = 0;
+ enum device_responsive_state retval;
+ u8 count = 0;
qdepth = 1;
sas_device_priv_data = sdev->hostdata;
@@ -2686,6 +2745,7 @@ scsih_sdev_configure(struct scsi_device *sdev, struct queue_limits *lim)
pcie_device_put(pcie_device);
spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);
+
mpt3sas_scsih_change_queue_depth(sdev, qdepth);
lim->virt_boundary_mask = ioc->page_size - 1;
return 0;
@@ -2737,9 +2797,16 @@ scsih_sdev_configure(struct scsi_device *sdev, struct queue_limits *lim)
sas_device_put(sas_device);
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- if (!ssp_target)
+ if (!ssp_target) {
_scsih_display_sata_capabilities(ioc, handle, sdev);
+ do {
+ retval = _scsih_ata_pass_thru_idd(ioc, handle,
+ &sas_device->ssd_device, 30, 0);
+ } while ((retval == DEVICE_RETRY || retval == DEVICE_RETRY_UA)
+ && count++ < 3);
+ }
+
mpt3sas_scsih_change_queue_depth(sdev, qdepth);
@@ -3595,6 +3662,37 @@ _scsih_fw_event_del_from_list(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work
spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
}
+/**
+ * _scsih_fw_event_requeue - requeue an event
+ * @ioc: per adapter object
+ * @fw_event: object describing the event
+ * @delay: time in milliseconds to wait before retrying the event
+ *
+ * Context: This function will acquire ioc->fw_event_lock.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_fw_event_requeue(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work
+ *fw_event, unsigned long delay)
+{
+ unsigned long flags;
+
+ if (ioc->firmware_event_thread == NULL)
+ return;
+
+ spin_lock_irqsave(&ioc->fw_event_lock, flags);
+ fw_event_work_get(fw_event);
+ list_add_tail(&fw_event->list, &ioc->fw_event_list);
+ if (!fw_event->delayed_work_active) {
+ fw_event->delayed_work_active = 1;
+ INIT_DELAYED_WORK(&fw_event->delayed_work,
+ _firmware_event_work_delayed);
+ }
+ queue_delayed_work(ioc->firmware_event_thread, &fw_event->delayed_work,
+ msecs_to_jiffies(delay));
+ spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+}
/**
* mpt3sas_send_trigger_data_event - send event for processing trigger data
@@ -3825,29 +3923,235 @@ _scsih_internal_device_unblock(struct scsi_device *sdev,
/**
* _scsih_ublock_io_all_device - unblock every device
* @ioc: per adapter object
+ * @no_turs: flag to disable TEST UNIT READY checks during device unblocking
*
* change the device state from block to running
*/
static void
-_scsih_ublock_io_all_device(struct MPT3SAS_ADAPTER *ioc)
+_scsih_ublock_io_all_device(struct MPT3SAS_ADAPTER *ioc, u8 no_turs)
{
struct MPT3SAS_DEVICE *sas_device_priv_data;
struct scsi_device *sdev;
+ struct MPT3SAS_TARGET *sas_target;
+ enum device_responsive_state rc;
+ struct _sas_device *sas_device = NULL;
+ struct _pcie_device *pcie_device = NULL;
+ int count = 0;
+ u8 tr_method = 0;
+ u8 tr_timeout = 30;
+
shost_for_each_device(sdev, ioc->shost) {
sas_device_priv_data = sdev->hostdata;
if (!sas_device_priv_data)
continue;
+
+ sas_target = sas_device_priv_data->sas_target;
+ if (!sas_target || sas_target->deleted)
+ continue;
+
if (!sas_device_priv_data->block)
continue;
- dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
- "device_running, handle(0x%04x)\n",
- sas_device_priv_data->sas_target->handle));
+ if ((no_turs) || (!issue_scsi_cmd_to_bringup_drive)) {
+ sdev_printk(KERN_WARNING, sdev, "device_unblocked handle(0x%04x)\n",
+ sas_device_priv_data->sas_target->handle);
+ _scsih_internal_device_unblock(sdev, sas_device_priv_data);
+ continue;
+ }
+
+ do {
+ pcie_device = mpt3sas_get_pdev_by_handle(ioc, sas_target->handle);
+ if (pcie_device && (!ioc->tm_custom_handling) &&
+ (!(mpt3sas_scsih_is_pcie_scsi_device(pcie_device->device_info)))) {
+ tr_timeout = pcie_device->reset_timeout;
+ tr_method = MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE;
+ }
+ rc = _scsih_wait_for_device_to_become_ready(ioc,
+ sas_target->handle, 0, (sas_target->flags &
+ MPT_TARGET_FLAGS_RAID_COMPONENT), sdev->lun, tr_timeout, tr_method);
+ if (rc == DEVICE_RETRY || rc == DEVICE_START_UNIT ||
+ rc == DEVICE_STOP_UNIT || rc == DEVICE_RETRY_UA)
+ ssleep(1);
+ if (pcie_device)
+ pcie_device_put(pcie_device);
+ } while ((rc == DEVICE_RETRY || rc == DEVICE_START_UNIT ||
+ rc == DEVICE_STOP_UNIT || rc == DEVICE_RETRY_UA)
+ && count++ < command_retry_count);
+ sas_device_priv_data->block = 0;
+ if (rc != DEVICE_READY)
+ sas_device_priv_data->deleted = 1;
+
_scsih_internal_device_unblock(sdev, sas_device_priv_data);
+
+ if (rc != DEVICE_READY) {
+ sdev_printk(KERN_WARNING, sdev, "%s: device_offlined,\n"
+ "handle(0x%04x)\n",
+ __func__, sas_device_priv_data->sas_target->handle);
+ scsi_device_set_state(sdev, SDEV_OFFLINE);
+ sas_device = mpt3sas_get_sdev_by_addr(ioc,
+ sas_device_priv_data->sas_target->sas_address,
+ sas_device_priv_data->sas_target->port);
+ if (sas_device) {
+ _scsih_display_enclosure_chassis_info(NULL, sas_device, sdev, NULL);
+ sas_device_put(sas_device);
+ } else {
+ pcie_device = mpt3sas_get_pdev_by_wwid(ioc,
+ sas_device_priv_data->sas_target->sas_address);
+ if (pcie_device) {
+ if (pcie_device->enclosure_handle != 0)
+ sdev_printk(KERN_INFO, sdev, "enclosure logical id\n"
+ "(0x%016llx), slot(%d)\n", (unsigned long long)
+ pcie_device->enclosure_logical_id,
+ pcie_device->slot);
+ if (pcie_device->connector_name[0] != '\0')
+ sdev_printk(KERN_INFO, sdev, "enclosure level(0x%04x),\n"
+ " connector name( %s)\n",
+ pcie_device->enclosure_level,
+ pcie_device->connector_name);
+ pcie_device_put(pcie_device);
+ }
+ }
+ } else
+ sdev_printk(KERN_WARNING, sdev, "device_unblocked,\n"
+ "handle(0x%04x)\n",
+ sas_device_priv_data->sas_target->handle);
}
}
+/**
+ * _scsih_ublock_io_device_wait - unblock IO for target
+ * @ioc: per adapter object
+ * @sas_address: sas address
+ * @port: hba port entry
+ *
+ * make sure device is reponsponding before unblocking
+ */
+static void
+_scsih_ublock_io_device_wait(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
+ struct hba_port *port)
+{
+ struct MPT3SAS_DEVICE *sas_device_priv_data;
+ struct MPT3SAS_TARGET *sas_target;
+ enum device_responsive_state rc;
+ struct scsi_device *sdev;
+ int host_reset_completion_count;
+ struct _sas_device *sas_device;
+ struct _pcie_device *pcie_device;
+ u8 tr_timeout = 30;
+ u8 tr_method = 0;
+ int count = 0;
+
+ /* moving devices from SDEV_OFFLINE to SDEV_BLOCK */
+ shost_for_each_device(sdev, ioc->shost) {
+ sas_device_priv_data = sdev->hostdata;
+ if (!sas_device_priv_data)
+ continue;
+ sas_target = sas_device_priv_data->sas_target;
+ if (!sas_target)
+ continue;
+ if (sas_target->sas_address != sas_address ||
+ sas_target->port != port)
+ continue;
+ if (sdev->sdev_state == SDEV_OFFLINE) {
+ sas_device_priv_data->block = 1;
+ sas_device_priv_data->deleted = 0;
+ scsi_device_set_state(sdev, SDEV_RUNNING);
+ scsi_internal_device_block_nowait(sdev);
+ }
+ }
+
+ /* moving devices from SDEV_BLOCK to SDEV_RUNNING state */
+ shost_for_each_device(sdev, ioc->shost) {
+ sas_device_priv_data = sdev->hostdata;
+ if (!sas_device_priv_data)
+ continue;
+ sas_target = sas_device_priv_data->sas_target;
+ if (!sas_target)
+ continue;
+ if (sas_target->sas_address != sas_address ||
+ sas_target->port != port)
+ continue;
+ if (!sas_device_priv_data->block)
+ continue;
+
+ do {
+ host_reset_completion_count = 0;
+ pcie_device = mpt3sas_get_pdev_by_handle(ioc, sas_target->handle);
+ if (pcie_device && (!ioc->tm_custom_handling) &&
+ (!(mpt3sas_scsih_is_pcie_scsi_device(pcie_device->device_info)))) {
+ tr_timeout = pcie_device->reset_timeout;
+ tr_method = MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE;
+ }
+ rc = _scsih_wait_for_device_to_become_ready(ioc,
+ sas_target->handle, 0, (sas_target->flags &
+ MPT_TARGET_FLAGS_RAID_COMPONENT), sdev->lun, tr_timeout, tr_method);
+ if (rc == DEVICE_RETRY || rc == DEVICE_START_UNIT ||
+ rc == DEVICE_STOP_UNIT || rc == DEVICE_RETRY_UA) {
+ do {
+ msleep(500);
+ host_reset_completion_count++;
+ } while (rc == DEVICE_RETRY &&
+ ioc->shost_recovery);
+ if (host_reset_completion_count > 1) {
+ rc = _scsih_wait_for_device_to_become_ready(ioc,
+ sas_target->handle, 0, (sas_target->flags &
+ MPT_TARGET_FLAGS_RAID_COMPONENT), sdev->lun,
+ tr_timeout, tr_method);
+ if (rc == DEVICE_RETRY || rc == DEVICE_START_UNIT ||
+ rc == DEVICE_STOP_UNIT || rc == DEVICE_RETRY_UA)
+ msleep(500);
+ }
+ continue;
+ }
+ if (pcie_device)
+ pcie_device_put(pcie_device);
+ } while ((rc == DEVICE_RETRY || rc == DEVICE_START_UNIT ||
+ rc == DEVICE_STOP_UNIT || rc == DEVICE_RETRY_UA)
+ && count++ <= command_retry_count);
+
+ sas_device_priv_data->block = 0;
+ if (rc != DEVICE_READY)
+ sas_device_priv_data->deleted = 1;
+ scsi_internal_device_unblock_nowait(sdev, SDEV_RUNNING);
+
+ if (rc != DEVICE_READY) {
+ sdev_printk(KERN_WARNING, sdev,
+ "%s: device_offlined, handle(0x%04x)\n",
+ __func__, sas_device_priv_data->sas_target->handle);
+
+ sas_device = mpt3sas_get_sdev_by_handle(ioc,
+ sas_device_priv_data->sas_target->handle);
+ if (sas_device) {
+ _scsih_display_enclosure_chassis_info(NULL, sas_device, sdev, NULL);
+ sas_device_put(sas_device);
+ } else {
+ pcie_device = mpt3sas_get_pdev_by_handle(ioc,
+ sas_device_priv_data->sas_target->handle);
+ if (pcie_device) {
+ if (pcie_device->enclosure_handle != 0)
+ sdev_printk(KERN_INFO, sdev,
+ "device_offlined, enclosure logical id(0x%016llx),\n"
+ " slot(%d)\n", (unsigned long long)
+ pcie_device->enclosure_logical_id,
+ pcie_device->slot);
+ if (pcie_device->connector_name[0] != '\0')
+ sdev_printk(KERN_WARNING, sdev,
+ "device_offlined, enclosure level(0x%04x),\n"
+ "connector name( %s)\n",
+ pcie_device->enclosure_level,
+ pcie_device->connector_name);
+ pcie_device_put(pcie_device);
+ }
+ }
+ scsi_device_set_state(sdev, SDEV_OFFLINE);
+ } else {
+ sdev_printk(KERN_WARNING, sdev,
+ "device_unblocked, handle(0x%04x)\n",
+ sas_device_priv_data->sas_target->handle);
+ }
+ }
+}
/**
* _scsih_ublock_io_device - prepare device to be deleted
@@ -5118,8 +5422,8 @@ _scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status)
* SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or
* SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full
*/
-static int
-scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
+static enum scsi_qc_status scsih_qcmd(struct Scsi_Host *shost,
+ struct scsi_cmnd *scmd)
{
struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
struct MPT3SAS_DEVICE *sas_device_priv_data;
@@ -7108,10 +7412,769 @@ _scsih_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
return 1;
}
+/**
+ * _scsi_send_scsi_io - send internal SCSI_IO to target
+ * @ioc: per adapter object
+ * @transfer_packet: packet describing the transfer
+ * @tr_timeout: Target Reset Timeout
+ * @tr_method: Target Reset Method
+ * Context: user
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_scsi_send_scsi_io(struct MPT3SAS_ADAPTER *ioc, struct _scsi_io_transfer
+ *transfer_packet, u8 tr_timeout, u8 tr_method)
+{
+ Mpi2SCSIIOReply_t *mpi_reply;
+ Mpi2SCSIIORequest_t *mpi_request;
+ u16 smid;
+ u8 issue_reset = 0;
+ int rc;
+ void *priv_sense;
+ u32 mpi_control;
+ void *psge;
+ dma_addr_t data_out_dma = 0;
+ dma_addr_t data_in_dma = 0;
+ size_t data_in_sz = 0;
+ size_t data_out_sz = 0;
+ u16 handle;
+ u8 retry_count = 0, host_reset_count = 0;
+ int tm_return_code;
+ if (ioc->pci_error_recovery) {
+ pr_info("%s: pci error recovery in progress!\n", __func__);
+ return -EFAULT;
+ }
+ if (ioc->shost_recovery) {
+ pr_info("%s: host recovery in progress!\n", __func__);
+ return -EAGAIN;
+ }
-#define MPT3_MAX_LUNS (255)
+ handle = transfer_packet->handle;
+ if (handle == MPT3SAS_INVALID_DEVICE_HANDLE) {
+ pr_info("%s: no device!\n", __func__);
+ return -EFAULT;
+ }
+
+ mutex_lock(&ioc->scsih_cmds.mutex);
+
+ if (ioc->scsih_cmds.status != MPT3_CMD_NOT_USED) {
+ pr_err("%s: scsih_cmd in use\n", __func__);
+ rc = -EAGAIN;
+ goto out;
+ }
+
+ retry_loop:
+ if (test_bit(handle, ioc->device_remove_in_progress)) {
+ pr_info("%s: device removal in progress\n", __func__);
+ rc = -EFAULT;
+ goto out;
+ }
+
+ ioc->scsih_cmds.status = MPT3_CMD_PENDING;
+
+ rc = mpt3sas_wait_for_ioc(ioc, 10);
+ if (rc)
+ goto out;
+
+ /* Use second reserved smid for discovery related IOs */
+ smid = ioc->shost->can_queue + INTERNAL_SCSIIO_FOR_DISCOVERY;
+
+ rc = 0;
+ mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+ ioc->scsih_cmds.smid = smid;
+ memset(mpi_request, 0, sizeof(Mpi2SCSIIORequest_t));
+ if (transfer_packet->is_raid)
+ mpi_request->Function = MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
+ else
+ mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
+ mpi_request->DevHandle = cpu_to_le16(handle);
+
+ switch (transfer_packet->dir) {
+ case DMA_TO_DEVICE:
+ mpi_control = MPI2_SCSIIO_CONTROL_WRITE;
+ data_out_dma = transfer_packet->data_dma;
+ data_out_sz = transfer_packet->data_length;
+ break;
+ case DMA_FROM_DEVICE:
+ mpi_control = MPI2_SCSIIO_CONTROL_READ;
+ data_in_dma = transfer_packet->data_dma;
+ data_in_sz = transfer_packet->data_length;
+ break;
+ case DMA_BIDIRECTIONAL:
+ mpi_control = MPI2_SCSIIO_CONTROL_BIDIRECTIONAL;
+ /* TODO - is BIDI support needed ?? */
+ WARN_ON_ONCE(true);
+ break;
+ default:
+ case DMA_NONE:
+ mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER;
+ break;
+ }
+
+ psge = &mpi_request->SGL;
+ ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma,
+ data_in_sz);
+
+ mpi_request->Control = cpu_to_le32(mpi_control |
+ MPI2_SCSIIO_CONTROL_SIMPLEQ);
+ mpi_request->DataLength = cpu_to_le32(transfer_packet->data_length);
+ mpi_request->MsgFlags = MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR;
+ mpi_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
+ mpi_request->SenseBufferLowAddress =
+ mpt3sas_base_get_sense_buffer_dma(ioc, smid);
+ priv_sense = mpt3sas_base_get_sense_buffer(ioc, smid);
+ mpi_request->SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4;
+ mpi_request->IoFlags = cpu_to_le16(transfer_packet->cdb_length);
+ int_to_scsilun(transfer_packet->lun, (struct scsi_lun *)
+ mpi_request->LUN);
+ memcpy(mpi_request->CDB.CDB32, transfer_packet->cdb,
+ transfer_packet->cdb_length);
+ init_completion(&ioc->scsih_cmds.done);
+ if (likely(mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST))
+ ioc->put_smid_scsi_io(ioc, smid, handle);
+ else
+ ioc->put_smid_default(ioc, smid);
+ wait_for_completion_timeout(&ioc->scsih_cmds.done,
+ transfer_packet->timeout*HZ);
+ if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) {
+ mpt3sas_check_cmd_timeout(ioc,
+ ioc->scsih_cmds.status, mpi_request,
+ sizeof(Mpi2SCSIIORequest_t)/4, issue_reset);
+ goto issue_target_reset;
+ }
+ if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) {
+ transfer_packet->valid_reply = 1;
+ mpi_reply = ioc->scsih_cmds.reply;
+ transfer_packet->sense_length =
+ le32_to_cpu(mpi_reply->SenseCount);
+ if (transfer_packet->sense_length)
+ memcpy(transfer_packet->sense, priv_sense,
+ transfer_packet->sense_length);
+ transfer_packet->transfer_length =
+ le32_to_cpu(mpi_reply->TransferCount);
+ transfer_packet->ioc_status =
+ le16_to_cpu(mpi_reply->IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ transfer_packet->scsi_state = mpi_reply->SCSIState;
+ transfer_packet->scsi_status = mpi_reply->SCSIStatus;
+ transfer_packet->log_info =
+ le32_to_cpu(mpi_reply->IOCLogInfo);
+ }
+ goto out;
+
+ issue_target_reset:
+ if (issue_reset) {
+ pr_info("issue target reset: handle (0x%04x)\n", handle);
+ tm_return_code =
+ mpt3sas_scsih_issue_locked_tm(ioc, handle,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0,
+ MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, smid, 0,
+ tr_timeout, tr_method);
+
+ if (tm_return_code == SUCCESS) {
+ pr_info("target reset completed: handle (0x%04x)\n", handle);
+ /* If the command is successfully aborted due to
+ * target reset TM then do up to three retries else
+ * command will be terminated by the host reset TM and
+ * hence retry once.
+ */
+ if (((ioc->scsih_cmds.status & MPT3_CMD_COMPLETE) &&
+ retry_count++ < 3) ||
+ ((ioc->scsih_cmds.status & MPT3_CMD_RESET) &&
+ host_reset_count++ == 0)) {
+ pr_info("issue retry: handle (0x%04x)\n", handle);
+ goto retry_loop;
+ }
+ } else
+ pr_info("target reset didn't complete: handle(0x%04x)\n", handle);
+ rc = -EFAULT;
+ } else
+ rc = -EAGAIN;
+
+ out:
+ ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
+ mutex_unlock(&ioc->scsih_cmds.mutex);
+ return rc;
+}
+
+/**
+ * _scsih_determine_disposition -
+ * @ioc: per adapter object
+ * @transfer_packet: packet describing the transfer
+ * Context: user
+ *
+ * Determines if an internal generated scsi_io is good data, or
+ * whether it needs to be retried or treated as an error.
+ *
+ * Returns device_responsive_state
+ */
+static enum device_responsive_state
+_scsih_determine_disposition(struct MPT3SAS_ADAPTER *ioc,
+ struct _scsi_io_transfer *transfer_packet)
+{
+ static enum device_responsive_state rc;
+ struct sense_info sense_info = {0, 0, 0};
+ u8 check_sense = 0;
+ char *desc = NULL;
+
+ if (!transfer_packet->valid_reply)
+ return DEVICE_READY;
+
+ switch (transfer_packet->ioc_status) {
+ case MPI2_IOCSTATUS_BUSY:
+ case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
+ case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
+ case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
+ case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
+ rc = DEVICE_RETRY;
+ break;
+ case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
+ if (transfer_packet->log_info == 0x31170000) {
+ rc = DEVICE_RETRY;
+ break;
+ }
+ if (transfer_packet->cdb[0] == REPORT_LUNS)
+ rc = DEVICE_READY;
+ else
+ rc = DEVICE_RETRY;
+ break;
+ case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
+ case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
+ case MPI2_IOCSTATUS_SUCCESS:
+ if (!transfer_packet->scsi_state &&
+ !transfer_packet->scsi_status) {
+ rc = DEVICE_READY;
+ break;
+ }
+ if (transfer_packet->scsi_state &
+ MPI2_SCSI_STATE_AUTOSENSE_VALID) {
+ rc = DEVICE_ERROR;
+ check_sense = 1;
+ break;
+ }
+ if (transfer_packet->scsi_state &
+ (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
+ MPI2_SCSI_STATE_NO_SCSI_STATUS |
+ MPI2_SCSI_STATE_TERMINATED)) {
+ rc = DEVICE_RETRY;
+ break;
+ }
+ if (transfer_packet->scsi_status >=
+ MPI2_SCSI_STATUS_BUSY) {
+ rc = DEVICE_RETRY;
+ break;
+ }
+ rc = DEVICE_READY;
+ break;
+ case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
+ if (transfer_packet->scsi_state &
+ MPI2_SCSI_STATE_TERMINATED)
+ rc = DEVICE_RETRY;
+ else
+ rc = DEVICE_ERROR;
+ break;
+ case MPI2_IOCSTATUS_INSUFFICIENT_POWER:
+ default:
+ rc = DEVICE_ERROR;
+ break;
+ }
+
+ if (check_sense) {
+ _scsih_normalize_sense(transfer_packet->sense, &sense_info);
+ if (sense_info.skey == UNIT_ATTENTION)
+ rc = DEVICE_RETRY_UA;
+ else if (sense_info.skey == NOT_READY) {
+ /* medium isn't present */
+ if (sense_info.asc == 0x3a)
+ rc = DEVICE_READY;
+ /* LOGICAL UNIT NOT READY */
+ else if (sense_info.asc == 0x04) {
+ if (sense_info.ascq == 0x03 ||
+ sense_info.ascq == 0x0b ||
+ sense_info.ascq == 0x0c) {
+ rc = DEVICE_ERROR;
+ } else
+ rc = DEVICE_START_UNIT;
+ }
+ /* LOGICAL UNIT HAS NOT SELF-CONFIGURED YET */
+ else if (sense_info.asc == 0x3e && !sense_info.ascq)
+ rc = DEVICE_START_UNIT;
+ } else if (sense_info.skey == ILLEGAL_REQUEST &&
+ transfer_packet->cdb[0] == REPORT_LUNS) {
+ rc = DEVICE_READY;
+ } else if (sense_info.skey == MEDIUM_ERROR) {
+
+ /* medium is corrupt, lets add the device so
+ * users can collect some info as needed
+ */
+
+ if (sense_info.asc == 0x31)
+ rc = DEVICE_READY;
+ } else if (sense_info.skey == HARDWARE_ERROR) {
+ /* Defect List Error, still add the device */
+ if (sense_info.asc == 0x19)
+ rc = DEVICE_READY;
+ }
+ }
+
+ if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) {
+ switch (rc) {
+ case DEVICE_READY:
+ desc = "ready";
+ break;
+ case DEVICE_RETRY:
+ desc = "retry";
+ break;
+ case DEVICE_RETRY_UA:
+ desc = "retry_ua";
+ break;
+ case DEVICE_START_UNIT:
+ desc = "start_unit";
+ break;
+ case DEVICE_STOP_UNIT:
+ desc = "stop_unit";
+ break;
+ case DEVICE_ERROR:
+ desc = "error";
+ break;
+ }
+
+ pr_info("ioc_status(0x%04x),\n"
+ "loginfo(0x%08x), scsi_status(0x%02x),\n"
+ "scsi_state(0x%02x), rc(%s)\n",
+ transfer_packet->ioc_status,
+ transfer_packet->log_info, transfer_packet->scsi_status,
+ transfer_packet->scsi_state, desc);
+
+ if (check_sense)
+ pr_info("\t[sense_key,asc,ascq]:\n"
+ "[0x%02x,0x%02x,0x%02x]\n",
+ sense_info.skey, sense_info.asc, sense_info.ascq);
+ }
+ return rc;
+}
+
+/**
+ * _scsih_report_luns - send REPORT_LUNS to target
+ * @ioc: per adapter object
+ * @handle: expander handle
+ * @data: report luns data payload
+ * @data_length: length of data in bytes
+ * @retry_count: Requeue count
+ * @is_pd: is this hidden raid component
+ * @tr_timeout: Target Reset Timeout
+ * @tr_method: Target Reset Method
+ * Context: user
+ *
+ * Returns device_responsive_state
+ */
+static enum device_responsive_state
+_scsih_report_luns(struct MPT3SAS_ADAPTER *ioc, u16 handle, void *data,
+ u32 data_length, u8 retry_count, u8 is_pd, u8 tr_timeout, u8 tr_method)
+{
+ struct _scsi_io_transfer *transfer_packet;
+ enum device_responsive_state rc;
+ void *lun_data;
+ int return_code;
+ int retries;
+
+ lun_data = NULL;
+ transfer_packet = kzalloc(sizeof(struct _scsi_io_transfer), GFP_KERNEL);
+ if (!transfer_packet) {
+
+ ioc_err(ioc, "failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__);
+ rc = DEVICE_RETRY;
+ goto out;
+ }
+
+ lun_data = dma_alloc_coherent(&ioc->pdev->dev, data_length,
+ &transfer_packet->data_dma, GFP_ATOMIC);
+ if (!lun_data) {
+
+ ioc_err(ioc, "failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__);
+ rc = DEVICE_RETRY;
+ goto out;
+ }
+
+ for (retries = 0; retries < 4; retries++) {
+ rc = DEVICE_ERROR;
+ ioc_info(ioc, "REPORT_LUNS: handle(0x%04x),\n"
+ "retries(%d)\n", handle, retries);
+ memset(lun_data, 0, data_length);
+ transfer_packet->handle = handle;
+ transfer_packet->dir = DMA_FROM_DEVICE;
+ transfer_packet->data_length = data_length;
+ transfer_packet->cdb_length = 12;
+ transfer_packet->cdb[0] = REPORT_LUNS;
+ transfer_packet->cdb[6] = (data_length >> 24) & 0xFF;
+ transfer_packet->cdb[7] = (data_length >> 16) & 0xFF;
+ transfer_packet->cdb[8] = (data_length >> 8) & 0xFF;
+ transfer_packet->cdb[9] = data_length & 0xFF;
+ transfer_packet->timeout = 30;
+ transfer_packet->is_raid = is_pd;
+
+ return_code = _scsi_send_scsi_io(ioc, transfer_packet, tr_timeout, tr_method);
+ switch (return_code) {
+ case 0:
+ rc = _scsih_determine_disposition(ioc, transfer_packet);
+ if (rc == DEVICE_READY) {
+ memcpy(data, lun_data, data_length);
+ goto out;
+ } else if (rc == DEVICE_ERROR)
+ goto out;
+ break;
+ case -EAGAIN:
+ rc = DEVICE_RETRY;
+ break;
+ case -EFAULT:
+ default:
+ ioc_err(ioc, "failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__);
+ goto out;
+ }
+ }
+ out:
+
+ if (lun_data)
+ dma_free_coherent(&ioc->pdev->dev, data_length, lun_data,
+ transfer_packet->data_dma);
+ kfree(transfer_packet);
+
+ if ((rc == DEVICE_RETRY || rc == DEVICE_START_UNIT ||
+ rc == DEVICE_RETRY_UA) && retry_count >= command_retry_count)
+ rc = DEVICE_ERROR;
+
+ return rc;
+}
+
+/**
+ * _scsih_start_unit - send START_UNIT to target
+ * @ioc: per adapter object
+ * @handle: expander handle
+ * @lun: lun number
+ * @is_pd: is this hidden raid component
+ * @tr_timeout: Target Reset Timeout
+ * @tr_method: Target Reset Method
+ * Context: user
+ *
+ * Returns device_responsive_state
+ */
+static enum device_responsive_state
+_scsih_start_unit(struct MPT3SAS_ADAPTER *ioc, u16 handle, u32 lun, u8 is_pd,
+ u8 tr_timeout, u8 tr_method)
+{
+ struct _scsi_io_transfer *transfer_packet;
+ enum device_responsive_state rc;
+ int return_code;
+
+ transfer_packet = kzalloc(sizeof(struct _scsi_io_transfer), GFP_KERNEL);
+ if (!transfer_packet) {
+
+ pr_info("failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__);
+ rc = DEVICE_RETRY;
+ goto out;
+ }
+
+ rc = DEVICE_READY;
+ transfer_packet->handle = handle;
+ transfer_packet->dir = DMA_NONE;
+ transfer_packet->lun = lun;
+ transfer_packet->cdb_length = 6;
+ transfer_packet->cdb[0] = START_STOP;
+ transfer_packet->cdb[1] = 1;
+ transfer_packet->cdb[4] = 1;
+ transfer_packet->timeout = 30;
+ transfer_packet->is_raid = is_pd;
+
+ pr_info("START_UNIT: handle(0x%04x), lun(%d)\n", handle, lun);
+
+ return_code = _scsi_send_scsi_io(ioc, transfer_packet, tr_timeout, tr_method);
+ switch (return_code) {
+ case 0:
+ rc = _scsih_determine_disposition(ioc, transfer_packet);
+ break;
+ case -EAGAIN:
+ rc = DEVICE_RETRY;
+ break;
+ case -EFAULT:
+ default:
+ pr_err("failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__);
+ rc = DEVICE_ERROR;
+ break;
+ }
+ out:
+ kfree(transfer_packet);
+ return rc;
+}
+
+/**
+ * _scsih_test_unit_ready - send TUR to target
+ * @ioc: per adapter object
+ * @handle: expander handle
+ * @lun: lun number
+ * @is_pd: is this hidden raid component
+ * @tr_timeout: Target Reset timeout value for Pcie devie
+ * @tr_method: pcie device Target reset method
+ * Context: user
+ *
+ * Returns device_responsive_state
+ */
+static enum device_responsive_state
+_scsih_test_unit_ready(struct MPT3SAS_ADAPTER *ioc, u16 handle, u32 lun,
+ u8 is_pd, u8 tr_timeout, u8 tr_method)
+{
+ struct _scsi_io_transfer *transfer_packet;
+ enum device_responsive_state rc;
+ int return_code;
+ int sata_init_failure = 0;
+
+ transfer_packet = kzalloc(sizeof(struct _scsi_io_transfer), GFP_KERNEL);
+ if (!transfer_packet) {
+
+ pr_info("failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__);
+ rc = DEVICE_RETRY;
+ goto out;
+ }
+
+ rc = DEVICE_READY;
+ transfer_packet->handle = handle;
+ transfer_packet->dir = DMA_NONE;
+ transfer_packet->lun = lun;
+ transfer_packet->cdb_length = 6;
+ transfer_packet->cdb[0] = TEST_UNIT_READY;
+ transfer_packet->timeout = 30;
+ transfer_packet->is_raid = is_pd;
+
+ sata_init_retry:
+ pr_info("TEST_UNIT_READY: handle(0x%04x) lun(%d)\n", handle, lun);
+
+ return_code = _scsi_send_scsi_io(ioc, transfer_packet, tr_timeout, tr_method);
+ switch (return_code) {
+ case 0:
+ rc = _scsih_determine_disposition(ioc, transfer_packet);
+ if (rc == DEVICE_RETRY &&
+ transfer_packet->log_info == 0x31111000) {
+ if (!sata_init_failure++) {
+ pr_info("SATA Initialization Timeout sending a retry\n");
+ rc = DEVICE_READY;
+ goto sata_init_retry;
+ } else {
+ pr_err("SATA Initialization Failed\n");
+ rc = DEVICE_ERROR;
+ }
+ }
+ break;
+ case -EAGAIN:
+ rc = DEVICE_RETRY;
+ break;
+ case -EFAULT:
+ default:
+ pr_err("failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__);
+ rc = DEVICE_ERROR;
+ break;
+ }
+ out:
+ kfree(transfer_packet);
+ return rc;
+}
+
+/**
+ * _scsih_ata_pass_thru_idd - obtain SATA device Identify Device Data
+ * @ioc: per adapter object
+ * @handle: device handle
+ * @is_ssd_device : is this SATA SSD device
+ * @tr_timeout: Target Reset Timeout
+ * @tr_method: Target Reset Method
+ * Context: user
+ *
+ * Returns device_responsive_state
+ */
+static enum device_responsive_state
+_scsih_ata_pass_thru_idd(struct MPT3SAS_ADAPTER *ioc, u16 handle,
+ u8 *is_ssd_device, u8 tr_timeout, u8 tr_method)
+{
+ struct _scsi_io_transfer *transfer_packet;
+ enum device_responsive_state rc;
+ u16 *idd_data;
+ int return_code;
+ u32 data_length;
+
+ idd_data = NULL;
+ transfer_packet = kzalloc(sizeof(struct _scsi_io_transfer), GFP_KERNEL);
+ if (!transfer_packet) {
+
+ ioc_err(ioc, "failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__);
+ rc = DEVICE_RETRY;
+ goto out;
+ }
+ data_length = 512;
+ idd_data = dma_alloc_coherent(&ioc->pdev->dev, data_length,
+ &transfer_packet->data_dma, GFP_ATOMIC);
+ if (!idd_data) {
+
+ ioc_err(ioc, "failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__);
+ rc = DEVICE_RETRY;
+ goto out;
+ }
+ rc = DEVICE_READY;
+ memset(idd_data, 0, data_length);
+ transfer_packet->handle = handle;
+ transfer_packet->dir = DMA_FROM_DEVICE;
+ transfer_packet->data_length = data_length;
+ transfer_packet->cdb_length = 12;
+ transfer_packet->cdb[0] = ATA_12;
+ transfer_packet->cdb[1] = 0x8;
+ transfer_packet->cdb[2] = 0xd;
+ transfer_packet->cdb[3] = 0x1;
+ transfer_packet->cdb[9] = 0xec;
+ transfer_packet->timeout = 30;
+
+ return_code = _scsi_send_scsi_io(ioc, transfer_packet, 30, 0);
+ switch (return_code) {
+ case 0:
+ rc = _scsih_determine_disposition(ioc, transfer_packet);
+ if (rc == DEVICE_READY) {
+ // Check if nominal media rotation rate is set to 1 i.e. SSD device
+ if (idd_data[217] == 1)
+ *is_ssd_device = 1;
+ }
+ break;
+ case -EAGAIN:
+ rc = DEVICE_RETRY;
+ break;
+ case -EFAULT:
+ default:
+
+ ioc_err(ioc, "failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__);
+ rc = DEVICE_ERROR;
+ break;
+ }
+
+ out:
+ if (idd_data) {
+ dma_free_coherent(&ioc->pdev->dev, data_length, idd_data,
+ transfer_packet->data_dma);
+ }
+ kfree(transfer_packet);
+ return rc;
+}
+
+/**
+ * _scsih_wait_for_device_to_become_ready - handle busy devices
+ * @ioc: per adapter object
+ * @handle: expander handle
+ * @retry_count: number of times this event has been retried
+ * @is_pd: is this hidden raid component
+ * @lun: lun number
+ * @tr_timeout: Target Reset Timeout
+ * @tr_method: Target Reset Method
+ *
+ * Some devices spend too much time in busy state, queue event later
+ *
+ * Return the device_responsive_state.
+ */
+
+static enum device_responsive_state
+_scsih_wait_for_device_to_become_ready(struct MPT3SAS_ADAPTER *ioc, u16 handle,
+ u8 retry_count, u8 is_pd, int lun, u8 tr_timeout, u8 tr_method)
+{
+ enum device_responsive_state rc;
+
+ if (ioc->pci_error_recovery)
+ return DEVICE_ERROR;
+
+ if (ioc->shost_recovery)
+ return DEVICE_RETRY;
+
+ rc = _scsih_test_unit_ready(ioc, handle, lun, is_pd, tr_timeout, tr_method);
+ if (rc == DEVICE_READY || rc == DEVICE_ERROR)
+ return rc;
+ else if (rc == DEVICE_START_UNIT) {
+ rc = _scsih_start_unit(ioc, handle, lun, is_pd, tr_timeout, tr_method);
+ if (rc == DEVICE_ERROR)
+ return rc;
+ rc = _scsih_test_unit_ready(ioc, handle, lun, is_pd, tr_timeout, tr_method);
+ }
+
+ if ((rc == DEVICE_RETRY || rc == DEVICE_START_UNIT ||
+ rc == DEVICE_RETRY_UA) && retry_count >= command_retry_count)
+ rc = DEVICE_ERROR;
+ return rc;
+}
+
+static inline int mpt_scsilun_to_int(struct scsi_lun *scsilun)
+{
+ return scsilun_to_int(scsilun);
+}
+
+/**
+ * _scsih_wait_for_target_to_become_ready - handle busy devices
+ * @ioc: per adapter object
+ * @handle: expander handle
+ * @retry_count: number of times this event has been retried
+ * @is_pd: is this hidden raid component
+ * @tr_timeout: Target Reset timeout value
+ * @tr_method: Target Reset method Hot/Protocol level.
+ *
+ * Some devices spend too much time in busy state, queue event later
+ *
+ * Return the device_responsive_state.
+ */
+static enum device_responsive_state
+_scsih_wait_for_target_to_become_ready(struct MPT3SAS_ADAPTER *ioc, u16 handle,
+ u8 retry_count, u8 is_pd, u8 tr_timeout, u8 tr_method)
+{
+ enum device_responsive_state rc;
+ struct scsi_lun *lun_data;
+ u32 length, num_luns;
+ u8 *data;
+ int lun;
+ struct scsi_lun *lunp;
+
+ lun_data = kcalloc(MPT3_MAX_LUNS, sizeof(struct scsi_lun), GFP_KERNEL);
+ if (!lun_data) {
+
+ ioc_err(ioc, "failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__);
+ return DEVICE_RETRY;
+ }
+
+ rc = _scsih_report_luns(ioc, handle, lun_data,
+ MPT3_MAX_LUNS * sizeof(struct scsi_lun), retry_count, is_pd,
+ tr_timeout, tr_method);
+
+ if (rc != DEVICE_READY)
+ goto out;
+
+ /* some debug bits*/
+ data = (u8 *)lun_data;
+ length = ((data[0] << 24) | (data[1] << 16) |
+ (data[2] << 8) | (data[3] << 0));
+
+ num_luns = (length / sizeof(struct scsi_lun));
+
+ lunp = &lun_data[1];
+ lun = (num_luns) ? mpt_scsilun_to_int(&lun_data[1]) : 0;
+ rc = _scsih_wait_for_device_to_become_ready(ioc, handle, retry_count,
+ is_pd, lun, tr_timeout, tr_method);
+
+ if (rc == DEVICE_ERROR) {
+ struct scsi_lun *lunq;
+
+ for (lunq = lunp++; lunq <= &lun_data[num_luns]; lunq++) {
+
+ rc = _scsih_wait_for_device_to_become_ready(ioc, handle,
+ retry_count, is_pd, mpt_scsilun_to_int(lunq),
+ tr_timeout, tr_method);
+ if (rc != DEVICE_ERROR)
+ goto out;
+ }
+ }
+out:
+ kfree(lun_data);
+ return rc;
+}
/**
@@ -7239,8 +8302,8 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
sas_device->handle, handle);
sas_target_priv_data->handle = handle;
sas_device->handle = handle;
- if (le16_to_cpu(sas_device_pg0.Flags) &
- MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
+ if ((le16_to_cpu(sas_device_pg0.Flags) & MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID)
+ && (ioc->hba_mpi_version_belonged != MPI2_VERSION)) {
sas_device->enclosure_level =
sas_device_pg0.EnclosureLevel;
memcpy(sas_device->connector_name,
@@ -7282,7 +8345,11 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
goto out_unlock;
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- _scsih_ublock_io_device(ioc, sas_address, port);
+
+ if (issue_scsi_cmd_to_bringup_drive)
+ _scsih_ublock_io_device_wait(ioc, sas_address, port);
+ else
+ _scsih_ublock_io_device(ioc, sas_address, port);
if (sas_device)
sas_device_put(sas_device);
@@ -7298,7 +8365,7 @@ out_unlock:
* _scsih_add_device - creating sas device object
* @ioc: per adapter object
* @handle: sas device handle
- * @phy_num: phy number end device attached to
+ * @retry_count: number of times this event has been retried
* @is_pd: is this hidden raid component
*
* Creating end device object, stored in ioc->sas_device_list.
@@ -7306,16 +8373,18 @@ out_unlock:
* Return: 0 for success, non-zero for failure.
*/
static int
-_scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
+_scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 retry_count,
u8 is_pd)
{
Mpi2ConfigReply_t mpi_reply;
Mpi2SasDevicePage0_t sas_device_pg0;
struct _sas_device *sas_device;
struct _enclosure_node *enclosure_dev = NULL;
+ enum device_responsive_state rc;
u32 ioc_status;
u64 sas_address;
u32 device_info;
+ u8 connector_name[5];
u8 port_id;
if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
@@ -7371,6 +8440,48 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
sas_device_pg0.EnclosureHandle);
}
+ /*
+ * Wait for device that is becoming ready
+ * queue request later if device is busy.
+ */
+ if ((!ioc->wait_for_discovery_to_complete) &&
+ (issue_scsi_cmd_to_bringup_drive)) {
+ ioc_info(ioc, "detecting: handle(0x%04x),\n"
+ "sas_address(0x%016llx), phy(%d)\n", handle,
+ (unsigned long long)sas_address, sas_device_pg0.PhyNum);
+ rc = _scsih_wait_for_target_to_become_ready(ioc, handle,
+ retry_count, is_pd, 30, 0);
+ if (rc != DEVICE_READY) {
+ if (le16_to_cpu(sas_device_pg0.EnclosureHandle) != 0)
+ dewtprintk(ioc, ioc_info(ioc, "%s:\n"
+ "device not ready: slot(%d)\n", __func__,
+ le16_to_cpu(sas_device_pg0.Slot)));
+ if ((le16_to_cpu(sas_device_pg0.Flags) &
+ MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) &&
+ (ioc->hba_mpi_version_belonged != MPI2_VERSION)) {
+ memcpy(connector_name,
+ sas_device_pg0.ConnectorName, 4);
+ connector_name[4] = '\0';
+ dewtprintk(ioc, ioc_info(ioc, "%s:\n"
+ "device not ready:\n"
+ "enclosure level(0x%04x),\n"
+ "connector name( %s)\n", __func__,
+ sas_device_pg0.EnclosureLevel, connector_name));
+ }
+
+ if ((enclosure_dev) && (le16_to_cpu(enclosure_dev->pg0.Flags) &
+ MPI2_SAS_ENCLS0_FLAGS_CHASSIS_SLOT_VALID))
+ ioc_info(ioc, "chassis slot(0x%04x)\n",
+ enclosure_dev->pg0.ChassisSlot);
+
+ if (rc == DEVICE_RETRY || rc == DEVICE_START_UNIT ||
+ rc == DEVICE_STOP_UNIT || rc == DEVICE_RETRY_UA)
+ return 1;
+ else if (rc == DEVICE_ERROR)
+ return 0;
+ }
+ }
+
sas_device = kzalloc(sizeof(struct _sas_device),
GFP_KERNEL);
if (!sas_device) {
@@ -7586,10 +8697,13 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
struct fw_event_work *fw_event)
{
int i;
+ int rc;
+ int requeue_event;
u16 parent_handle, handle;
u16 reason_code;
u8 phy_number, max_phys;
struct _sas_node *sas_expander;
+ struct _sas_device *sas_device;
u64 sas_address;
unsigned long flags;
u8 link_rate, prev_link_rate;
@@ -7639,7 +8753,7 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
/* handle siblings events */
- for (i = 0; i < event_data->NumEntries; i++) {
+ for (i = 0, requeue_event = 0; i < event_data->NumEntries; i++) {
if (fw_event->ignore) {
dewtprintk(ioc,
ioc_info(ioc, "ignoring expander event\n"));
@@ -7656,6 +8770,20 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) && (reason_code !=
MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING))
continue;
+ if (fw_event->delayed_work_active && (reason_code ==
+ MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)) {
+ dewtprintk(ioc, ioc_info(ioc, "ignoring\n"
+ "Target not responding event phy in re-queued event processing\n"));
+ continue;
+ }
+
+ if (fw_event->delayed_work_active && (reason_code ==
+ MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)) {
+ dewtprintk(ioc, ioc_info(ioc, "ignoring Target not responding\n"
+ "event phy in re-queued event processing\n"));
+ continue;
+ }
+
handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
if (!handle)
continue;
@@ -7679,9 +8807,32 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
_scsih_check_device(ioc, sas_address, handle,
phy_number, link_rate);
+ /* This code after this point handles the test case
+ * where a device has been added, however its returning
+ * BUSY for sometime. Then before the Device Missing
+ * Delay expires and the device becomes READY, the
+ * device is removed and added back.
+ */
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device = __mpt3sas_get_sdev_by_handle(ioc,
+ handle);
+ spin_unlock_irqrestore(&ioc->sas_device_lock,
+ flags);
+
+ if (sas_device) {
+ sas_device_put(sas_device);
+ break;
+ }
+
if (!test_bit(handle, ioc->pend_os_device_add))
break;
+ dewtprintk(ioc, ioc_info(ioc, "handle(0x%04x) device not found: convert\n"
+ "event to a device add\n", handle));
+ event_data->PHY[i].PhyStatus &= 0xF0;
+ event_data->PHY[i].PhyStatus |=
+ MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED;
+
fallthrough;
case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
@@ -7692,7 +8843,18 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
mpt3sas_transport_update_links(ioc, sas_address,
handle, phy_number, link_rate, port);
- _scsih_add_device(ioc, handle, phy_number, 0);
+ if (link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
+ break;
+
+ rc = _scsih_add_device(ioc, handle,
+ fw_event->retries[i], 0);
+ if (rc) {/* retry due to busy device */
+ fw_event->retries[i]++;
+ requeue_event = 1;
+ } else {/* mark entry vacant */
+ event_data->PHY[i].PhyStatus |=
+ MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT;
+ }
break;
case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
@@ -7707,7 +8869,7 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
sas_expander)
mpt3sas_expander_remove(ioc, sas_address, port);
- return 0;
+ return requeue_event;
}
/**
@@ -8078,7 +9240,10 @@ _scsih_pcie_check_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);
pcie_device_put(pcie_device);
- _scsih_ublock_io_device(ioc, wwid, NULL);
+ if (issue_scsi_cmd_to_bringup_drive)
+ _scsih_ublock_io_device_wait(ioc, wwid, NULL);
+ else
+ _scsih_ublock_io_device(ioc, wwid, NULL);
return;
}
@@ -8087,19 +9252,24 @@ _scsih_pcie_check_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
* _scsih_pcie_add_device - creating pcie device object
* @ioc: per adapter object
* @handle: pcie device handle
+ * @retry_count: number of times this event has been retried
*
* Creating end device object, stored in ioc->pcie_device_list.
*
* Return: 1 means queue the event later, 0 means complete the event
*/
static int
-_scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+_scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 retry_count)
{
Mpi26PCIeDevicePage0_t pcie_device_pg0;
Mpi26PCIeDevicePage2_t pcie_device_pg2;
Mpi2ConfigReply_t mpi_reply;
struct _pcie_device *pcie_device;
struct _enclosure_node *enclosure_dev;
+ enum device_responsive_state rc;
+ u8 connector_name[5];
+ u8 tr_timeout = 30;
+ u8 tr_method = 0;
u32 ioc_status;
u64 wwid;
@@ -8167,6 +9337,53 @@ _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
__LINE__, __func__);
return 0;
}
+
+ if (!ioc->tm_custom_handling) {
+ tr_method = MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE;
+ if (pcie_device_pg2.ControllerResetTO)
+ tr_timeout = pcie_device_pg2.ControllerResetTO;
+
+ }
+ }
+
+ /*
+ * Wait for device that is becoming ready
+ * queue request later if device is busy.
+ */
+ if ((!ioc->wait_for_discovery_to_complete) &&
+ (issue_scsi_cmd_to_bringup_drive) &&
+ (pcie_device_pg0.AccessStatus !=
+ MPI26_PCIEDEV0_ASTATUS_DEVICE_BLOCKED)) {
+ ioc_info(ioc, "detecting: handle(0x%04x),\n"
+ "wwid(0x%016llx), port(%d)\n", handle,
+ (unsigned long long)wwid, pcie_device_pg0.PortNum);
+
+ rc = _scsih_wait_for_target_to_become_ready(ioc, handle,
+ retry_count, 0, tr_timeout, tr_method);
+ if (rc != DEVICE_READY) {
+ if (le16_to_cpu(pcie_device_pg0.EnclosureHandle) != 0)
+ dewtprintk(ioc, ioc_info(ioc, "%s:\n"
+ "device not ready: slot(%d)\n",
+ __func__,
+ le16_to_cpu(pcie_device_pg0.Slot)));
+
+ if (le32_to_cpu(pcie_device_pg0.Flags) &
+ MPI26_PCIEDEV0_FLAGS_ENCL_LEVEL_VALID) {
+ memcpy(connector_name,
+ pcie_device_pg0.ConnectorName, 4);
+ connector_name[4] = '\0';
+ dewtprintk(ioc, ioc_info(ioc, "%s: device not ready: enclosure\n"
+ "level(0x%04x), connector name( %s)\n", __func__,
+ pcie_device_pg0.EnclosureLevel,
+ connector_name));
+ }
+
+ if (rc == DEVICE_RETRY || rc == DEVICE_START_UNIT ||
+ rc == DEVICE_STOP_UNIT || rc == DEVICE_RETRY_UA)
+ return 1;
+ else if (rc == DEVICE_ERROR)
+ return 0;
+ }
}
pcie_device = kzalloc(sizeof(struct _pcie_device), GFP_KERNEL);
@@ -8330,7 +9547,7 @@ _scsih_pcie_topology_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
* Context: user.
*
*/
-static void
+static int
_scsih_pcie_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
struct fw_event_work *fw_event)
{
@@ -8340,6 +9557,7 @@ _scsih_pcie_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
u8 link_rate, prev_link_rate;
unsigned long flags;
int rc;
+ int requeue_event;
Mpi26EventDataPCIeTopologyChangeList_t *event_data =
(Mpi26EventDataPCIeTopologyChangeList_t *) fw_event->event_data;
struct _pcie_device *pcie_device;
@@ -8349,22 +9567,22 @@ _scsih_pcie_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
if (ioc->shost_recovery || ioc->remove_host ||
ioc->pci_error_recovery)
- return;
+ return 0;
if (fw_event->ignore) {
dewtprintk(ioc, ioc_info(ioc, "ignoring switch event\n"));
- return;
+ return 0;
}
/* handle siblings events */
- for (i = 0; i < event_data->NumEntries; i++) {
+ for (i = 0, requeue_event = 0; i < event_data->NumEntries; i++) {
if (fw_event->ignore) {
dewtprintk(ioc,
ioc_info(ioc, "ignoring switch event\n"));
- return;
+ return 0;
}
if (ioc->remove_host || ioc->pci_error_recovery)
- return;
+ return 0;
reason_code = event_data->PortEntry[i].PortStatus;
handle =
le16_to_cpu(event_data->PortEntry[i].AttachedDevHandle);
@@ -8418,8 +9636,11 @@ _scsih_pcie_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
if (link_rate < MPI26_EVENT_PCIE_TOPO_PI_RATE_2_5)
break;
- rc = _scsih_pcie_add_device(ioc, handle);
- if (!rc) {
+ rc = _scsih_pcie_add_device(ioc, handle, fw_event->retries[i]);
+ if (rc) {/* retry due to busy device */
+ fw_event->retries[i]++;
+ requeue_event = 1;
+ } else {
/* mark entry vacant */
/* TODO This needs to be reviewed and fixed,
* we dont have an entry
@@ -8434,11 +9655,12 @@ _scsih_pcie_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
break;
}
}
+ return requeue_event;
}
/**
* _scsih_pcie_device_status_change_event_debug - debug for device event
- * @ioc: ?
+ * @ioc: per adapter object
* @event_data: event data payload
* Context: user.
*/
@@ -8810,7 +10032,7 @@ _scsih_sas_broadcast_primitive_event(struct MPT3SAS_ADAPTER *ioc,
ioc->broadcast_aen_busy = 0;
if (!ioc->shost_recovery)
- _scsih_ublock_io_all_device(ioc);
+ _scsih_ublock_io_all_device(ioc, 1);
mutex_unlock(&ioc->tm_cmds.mutex);
}
@@ -10344,7 +11566,7 @@ _scsih_remove_unresponding_devices(struct MPT3SAS_ADAPTER *ioc)
ioc_info(ioc, "removing unresponding devices: complete\n");
/* unblock devices */
- _scsih_ublock_io_all_device(ioc);
+ _scsih_ublock_io_all_device(ioc, 0);
}
static void
@@ -10624,7 +11846,8 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
}
retry_count = 0;
parent_handle = le16_to_cpu(pcie_device_pg0.ParentDevHandle);
- _scsih_pcie_add_device(ioc, handle);
+ while (_scsih_pcie_add_device(ioc, handle, retry_count++))
+ ssleep(1);
ioc_info(ioc, "\tAFTER adding pcie end device: handle (0x%04x), wwid(0x%016llx)\n",
handle, (u64)le64_to_cpu(pcie_device_pg0.WWID));
@@ -10768,7 +11991,11 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
_scsih_turn_on_pfa_led(ioc, fw_event->device_handle);
break;
case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
- _scsih_sas_topology_change_event(ioc, fw_event);
+ if (_scsih_sas_topology_change_event(ioc, fw_event)) {
+ _scsih_fw_event_requeue(ioc, fw_event, 1000);
+ ioc->current_event = NULL;
+ return;
+ }
break;
case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
@@ -10808,7 +12035,11 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
_scsih_pcie_enumeration_event(ioc, fw_event);
break;
case MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST:
- _scsih_pcie_topology_change_event(ioc, fw_event);
+ if (_scsih_pcie_topology_change_event(ioc, fw_event)) {
+ _scsih_fw_event_requeue(ioc, fw_event, 1000);
+ ioc->current_event = NULL;
+ return;
+ }
break;
}
out:
@@ -10833,6 +12064,15 @@ _firmware_event_work(struct work_struct *work)
_mpt3sas_fw_work(fw_event->ioc, fw_event);
}
+static void
+_firmware_event_work_delayed(struct work_struct *work)
+{
+ struct fw_event_work *fw_event = container_of(work,
+ struct fw_event_work, delayed_work.work);
+
+ _mpt3sas_fw_work(fw_event->ioc, fw_event);
+}
+
/**
* mpt3sas_scsih_event_callback - firmware event handler (called at ISR time)
* @ioc: per adapter object
@@ -11013,6 +12253,34 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
return 1;
}
+ if (event == MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST) {
+ Mpi2EventDataSasTopologyChangeList_t *topo_event_data =
+ (Mpi2EventDataSasTopologyChangeList_t *)
+ mpi_reply->EventData;
+ fw_event->retries = kzalloc(topo_event_data->NumEntries,
+ GFP_ATOMIC);
+ if (!fw_event->retries) {
+
+ ioc_err(ioc, "failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__);
+ kfree(fw_event->event_data);
+ fw_event_work_put(fw_event);
+ return 1;
+ }
+ }
+
+ if (event == MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST) {
+ Mpi26EventDataPCIeTopologyChangeList_t *topo_event_data =
+ (Mpi26EventDataPCIeTopologyChangeList_t *) mpi_reply->EventData;
+ fw_event->retries = kzalloc(topo_event_data->NumEntries,
+ GFP_ATOMIC);
+ if (!fw_event->retries) {
+
+ ioc_err(ioc, "failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__);
+ fw_event_work_put(fw_event);
+ return 1;
+ }
+ }
+
memcpy(fw_event->event_data, mpi_reply->EventData, sz);
fw_event->ioc = ioc;
fw_event->VF_ID = mpi_reply->VF_ID;
diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c
index bdc2f2f17753..cda8bd083a38 100644
--- a/drivers/scsi/mvumi.c
+++ b/drivers/scsi/mvumi.c
@@ -2077,8 +2077,8 @@ error:
* @shost: Scsi host to queue command on
* @scmd: SCSI command to be queued
*/
-static int mvumi_queue_command(struct Scsi_Host *shost,
- struct scsi_cmnd *scmd)
+static enum scsi_qc_status mvumi_queue_command(struct Scsi_Host *shost,
+ struct scsi_cmnd *scmd)
{
struct mvumi_cmd *cmd;
struct mvumi_hba *mhba;
diff --git a/drivers/scsi/myrb.c b/drivers/scsi/myrb.c
index b8453c0333dc..efeacb9ffd7c 100644
--- a/drivers/scsi/myrb.c
+++ b/drivers/scsi/myrb.c
@@ -1260,8 +1260,8 @@ static int myrb_host_reset(struct scsi_cmnd *scmd)
return SUCCESS;
}
-static int myrb_pthru_queuecommand(struct Scsi_Host *shost,
- struct scsi_cmnd *scmd)
+static enum scsi_qc_status myrb_pthru_queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *scmd)
{
struct request *rq = scsi_cmd_to_rq(scmd);
struct myrb_hba *cb = shost_priv(shost);
@@ -1416,8 +1416,8 @@ static void myrb_read_capacity(struct myrb_hba *cb, struct scsi_cmnd *scmd,
scsi_sg_copy_from_buffer(scmd, data, 8);
}
-static int myrb_ldev_queuecommand(struct Scsi_Host *shost,
- struct scsi_cmnd *scmd)
+static enum scsi_qc_status myrb_ldev_queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *scmd)
{
struct myrb_hba *cb = shost_priv(shost);
struct myrb_cmdblk *cmd_blk = scsi_cmd_priv(scmd);
@@ -1603,8 +1603,8 @@ submit:
return 0;
}
-static int myrb_queuecommand(struct Scsi_Host *shost,
- struct scsi_cmnd *scmd)
+static enum scsi_qc_status myrb_queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *scmd)
{
struct scsi_device *sdev = scmd->device;
diff --git a/drivers/scsi/myrs.c b/drivers/scsi/myrs.c
index a58abd796603..7e8bb533c669 100644
--- a/drivers/scsi/myrs.c
+++ b/drivers/scsi/myrs.c
@@ -1581,8 +1581,8 @@ static void myrs_mode_sense(struct myrs_hba *cs, struct scsi_cmnd *scmd,
scsi_sg_copy_from_buffer(scmd, modes, mode_len);
}
-static int myrs_queuecommand(struct Scsi_Host *shost,
- struct scsi_cmnd *scmd)
+static enum scsi_qc_status myrs_queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *scmd)
{
struct request *rq = scsi_cmd_to_rq(scmd);
struct myrs_hba *cs = shost_priv(shost);
diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
index 34ba9b137789..4a255aafed80 100644
--- a/drivers/scsi/ncr53c8xx.c
+++ b/drivers/scsi/ncr53c8xx.c
@@ -7852,7 +7852,7 @@ static int ncr53c8xx_sdev_configure(struct scsi_device *device,
return 0;
}
-static int ncr53c8xx_queue_command_lck(struct scsi_cmnd *cmd)
+static enum scsi_qc_status ncr53c8xx_queue_command_lck(struct scsi_cmnd *cmd)
{
struct ncr_cmd_priv *cmd_priv = scsi_cmd_priv(cmd);
void (*done)(struct scsi_cmnd *) = scsi_done;
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
index abc4ce9eae74..e893d5677241 100644
--- a/drivers/scsi/nsp32.c
+++ b/drivers/scsi/nsp32.c
@@ -185,7 +185,8 @@ static void __exit exit_nsp32 (void);
static int nsp32_show_info (struct seq_file *, struct Scsi_Host *);
static int nsp32_detect (struct pci_dev *pdev);
-static int nsp32_queuecommand(struct Scsi_Host *, struct scsi_cmnd *);
+static enum scsi_qc_status nsp32_queuecommand(struct Scsi_Host *,
+ struct scsi_cmnd *);
static const char *nsp32_info (struct Scsi_Host *);
static int nsp32_release (struct Scsi_Host *);
@@ -905,7 +906,7 @@ static int nsp32_setup_sg_table(struct scsi_cmnd *SCpnt)
return TRUE;
}
-static int nsp32_queuecommand_lck(struct scsi_cmnd *SCpnt)
+static enum scsi_qc_status nsp32_queuecommand_lck(struct scsi_cmnd *SCpnt)
{
void (*done)(struct scsi_cmnd *) = scsi_done;
nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index a5a1406a2bde..fb3a1b43d8bd 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -186,7 +186,7 @@ static void nsp_scsi_done(struct scsi_cmnd *SCpnt)
scsi_done(SCpnt);
}
-static int nsp_queuecommand_lck(struct scsi_cmnd *const SCpnt)
+static enum scsi_qc_status nsp_queuecommand_lck(struct scsi_cmnd *const SCpnt)
{
struct scsi_pointer *scsi_pointer = nsp_priv(SCpnt);
#ifdef NSP_DEBUG
diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h
index e1ee8ef90ad3..12e58386bb8f 100644
--- a/drivers/scsi/pcmcia/nsp_cs.h
+++ b/drivers/scsi/pcmcia/nsp_cs.h
@@ -294,7 +294,8 @@ static struct Scsi_Host *nsp_detect (struct scsi_host_template *sht);
static const char *nsp_info (struct Scsi_Host *shpnt);
static int nsp_show_info (struct seq_file *m,
struct Scsi_Host *host);
-static int nsp_queuecommand(struct Scsi_Host *h, struct scsi_cmnd *SCpnt);
+static enum scsi_qc_status nsp_queuecommand(struct Scsi_Host *h,
+ struct scsi_cmnd *SCpnt);
/* Error handler */
/*static int nsp_eh_abort (struct scsi_cmnd *SCpnt);*/
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index a3b505240351..8f56f7277dee 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -544,7 +544,7 @@ SYM53C500_info(struct Scsi_Host *SChost)
return (info_msg);
}
-static int SYM53C500_queue_lck(struct scsi_cmnd *SCpnt)
+static enum scsi_qc_status SYM53C500_queue_lck(struct scsi_cmnd *SCpnt)
{
struct sym53c500_cmd_priv *scp = scsi_cmd_priv(SCpnt);
int i;
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
index 33f403e307eb..cf163e63054b 100644
--- a/drivers/scsi/pmcraid.c
+++ b/drivers/scsi/pmcraid.c
@@ -3242,14 +3242,14 @@ static int pmcraid_build_ioadl(
* SCSI_MLQUEUE_DEVICE_BUSY if device is busy
* SCSI_MLQUEUE_HOST_BUSY if host is busy
*/
-static int pmcraid_queuecommand_lck(struct scsi_cmnd *scsi_cmd)
+static enum scsi_qc_status pmcraid_queuecommand_lck(struct scsi_cmnd *scsi_cmd)
{
struct pmcraid_instance *pinstance;
struct pmcraid_resource_entry *res;
struct pmcraid_ioarcb *ioarcb;
+ enum scsi_qc_status rc = 0;
struct pmcraid_cmd *cmd;
u32 fw_version;
- int rc = 0;
pinstance =
(struct pmcraid_instance *)scsi_cmd->device->host->hostdata;
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
index ea682f3044b6..ddcef40789e5 100644
--- a/drivers/scsi/ppa.c
+++ b/drivers/scsi/ppa.c
@@ -816,7 +816,7 @@ static int ppa_engine(ppa_struct *dev, struct scsi_cmnd *cmd)
return 0;
}
-static int ppa_queuecommand_lck(struct scsi_cmnd *cmd)
+static enum scsi_qc_status ppa_queuecommand_lck(struct scsi_cmnd *cmd)
{
ppa_struct *dev = ppa_dev(cmd->device->host);
diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c
index 92fe5c5c5bb0..a9c727d22931 100644
--- a/drivers/scsi/ps3rom.c
+++ b/drivers/scsi/ps3rom.c
@@ -201,7 +201,7 @@ static int ps3rom_write_request(struct ps3_storage_device *dev,
return 0;
}
-static int ps3rom_queuecommand_lck(struct scsi_cmnd *cmd)
+static enum scsi_qc_status ps3rom_queuecommand_lck(struct scsi_cmnd *cmd)
{
struct ps3rom_private *priv = shost_priv(cmd->device->host);
struct ps3_storage_device *dev = priv->dev;
diff --git a/drivers/scsi/qedf/qedf.h b/drivers/scsi/qedf/qedf.h
index 98afdfe63600..5b330a3203e1 100644
--- a/drivers/scsi/qedf/qedf.h
+++ b/drivers/scsi/qedf/qedf.h
@@ -487,8 +487,8 @@ extern uint qedf_debug;
extern struct qedf_cmd_mgr *qedf_cmd_mgr_alloc(struct qedf_ctx *qedf);
extern void qedf_cmd_mgr_free(struct qedf_cmd_mgr *cmgr);
-extern int qedf_queuecommand(struct Scsi_Host *host,
- struct scsi_cmnd *sc_cmd);
+extern enum scsi_qc_status qedf_queuecommand(struct Scsi_Host *host,
+ struct scsi_cmnd *sc_cmd);
extern void qedf_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb);
extern u8 *qedf_get_src_mac(struct fc_lport *lport);
extern void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff *skb);
diff --git a/drivers/scsi/qedf/qedf_io.c b/drivers/scsi/qedf/qedf_io.c
index fcfc3bed02c6..d12c47be016e 100644
--- a/drivers/scsi/qedf/qedf_io.c
+++ b/drivers/scsi/qedf/qedf_io.c
@@ -930,8 +930,8 @@ int qedf_post_io_req(struct qedf_rport *fcport, struct qedf_ioreq *io_req)
return false;
}
-int
-qedf_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc_cmd)
+enum scsi_qc_status qedf_queuecommand(struct Scsi_Host *host,
+ struct scsi_cmnd *sc_cmd)
{
struct fc_lport *lport = shost_priv(host);
struct qedf_ctx *qedf = lport_priv(lport);
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 26c312a48a19..cdd6fe002c32 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -406,9 +406,11 @@ static int qla1280_device_reset(struct scsi_qla_host *, int, int);
static int qla1280_abort_command(struct scsi_qla_host *, struct srb *, int);
static int qla1280_abort_isp(struct scsi_qla_host *);
#ifdef QLA_64BIT_PTR
-static int qla1280_64bit_start_scsi(struct scsi_qla_host *, struct srb *);
+static enum scsi_qc_status qla1280_64bit_start_scsi(struct scsi_qla_host *,
+ struct srb *);
#else
-static int qla1280_32bit_start_scsi(struct scsi_qla_host *, struct srb *);
+static enum scsi_qc_status qla1280_32bit_start_scsi(struct scsi_qla_host *,
+ struct srb *);
#endif
static void qla1280_nv_write(struct scsi_qla_host *, uint16_t);
static void qla1280_poll(struct scsi_qla_host *);
@@ -682,12 +684,12 @@ qla1280_info(struct Scsi_Host *host)
* handling). Unfortunately, it sometimes calls the scheduler in interrupt
* context which is a big NO! NO!.
**************************************************************************/
-static int qla1280_queuecommand_lck(struct scsi_cmnd *cmd)
+static enum scsi_qc_status qla1280_queuecommand_lck(struct scsi_cmnd *cmd)
{
struct Scsi_Host *host = cmd->device->host;
struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata;
struct srb *sp = scsi_cmd_priv(cmd);
- int status;
+ enum scsi_qc_status status;
sp->cmd = cmd;
sp->flags = 0;
@@ -2730,7 +2732,7 @@ qla1280_marker(struct scsi_qla_host *ha, int bus, int id, int lun, u8 type)
* 0 = success, was able to issue command.
*/
#ifdef QLA_64BIT_PTR
-static int
+static enum scsi_qc_status
qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
{
struct device_reg __iomem *reg = ha->iobase;
@@ -2738,7 +2740,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
cmd_a64_entry_t *pkt;
__le32 *dword_ptr;
dma_addr_t dma_handle;
- int status = 0;
+ enum scsi_qc_status status = 0;
int cnt;
int req_cnt;
int seg_cnt;
@@ -2984,14 +2986,14 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
* Returns:
* 0 = success, was able to issue command.
*/
-static int
+static enum scsi_qc_status
qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
{
struct device_reg __iomem *reg = ha->iobase;
struct scsi_cmnd *cmd = sp->cmd;
struct cmd_entry *pkt;
__le32 *dword_ptr;
- int status = 0;
+ enum scsi_qc_status status = 0;
int cnt;
int req_cnt;
int seg_cnt;
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index ccfc2d26dd37..2c44a379cb23 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -11,6 +11,8 @@
#include <linux/delay.h>
#include <linux/bsg-lib.h>
+static int qla28xx_validate_flash_image(struct bsg_job *bsg_job);
+
static void qla2xxx_free_fcport_work(struct work_struct *work)
{
struct fc_port *fcport = container_of(work, typeof(*fcport),
@@ -1546,8 +1548,9 @@ qla2x00_update_optrom(struct bsg_job *bsg_job)
ha->optrom_buffer = NULL;
ha->optrom_state = QLA_SWAITING;
mutex_unlock(&ha->optrom_mutex);
- bsg_job_done(bsg_job, bsg_reply->result,
- bsg_reply->reply_payload_rcv_len);
+ if (!rval)
+ bsg_job_done(bsg_job, bsg_reply->result,
+ bsg_reply->reply_payload_rcv_len);
return rval;
}
@@ -2550,6 +2553,30 @@ qla2x00_get_flash_image_status(struct bsg_job *bsg_job)
}
static int
+qla2x00_get_drv_attr(struct bsg_job *bsg_job)
+{
+ struct qla_drv_attr drv_attr;
+ struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+
+ memset(&drv_attr, 0, sizeof(struct qla_drv_attr));
+ drv_attr.ext_attributes |= QLA_IMG_SET_VALID_SUPPORT;
+
+
+ sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+ bsg_job->reply_payload.sg_cnt, &drv_attr,
+ sizeof(struct qla_drv_attr));
+
+ bsg_reply->reply_payload_rcv_len = sizeof(struct qla_drv_attr);
+ bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
+
+ bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+ bsg_reply->result = DID_OK << 16;
+ bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len);
+
+ return 0;
+}
+
+static int
qla2x00_manage_host_stats(struct bsg_job *bsg_job)
{
scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
@@ -2612,8 +2639,9 @@ qla2x00_manage_host_stats(struct bsg_job *bsg_job)
sizeof(struct ql_vnd_mng_host_stats_resp));
bsg_reply->result = DID_OK;
- bsg_job_done(bsg_job, bsg_reply->result,
- bsg_reply->reply_payload_rcv_len);
+ if (!ret)
+ bsg_job_done(bsg_job, bsg_reply->result,
+ bsg_reply->reply_payload_rcv_len);
return ret;
}
@@ -2702,8 +2730,9 @@ qla2x00_get_host_stats(struct bsg_job *bsg_job)
bsg_job->reply_payload.sg_cnt,
data, response_len);
bsg_reply->result = DID_OK;
- bsg_job_done(bsg_job, bsg_reply->result,
- bsg_reply->reply_payload_rcv_len);
+ if (!ret)
+ bsg_job_done(bsg_job, bsg_reply->result,
+ bsg_reply->reply_payload_rcv_len);
kfree(data);
host_stat_out:
@@ -2802,8 +2831,9 @@ reply:
bsg_job->reply_payload.sg_cnt, data,
response_len);
bsg_reply->result = DID_OK;
- bsg_job_done(bsg_job, bsg_reply->result,
- bsg_reply->reply_payload_rcv_len);
+ if (!ret)
+ bsg_job_done(bsg_job, bsg_reply->result,
+ bsg_reply->reply_payload_rcv_len);
tgt_stat_out:
kfree(data);
@@ -2864,8 +2894,9 @@ qla2x00_manage_host_port(struct bsg_job *bsg_job)
bsg_job->reply_payload.sg_cnt, &rsp_data,
sizeof(struct ql_vnd_mng_host_port_resp));
bsg_reply->result = DID_OK;
- bsg_job_done(bsg_job, bsg_reply->result,
- bsg_reply->reply_payload_rcv_len);
+ if (!ret)
+ bsg_job_done(bsg_job, bsg_reply->result,
+ bsg_reply->reply_payload_rcv_len);
return ret;
}
@@ -2933,6 +2964,12 @@ qla2x00_process_vendor_specific(struct scsi_qla_host *vha, struct bsg_job *bsg_j
case QL_VND_GET_FLASH_UPDATE_CAPS:
return qla27xx_get_flash_upd_cap(bsg_job);
+ case QL_VND_GET_DRV_ATTR:
+ return qla2x00_get_drv_attr(bsg_job);
+
+ case QL_VND_IMG_SET_VALID:
+ return qla28xx_validate_flash_image(bsg_job);
+
case QL_VND_SET_FLASH_UPDATE_CAPS:
return qla27xx_set_flash_upd_cap(bsg_job);
@@ -3240,9 +3277,97 @@ int qla2x00_mailbox_passthru(struct bsg_job *bsg_job)
bsg_job->reply_len = sizeof(*bsg_job->reply);
bsg_reply->result = DID_OK << 16;
- bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len);
+ if (!ret)
+ bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len);
kfree(req_data);
return ret;
}
+
+static int
+qla28xx_do_validate_flash_image(struct bsg_job *bsg_job, uint16_t *state)
+{
+ struct fc_bsg_request *bsg_request = bsg_job->request;
+ scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
+ uint16_t mstate[16];
+ uint16_t mpi_state = 0;
+ uint16_t img_idx;
+ int rval = QLA_SUCCESS;
+
+ memset(mstate, 0, sizeof(mstate));
+
+ rval = qla2x00_get_firmware_state(vha, mstate);
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0xffff,
+ "MBC to get MPI state failed (%d)\n", rval);
+ rval = -EINVAL;
+ goto exit_flash_img;
+ }
+
+ mpi_state = mstate[11];
+
+ if (!(mpi_state & BIT_9 && mpi_state & BIT_8 && mpi_state & BIT_15)) {
+ ql_log(ql_log_warn, vha, 0xffff,
+ "MPI firmware state failed (0x%02x)\n", mpi_state);
+ rval = -EINVAL;
+ goto exit_flash_img;
+ }
+
+ rval = qla81xx_fac_semaphore_access(vha, FAC_SEMAPHORE_LOCK);
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0xffff,
+ "Unable to lock flash semaphore.");
+ goto exit_flash_img;
+ }
+
+ img_idx = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
+
+ rval = qla_mpipt_validate_fw(vha, img_idx, state);
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0xffff,
+ "Failed to validate Firmware image index [0x%x].\n",
+ img_idx);
+ }
+
+ qla81xx_fac_semaphore_access(vha, FAC_SEMAPHORE_UNLOCK);
+
+exit_flash_img:
+ return rval;
+}
+
+static int qla28xx_validate_flash_image(struct bsg_job *bsg_job)
+{
+ scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
+ struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+ struct qla_hw_data *ha = vha->hw;
+ uint16_t state = 0;
+ int rval = 0;
+
+ if (!IS_QLA28XX(ha) || vha->vp_idx != 0)
+ return -EPERM;
+
+ mutex_lock(&ha->optrom_mutex);
+ rval = qla28xx_do_validate_flash_image(bsg_job, &state);
+ if (rval)
+ rval = -EINVAL;
+ mutex_unlock(&ha->optrom_mutex);
+
+ bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+
+ if (rval)
+ bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
+ (state == 39) ? EXT_STATUS_IMG_SET_VALID_ERR :
+ EXT_STATUS_IMG_SET_CONFIG_ERR;
+ else
+ bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
+
+ bsg_reply->result = DID_OK << 16;
+ bsg_reply->reply_payload_rcv_len = 0;
+ bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+ if (!rval)
+ bsg_job_done(bsg_job, bsg_reply->result,
+ bsg_reply->reply_payload_rcv_len);
+
+ return QLA_SUCCESS;
+}
diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h
index d38dab0a07e8..a920c8e482bc 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.h
+++ b/drivers/scsi/qla2xxx/qla_bsg.h
@@ -32,12 +32,14 @@
#define QL_VND_GET_PRIV_STATS_EX 0x1A
#define QL_VND_SS_GET_FLASH_IMAGE_STATUS 0x1E
#define QL_VND_EDIF_MGMT 0X1F
+#define QL_VND_GET_DRV_ATTR 0x22
#define QL_VND_MANAGE_HOST_STATS 0x23
#define QL_VND_GET_HOST_STATS 0x24
#define QL_VND_GET_TGT_STATS 0x25
#define QL_VND_MANAGE_HOST_PORT 0x26
#define QL_VND_MBX_PASSTHRU 0x2B
#define QL_VND_DPORT_DIAGNOSTICS_V2 0x2C
+#define QL_VND_IMG_SET_VALID 0x30
/* BSG Vendor specific subcode returns */
#define EXT_STATUS_OK 0
@@ -50,6 +52,8 @@
#define EXT_STATUS_BUFFER_TOO_SMALL 16
#define EXT_STATUS_NO_MEMORY 17
#define EXT_STATUS_DEVICE_OFFLINE 22
+#define EXT_STATUS_IMG_SET_VALID_ERR 47
+#define EXT_STATUS_IMG_SET_CONFIG_ERR 48
/*
* To support bidirectional iocb
@@ -318,6 +322,14 @@ struct qla_active_regions {
uint8_t reserved[31];
} __packed;
+struct qla_drv_attr {
+ uint32_t attributes;
+ u32 ext_attributes;
+#define QLA_IMG_SET_VALID_SUPPORT BIT_4
+ u32 status_flags;
+ uint8_t reserved[20];
+} __packed;
+
#include "qla_edif_bsg.h"
#endif
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index b3265952c4be..5593ad7fad27 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1270,6 +1270,7 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs)
*/
#define MBC_LOAD_RAM 1 /* Load RAM. */
#define MBC_EXECUTE_FIRMWARE 2 /* Execute firmware. */
+#define MBC_LOAD_FLASH_FIRMWARE 3 /* Load flash firmware. */
#define MBC_READ_RAM_WORD 5 /* Read RAM word. */
#define MBC_MAILBOX_REGISTER_TEST 6 /* Wrap incoming mailboxes */
#define MBC_VERIFY_CHECKSUM 7 /* Verify checksum. */
@@ -1385,6 +1386,26 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs)
#define HCS_WRITE_SERDES 0x3
#define HCS_READ_SERDES 0x4
+/*
+ * ISP2[7|8]xx mailbox commands.
+ */
+#define MBC_MPI_PASSTHROUGH 0x200
+
+/* MBC_MPI_PASSTHROUGH */
+#define MPIPT_REQ_V1 1
+enum {
+ MPIPT_SUBCMD_GET_SUP_CMD = 0x10,
+ MPIPT_SUBCMD_GET_SUP_FEATURE,
+ MPIPT_SUBCMD_GET_STATUS,
+ MPIPT_SUBCMD_VALIDATE_FW,
+};
+
+enum {
+ MPIPT_MPI_STATUS = 1,
+ MPIPT_FCORE_STATUS,
+ MPIPT_LOCKDOWN_STATUS,
+};
+
/* Firmware return data sizes */
#define FCAL_MAP_SIZE 128
@@ -4149,6 +4170,7 @@ struct qla_hw_data {
uint32_t eeh_flush:2;
#define EEH_FLUSH_RDY 1
#define EEH_FLUSH_DONE 2
+ uint32_t secure_mcu:1;
} flags;
uint16_t max_exchg;
@@ -4414,6 +4436,8 @@ struct qla_hw_data {
((IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) &&\
(ha->zio_mode == QLA_ZIO_MODE_6))
+#define IS_QLA28XX_SECURED(ha) (IS_QLA28XX(ha) && ha->flags.secure_mcu)
+
/* HBA serial number */
uint8_t serial0;
uint8_t serial1;
@@ -5368,7 +5392,7 @@ struct edif_sa_index_entry {
struct list_head next;
};
-/* Refer to SNIA SFF 8247 */
+/* Refer to SNIA SFF 8472 */
struct sff_8247_a0 {
u8 txid; /* transceiver id */
u8 ext_txid;
@@ -5412,6 +5436,7 @@ struct sff_8247_a0 {
#define FC_SP_32 BIT_3
#define FC_SP_2 BIT_2
#define FC_SP_1 BIT_0
+#define FC_SPEED_2 BIT_1
u8 fc_sp_cc10;
u8 encode;
u8 bitrate;
@@ -5430,7 +5455,8 @@ struct sff_8247_a0 {
u8 vendor_pn[SFF_PART_NAME_LEN]; /* part number */
u8 vendor_rev[4];
u8 wavelength[2];
- u8 resv;
+#define FC_SP_64 BIT_0
+ u8 fiber_channel_speed2;
u8 cc_base;
u8 options[2]; /* offset 64 */
u8 br_max;
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 55d531c19e6b..9e328c235e39 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -345,6 +345,9 @@ extern int
qla2x00_execute_fw(scsi_qla_host_t *, uint32_t);
extern int
+qla28xx_load_flash_firmware(scsi_qla_host_t *vha);
+
+extern int
qla2x00_get_fw_version(scsi_qla_host_t *);
extern int
@@ -839,6 +842,8 @@ extern int qla82xx_write_optrom_data(struct scsi_qla_host *, void *,
extern int qla82xx_abort_isp(scsi_qla_host_t *);
extern int qla82xx_restart_isp(scsi_qla_host_t *);
+extern int qla_mpipt_validate_fw(scsi_qla_host_t *vha, u16 img_idx, u16 *state);
+
/* IOCB related functions */
extern int qla82xx_start_scsi(srb_t *);
extern void qla2x00_sp_free(srb_t *sp);
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 51c7cea71f90..880cd73feaca 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -3266,9 +3266,6 @@ login_logout:
atomic_read(&fcport->state) == FCS_ONLINE) ||
do_delete) {
if (fcport->loop_id != FC_NO_LOOP_ID) {
- if (fcport->flags & FCF_FCP2_DEVICE)
- continue;
-
ql_log(ql_log_warn, vha, 0x20f0,
"%s %d %8phC post del sess\n",
__func__, __LINE__,
@@ -3535,8 +3532,8 @@ int qla_fab_async_scan(scsi_qla_host_t *vha, srb_t *sp)
if (vha->scan.scan_flags & SF_SCANNING) {
spin_unlock_irqrestore(&vha->work_lock, flags);
ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2012,
- "%s: scan active\n", __func__);
- return rval;
+ "%s: scan active for sp:%p\n", __func__, sp);
+ goto done_free_sp;
}
vha->scan.scan_flags |= SF_SCANNING;
if (!sp)
@@ -3701,23 +3698,25 @@ int qla_fab_async_scan(scsi_qla_host_t *vha, srb_t *sp)
return rval;
done_free_sp:
- if (sp->u.iocb_cmd.u.ctarg.req) {
- dma_free_coherent(&vha->hw->pdev->dev,
- sp->u.iocb_cmd.u.ctarg.req_allocated_size,
- sp->u.iocb_cmd.u.ctarg.req,
- sp->u.iocb_cmd.u.ctarg.req_dma);
- sp->u.iocb_cmd.u.ctarg.req = NULL;
- }
- if (sp->u.iocb_cmd.u.ctarg.rsp) {
- dma_free_coherent(&vha->hw->pdev->dev,
- sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
- sp->u.iocb_cmd.u.ctarg.rsp,
- sp->u.iocb_cmd.u.ctarg.rsp_dma);
- sp->u.iocb_cmd.u.ctarg.rsp = NULL;
- }
+ if (sp) {
+ if (sp->u.iocb_cmd.u.ctarg.req) {
+ dma_free_coherent(&vha->hw->pdev->dev,
+ sp->u.iocb_cmd.u.ctarg.req_allocated_size,
+ sp->u.iocb_cmd.u.ctarg.req,
+ sp->u.iocb_cmd.u.ctarg.req_dma);
+ sp->u.iocb_cmd.u.ctarg.req = NULL;
+ }
+ if (sp->u.iocb_cmd.u.ctarg.rsp) {
+ dma_free_coherent(&vha->hw->pdev->dev,
+ sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
+ sp->u.iocb_cmd.u.ctarg.rsp,
+ sp->u.iocb_cmd.u.ctarg.rsp_dma);
+ sp->u.iocb_cmd.u.ctarg.rsp = NULL;
+ }
- /* ref: INIT */
- kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ }
spin_lock_irqsave(&vha->work_lock, flags);
vha->scan.scan_flags &= ~SF_SCANNING;
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index d395cbfe6802..689f909943b4 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1859,15 +1859,6 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea)
case RSCN_PORT_ADDR:
fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1);
if (fcport) {
- if (ql2xfc2target &&
- fcport->flags & FCF_FCP2_DEVICE &&
- atomic_read(&fcport->state) == FCS_ONLINE) {
- ql_dbg(ql_dbg_disc, vha, 0x2115,
- "Delaying session delete for FCP2 portid=%06x %8phC ",
- fcport->d_id.b24, fcport->port_name);
- return;
- }
-
if (vha->hw->flags.edif_enabled && DBELL_ACTIVE(vha)) {
/*
* On ipsec start by remote port, Target port
@@ -2471,8 +2462,23 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
ea->sp->gen1, fcport->rscn_gen,
ea->data[0], ea->data[1], ea->iop[0], ea->iop[1]);
- if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
- (fcport->fw_login_state == DSC_LS_PRLI_PEND)) {
+ if (fcport->fw_login_state == DSC_LS_PLOGI_PEND) {
+ ql_dbg(ql_dbg_disc, vha, 0x20ea,
+ "%s %d %8phC Remote is trying to login\n",
+ __func__, __LINE__, fcport->port_name);
+ /*
+ * If we get here, there is port thats already logged in,
+ * but it's state has not moved ahead. Recheck with FW on
+ * what state it is in and proceed ahead
+ */
+ if (!N2N_TOPO(vha->hw)) {
+ fcport->fw_login_state = DSC_LS_PRLI_COMP;
+ qla24xx_post_gpdb_work(vha, fcport, 0);
+ }
+ return;
+ }
+
+ if (fcport->fw_login_state == DSC_LS_PRLI_PEND) {
ql_dbg(ql_dbg_disc, vha, 0x20ea,
"%s %d %8phC Remote is trying to login\n",
__func__, __LINE__, fcport->port_name);
@@ -4074,6 +4080,22 @@ static void qla2xxx_print_sfp_info(struct scsi_qla_host *vha)
u8 str[STR_LEN], *ptr, p;
int leftover, len;
+ ql_dbg(ql_dbg_init, vha, 0x015a,
+ "SFP: %.*s -> %.*s ->%s%s%s%s%s%s%s\n",
+ (int)sizeof(a0->vendor_name), a0->vendor_name,
+ (int)sizeof(a0->vendor_pn), a0->vendor_pn,
+ a0->fc_sp_cc10 & FC_SP_2 ? a0->fiber_channel_speed2 & FC_SP_64 ?
+ " 64G" : "" : "",
+ a0->fc_sp_cc10 & FC_SP_32 ? " 32G" : "",
+ a0->fc_sp_cc10 & FC_SP_16 ? " 16G" : "",
+ a0->fc_sp_cc10 & FC_SP_8 ? " 8G" : "",
+ a0->fc_sp_cc10 & FC_SP_4 ? " 4G" : "",
+ a0->fc_sp_cc10 & FC_SP_2 ? " 2G" : "",
+ a0->fc_sp_cc10 & FC_SP_1 ? " 1G" : "");
+
+ if (!(ql2xextended_error_logging & ql_dbg_verbose))
+ return;
+
memset(str, 0, STR_LEN);
snprintf(str, SFF_VEN_NAME_LEN+1, a0->vendor_name);
ql_dbg(ql_dbg_init, vha, 0x015a,
@@ -8443,6 +8465,148 @@ bool qla24xx_risc_firmware_invalid(uint32_t *dword)
}
static int
+qla28xx_get_srisc_addr(scsi_qla_host_t *vha, uint32_t *srisc_addr,
+ uint32_t faddr)
+{
+ struct qla_hw_data *ha = vha->hw;
+ struct req_que *req = ha->req_q_map[0];
+ uint32_t *dcode;
+ int rval;
+
+ *srisc_addr = 0;
+ dcode = (uint32_t *)req->ring;
+
+ rval = qla24xx_read_flash_data(vha, dcode, faddr, 10);
+ if (rval) {
+ ql_log(ql_log_fatal, vha, 0x01aa,
+ "-> Failed to read flash addr + size .\n");
+ return QLA_FUNCTION_FAILED;
+ }
+
+ *srisc_addr = be32_to_cpu((__force __be32)dcode[2]);
+ return QLA_SUCCESS;
+}
+
+static int
+qla28xx_load_fw_template(scsi_qla_host_t *vha, uint32_t faddr)
+{
+ struct qla_hw_data *ha = vha->hw;
+ struct fwdt *fwdt = ha->fwdt;
+ struct req_que *req = ha->req_q_map[0];
+ uint32_t risc_size, risc_attr = 0;
+ uint templates, segments, fragment;
+ uint32_t *dcode;
+ ulong dlen;
+ int rval;
+ uint j;
+
+ dcode = (uint32_t *)req->ring;
+ segments = FA_RISC_CODE_SEGMENTS;
+
+ for (j = 0; j < segments; j++) {
+ rval = qla24xx_read_flash_data(vha, dcode, faddr, 10);
+ if (rval) {
+ ql_log(ql_log_fatal, vha, 0x01a1,
+ "-> Failed to read flash addr + size .\n");
+ return QLA_FUNCTION_FAILED;
+ }
+
+ risc_size = be32_to_cpu((__force __be32)dcode[3]);
+
+ if (risc_attr == 0)
+ risc_attr = be32_to_cpu((__force __be32)dcode[9]);
+
+ dlen = ha->fw_transfer_size >> 2;
+ for (fragment = 0; fragment < risc_size; fragment++) {
+ if (dlen > risc_size)
+ dlen = risc_size;
+
+ faddr += dlen;
+ risc_size -= dlen;
+ }
+ }
+
+ templates = (risc_attr & BIT_9) ? 2 : 1;
+
+ ql_dbg(ql_dbg_init, vha, 0x01a1, "-> templates = %u\n", templates);
+
+ for (j = 0; j < templates; j++, fwdt++) {
+ vfree(fwdt->template);
+ fwdt->template = NULL;
+ fwdt->length = 0;
+
+ dcode = (uint32_t *)req->ring;
+
+ rval = qla24xx_read_flash_data(vha, dcode, faddr, 7);
+ if (rval) {
+ ql_log(ql_log_fatal, vha, 0x01a2,
+ "-> Unable to read template size.\n");
+ goto failed;
+ }
+
+ risc_size = be32_to_cpu((__force __be32)dcode[2]);
+ ql_dbg(ql_dbg_init, vha, 0x01a3,
+ "-> fwdt%u template array at %#x (%#x dwords)\n",
+ j, faddr, risc_size);
+ if (!risc_size || !~risc_size) {
+ ql_dbg(ql_dbg_init, vha, 0x01a4,
+ "-> fwdt%u failed to read array\n", j);
+ goto failed;
+ }
+
+ /* skip header and ignore checksum */
+ faddr += 7;
+ risc_size -= 8;
+
+ ql_dbg(ql_dbg_init, vha, 0x01a5,
+ "-> fwdt%u template allocate template %#x words...\n",
+ j, risc_size);
+ fwdt->template = vmalloc(risc_size * sizeof(*dcode));
+ if (!fwdt->template) {
+ ql_log(ql_log_warn, vha, 0x01a6,
+ "-> fwdt%u failed allocate template.\n", j);
+ goto failed;
+ }
+
+ dcode = fwdt->template;
+ rval = qla24xx_read_flash_data(vha, dcode, faddr, risc_size);
+
+ if (rval || !qla27xx_fwdt_template_valid(dcode)) {
+ ql_log(ql_log_warn, vha, 0x01a7,
+ "-> fwdt%u failed template validate (rval %x)\n",
+ j, rval);
+ goto failed;
+ }
+
+ dlen = qla27xx_fwdt_template_size(dcode);
+ ql_dbg(ql_dbg_init, vha, 0x01a7,
+ "-> fwdt%u template size %#lx bytes (%#lx words)\n",
+ j, dlen, dlen / sizeof(*dcode));
+ if (dlen > risc_size * sizeof(*dcode)) {
+ ql_log(ql_log_warn, vha, 0x01a8,
+ "-> fwdt%u template exceeds array (%-lu bytes)\n",
+ j, dlen - risc_size * sizeof(*dcode));
+ goto failed;
+ }
+
+ fwdt->length = dlen;
+ ql_dbg(ql_dbg_init, vha, 0x01a9,
+ "-> fwdt%u loaded template ok\n", j);
+
+ faddr += risc_size + 1;
+ }
+
+ return QLA_SUCCESS;
+
+failed:
+ vfree(fwdt->template);
+ fwdt->template = NULL;
+ fwdt->length = 0;
+
+ return QLA_SUCCESS;
+}
+
+static int
qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr,
uint32_t faddr)
{
@@ -8881,16 +9045,18 @@ int
qla81xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
{
int rval;
+ uint32_t f_region = 0;
struct qla_hw_data *ha = vha->hw;
struct active_regions active_regions = { };
- if (ql2xfwloadbin == 2)
+ if (ql2xfwloadbin == 2 && !IS_QLA28XX(ha))
goto try_blob_fw;
/* FW Load priority:
- * 1) Firmware residing in flash.
- * 2) Firmware via request-firmware interface (.bin file).
- * 3) Golden-Firmware residing in flash -- (limited operation).
+ * 1) If 28xxx, ROM cmd to load flash firmware.
+ * 2) Firmware residing in flash.
+ * 3) Firmware via request-firmware interface (.bin file).
+ * 4) Golden-Firmware residing in flash -- (limited operation).
*/
if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
@@ -8898,6 +9064,40 @@ qla81xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
qla27xx_get_active_image(vha, &active_regions);
+ /* For 28XXX, always load the flash firmware using rom mbx */
+ if (IS_QLA28XX_SECURED(ha)) {
+ rval = qla28xx_load_flash_firmware(vha);
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_fatal, vha, 0x019e,
+ "Failed to load flash firmware.\n");
+ goto exit_load_risc;
+ }
+
+ f_region =
+ (active_regions.global != QLA27XX_SECONDARY_IMAGE) ?
+ ha->flt_region_fw : ha->flt_region_fw_sec;
+
+ ql_log(ql_log_info, vha, 0x019f,
+ "Load flash firmware successful (%s).\n",
+ ((active_regions.global != QLA27XX_SECONDARY_IMAGE) ?
+ "Primary" : "Secondary"));
+
+ rval = qla28xx_get_srisc_addr(vha, srisc_addr, f_region);
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x019f,
+ "failed to read srisc address\n");
+ goto exit_load_risc;
+ }
+
+ rval = qla28xx_load_fw_template(vha, f_region);
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x01a0,
+ "failed to read firmware template\n");
+ }
+
+ goto exit_load_risc;
+ }
+
if (active_regions.global != QLA27XX_SECONDARY_IMAGE)
goto try_primary_fw;
@@ -8927,6 +9127,8 @@ try_blob_fw:
ql_log(ql_log_info, vha, 0x009a, "Need firmware flash update.\n");
ha->flags.running_gold_fw = 1;
+
+exit_load_risc:
return rval;
}
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index a04a5aa0d005..608d2f36e7b4 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1676,13 +1676,28 @@ skip_rio:
/* Port logout */
fcport = qla2x00_find_fcport_by_loopid(vha, mb[1]);
- if (!fcport)
+ if (!fcport) {
+ ql_dbg(ql_dbg_async, vha, 0x5011,
+ "Could not find fcport:%04x %04x %04x\n",
+ mb[1], mb[2], mb[3]);
break;
- if (atomic_read(&fcport->state) != FCS_ONLINE)
+ }
+
+ if (atomic_read(&fcport->state) != FCS_ONLINE) {
+ ql_dbg(ql_dbg_async, vha, 0x5012,
+ "Port state is not online State:0x%x \n",
+ atomic_read(&fcport->state));
+ ql_dbg(ql_dbg_async, vha, 0x5012,
+ "Scheduling session for deletion \n");
+ fcport->logout_on_delete = 0;
+ qlt_schedule_sess_for_deletion(fcport);
break;
+ }
+
ql_dbg(ql_dbg_async, vha, 0x508a,
"Marking port lost loopid=%04x portid=%06x.\n",
fcport->loop_id, fcport->d_id.b24);
+
if (qla_ini_mode_enabled(vha)) {
fcport->logout_on_delete = 0;
qlt_schedule_sess_for_deletion(fcport);
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 1f01576f044b..0d598be6f3ea 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -43,6 +43,7 @@ static struct rom_cmd {
} rom_cmds[] = {
{ MBC_LOAD_RAM },
{ MBC_EXECUTE_FIRMWARE },
+ { MBC_LOAD_FLASH_FIRMWARE },
{ MBC_READ_RAM_WORD },
{ MBC_MAILBOX_REGISTER_TEST },
{ MBC_VERIFY_CHECKSUM },
@@ -825,6 +826,53 @@ done:
}
/*
+ * qla2x00_load_flash_firmware
+ * Load firmware from flash.
+ *
+ * Input:
+ * vha = adapter block pointer.
+ *
+ * Returns:
+ * qla28xx local function return status code.
+ *
+ * Context:
+ * Kernel context.
+ */
+int
+qla28xx_load_flash_firmware(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ int rval = QLA_COMMAND_ERROR;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+
+ if (!IS_QLA28XX(ha))
+ return rval;
+
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x11a6,
+ "Entered %s.\n", __func__);
+
+ mcp->mb[0] = MBC_LOAD_FLASH_FIRMWARE;
+ mcp->out_mb = MBX_2 | MBX_1 | MBX_0;
+ mcp->in_mb = MBX_0;
+ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(vha, mcp);
+
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_log_info, vha, 0x11a7,
+ "Failed=%x cmd error=%x img error=%x.\n",
+ rval, mcp->mb[1], mcp->mb[2]);
+ } else {
+ ql_dbg(ql_log_info, vha, 0x11a8,
+ "Done %s.\n", __func__);
+ }
+
+ return rval;
+}
+
+
+/*
* qla_get_exlogin_status
* Get extended login status
* uses the memory offload control/status Mailbox
@@ -7157,3 +7205,43 @@ int qla_mailbox_passthru(scsi_qla_host_t *vha,
return rval;
}
+
+int qla_mpipt_validate_fw(scsi_qla_host_t *vha, u16 img_idx, uint16_t *state)
+{
+ struct qla_hw_data *ha = vha->hw;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+ int rval;
+
+ if (!IS_QLA28XX(ha)) {
+ ql_dbg(ql_dbg_mbx, vha, 0xffff, "%s %d\n", __func__, __LINE__);
+ return QLA_FUNCTION_FAILED;
+ }
+
+ if (img_idx > 1) {
+ ql_log(ql_log_info, vha, 0xffff,
+ "%s %d Invalid flash image index [%d]\n",
+ __func__, __LINE__, img_idx);
+ return QLA_INVALID_COMMAND;
+ }
+
+ memset(&mc, 0, sizeof(mc));
+ mcp->mb[0] = MBC_MPI_PASSTHROUGH;
+ mcp->mb[1] = MPIPT_SUBCMD_VALIDATE_FW;
+ mcp->mb[2] = img_idx;
+ mcp->out_mb = MBX_1|MBX_0;
+ mcp->in_mb = MBX_2|MBX_1|MBX_0;
+
+ /* send mb via iocb */
+ rval = qla24xx_send_mb_cmd(vha, &mc);
+ if (rval) {
+ ql_log(ql_log_info, vha, 0xffff, "%s:Failed %x (mb=%x,%x)\n",
+ __func__, rval, mcp->mb[0], mcp->mb[1]);
+ *state = mcp->mb[1];
+ } else {
+ ql_log(ql_log_info, vha, 0xffff, "%s: mb=%x,%x,%x\n", __func__,
+ mcp->mb[0], mcp->mb[1], mcp->mb[2]);
+ }
+
+ return rval;
+}
diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h
index 5d1bdc15b75c..8e7a7f5f0adb 100644
--- a/drivers/scsi/qla2xxx/qla_nx.h
+++ b/drivers/scsi/qla2xxx/qla_nx.h
@@ -892,6 +892,7 @@ struct ct6_dsd {
#define FA_VPD_SIZE_82XX 0x400
#define FA_FLASH_LAYOUT_ADDR_82 0xFC400
+#define FA_FLASH_MCU_OFF 0x13000
/******************************************************************************
*
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index e939bc88e151..a88b460641f2 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -402,8 +402,9 @@ static int qla2x00_mem_alloc(struct qla_hw_data *, uint16_t, uint16_t,
struct req_que **, struct rsp_que **);
static void qla2x00_free_fw_dump(struct qla_hw_data *);
static void qla2x00_mem_free(struct qla_hw_data *);
-int qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd,
- struct qla_qpair *qpair);
+static enum scsi_qc_status qla2xxx_mqueuecommand(struct Scsi_Host *host,
+ struct scsi_cmnd *cmd,
+ struct qla_qpair *qpair);
/* -------------------------------------------------------------------------- */
static void qla_init_base_qpair(struct scsi_qla_host *vha, struct req_que *req,
@@ -858,8 +859,8 @@ void qla2xxx_qpair_sp_compl(srb_t *sp, int res)
complete(comp);
}
-static int
-qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
+static enum scsi_qc_status qla2xxx_queuecommand(struct Scsi_Host *host,
+ struct scsi_cmnd *cmd)
{
scsi_qla_host_t *vha = shost_priv(host);
fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
@@ -981,9 +982,9 @@ qc24_fail_command:
}
/* For MQ supported I/O */
-int
+static enum scsi_qc_status
qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd,
- struct qla_qpair *qpair)
+ struct qla_qpair *qpair)
{
scsi_qla_host_t *vha = shost_priv(host);
fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
@@ -1183,7 +1184,8 @@ qla2x00_wait_for_hba_ready(scsi_qla_host_t *vha)
while ((qla2x00_reset_active(vha) || ha->dpc_active ||
ha->flags.mbox_busy) ||
test_bit(FX00_RESET_RECOVERY, &vha->dpc_flags) ||
- test_bit(FX00_TARGET_SCAN, &vha->dpc_flags)) {
+ test_bit(FX00_TARGET_SCAN, &vha->dpc_flags) ||
+ (vha->scan.scan_flags & SF_SCANNING)) {
if (test_bit(UNLOADING, &base_vha->dpc_flags))
break;
msleep(1000);
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 9e7a407ba1b9..b6c36a8a2d60 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -1084,6 +1084,32 @@ qla2xxx_get_idc_param(scsi_qla_host_t *vha)
return;
}
+static int qla28xx_validate_mcu_signature(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ struct req_que *req = ha->req_q_map[0];
+ uint32_t *dcode = (uint32_t *)req->ring;
+ uint32_t signature[2] = {0x000c0000, 0x00050000};
+ int ret = QLA_SUCCESS;
+
+ ret = qla24xx_read_flash_data(vha, dcode, FA_FLASH_MCU_OFF >> 2, 2);
+ if (ret) {
+ ql_log(ql_log_fatal, vha, 0x01ab,
+ "-> Failed to read flash mcu signature.\n");
+ ret = QLA_FUNCTION_FAILED;
+ goto done;
+ }
+
+ ql_dbg(ql_dbg_init, vha, 0x01ac,
+ "Flash data 0x%08x 0x%08x.\n", dcode[0], dcode[1]);
+
+ if (!(dcode[0] == signature[0] && dcode[1] == signature[1]))
+ ret = QLA_FUNCTION_FAILED;
+
+done:
+ return ret;
+}
+
int
qla2xxx_get_flash_info(scsi_qla_host_t *vha)
{
@@ -1096,6 +1122,9 @@ qla2xxx_get_flash_info(scsi_qla_host_t *vha)
!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
return QLA_SUCCESS;
+ if (IS_QLA28XX(ha) && !qla28xx_validate_mcu_signature(vha))
+ ha->flags.secure_mcu = 1;
+
ret = qla2xxx_find_flt_start(vha, &flt_addr);
if (ret != QLA_SUCCESS)
return ret;
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index d772136984c9..ef3a5fac2b48 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -8390,7 +8390,7 @@ int __init qlt_init(void)
goto out_plogi_cachep;
}
- qla_tgt_wq = alloc_workqueue("qla_tgt_wq", 0, 0);
+ qla_tgt_wq = alloc_workqueue("qla_tgt_wq", WQ_PERCPU, 0);
if (!qla_tgt_wq) {
ql_log(ql_log_fatal, NULL, 0xe06f,
"alloc_workqueue for qla_tgt_wq failed\n");
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index a491d6ee5c94..9564beafdab7 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -6,9 +6,9 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "10.02.09.400-k"
+#define QLA2XXX_VERSION "10.02.10.100-k"
#define QLA_DRIVER_MAJOR_VER 10
-#define QLA_DRIVER_MINOR_VER 2
-#define QLA_DRIVER_PATCH_VER 9
-#define QLA_DRIVER_BETA_VER 400
+#define QLA_DRIVER_MINOR_VER 02
+#define QLA_DRIVER_PATCH_VER 10
+#define QLA_DRIVER_BETA_VER 100
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index 9f16164faa1e..3177cb7864a7 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -1902,7 +1902,7 @@ static int tcm_qla2xxx_register_configfs(void)
goto out_fabric;
tcm_qla2xxx_free_wq = alloc_workqueue("tcm_qla2xxx_free",
- WQ_MEM_RECLAIM, 0);
+ WQ_MEM_RECLAIM | WQ_PERCPU, 0);
if (!tcm_qla2xxx_free_wq) {
ret = -ENOMEM;
goto out_fabric_npiv;
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 97329c97332f..d598ab4126f8 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -155,7 +155,8 @@ static int qla4xxx_get_host_stats(struct Scsi_Host *shost, char *buf, int len);
/*
* SCSI host template entry points
*/
-static int qla4xxx_queuecommand(struct Scsi_Host *h, struct scsi_cmnd *cmd);
+static enum scsi_qc_status qla4xxx_queuecommand(struct Scsi_Host *h,
+ struct scsi_cmnd *cmd);
static int qla4xxx_eh_abort(struct scsi_cmnd *cmd);
static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd);
static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd);
@@ -4107,7 +4108,8 @@ void qla4xxx_srb_compl(struct kref *ref)
* completion handling). Unfortunately, it sometimes calls the scheduler
* in interrupt context which is a big NO! NO!.
**/
-static int qla4xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
+static enum scsi_qc_status qla4xxx_queuecommand(struct Scsi_Host *host,
+ struct scsi_cmnd *cmd)
{
struct scsi_qla_host *ha = to_qla_host(host);
struct ddb_entry *ddb_entry = cmd->device->hostdata;
@@ -8819,7 +8821,7 @@ skip_retry_init:
}
INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc);
- ha->task_wq = alloc_workqueue("qla4xxx_%lu_task", WQ_MEM_RECLAIM, 1,
+ ha->task_wq = alloc_workqueue("qla4xxx_%lu_task", WQ_MEM_RECLAIM | WQ_PERCPU, 1,
ha->host_no);
if (!ha->task_wq) {
ql4_printk(KERN_WARNING, ha, "Unable to start task thread!\n");
diff --git a/drivers/scsi/qlogicfas408.c b/drivers/scsi/qlogicfas408.c
index 1ce469b7db99..d36293bc2717 100644
--- a/drivers/scsi/qlogicfas408.c
+++ b/drivers/scsi/qlogicfas408.c
@@ -464,7 +464,7 @@ irqreturn_t qlogicfas408_ihandl(int irq, void *dev_id)
* Queued command
*/
-static int qlogicfas408_queuecommand_lck(struct scsi_cmnd *cmd)
+static enum scsi_qc_status qlogicfas408_queuecommand_lck(struct scsi_cmnd *cmd)
{
void (*done)(struct scsi_cmnd *) = scsi_done;
struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
diff --git a/drivers/scsi/qlogicfas408.h b/drivers/scsi/qlogicfas408.h
index 83ef86c71f2f..a589c7656f57 100644
--- a/drivers/scsi/qlogicfas408.h
+++ b/drivers/scsi/qlogicfas408.h
@@ -104,7 +104,8 @@ struct qlogicfas408_priv {
#define get_priv_by_host(x) (struct qlogicfas408_priv *)&((x)->hostdata[0])
irqreturn_t qlogicfas408_ihandl(int irq, void *dev_id);
-int qlogicfas408_queuecommand(struct Scsi_Host *h, struct scsi_cmnd * cmd);
+enum scsi_qc_status qlogicfas408_queuecommand(struct Scsi_Host *h,
+ struct scsi_cmnd *cmd);
int qlogicfas408_biosparam(struct scsi_device * disk,
struct gendisk *unused,
sector_t capacity, int ip[]);
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index c9984ef57f26..ea0a2b5a0a42 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -1015,7 +1015,7 @@ static int qlogicpti_sdev_configure(struct scsi_device *sdev,
*
* "This code must fly." -davem
*/
-static int qlogicpti_queuecommand_lck(struct scsi_cmnd *Cmnd)
+static enum scsi_qc_status qlogicpti_queuecommand_lck(struct scsi_cmnd *Cmnd)
{
void (*done)(struct scsi_cmnd *) = scsi_done;
struct Scsi_Host *host = Cmnd->device->host;
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index c5085e6d2e75..c947655db518 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -1371,8 +1371,7 @@ static void mk_sense_invalid_fld(struct scsi_cmnd *scp,
sbuff = scp->sense_buffer;
if (!sbuff) {
- sdev_printk(KERN_ERR, scp->device,
- "%s: sense_buffer is NULL\n", __func__);
+ sdev_printk(KERN_ERR, scp->device, "sense_buffer is NULL\n");
return;
}
asc = c_d ? INVALID_FIELD_IN_CDB : INVALID_FIELD_IN_PARAM_LIST;
@@ -1404,8 +1403,7 @@ static void mk_sense_invalid_fld(struct scsi_cmnd *scp,
static void mk_sense_buffer(struct scsi_cmnd *scp, int key, int asc, int asq)
{
if (!scp->sense_buffer) {
- sdev_printk(KERN_ERR, scp->device,
- "%s: sense_buffer is NULL\n", __func__);
+ sdev_printk(KERN_ERR, scp->device, "sense_buffer is NULL\n");
return;
}
memset(scp->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
@@ -1423,8 +1421,7 @@ static void mk_sense_info_tape(struct scsi_cmnd *scp, int key, int asc, int asq,
unsigned int information, unsigned char tape_flags)
{
if (!scp->sense_buffer) {
- sdev_printk(KERN_ERR, scp->device,
- "%s: sense_buffer is NULL\n", __func__);
+ sdev_printk(KERN_ERR, scp->device, "sense_buffer is NULL\n");
return;
}
memset(scp->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
@@ -1452,15 +1449,12 @@ static int scsi_debug_ioctl(struct scsi_device *dev, unsigned int cmd,
{
if (sdebug_verbose) {
if (0x1261 == cmd)
- sdev_printk(KERN_INFO, dev,
- "%s: BLKFLSBUF [0x1261]\n", __func__);
+ sdev_printk(KERN_INFO, dev, "BLKFLSBUF [0x1261]\n");
else if (0x5331 == cmd)
sdev_printk(KERN_INFO, dev,
- "%s: CDROM_GET_CAPABILITY [0x5331]\n",
- __func__);
+ "CDROM_GET_CAPABILITY [0x5331]\n");
else
- sdev_printk(KERN_INFO, dev, "%s: cmd=0x%x\n",
- __func__, cmd);
+ sdev_printk(KERN_INFO, dev, "cmd=0x%x\n", cmd);
}
return -EINVAL;
/* return -ENOTTY; // correct return but upsets fdisk */
@@ -1664,8 +1658,8 @@ static int p_fill_from_dev_buffer(struct scsi_cmnd *scp, const void *arr,
act_len = sg_pcopy_from_buffer(sdb->table.sgl, sdb->table.nents,
arr, arr_len, skip);
- pr_debug("%s: off_dst=%u, scsi_bufflen=%u, act_len=%u, resid=%d\n",
- __func__, off_dst, scsi_bufflen(scp), act_len,
+ pr_debug("off_dst=%u, scsi_bufflen=%u, act_len=%u, resid=%d\n",
+ off_dst, scsi_bufflen(scp), act_len,
scsi_get_resid(scp));
n = scsi_bufflen(scp) - (off_dst + act_len);
scsi_set_resid(scp, min_t(u32, scsi_get_resid(scp), n));
@@ -3188,8 +3182,8 @@ static int resp_mode_select(struct scsi_cmnd *scp,
return DID_ERROR << 16;
else if (sdebug_verbose && (res < param_len))
sdev_printk(KERN_INFO, scp->device,
- "%s: cdb indicated=%d, IO sent=%d bytes\n",
- __func__, param_len, res);
+ "cdb indicated=%d, IO sent=%d bytes\n",
+ param_len, res);
md_len = mselect6 ? (arr[0] + 1) : (get_unaligned_be16(arr + 0) + 2);
bd_len = mselect6 ? arr[3] : get_unaligned_be16(arr + 6);
off = (mselect6 ? 4 : 8);
@@ -5133,8 +5127,7 @@ static int resp_write_scat(struct scsi_cmnd *scp,
if (lbdof == 0) {
if (sdebug_verbose)
sdev_printk(KERN_INFO, scp->device,
- "%s: %s: LB Data Offset field bad\n",
- my_name, __func__);
+ "%s: LB Data Offset field bad\n", my_name);
mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
return illegal_condition_result;
}
@@ -5142,8 +5135,7 @@ static int resp_write_scat(struct scsi_cmnd *scp,
if ((lrd_size + (num_lrd * lrd_size)) > lbdof_blen) {
if (sdebug_verbose)
sdev_printk(KERN_INFO, scp->device,
- "%s: %s: LBA range descriptors don't fit\n",
- my_name, __func__);
+ "%s: LBA range descriptors don't fit\n", my_name);
mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
return illegal_condition_result;
}
@@ -5152,8 +5144,8 @@ static int resp_write_scat(struct scsi_cmnd *scp,
return SCSI_MLQUEUE_HOST_BUSY;
if (sdebug_verbose)
sdev_printk(KERN_INFO, scp->device,
- "%s: %s: Fetch header+scatter_list, lbdof_blen=%u\n",
- my_name, __func__, lbdof_blen);
+ "%s: Fetch header+scatter_list, lbdof_blen=%u\n",
+ my_name, lbdof_blen);
res = fetch_to_dev_buffer(scp, lrdp, lbdof_blen);
if (res == -1) {
ret = DID_ERROR << 16;
@@ -5170,8 +5162,8 @@ static int resp_write_scat(struct scsi_cmnd *scp,
num = get_unaligned_be32(up + 8);
if (sdebug_verbose)
sdev_printk(KERN_INFO, scp->device,
- "%s: %s: k=%d LBA=0x%llx num=%u sg_off=%u\n",
- my_name, __func__, k, lba, num, sg_off);
+ "%s: k=%d LBA=0x%llx num=%u sg_off=%u\n",
+ my_name, k, lba, num, sg_off);
if (num == 0)
continue;
ret = check_device_access_params(scp, lba, num, true);
@@ -5183,8 +5175,8 @@ static int resp_write_scat(struct scsi_cmnd *scp,
if ((cum_lb + num) > bt_len) {
if (sdebug_verbose)
sdev_printk(KERN_INFO, scp->device,
- "%s: %s: sum of blocks > data provided\n",
- my_name, __func__);
+ "%s: sum of blocks > data provided\n",
+ my_name);
mk_sense_buffer(scp, ILLEGAL_REQUEST, WRITE_ERROR_ASC,
0);
ret = illegal_condition_result;
@@ -5876,8 +5868,8 @@ static int resp_verify(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
goto cleanup;
} else if (sdebug_verbose && (ret < (a_num * lb_size))) {
sdev_printk(KERN_INFO, scp->device,
- "%s: %s: cdb indicated=%u, IO sent=%d bytes\n",
- my_name, __func__, a_num * lb_size, ret);
+ "%s: cdb indicated=%u, IO sent=%d bytes\n",
+ my_name, a_num * lb_size, ret);
}
if (is_bytchk3) {
for (j = 1, off = lb_size; j < vnum; ++j, off += lb_size)
@@ -6404,11 +6396,6 @@ static void sdebug_q_cmd_complete(struct sdebug_defer *sd_dp)
atomic_inc(&sdebug_miss_cpus);
}
- if (!scp) {
- pr_err("scmd=NULL\n");
- return;
- }
-
spin_lock_irqsave(&sdsc->lock, flags);
aborted = sd_dp->aborted;
if (unlikely(aborted))
@@ -6685,14 +6672,14 @@ static int scsi_debug_sdev_configure(struct scsi_device *sdp,
devip->debugfs_entry = debugfs_create_dir(dev_name(&sdp->sdev_dev),
sdebug_debugfs_root);
if (IS_ERR_OR_NULL(devip->debugfs_entry))
- pr_info("%s: failed to create debugfs directory for device %s\n",
- __func__, dev_name(&sdp->sdev_gendev));
+ pr_info("failed to create debugfs directory for device %s\n",
+ dev_name(&sdp->sdev_gendev));
dentry = debugfs_create_file("error", 0600, devip->debugfs_entry, sdp,
&sdebug_error_fops);
if (IS_ERR_OR_NULL(dentry))
- pr_info("%s: failed to create error file for device %s\n",
- __func__, dev_name(&sdp->sdev_gendev));
+ pr_info("failed to create error file for device %s\n",
+ dev_name(&sdp->sdev_gendev));
return 0;
}
@@ -6734,7 +6721,7 @@ static bool scsi_debug_stop_cmnd(struct scsi_cmnd *cmnd)
{
struct sdebug_scsi_cmd *sdsc = scsi_cmd_priv(cmnd);
struct sdebug_defer *sd_dp = &sdsc->sd_dp;
- enum sdeb_defer_type defer_t = READ_ONCE(sd_dp->defer_t);
+ enum sdeb_defer_type defer_t = sd_dp->defer_t;
lockdep_assert_held(&sdsc->lock);
@@ -6880,7 +6867,7 @@ static int scsi_debug_abort(struct scsi_cmnd *SCpnt)
if (SDEBUG_OPT_ALL_NOISE & sdebug_opts)
sdev_printk(KERN_INFO, SCpnt->device,
- "%s: command%s found\n", __func__,
+ "command%s found\n",
aborted ? "" : " not");
@@ -6968,7 +6955,7 @@ static int scsi_debug_device_reset(struct scsi_cmnd *SCpnt)
++num_dev_resets;
if (SDEBUG_OPT_ALL_NOISE & sdebug_opts)
- sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
+ sdev_printk(KERN_INFO, sdp, "doing device reset");
scsi_debug_stop_all_queued(sdp);
if (devip) {
@@ -7008,7 +6995,7 @@ static int scsi_debug_target_reset(struct scsi_cmnd *SCpnt)
++num_target_resets;
if (SDEBUG_OPT_ALL_NOISE & sdebug_opts)
- sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
+ sdev_printk(KERN_INFO, sdp, "doing target reset\n");
list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) {
if (devip->target == sdp->id) {
@@ -7021,7 +7008,7 @@ static int scsi_debug_target_reset(struct scsi_cmnd *SCpnt)
if (SDEBUG_OPT_RESET_NOISE & sdebug_opts)
sdev_printk(KERN_INFO, sdp,
- "%s: %d device(s) found in target\n", __func__, k);
+ "%d device(s) found in target\n", k);
if (sdebug_fail_target_reset(SCpnt)) {
scmd_printk(KERN_INFO, SCpnt, "fail target reset 0x%x\n",
@@ -7042,7 +7029,7 @@ static int scsi_debug_bus_reset(struct scsi_cmnd *SCpnt)
++num_bus_resets;
if (SDEBUG_OPT_ALL_NOISE & sdebug_opts)
- sdev_printk(KERN_INFO, sdp, "%s\n", __func__);
+ sdev_printk(KERN_INFO, sdp, "doing bus reset\n");
list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) {
set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm);
@@ -7053,7 +7040,7 @@ static int scsi_debug_bus_reset(struct scsi_cmnd *SCpnt)
if (SDEBUG_OPT_RESET_NOISE & sdebug_opts)
sdev_printk(KERN_INFO, sdp,
- "%s: %d device(s) found in host\n", __func__, k);
+ "%d device(s) found in host\n", k);
return SUCCESS;
}
@@ -7065,7 +7052,7 @@ static int scsi_debug_host_reset(struct scsi_cmnd *SCpnt)
++num_host_resets;
if (SDEBUG_OPT_ALL_NOISE & sdebug_opts)
- sdev_printk(KERN_INFO, SCpnt->device, "%s\n", __func__);
+ sdev_printk(KERN_INFO, SCpnt->device, "doing host reset\n");
mutex_lock(&sdebug_host_list_mutex);
list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) {
list_for_each_entry(devip, &sdbg_host->dev_info_list,
@@ -7080,7 +7067,7 @@ static int scsi_debug_host_reset(struct scsi_cmnd *SCpnt)
stop_all_queued();
if (SDEBUG_OPT_RESET_NOISE & sdebug_opts)
sdev_printk(KERN_INFO, SCpnt->device,
- "%s: %d device(s) found\n", __func__, k);
+ "%d device(s) found\n", k);
return SUCCESS;
}
@@ -7231,8 +7218,8 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
scsi_result = device_qfull_result;
if (unlikely(SDEBUG_OPT_Q_NOISE & sdebug_opts))
- sdev_printk(KERN_INFO, sdp, "%s: num_in_q=%d +1, <inject> status: TASK SET FULL\n",
- __func__, num_in_q);
+ sdev_printk(KERN_INFO, sdp, "num_in_q=%d +1, <inject> status: TASK SET FULL\n",
+ num_in_q);
}
}
@@ -7258,8 +7245,8 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
}
if (unlikely(sdebug_verbose && cmnd->result))
- sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n",
- __func__, cmnd->result);
+ sdev_printk(KERN_INFO, sdp, "non-zero result=0x%x\n",
+ cmnd->result);
if (delta_jiff > 0 || ndelay > 0) {
ktime_t kt;
@@ -7296,12 +7283,12 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
if (polled) {
spin_lock_irqsave(&sdsc->lock, flags);
sd_dp->cmpl_ts = ktime_add(ns_to_ktime(ns_from_boot), kt);
- WRITE_ONCE(sd_dp->defer_t, SDEB_DEFER_POLL);
+ sd_dp->defer_t = SDEB_DEFER_POLL;
spin_unlock_irqrestore(&sdsc->lock, flags);
} else {
/* schedule the invocation of scsi_done() for a later time */
spin_lock_irqsave(&sdsc->lock, flags);
- WRITE_ONCE(sd_dp->defer_t, SDEB_DEFER_HRT);
+ sd_dp->defer_t = SDEB_DEFER_HRT;
hrtimer_start(&sd_dp->hrt, kt, HRTIMER_MODE_REL_PINNED);
/*
* The completion handler will try to grab sqcp->lock,
@@ -7325,11 +7312,11 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
if (polled) {
spin_lock_irqsave(&sdsc->lock, flags);
sd_dp->cmpl_ts = ns_to_ktime(ns_from_boot);
- WRITE_ONCE(sd_dp->defer_t, SDEB_DEFER_POLL);
+ sd_dp->defer_t = SDEB_DEFER_POLL;
spin_unlock_irqrestore(&sdsc->lock, flags);
} else {
spin_lock_irqsave(&sdsc->lock, flags);
- WRITE_ONCE(sd_dp->defer_t, SDEB_DEFER_WQ);
+ sd_dp->defer_t = SDEB_DEFER_WQ;
schedule_work(&sd_dp->ew.work);
spin_unlock_irqrestore(&sdsc->lock, flags);
}
@@ -8697,7 +8684,7 @@ static int __init scsi_debug_init(void)
sdebug_debugfs_root = debugfs_create_dir("scsi_debug", NULL);
if (IS_ERR_OR_NULL(sdebug_debugfs_root))
- pr_info("%s: failed to create initial debugfs directory\n", __func__);
+ pr_info("failed to create initial debugfs directory\n");
for (k = 0; k < hosts_to_add; k++) {
if (want_store && k == 0) {
@@ -8813,7 +8800,7 @@ static int sdebug_add_store(void)
if (unlikely(res < 0)) {
xa_unlock_irqrestore(per_store_ap, iflags);
kfree(sip);
- pr_warn("%s: xa_alloc() errno=%d\n", __func__, -res);
+ pr_warn("xa_alloc() errno=%d\n", -res);
return res;
}
sdeb_most_recent_idx = n_idx;
@@ -8870,7 +8857,7 @@ static int sdebug_add_store(void)
return (int)n_idx;
err:
sdebug_erase_store((int)n_idx, sip);
- pr_warn("%s: failed, errno=%d\n", __func__, -res);
+ pr_warn("failed, errno=%d\n", -res);
return res;
}
@@ -8929,7 +8916,7 @@ clean:
put_device(&sdbg_host->dev);
else
kfree(sdbg_host);
- pr_warn("%s: failed, errno=%d\n", __func__, -error);
+ pr_warn("failed, errno=%d\n", -error);
return error;
}
@@ -8997,7 +8984,7 @@ static int sdebug_change_qdepth(struct scsi_device *sdev, int qdepth)
if (qdepth > SDEBUG_CANQUEUE) {
qdepth = SDEBUG_CANQUEUE;
- pr_warn("%s: requested qdepth [%d] exceeds canqueue [%d], trim\n", __func__,
+ pr_warn("requested qdepth [%d] exceeds canqueue [%d], trim\n",
qdepth, SDEBUG_CANQUEUE);
}
if (qdepth < 1)
@@ -9009,7 +8996,7 @@ static int sdebug_change_qdepth(struct scsi_device *sdev, int qdepth)
mutex_unlock(&sdebug_host_list_mutex);
if (SDEBUG_OPT_Q_NOISE & sdebug_opts)
- sdev_printk(KERN_INFO, sdev, "%s: qdepth=%d\n", __func__, qdepth);
+ sdev_printk(KERN_INFO, sdev, "qdepth=%d\n", qdepth);
return sdev->queue_depth;
}
@@ -9133,7 +9120,7 @@ static bool sdebug_blk_mq_poll_iter(struct request *rq, void *opaque)
spin_lock_irqsave(&sdsc->lock, flags);
sd_dp = &sdsc->sd_dp;
- if (READ_ONCE(sd_dp->defer_t) != SDEB_DEFER_POLL) {
+ if (sd_dp->defer_t != SDEB_DEFER_POLL) {
spin_unlock_irqrestore(&sdsc->lock, flags);
return true;
}
@@ -9282,8 +9269,7 @@ static void scsi_debug_abort_cmd(struct Scsi_Host *shost, struct scsi_cmnd *scp)
bool res = false;
if (!to_be_aborted_scmd) {
- pr_err("%s: command with tag %#x not found\n", __func__,
- unique_tag);
+ pr_err("command with tag %#x not found\n", unique_tag);
return;
}
@@ -9291,17 +9277,16 @@ static void scsi_debug_abort_cmd(struct Scsi_Host *shost, struct scsi_cmnd *scp)
res = scsi_debug_stop_cmnd(to_be_aborted_scmd);
if (res)
- pr_info("%s: aborted command with tag %#x\n",
- __func__, unique_tag);
+ pr_info("aborted command with tag %#x\n", unique_tag);
else
- pr_err("%s: failed to abort command with tag %#x\n",
- __func__, unique_tag);
+ pr_err("failed to abort command with tag %#x\n", unique_tag);
set_host_byte(scp, res ? DID_OK : DID_ERROR);
}
-static int scsi_debug_process_reserved_command(struct Scsi_Host *shost,
- struct scsi_cmnd *scp)
+static enum scsi_qc_status
+scsi_debug_process_reserved_command(struct Scsi_Host *shost,
+ struct scsi_cmnd *scp)
{
struct sdebug_internal_cmd *internal_cmd = scsi_cmd_priv(scp);
@@ -9319,8 +9304,8 @@ static int scsi_debug_process_reserved_command(struct Scsi_Host *shost,
return 0;
}
-static int scsi_debug_queuecommand(struct Scsi_Host *shost,
- struct scsi_cmnd *scp)
+static enum scsi_qc_status scsi_debug_queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *scp)
{
u8 sdeb_i;
struct scsi_device *sdp = scp->device;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 4a902c9dfd8b..68c411aa5665 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -76,7 +76,7 @@ int scsi_init_sense_cache(struct Scsi_Host *shost)
}
static void
-scsi_set_blocked(struct scsi_cmnd *cmd, int reason)
+scsi_set_blocked(struct scsi_cmnd *cmd, enum scsi_qc_status reason)
{
struct Scsi_Host *host = cmd->device->host;
struct scsi_device *device = cmd->device;
@@ -139,7 +139,8 @@ static void scsi_mq_requeue_cmd(struct scsi_cmnd *cmd, unsigned long msecs)
* for a requeue after completion, which should only occur in this
* file.
*/
-static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, bool unbusy)
+static void __scsi_queue_insert(struct scsi_cmnd *cmd,
+ enum scsi_qc_status reason, bool unbusy)
{
struct scsi_device *device = cmd->device;
@@ -179,7 +180,7 @@ static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, bool unbusy)
* Context: This could be called either from an interrupt context or a normal
* process context.
*/
-void scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
+void scsi_queue_insert(struct scsi_cmnd *cmd, enum scsi_qc_status reason)
{
__scsi_queue_insert(cmd, reason, true);
}
@@ -1585,7 +1586,7 @@ static void scsi_complete(struct request *rq)
* Return: nonzero return request was rejected and device's queue needs to be
* plugged.
*/
-static int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
+static enum scsi_qc_status scsi_dispatch_cmd(struct scsi_cmnd *cmd)
{
struct Scsi_Host *host = cmd->device->host;
int rtn = 0;
@@ -1834,7 +1835,7 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx,
struct Scsi_Host *shost = sdev->host;
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
blk_status_t ret;
- int reason;
+ enum scsi_qc_status reason;
WARN_ON_ONCE(cmd->budget_token < 0);
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index d07ec15d6c00..7a193cc04e5b 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -102,7 +102,8 @@ void scsi_eh_done(struct scsi_cmnd *scmd);
/* scsi_lib.c */
extern void scsi_device_unbusy(struct scsi_device *sdev, struct scsi_cmnd *cmd);
-extern void scsi_queue_insert(struct scsi_cmnd *cmd, int reason);
+extern void scsi_queue_insert(struct scsi_cmnd *cmd,
+ enum scsi_qc_status reason);
extern void scsi_io_completion(struct scsi_cmnd *, unsigned int);
extern void scsi_run_host_queues(struct Scsi_Host *shost);
extern void scsi_requeue_run_queue(struct work_struct *work);
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 99eb0a30df61..6b8c5c05f294 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -554,10 +554,48 @@ static int scsi_bus_uevent(const struct device *dev, struct kobj_uevent_env *env
return 0;
}
+static int scsi_bus_probe(struct device *dev)
+{
+ struct scsi_device *sdp = to_scsi_device(dev);
+ struct scsi_driver *drv = to_scsi_driver(dev->driver);
+
+ if (drv->probe)
+ return drv->probe(sdp);
+ else
+ return 0;
+}
+
+static void scsi_bus_remove(struct device *dev)
+{
+ struct scsi_device *sdp = to_scsi_device(dev);
+ struct scsi_driver *drv = to_scsi_driver(dev->driver);
+
+ if (drv->remove)
+ drv->remove(sdp);
+}
+
+static void scsi_bus_shutdown(struct device *dev)
+{
+ struct scsi_device *sdp = to_scsi_device(dev);
+ struct scsi_driver *drv;
+
+ if (!dev->driver)
+ return;
+
+ drv = to_scsi_driver(dev->driver);
+
+ if (drv->shutdown)
+ drv->shutdown(sdp);
+}
+
+
const struct bus_type scsi_bus_type = {
- .name = "scsi",
- .match = scsi_bus_match,
+ .name = "scsi",
+ .match = scsi_bus_match,
.uevent = scsi_bus_uevent,
+ .probe = scsi_bus_probe,
+ .remove = scsi_bus_remove,
+ .shutdown = scsi_bus_shutdown,
#ifdef CONFIG_PM
.pm = &scsi_bus_pm_ops,
#endif
@@ -1554,11 +1592,44 @@ restart:
}
EXPORT_SYMBOL(scsi_remove_target);
-int __scsi_register_driver(struct device_driver *drv, struct module *owner)
+static int scsi_legacy_probe(struct scsi_device *sdp)
+{
+ struct device *dev = &sdp->sdev_gendev;
+ struct device_driver *driver = dev->driver;
+
+ return driver->probe(dev);
+}
+
+static void scsi_legacy_remove(struct scsi_device *sdp)
+{
+ struct device *dev = &sdp->sdev_gendev;
+ struct device_driver *driver = dev->driver;
+
+ driver->remove(dev);
+}
+
+static void scsi_legacy_shutdown(struct scsi_device *sdp)
+{
+ struct device *dev = &sdp->sdev_gendev;
+ struct device_driver *driver = dev->driver;
+
+ driver->shutdown(dev);
+}
+
+int __scsi_register_driver(struct scsi_driver *sdrv, struct module *owner)
{
+ struct device_driver *drv = &sdrv->gendrv;
+
drv->bus = &scsi_bus_type;
drv->owner = owner;
+ if (!sdrv->probe && drv->probe)
+ sdrv->probe = scsi_legacy_probe;
+ if (!sdrv->remove && drv->remove)
+ sdrv->remove = scsi_legacy_remove;
+ if (!sdrv->shutdown && drv->shutdown)
+ sdrv->shutdown = scsi_legacy_shutdown;
+
return driver_register(drv);
}
EXPORT_SYMBOL(__scsi_register_driver);
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 6bd68f493f20..9532138105c1 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -1329,6 +1329,46 @@ store_fc_rport_fast_io_fail_tmo(struct device *dev,
static FC_DEVICE_ATTR(rport, fast_io_fail_tmo, S_IRUGO | S_IWUSR,
show_fc_rport_fast_io_fail_tmo, store_fc_rport_fast_io_fail_tmo);
+#define fc_rport_encryption(name) \
+static ssize_t fc_rport_encinfo_##name(struct device *cd, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct fc_rport *rport = transport_class_to_rport(cd); \
+ struct Scsi_Host *shost = rport_to_shost(rport); \
+ struct fc_internal *i = to_fc_internal(shost->transportt); \
+ struct fc_encryption_info *info; \
+ ssize_t ret = -ENOENT; \
+ u32 data; \
+ \
+ if (i->f->get_fc_rport_enc_info) { \
+ info = (i->f->get_fc_rport_enc_info)(rport); \
+ if (info) { \
+ data = info->name; \
+ if (!strcmp(#name, "status")) { \
+ ret = scnprintf(buf, \
+ FC_RPORT_ENCRYPTION_STATUS_MAX_LEN, \
+ "%s\n", \
+ data ? "Encrypted" : "Unencrypted"); \
+ } \
+ } \
+ } \
+ return ret; \
+} \
+static FC_DEVICE_ATTR(rport, encryption_##name, 0444, fc_rport_encinfo_##name, NULL) \
+
+fc_rport_encryption(status);
+
+static struct attribute *fc_rport_encryption_attrs[] = {
+ &device_attr_rport_encryption_status.attr,
+ NULL
+};
+
+static struct attribute_group fc_rport_encryption_group = {
+ .name = "encryption",
+ .attrs = fc_rport_encryption_attrs,
+};
+
#define fc_rport_fpin_statistic(name) \
static ssize_t fc_rport_fpinstat_##name(struct device *cd, \
struct device_attribute *attr, \
@@ -2634,6 +2674,8 @@ fc_attach_transport(struct fc_function_template *ft)
i->rport_attr_cont.ac.attrs = &i->rport_attrs[0];
i->rport_attr_cont.ac.class = &fc_rport_class.class;
i->rport_attr_cont.ac.match = fc_rport_match;
+ if (ft->get_fc_rport_enc_info)
+ i->rport_attr_cont.encryption = &fc_rport_encryption_group;
i->rport_attr_cont.statistics = &fc_rport_statistics_group;
transport_container_register(&i->rport_attr_cont);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index f50b92e63201..d76996d6cbc9 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -102,14 +102,9 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_ZBC);
#define SD_MINORS 16
-static void sd_config_discard(struct scsi_disk *sdkp, struct queue_limits *lim,
- unsigned int mode);
static void sd_config_write_same(struct scsi_disk *sdkp,
struct queue_limits *lim);
static void sd_revalidate_disk(struct gendisk *);
-static void sd_unlock_native_capacity(struct gendisk *disk);
-static void sd_shutdown(struct device *);
-static void scsi_disk_release(struct device *cdev);
static DEFINE_IDA(sd_index_ida);
@@ -121,6 +116,62 @@ static const char *sd_cache_types[] = {
"write back, no read (daft)"
};
+static void sd_disable_discard(struct scsi_disk *sdkp)
+{
+ sdkp->provisioning_mode = SD_LBP_DISABLE;
+ blk_queue_disable_discard(sdkp->disk->queue);
+}
+
+static void sd_config_discard(struct scsi_disk *sdkp, struct queue_limits *lim,
+ unsigned int mode)
+{
+ unsigned int logical_block_size = sdkp->device->sector_size;
+ unsigned int max_blocks = 0;
+
+ lim->discard_alignment = sdkp->unmap_alignment * logical_block_size;
+ lim->discard_granularity = max(sdkp->physical_block_size,
+ sdkp->unmap_granularity * logical_block_size);
+ sdkp->provisioning_mode = mode;
+
+ switch (mode) {
+
+ case SD_LBP_FULL:
+ case SD_LBP_DISABLE:
+ break;
+
+ case SD_LBP_UNMAP:
+ max_blocks = min_not_zero(sdkp->max_unmap_blocks,
+ (u32)SD_MAX_WS16_BLOCKS);
+ break;
+
+ case SD_LBP_WS16:
+ if (sdkp->device->unmap_limit_for_ws)
+ max_blocks = sdkp->max_unmap_blocks;
+ else
+ max_blocks = sdkp->max_ws_blocks;
+
+ max_blocks = min_not_zero(max_blocks, (u32)SD_MAX_WS16_BLOCKS);
+ break;
+
+ case SD_LBP_WS10:
+ if (sdkp->device->unmap_limit_for_ws)
+ max_blocks = sdkp->max_unmap_blocks;
+ else
+ max_blocks = sdkp->max_ws_blocks;
+
+ max_blocks = min_not_zero(max_blocks, (u32)SD_MAX_WS10_BLOCKS);
+ break;
+
+ case SD_LBP_ZERO:
+ max_blocks = min_not_zero(sdkp->max_ws_blocks,
+ (u32)SD_MAX_WS10_BLOCKS);
+ break;
+ }
+
+ lim->max_hw_discard_sectors = max_blocks *
+ (logical_block_size >> SECTOR_SHIFT);
+}
+
static void sd_set_flush_flag(struct scsi_disk *sdkp,
struct queue_limits *lim)
{
@@ -698,6 +749,17 @@ static struct attribute *sd_disk_attrs[] = {
};
ATTRIBUTE_GROUPS(sd_disk);
+static void scsi_disk_release(struct device *dev)
+{
+ struct scsi_disk *sdkp = to_scsi_disk(dev);
+
+ ida_free(&sd_index_ida, sdkp->index);
+ put_device(&sdkp->device->sdev_gendev);
+ free_opal_dev(sdkp->opal_dev);
+
+ kfree(sdkp);
+}
+
static struct class sd_disk_class = {
.name = "scsi_disk",
.dev_release = scsi_disk_release,
@@ -866,62 +928,6 @@ static unsigned char sd_setup_protect_cmnd(struct scsi_cmnd *scmd,
return protect;
}
-static void sd_disable_discard(struct scsi_disk *sdkp)
-{
- sdkp->provisioning_mode = SD_LBP_DISABLE;
- blk_queue_disable_discard(sdkp->disk->queue);
-}
-
-static void sd_config_discard(struct scsi_disk *sdkp, struct queue_limits *lim,
- unsigned int mode)
-{
- unsigned int logical_block_size = sdkp->device->sector_size;
- unsigned int max_blocks = 0;
-
- lim->discard_alignment = sdkp->unmap_alignment * logical_block_size;
- lim->discard_granularity = max(sdkp->physical_block_size,
- sdkp->unmap_granularity * logical_block_size);
- sdkp->provisioning_mode = mode;
-
- switch (mode) {
-
- case SD_LBP_FULL:
- case SD_LBP_DISABLE:
- break;
-
- case SD_LBP_UNMAP:
- max_blocks = min_not_zero(sdkp->max_unmap_blocks,
- (u32)SD_MAX_WS16_BLOCKS);
- break;
-
- case SD_LBP_WS16:
- if (sdkp->device->unmap_limit_for_ws)
- max_blocks = sdkp->max_unmap_blocks;
- else
- max_blocks = sdkp->max_ws_blocks;
-
- max_blocks = min_not_zero(max_blocks, (u32)SD_MAX_WS16_BLOCKS);
- break;
-
- case SD_LBP_WS10:
- if (sdkp->device->unmap_limit_for_ws)
- max_blocks = sdkp->max_unmap_blocks;
- else
- max_blocks = sdkp->max_ws_blocks;
-
- max_blocks = min_not_zero(max_blocks, (u32)SD_MAX_WS10_BLOCKS);
- break;
-
- case SD_LBP_ZERO:
- max_blocks = min_not_zero(sdkp->max_ws_blocks,
- (u32)SD_MAX_WS10_BLOCKS);
- break;
- }
-
- lim->max_hw_discard_sectors = max_blocks *
- (logical_block_size >> SECTOR_SHIFT);
-}
-
static void *sd_set_special_bvec(struct request *rq, unsigned int data_len)
{
struct page *page;
@@ -1676,9 +1682,10 @@ static int sd_ioctl(struct block_device *bdev, blk_mode_t mode,
struct scsi_device *sdp = sdkp->device;
void __user *p = (void __user *)arg;
int error;
-
- SCSI_LOG_IOCTL(1, sd_printk(KERN_INFO, sdkp, "sd_ioctl: disk=%s, "
- "cmd=0x%x\n", disk->disk_name, cmd));
+
+ SCSI_LOG_IOCTL(1, sd_printk(KERN_INFO, sdkp,
+ "sd_ioctl: disk=%s, cmd=0x%x\n",
+ disk->disk_name, cmd));
if (bdev_is_partition(bdev) && !capable(CAP_SYS_RAWIO))
return -ENOIOCTLCMD;
@@ -2177,21 +2184,6 @@ static void scsi_disk_free_disk(struct gendisk *disk)
put_device(&sdkp->disk_dev);
}
-static const struct block_device_operations sd_fops = {
- .owner = THIS_MODULE,
- .open = sd_open,
- .release = sd_release,
- .ioctl = sd_ioctl,
- .getgeo = sd_getgeo,
- .compat_ioctl = blkdev_compat_ptr_ioctl,
- .check_events = sd_check_events,
- .unlock_native_capacity = sd_unlock_native_capacity,
- .report_zones = sd_zbc_report_zones,
- .get_unique_id = sd_get_unique_id,
- .free_disk = scsi_disk_free_disk,
- .pr_ops = &sd_pr_ops,
-};
-
/**
* sd_eh_reset - reset error handling callback
* @scmd: sd-issued command that has failed
@@ -2602,8 +2594,8 @@ static int sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer
type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */
if (type > T10_PI_TYPE3_PROTECTION) {
- sd_printk(KERN_ERR, sdkp, "formatted with unsupported" \
- " protection type %u. Disabling disk!\n",
+ sd_printk(KERN_ERR, sdkp,
+ "formatted with unsupported protection type %u. Disabling disk!\n",
type);
sdkp->protection_type = 0;
return -ENODEV;
@@ -2880,8 +2872,8 @@ sd_read_capacity(struct scsi_disk *sdkp, struct queue_limits *lim,
if ((sizeof(sdkp->capacity) > 4) &&
(sdkp->capacity > 0xffffffffULL)) {
int old_sector_size = sector_size;
- sd_printk(KERN_NOTICE, sdkp, "Very big device. "
- "Trying to use READ CAPACITY(16).\n");
+ sd_printk(KERN_NOTICE, sdkp,
+ "Very big device. Trying to use READ CAPACITY(16).\n");
sector_size = read_capacity_16(sdkp, sdp, lim, buffer);
if (sector_size < 0) {
sd_printk(KERN_NOTICE, sdkp,
@@ -2907,17 +2899,17 @@ sd_read_capacity(struct scsi_disk *sdkp, struct queue_limits *lim,
*/
if (sdp->fix_capacity ||
(sdp->guess_capacity && (sdkp->capacity & 0x01))) {
- sd_printk(KERN_INFO, sdkp, "Adjusting the sector count "
- "from its reported value: %llu\n",
- (unsigned long long) sdkp->capacity);
+ sd_printk(KERN_INFO, sdkp,
+ "Adjusting the sector count from its reported value: %llu\n",
+ (unsigned long long) sdkp->capacity);
--sdkp->capacity;
}
got_data:
if (sector_size == 0) {
sector_size = 512;
- sd_printk(KERN_NOTICE, sdkp, "Sector size 0 reported, "
- "assuming 512.\n");
+ sd_printk(KERN_NOTICE, sdkp,
+ "Sector size 0 reported, assuming 512.\n");
}
if (sector_size != 512 &&
@@ -3122,8 +3114,9 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
if (len < 3)
goto bad_sense;
else if (len > SD_BUF_SIZE) {
- sd_first_printk(KERN_NOTICE, sdkp, "Truncating mode parameter "
- "data from %d to %d bytes\n", len, SD_BUF_SIZE);
+ sd_first_printk(KERN_NOTICE, sdkp,
+ "Truncating mode parameter data from %d to %d bytes\n",
+ len, SD_BUF_SIZE);
len = SD_BUF_SIZE;
}
if (modepage == 0x3F && sdp->use_192_bytes_for_3f)
@@ -3146,8 +3139,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
*/
if (len - offset <= 2) {
sd_first_printk(KERN_ERR, sdkp,
- "Incomplete mode parameter "
- "data\n");
+ "Incomplete mode parameter data\n");
goto defaults;
} else {
modepage = page_code;
@@ -3162,8 +3154,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
offset += 2 + buffer[offset+1];
else {
sd_first_printk(KERN_ERR, sdkp,
- "Incomplete mode "
- "parameter data\n");
+ "Incomplete mode parameter data\n");
goto defaults;
}
}
@@ -3626,8 +3617,7 @@ static bool sd_validate_min_xfer_size(struct scsi_disk *sdkp)
if (min_xfer_bytes & (sdkp->physical_block_size - 1)) {
sd_first_printk(KERN_WARNING, sdkp,
- "Preferred minimum I/O size %u bytes not a " \
- "multiple of physical block size (%u bytes)\n",
+ "Preferred minimum I/O size %u bytes not a multiple of physical block size (%u bytes)\n",
min_xfer_bytes, sdkp->physical_block_size);
sdkp->min_xfer_blocks = 0;
return false;
@@ -3657,41 +3647,35 @@ static bool sd_validate_opt_xfer_size(struct scsi_disk *sdkp,
if (sdkp->opt_xfer_blocks > dev_max) {
sd_first_printk(KERN_WARNING, sdkp,
- "Optimal transfer size %u logical blocks " \
- "> dev_max (%u logical blocks)\n",
+ "Optimal transfer size %u logical blocks > dev_max (%u logical blocks)\n",
sdkp->opt_xfer_blocks, dev_max);
return false;
}
if (sdkp->opt_xfer_blocks > SD_DEF_XFER_BLOCKS) {
sd_first_printk(KERN_WARNING, sdkp,
- "Optimal transfer size %u logical blocks " \
- "> sd driver limit (%u logical blocks)\n",
+ "Optimal transfer size %u logical blocks > sd driver limit (%u logical blocks)\n",
sdkp->opt_xfer_blocks, SD_DEF_XFER_BLOCKS);
return false;
}
if (opt_xfer_bytes < PAGE_SIZE) {
sd_first_printk(KERN_WARNING, sdkp,
- "Optimal transfer size %u bytes < " \
- "PAGE_SIZE (%u bytes)\n",
+ "Optimal transfer size %u bytes < PAGE_SIZE (%u bytes)\n",
opt_xfer_bytes, (unsigned int)PAGE_SIZE);
return false;
}
if (min_xfer_bytes && opt_xfer_bytes % min_xfer_bytes) {
sd_first_printk(KERN_WARNING, sdkp,
- "Optimal transfer size %u bytes not a " \
- "multiple of preferred minimum block " \
- "size (%u bytes)\n",
+ "Optimal transfer size %u bytes not a multiple of preferred minimum block size (%u bytes)\n",
opt_xfer_bytes, min_xfer_bytes);
return false;
}
if (opt_xfer_bytes & (sdkp->physical_block_size - 1)) {
sd_first_printk(KERN_WARNING, sdkp,
- "Optimal transfer size %u bytes not a " \
- "multiple of physical block size (%u bytes)\n",
+ "Optimal transfer size %u bytes not a multiple of physical block size (%u bytes)\n",
opt_xfer_bytes, sdkp->physical_block_size);
return false;
}
@@ -3885,6 +3869,21 @@ static void sd_unlock_native_capacity(struct gendisk *disk)
sdev->host->hostt->unlock_native_capacity(sdev);
}
+static const struct block_device_operations sd_fops = {
+ .owner = THIS_MODULE,
+ .open = sd_open,
+ .release = sd_release,
+ .ioctl = sd_ioctl,
+ .getgeo = sd_getgeo,
+ .compat_ioctl = blkdev_compat_ptr_ioctl,
+ .check_events = sd_check_events,
+ .unlock_native_capacity = sd_unlock_native_capacity,
+ .report_zones = sd_zbc_report_zones,
+ .get_unique_id = sd_get_unique_id,
+ .free_disk = scsi_disk_free_disk,
+ .pr_ops = &sd_pr_ops,
+};
+
/**
* sd_format_disk_name - format disk name
* @prefix: name prefix - ie. "sd" for SCSI disks
@@ -3935,7 +3934,7 @@ static int sd_format_disk_name(char *prefix, int index, char *buf, int buflen)
* sd_probe - called during driver initialization and whenever a
* new scsi device is attached to the system. It is called once
* for each scsi device (not just disks) present.
- * @dev: pointer to device object
+ * @sdp: pointer to device object
*
* Returns 0 if successful (or not interested in this scsi device
* (e.g. scanner)); 1 when there is an error.
@@ -3949,9 +3948,9 @@ static int sd_format_disk_name(char *prefix, int index, char *buf, int buflen)
* Assume sd_probe is not re-entrant (for time being)
* Also think about sd_probe() and sd_remove() running coincidentally.
**/
-static int sd_probe(struct device *dev)
+static int sd_probe(struct scsi_device *sdp)
{
- struct scsi_device *sdp = to_scsi_device(dev);
+ struct device *dev = &sdp->sdev_gendev;
struct scsi_disk *sdkp;
struct gendisk *gd;
int index;
@@ -4087,43 +4086,6 @@ static int sd_probe(struct device *dev)
return error;
}
-/**
- * sd_remove - called whenever a scsi disk (previously recognized by
- * sd_probe) is detached from the system. It is called (potentially
- * multiple times) during sd module unload.
- * @dev: pointer to device object
- *
- * Note: this function is invoked from the scsi mid-level.
- * This function potentially frees up a device name (e.g. /dev/sdc)
- * that could be re-used by a subsequent sd_probe().
- * This function is not called when the built-in sd driver is "exit-ed".
- **/
-static int sd_remove(struct device *dev)
-{
- struct scsi_disk *sdkp = dev_get_drvdata(dev);
-
- scsi_autopm_get_device(sdkp->device);
-
- device_del(&sdkp->disk_dev);
- del_gendisk(sdkp->disk);
- if (!sdkp->suspended)
- sd_shutdown(dev);
-
- put_disk(sdkp->disk);
- return 0;
-}
-
-static void scsi_disk_release(struct device *dev)
-{
- struct scsi_disk *sdkp = to_scsi_disk(dev);
-
- ida_free(&sd_index_ida, sdkp->index);
- put_device(&sdkp->device->sdev_gendev);
- free_opal_dev(sdkp->opal_dev);
-
- kfree(sdkp);
-}
-
static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
{
unsigned char cmd[6] = { START_STOP }; /* START_VALID */
@@ -4197,8 +4159,9 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
* the normal SCSI command structure. Wait for the command to
* complete.
*/
-static void sd_shutdown(struct device *dev)
+static void sd_shutdown(struct scsi_device *sdp)
{
+ struct device *dev = &sdp->sdev_gendev;
struct scsi_disk *sdkp = dev_get_drvdata(dev);
if (!sdkp)
@@ -4225,6 +4188,32 @@ static void sd_shutdown(struct device *dev)
}
}
+/**
+ * sd_remove - called whenever a scsi disk (previously recognized by
+ * sd_probe) is detached from the system. It is called (potentially
+ * multiple times) during sd module unload.
+ * @sdp: pointer to device object
+ *
+ * Note: this function is invoked from the scsi mid-level.
+ * This function potentially frees up a device name (e.g. /dev/sdc)
+ * that could be re-used by a subsequent sd_probe().
+ * This function is not called when the built-in sd driver is "exit-ed".
+ **/
+static void sd_remove(struct scsi_device *sdp)
+{
+ struct device *dev = &sdp->sdev_gendev;
+ struct scsi_disk *sdkp = dev_get_drvdata(dev);
+
+ scsi_autopm_get_device(sdkp->device);
+
+ device_del(&sdkp->disk_dev);
+ del_gendisk(sdkp->disk);
+ if (!sdkp->suspended)
+ sd_shutdown(sdp);
+
+ put_disk(sdkp->disk);
+}
+
static inline bool sd_do_start_stop(struct scsi_device *sdev, bool runtime)
{
return (sdev->manage_system_start_stop && !runtime) ||
@@ -4368,12 +4357,12 @@ static const struct dev_pm_ops sd_pm_ops = {
};
static struct scsi_driver sd_template = {
+ .probe = sd_probe,
+ .remove = sd_remove,
+ .shutdown = sd_shutdown,
.gendrv = {
.name = "sd",
- .probe = sd_probe,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
- .remove = sd_remove,
- .shutdown = sd_shutdown,
.pm = &sd_pm_ops,
},
.rescan = sd_rescan,
@@ -4417,7 +4406,7 @@ static int __init init_sd(void)
goto err_out_class;
}
- err = scsi_register_driver(&sd_template.gendrv);
+ err = scsi_register_driver(&sd_template);
if (err)
goto err_out_driver;
@@ -4444,7 +4433,7 @@ static void __exit exit_sd(void)
SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n"));
- scsi_unregister_driver(&sd_template.gendrv);
+ scsi_unregister_driver(&sd_template);
mempool_destroy(sd_page_pool);
class_unregister(&sd_disk_class);
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c
index 2c61624cb4b0..789b170da652 100644
--- a/drivers/scsi/ses.c
+++ b/drivers/scsi/ses.c
@@ -42,9 +42,8 @@ static bool ses_page2_supported(struct enclosure_device *edev)
return (ses_dev->page2 != NULL);
}
-static int ses_probe(struct device *dev)
+static int ses_probe(struct scsi_device *sdev)
{
- struct scsi_device *sdev = to_scsi_device(dev);
int err = -ENODEV;
if (sdev->type != TYPE_ENCLOSURE)
@@ -847,11 +846,6 @@ page2_not_supported:
return err;
}
-static int ses_remove(struct device *dev)
-{
- return 0;
-}
-
static void ses_intf_remove_component(struct scsi_device *sdev)
{
struct enclosure_device *edev, *prev = NULL;
@@ -906,10 +900,9 @@ static struct class_interface ses_interface = {
};
static struct scsi_driver ses_template = {
+ .probe = ses_probe,
.gendrv = {
.name = "ses",
- .probe = ses_probe,
- .remove = ses_remove,
},
};
@@ -921,7 +914,7 @@ static int __init ses_init(void)
if (err)
return err;
- err = scsi_register_driver(&ses_template.gendrv);
+ err = scsi_register_driver(&ses_template);
if (err)
goto out_unreg;
@@ -934,7 +927,7 @@ static int __init ses_init(void)
static void __exit ses_exit(void)
{
- scsi_unregister_driver(&ses_template.gendrv);
+ scsi_unregister_driver(&ses_template);
scsi_unregister_interface(&ses_interface);
}
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
index fe549e2b7c94..6f859f0d2046 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -1241,7 +1241,8 @@ static inline int pqi_report_phys_luns(struct pqi_ctrl_info *ctrl_info, void **b
dev_err(&ctrl_info->pci_dev->dev,
"RPL returned unsupported data format %u\n",
rpl_response_format);
- return -EINVAL;
+ rc = -EINVAL;
+ goto out_free_rpl_list;
} else {
dev_warn(&ctrl_info->pci_dev->dev,
"RPL returned extended format 2 instead of 4\n");
@@ -1253,8 +1254,10 @@ static inline int pqi_report_phys_luns(struct pqi_ctrl_info *ctrl_info, void **b
rpl_16byte_wwid_list = kmalloc(struct_size(rpl_16byte_wwid_list, lun_entries,
num_physicals), GFP_KERNEL);
- if (!rpl_16byte_wwid_list)
- return -ENOMEM;
+ if (!rpl_16byte_wwid_list) {
+ rc = -ENOMEM;
+ goto out_free_rpl_list;
+ }
put_unaligned_be32(num_physicals * sizeof(struct report_phys_lun_16byte_wwid),
&rpl_16byte_wwid_list->header.list_length);
@@ -1275,6 +1278,10 @@ static inline int pqi_report_phys_luns(struct pqi_ctrl_info *ctrl_info, void **b
*buffer = rpl_16byte_wwid_list;
return 0;
+
+out_free_rpl_list:
+ kfree(rpl_list);
+ return rc;
}
static inline int pqi_report_logical_luns(struct pqi_ctrl_info *ctrl_info, void **buffer)
@@ -6047,7 +6054,8 @@ static bool pqi_is_parity_write_stream(struct pqi_ctrl_info *ctrl_info,
return false;
}
-static int pqi_scsi_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
+static enum scsi_qc_status pqi_scsi_queue_command(struct Scsi_Host *shost,
+ struct scsi_cmnd *scmd)
{
int rc;
struct pqi_ctrl_info *ctrl_info;
diff --git a/drivers/scsi/snic/snic.h b/drivers/scsi/snic/snic.h
index 32f5a34b6987..ebaf6d63a59b 100644
--- a/drivers/scsi/snic/snic.h
+++ b/drivers/scsi/snic/snic.h
@@ -362,7 +362,8 @@ void snic_glob_cleanup(void);
extern struct workqueue_struct *snic_event_queue;
extern const struct attribute_group *snic_host_groups[];
-int snic_queuecommand(struct Scsi_Host *, struct scsi_cmnd *);
+enum scsi_qc_status snic_queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *sc);
int snic_abort_cmd(struct scsi_cmnd *);
int snic_device_reset(struct scsi_cmnd *);
int snic_host_reset(struct scsi_cmnd *);
diff --git a/drivers/scsi/snic/snic_scsi.c b/drivers/scsi/snic/snic_scsi.c
index 84973f0f771e..c6af3b8d2523 100644
--- a/drivers/scsi/snic/snic_scsi.c
+++ b/drivers/scsi/snic/snic_scsi.c
@@ -315,8 +315,8 @@ issue_sc_end:
* Routine to send a scsi cdb to LLD
* Called with host_lock held and interrupts disabled
*/
-int
-snic_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc)
+enum scsi_qc_status snic_queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *sc)
{
struct snic_tgt *tgt = NULL;
struct snic *snic = shost_priv(shost);
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index add13e306898..1fb85f548955 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -82,8 +82,8 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_WORM);
CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_DVD_RAM|CDC_GENERIC_PACKET| \
CDC_MRW|CDC_MRW_W|CDC_RAM)
-static int sr_probe(struct device *);
-static int sr_remove(struct device *);
+static int sr_probe(struct scsi_device *);
+static void sr_remove(struct scsi_device *);
static blk_status_t sr_init_command(struct scsi_cmnd *SCpnt);
static int sr_done(struct scsi_cmnd *);
static int sr_runtime_suspend(struct device *dev);
@@ -93,10 +93,10 @@ static const struct dev_pm_ops sr_pm_ops = {
};
static struct scsi_driver sr_template = {
+ .probe = sr_probe,
+ .remove = sr_remove,
.gendrv = {
.name = "sr",
- .probe = sr_probe,
- .remove = sr_remove,
.pm = &sr_pm_ops,
},
.init_command = sr_init_command,
@@ -616,9 +616,9 @@ static void sr_release(struct cdrom_device_info *cdi)
{
}
-static int sr_probe(struct device *dev)
+static int sr_probe(struct scsi_device *sdev)
{
- struct scsi_device *sdev = to_scsi_device(dev);
+ struct device *dev = &sdev->sdev_gendev;
struct gendisk *disk;
struct scsi_cd *cd;
int minor, error;
@@ -982,16 +982,15 @@ out_put_request:
return ret;
}
-static int sr_remove(struct device *dev)
+static void sr_remove(struct scsi_device *sdev)
{
+ struct device *dev = &sdev->sdev_gendev;
struct scsi_cd *cd = dev_get_drvdata(dev);
scsi_autopm_get_device(cd->device);
del_gendisk(cd->disk);
put_disk(cd->disk);
-
- return 0;
}
static int __init init_sr(void)
@@ -1001,7 +1000,7 @@ static int __init init_sr(void)
rc = register_blkdev(SCSI_CDROM_MAJOR, "sr");
if (rc)
return rc;
- rc = scsi_register_driver(&sr_template.gendrv);
+ rc = scsi_register_driver(&sr_template);
if (rc)
unregister_blkdev(SCSI_CDROM_MAJOR, "sr");
@@ -1010,7 +1009,7 @@ static int __init init_sr(void)
static void __exit exit_sr(void)
{
- scsi_unregister_driver(&sr_template.gendrv);
+ scsi_unregister_driver(&sr_template);
unregister_blkdev(SCSI_CDROM_MAJOR, "sr");
}
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 8aeaa3b68c25..413e844fa276 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -202,14 +202,14 @@ static int sgl_map_user_pages(struct st_buffer *, const unsigned int,
unsigned long, size_t, int);
static int sgl_unmap_user_pages(struct st_buffer *, const unsigned int, int);
-static int st_probe(struct device *);
-static int st_remove(struct device *);
+static int st_probe(struct scsi_device *);
+static void st_remove(struct scsi_device *);
static struct scsi_driver st_template = {
+ .probe = st_probe,
+ .remove = st_remove,
.gendrv = {
.name = "st",
- .probe = st_probe,
- .remove = st_remove,
.groups = st_drv_groups,
},
};
@@ -4343,9 +4343,9 @@ static void remove_cdevs(struct scsi_tape *tape)
}
}
-static int st_probe(struct device *dev)
+static int st_probe(struct scsi_device *SDp)
{
- struct scsi_device *SDp = to_scsi_device(dev);
+ struct device *dev = &SDp->sdev_gendev;
struct scsi_tape *tpnt = NULL;
struct st_modedef *STm;
struct st_partstat *STps;
@@ -4500,12 +4500,13 @@ out:
};
-static int st_remove(struct device *dev)
+static void st_remove(struct scsi_device *SDp)
{
+ struct device *dev = &SDp->sdev_gendev;
struct scsi_tape *tpnt = dev_get_drvdata(dev);
int index = tpnt->index;
- scsi_autopm_get_device(to_scsi_device(dev));
+ scsi_autopm_get_device(SDp);
remove_cdevs(tpnt);
mutex_lock(&st_ref_mutex);
@@ -4514,7 +4515,6 @@ static int st_remove(struct device *dev)
spin_lock(&st_index_lock);
idr_remove(&st_index_idr, index);
spin_unlock(&st_index_lock);
- return 0;
}
/**
@@ -4577,7 +4577,7 @@ static int __init init_st(void)
goto err_class;
}
- err = scsi_register_driver(&st_template.gendrv);
+ err = scsi_register_driver(&st_template);
if (err)
goto err_chrdev;
@@ -4593,7 +4593,7 @@ err_class:
static void __exit exit_st(void)
{
- scsi_unregister_driver(&st_template.gendrv);
+ scsi_unregister_driver(&st_template);
unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
ST_MAX_TAPE_ENTRIES);
class_unregister(&st_sysfs_class);
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
index 93c223e0a777..5a3f6fe22ae9 100644
--- a/drivers/scsi/stex.c
+++ b/drivers/scsi/stex.c
@@ -593,7 +593,7 @@ stex_sdev_configure(struct scsi_device *sdev, struct queue_limits *lim)
return 0;
}
-static int stex_queuecommand_lck(struct scsi_cmnd *cmd)
+static enum scsi_qc_status stex_queuecommand_lck(struct scsi_cmnd *cmd)
{
void (*done)(struct scsi_cmnd *) = scsi_done;
struct st_hba *hba;
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index b43d876747b7..b3f83c0dcced 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -1715,7 +1715,8 @@ static bool storvsc_scsi_cmd_ok(struct scsi_cmnd *scmnd)
return allowed;
}
-static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
+static enum scsi_qc_status storvsc_queuecommand(struct Scsi_Host *host,
+ struct scsi_cmnd *scmnd)
{
int ret;
struct hv_host_device *host_dev = shost_priv(host);
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 57637a81776d..27e22acaf1a7 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -485,7 +485,7 @@ void sym_log_bus_error(struct Scsi_Host *shost)
* queuecommand method. Entered with the host adapter lock held and
* interrupts disabled.
*/
-static int sym53c8xx_queue_command_lck(struct scsi_cmnd *cmd)
+static enum scsi_qc_status sym53c8xx_queue_command_lck(struct scsi_cmnd *cmd)
{
struct sym_hcb *np = SYM_SOFTC_PTR(cmd);
struct sym_ucmd *ucp = SYM_UCMD_PTR(cmd);
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index 96a69edddbe5..6b1d8bcd06b9 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -561,8 +561,8 @@ static struct virtio_scsi_vq *virtscsi_pick_vq_mq(struct virtio_scsi *vscsi,
return &vscsi->req_vqs[hwq];
}
-static int virtscsi_queuecommand(struct Scsi_Host *shost,
- struct scsi_cmnd *sc)
+static enum scsi_qc_status virtscsi_queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *sc)
{
struct virtio_scsi *vscsi = shost_priv(shost);
struct virtio_scsi_vq *req_vq = virtscsi_pick_vq_mq(vscsi, sc);
diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c
index 32242d86cf5b..11f86c76f391 100644
--- a/drivers/scsi/vmw_pvscsi.c
+++ b/drivers/scsi/vmw_pvscsi.c
@@ -771,7 +771,7 @@ static int pvscsi_queue_ring(struct pvscsi_adapter *adapter,
return 0;
}
-static int pvscsi_queue_lck(struct scsi_cmnd *cmd)
+static enum scsi_qc_status pvscsi_queue_lck(struct scsi_cmnd *cmd)
{
struct Scsi_Host *host = cmd->device->host;
struct pvscsi_adapter *adapter = shost_priv(host);
diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
index dd1fef9226f2..1e49d0402f0b 100644
--- a/drivers/scsi/wd33c93.c
+++ b/drivers/scsi/wd33c93.c
@@ -302,7 +302,7 @@ calc_sync_msg(unsigned int period, unsigned int offset, unsigned int fast,
msg[1] = offset;
}
-static int wd33c93_queuecommand_lck(struct scsi_cmnd *cmd)
+static enum scsi_qc_status wd33c93_queuecommand_lck(struct scsi_cmnd *cmd)
{
struct scsi_pointer *scsi_pointer = WD33C93_scsi_pointer(cmd);
struct WD33C93_hostdata *hostdata;
diff --git a/drivers/scsi/wd33c93.h b/drivers/scsi/wd33c93.h
index e5e4254b1477..e1e98280aad1 100644
--- a/drivers/scsi/wd33c93.h
+++ b/drivers/scsi/wd33c93.h
@@ -332,7 +332,8 @@ static inline struct scsi_pointer *WD33C93_scsi_pointer(struct scsi_cmnd *cmd)
void wd33c93_init (struct Scsi_Host *instance, const wd33c93_regs regs,
dma_setup_t setup, dma_stop_t stop, int clock_freq);
int wd33c93_abort (struct scsi_cmnd *cmd);
-int wd33c93_queuecommand (struct Scsi_Host *h, struct scsi_cmnd *cmd);
+enum scsi_qc_status wd33c93_queuecommand(struct Scsi_Host *h,
+ struct scsi_cmnd *cmd);
void wd33c93_intr (struct Scsi_Host *instance);
int wd33c93_show_info(struct seq_file *, struct Scsi_Host *);
int wd33c93_write_info(struct Scsi_Host *, char *, int);
diff --git a/drivers/scsi/wd719x.c b/drivers/scsi/wd719x.c
index 0c9987828774..830d40f57f6a 100644
--- a/drivers/scsi/wd719x.c
+++ b/drivers/scsi/wd719x.c
@@ -204,7 +204,8 @@ static void wd719x_finish_cmd(struct wd719x_scb *scb, int result)
}
/* Build a SCB and send it to the card */
-static int wd719x_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
+static enum scsi_qc_status wd719x_queuecommand(struct Scsi_Host *sh,
+ struct scsi_cmnd *cmd)
{
int i, count_sg;
unsigned long flags;
diff --git a/drivers/scsi/xen-scsifront.c b/drivers/scsi/xen-scsifront.c
index 924025305753..bf36c07c2b47 100644
--- a/drivers/scsi/xen-scsifront.c
+++ b/drivers/scsi/xen-scsifront.c
@@ -603,8 +603,8 @@ static void scsifront_return(struct vscsifrnt_info *info)
wake_up(&info->wq_pause);
}
-static int scsifront_queuecommand(struct Scsi_Host *shost,
- struct scsi_cmnd *sc)
+static enum scsi_qc_status scsifront_queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *sc)
{
struct vscsifrnt_info *info = shost_priv(shost);
struct vscsifrnt_shadow *shadow = scsi_cmd_priv(sc);
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index 01a8e349dc4d..0821a149573e 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -165,7 +165,8 @@ out_done:
* ->queuecommand can be and usually is called from interrupt context, so
* defer the actual submission to a workqueue.
*/
-static int tcm_loop_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
+static enum scsi_qc_status tcm_loop_queuecommand(struct Scsi_Host *sh,
+ struct scsi_cmnd *sc)
{
struct tcm_loop_cmd *tl_cmd = scsi_cmd_priv(sc);
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index f7868b41c5e6..b27a3b8dd767 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -288,7 +288,7 @@ static void target_core_deregister_fabric(
config_item_put(item);
}
-static struct configfs_group_operations target_core_fabric_group_ops = {
+static const struct configfs_group_operations target_core_fabric_group_ops = {
.make_group = &target_core_register_fabric,
.drop_item = &target_core_deregister_fabric,
};
@@ -1741,6 +1741,54 @@ static ssize_t target_wwn_vpd_protocol_identifier_show(struct config_item *item,
return len;
}
+static ssize_t target_wwn_pd_text_id_info_show(struct config_item *item,
+ char *page)
+{
+ return sysfs_emit(page, "%s\n", &to_t10_wwn(item)->pd_text_id_info[0]);
+}
+
+static ssize_t target_wwn_pd_text_id_info_store(struct config_item *item,
+ const char *page, size_t count)
+{
+ struct t10_wwn *t10_wwn = to_t10_wwn(item);
+ struct se_device *dev = t10_wwn->t10_dev;
+
+ /* +2 to allow for a trailing (stripped) '\n' and null-terminator */
+ unsigned char buf[PD_TEXT_ID_INFO_LEN + 2];
+ char *stripped;
+
+ /*
+ * Check to see if any active exports exist. If they do exist, fail
+ * here as changing this information on the fly (underneath the
+ * initiator side OS dependent multipath code) could cause negative
+ * effects.
+ */
+ if (dev->export_count) {
+ pr_err("Unable to set the peripheral device text id info while active %d exports exist\n",
+ dev->export_count);
+ return -EINVAL;
+ }
+
+ if (strscpy(buf, page, sizeof(buf)) < 0)
+ return -EOVERFLOW;
+
+ /* Strip any newline added from userspace. */
+ stripped = strstrip(buf);
+ if (strlen(stripped) >= PD_TEXT_ID_INFO_LEN) {
+ pr_err("Emulated peripheral device text id info exceeds PD_TEXT_ID_INFO_LEN: " __stringify(PD_TEXT_ID_INFO_LEN "\n"));
+ return -EOVERFLOW;
+ }
+
+ BUILD_BUG_ON(sizeof(dev->t10_wwn.pd_text_id_info) != PD_TEXT_ID_INFO_LEN);
+ strscpy(dev->t10_wwn.pd_text_id_info, stripped,
+ sizeof(dev->t10_wwn.pd_text_id_info));
+
+ pr_debug("Target_Core_ConfigFS: Set emulated peripheral dev text id info:"
+ " %s\n", dev->t10_wwn.pd_text_id_info);
+
+ return count;
+}
+
/*
* Generic wrapper for dumping VPD identifiers by association.
*/
@@ -1797,6 +1845,7 @@ CONFIGFS_ATTR_RO(target_wwn_, vpd_protocol_identifier);
CONFIGFS_ATTR_RO(target_wwn_, vpd_assoc_logical_unit);
CONFIGFS_ATTR_RO(target_wwn_, vpd_assoc_target_port);
CONFIGFS_ATTR_RO(target_wwn_, vpd_assoc_scsi_target_device);
+CONFIGFS_ATTR(target_wwn_, pd_text_id_info);
static struct configfs_attribute *target_core_dev_wwn_attrs[] = {
&target_wwn_attr_vendor_id,
@@ -1808,6 +1857,7 @@ static struct configfs_attribute *target_core_dev_wwn_attrs[] = {
&target_wwn_attr_vpd_assoc_logical_unit,
&target_wwn_attr_vpd_assoc_target_port,
&target_wwn_attr_vpd_assoc_scsi_target_device,
+ &target_wwn_attr_pd_text_id_info,
NULL,
};
@@ -2810,7 +2860,7 @@ static void target_core_alua_lu_gp_release(struct config_item *item)
core_alua_free_lu_gp(lu_gp);
}
-static struct configfs_item_operations target_core_alua_lu_gp_ops = {
+static const struct configfs_item_operations target_core_alua_lu_gp_ops = {
.release = target_core_alua_lu_gp_release,
};
@@ -2867,7 +2917,7 @@ static void target_core_alua_drop_lu_gp(
config_item_put(item);
}
-static struct configfs_group_operations target_core_alua_lu_gps_group_ops = {
+static const struct configfs_group_operations target_core_alua_lu_gps_group_ops = {
.make_group = &target_core_alua_create_lu_gp,
.drop_item = &target_core_alua_drop_lu_gp,
};
@@ -3240,7 +3290,7 @@ static void target_core_alua_tg_pt_gp_release(struct config_item *item)
core_alua_free_tg_pt_gp(tg_pt_gp);
}
-static struct configfs_item_operations target_core_alua_tg_pt_gp_ops = {
+static const struct configfs_item_operations target_core_alua_tg_pt_gp_ops = {
.release = target_core_alua_tg_pt_gp_release,
};
@@ -3298,7 +3348,7 @@ static void target_core_alua_drop_tg_pt_gp(
config_item_put(item);
}
-static struct configfs_group_operations target_core_alua_tg_pt_gps_group_ops = {
+static const struct configfs_group_operations target_core_alua_tg_pt_gps_group_ops = {
.make_group = &target_core_alua_create_tg_pt_gp,
.drop_item = &target_core_alua_drop_tg_pt_gp,
};
@@ -3339,7 +3389,7 @@ static void target_core_stat_rmdir(
return;
}
-static struct configfs_group_operations target_core_stat_group_ops = {
+static const struct configfs_group_operations target_core_stat_group_ops = {
.make_group = &target_core_stat_mkdir,
.drop_item = &target_core_stat_rmdir,
};
@@ -3466,7 +3516,7 @@ static void target_core_drop_subdev(
mutex_unlock(&hba->hba_access_mutex);
}
-static struct configfs_group_operations target_core_hba_group_ops = {
+static const struct configfs_group_operations target_core_hba_group_ops = {
.make_group = target_core_make_subdev,
.drop_item = target_core_drop_subdev,
};
@@ -3545,7 +3595,7 @@ static struct configfs_attribute *target_core_hba_attrs[] = {
NULL,
};
-static struct configfs_item_operations target_core_hba_item_ops = {
+static const struct configfs_item_operations target_core_hba_item_ops = {
.release = target_core_hba_release,
};
@@ -3626,7 +3676,7 @@ static void target_core_call_delhbafromtarget(
config_item_put(item);
}
-static struct configfs_group_operations target_core_group_ops = {
+static const struct configfs_group_operations target_core_group_ops = {
.make_group = target_core_call_addhbatotarget,
.drop_item = target_core_call_delhbafromtarget,
};
diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c
index 13159928e365..59713e9be10a 100644
--- a/drivers/target/target_core_fabric_configfs.c
+++ b/drivers/target/target_core_fabric_configfs.c
@@ -59,7 +59,7 @@ static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf)
pr_debug("Setup generic %s\n", __stringify(_name)); \
}
-static struct configfs_item_operations target_fabric_port_item_ops;
+static const struct configfs_item_operations target_fabric_port_item_ops;
/* Start of tfc_tpg_mappedlun_cit */
@@ -219,7 +219,7 @@ static void target_fabric_mappedlun_release(struct config_item *item)
core_dev_free_initiator_node_lun_acl(se_tpg, lacl);
}
-static struct configfs_item_operations target_fabric_mappedlun_item_ops = {
+static const struct configfs_item_operations target_fabric_mappedlun_item_ops = {
.release = target_fabric_mappedlun_release,
.allow_link = target_fabric_mappedlun_link,
.drop_link = target_fabric_mappedlun_unlink,
@@ -246,7 +246,7 @@ static void target_core_mappedlun_stat_rmdir(
return;
}
-static struct configfs_group_operations target_fabric_mappedlun_stat_group_ops = {
+static const struct configfs_group_operations target_fabric_mappedlun_stat_group_ops = {
.make_group = target_core_mappedlun_stat_mkdir,
.drop_item = target_core_mappedlun_stat_rmdir,
};
@@ -345,11 +345,11 @@ static void target_fabric_nacl_base_release(struct config_item *item)
core_tpg_del_initiator_node_acl(se_nacl);
}
-static struct configfs_item_operations target_fabric_nacl_base_item_ops = {
+static const struct configfs_item_operations target_fabric_nacl_base_item_ops = {
.release = target_fabric_nacl_base_release,
};
-static struct configfs_group_operations target_fabric_nacl_base_group_ops = {
+static const struct configfs_group_operations target_fabric_nacl_base_group_ops = {
.make_group = target_fabric_make_mappedlun,
.drop_item = target_fabric_drop_mappedlun,
};
@@ -433,7 +433,7 @@ static void target_fabric_drop_nodeacl(
config_item_put(item);
}
-static struct configfs_group_operations target_fabric_nacl_group_ops = {
+static const struct configfs_group_operations target_fabric_nacl_group_ops = {
.make_group = target_fabric_make_nodeacl,
.drop_item = target_fabric_drop_nodeacl,
};
@@ -454,7 +454,7 @@ static void target_fabric_np_base_release(struct config_item *item)
tf->tf_ops->fabric_drop_np(se_tpg_np);
}
-static struct configfs_item_operations target_fabric_np_base_item_ops = {
+static const struct configfs_item_operations target_fabric_np_base_item_ops = {
.release = target_fabric_np_base_release,
};
@@ -499,7 +499,7 @@ static void target_fabric_drop_np(
config_item_put(item);
}
-static struct configfs_group_operations target_fabric_np_group_ops = {
+static const struct configfs_group_operations target_fabric_np_group_ops = {
.make_group = &target_fabric_make_np,
.drop_item = &target_fabric_drop_np,
};
@@ -700,7 +700,7 @@ static void target_fabric_port_release(struct config_item *item)
call_rcu(&lun->rcu_head, target_tpg_free_lun);
}
-static struct configfs_item_operations target_fabric_port_item_ops = {
+static const struct configfs_item_operations target_fabric_port_item_ops = {
.release = target_fabric_port_release,
.allow_link = target_fabric_port_link,
.drop_link = target_fabric_port_unlink,
@@ -726,7 +726,7 @@ static void target_core_port_stat_rmdir(
return;
}
-static struct configfs_group_operations target_fabric_port_stat_group_ops = {
+static const struct configfs_group_operations target_fabric_port_stat_group_ops = {
.make_group = target_core_port_stat_mkdir,
.drop_item = target_core_port_stat_rmdir,
};
@@ -787,7 +787,7 @@ static void target_fabric_drop_lun(
config_item_put(item);
}
-static struct configfs_group_operations target_fabric_lun_group_ops = {
+static const struct configfs_group_operations target_fabric_lun_group_ops = {
.make_group = &target_fabric_make_lun,
.drop_item = &target_fabric_drop_lun,
};
@@ -812,7 +812,7 @@ static void target_fabric_tpg_release(struct config_item *item)
tf->tf_ops->fabric_drop_tpg(se_tpg);
}
-static struct configfs_item_operations target_fabric_tpg_base_item_ops = {
+static const struct configfs_item_operations target_fabric_tpg_base_item_ops = {
.release = target_fabric_tpg_release,
};
@@ -998,11 +998,11 @@ static void target_fabric_release_wwn(struct config_item *item)
tf->tf_ops->fabric_drop_wwn(wwn);
}
-static struct configfs_item_operations target_fabric_tpg_item_ops = {
+static const struct configfs_item_operations target_fabric_tpg_item_ops = {
.release = target_fabric_release_wwn,
};
-static struct configfs_group_operations target_fabric_tpg_group_ops = {
+static const struct configfs_group_operations target_fabric_tpg_group_ops = {
.make_group = target_fabric_make_tpg,
.drop_item = target_fabric_drop_tpg,
};
@@ -1144,7 +1144,7 @@ static void target_fabric_drop_wwn(
config_item_put(item);
}
-static struct configfs_group_operations target_fabric_wwn_group_ops = {
+static const struct configfs_group_operations target_fabric_wwn_group_ops = {
.make_group = target_fabric_make_wwn,
.drop_item = target_fabric_drop_wwn,
};
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
index 6360b66c7445..f964a531e053 100644
--- a/drivers/target/target_core_spc.c
+++ b/drivers/target/target_core_spc.c
@@ -26,6 +26,8 @@
#include "target_core_ua.h"
#include "target_core_xcopy.h"
+#define PD_TEXT_ID_INFO_HDR_LEN 4
+
static void spc_fill_alua_data(struct se_lun *lun, unsigned char *buf)
{
struct t10_alua_tg_pt_gp *tg_pt_gp;
@@ -2000,6 +2002,18 @@ static const struct target_opcode_descriptor tcm_opcode_report_supp_opcodes = {
.enabled = spc_rsoc_enabled,
};
+static struct target_opcode_descriptor tcm_opcode_report_identifying_information = {
+ .support = SCSI_SUPPORT_FULL,
+ .serv_action_valid = 1,
+ .opcode = MAINTENANCE_IN,
+ .service_action = MI_REPORT_IDENTIFYING_INFORMATION,
+ .cdb_size = 12,
+ .usage_bits = {MAINTENANCE_IN, MI_REPORT_IDENTIFYING_INFORMATION,
+ 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, SCSI_CONTROL_MASK},
+};
+
static bool tcm_is_set_tpg_enabled(const struct target_opcode_descriptor *descr,
struct se_cmd *cmd)
{
@@ -2087,6 +2101,7 @@ static const struct target_opcode_descriptor *tcm_supported_opcodes[] = {
&tcm_opcode_report_target_pgs,
&tcm_opcode_report_supp_opcodes,
&tcm_opcode_set_tpg,
+ &tcm_opcode_report_identifying_information,
};
static int
@@ -2304,6 +2319,72 @@ out:
return ret;
}
+static sense_reason_t
+spc_fill_pd_text_id_info(struct se_cmd *cmd, u8 *cdb)
+{
+ struct se_device *dev = cmd->se_dev;
+ unsigned char *buf;
+ unsigned char *rbuf;
+ u32 buf_len;
+ u16 data_len;
+
+ buf_len = get_unaligned_be32(&cdb[6]);
+ if (buf_len < PD_TEXT_ID_INFO_HDR_LEN)
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
+ data_len = strlen(dev->t10_wwn.pd_text_id_info);
+ if (data_len > 0)
+ /* trailing null */
+ data_len += 1;
+
+ data_len = data_len + PD_TEXT_ID_INFO_HDR_LEN;
+
+ if (data_len < buf_len)
+ buf_len = data_len;
+
+ buf = kzalloc(buf_len, GFP_KERNEL);
+ if (!buf) {
+ pr_err("Unable to allocate response buffer for IDENTITY INFO\n");
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+ }
+
+ scnprintf(&buf[PD_TEXT_ID_INFO_HDR_LEN], buf_len - PD_TEXT_ID_INFO_HDR_LEN, "%s",
+ dev->t10_wwn.pd_text_id_info);
+
+ put_unaligned_be16(data_len, &buf[2]);
+
+ rbuf = transport_kmap_data_sg(cmd);
+ if (!rbuf) {
+ pr_err("transport_kmap_data_sg() failed in %s\n", __func__);
+ kfree(buf);
+ return TCM_OUT_OF_RESOURCES;
+ }
+
+ memcpy(rbuf, buf, buf_len);
+ transport_kunmap_data_sg(cmd);
+ kfree(buf);
+
+ target_complete_cmd_with_length(cmd, SAM_STAT_GOOD, buf_len);
+ return TCM_NO_SENSE;
+}
+
+static sense_reason_t
+spc_emulate_report_id_info(struct se_cmd *cmd)
+{
+ u8 *cdb = cmd->t_task_cdb;
+ sense_reason_t rc;
+
+ switch ((cdb[10] >> 1)) {
+ case 2:
+ rc = spc_fill_pd_text_id_info(cmd, cdb);
+ break;
+ default:
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
+ }
+
+ return rc;
+}
+
sense_reason_t
spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
{
@@ -2443,6 +2524,11 @@ spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
MI_REPORT_SUPPORTED_OPERATION_CODES)
cmd->execute_cmd =
spc_emulate_report_supp_op_codes;
+ if ((cdb[1] & 0x1f) ==
+ MI_REPORT_IDENTIFYING_INFORMATION) {
+ cmd->execute_cmd =
+ spc_emulate_report_id_info;
+ }
*size = get_unaligned_be32(&cdb[6]);
} else {
/*
diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c
index 9ab91b4c05b0..18a95b728633 100644
--- a/drivers/ufs/core/ufs-mcq.c
+++ b/drivers/ufs/core/ufs-mcq.c
@@ -431,8 +431,7 @@ void ufshcd_mcq_disable(struct ufs_hba *hba)
void ufshcd_mcq_enable_esi(struct ufs_hba *hba)
{
- ufshcd_writel(hba, ufshcd_readl(hba, REG_UFS_MEM_CFG) | 0x2,
- REG_UFS_MEM_CFG);
+ ufshcd_rmwl(hba, ESI_ENABLE, ESI_ENABLE, REG_UFS_MEM_CFG);
}
EXPORT_SYMBOL_GPL(ufshcd_mcq_enable_esi);
@@ -445,7 +444,6 @@ EXPORT_SYMBOL_GPL(ufshcd_mcq_config_esi);
int ufshcd_mcq_init(struct ufs_hba *hba)
{
- struct Scsi_Host *host = hba->host;
struct ufs_hw_queue *hwq;
int ret, i;
@@ -479,7 +477,6 @@ int ufshcd_mcq_init(struct ufs_hba *hba)
mutex_init(&hwq->sq_mutex);
}
- host->host_tagset = 1;
return 0;
}
diff --git a/drivers/ufs/core/ufs-sysfs.c b/drivers/ufs/core/ufs-sysfs.c
index b33f8656edb5..384d958615d7 100644
--- a/drivers/ufs/core/ufs-sysfs.c
+++ b/drivers/ufs/core/ufs-sysfs.c
@@ -141,7 +141,7 @@ static inline ssize_t ufs_sysfs_pm_lvl_store(struct device *dev,
if (kstrtoul(buf, 0, &value))
return -EINVAL;
- if (value >= UFS_PM_LVL_MAX)
+ if (value >= UFS_PM_LVL_MAX || value < hba->pm_lvl_min)
return -EINVAL;
if (ufs_pm_lvl_states[value].dev_state == UFS_DEEPSLEEP_PWR_MODE &&
@@ -1847,6 +1847,7 @@ static ssize_t defrag_trigger_store(struct device *dev,
static DEVICE_ATTR_WO(defrag_trigger);
+#define UFS_HID_AVAILABLE_SIZE_INVALID 0xFFFFFFFFU
static ssize_t fragmented_size_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -1859,6 +1860,9 @@ static ssize_t fragmented_size_show(struct device *dev,
if (ret)
return ret;
+ if (value == UFS_HID_AVAILABLE_SIZE_INVALID)
+ return -ENODATA;
+
return sysfs_emit(buf, "%u\n", value);
}
diff --git a/drivers/ufs/core/ufshcd-priv.h b/drivers/ufs/core/ufshcd-priv.h
index 27b18b0cc058..37c32071e754 100644
--- a/drivers/ufs/core/ufshcd-priv.h
+++ b/drivers/ufs/core/ufshcd-priv.h
@@ -374,12 +374,7 @@ static inline bool ufs_is_valid_unit_desc_lun(struct ufs_dev_info *dev_info, u8
*/
static inline struct scsi_cmnd *ufshcd_tag_to_cmd(struct ufs_hba *hba, u32 tag)
{
- /*
- * Host-wide tags are enabled in MCQ mode only. See also the
- * host->host_tagset assignment in ufs-mcq.c.
- */
- struct blk_mq_tags *tags = hba->host->tag_set.shared_tags ?:
- hba->host->tag_set.tags[0];
+ struct blk_mq_tags *tags = hba->host->tag_set.shared_tags;
struct request *rq = blk_mq_tag_to_rq(tags, tag);
if (WARN_ON_ONCE(!rq))
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 31950fc51a4c..847b55789bb8 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -284,7 +284,8 @@ static bool ufshcd_has_pending_tasks(struct ufs_hba *hba)
static bool ufshcd_is_ufs_dev_busy(struct ufs_hba *hba)
{
- return scsi_host_busy(hba->host) || ufshcd_has_pending_tasks(hba);
+ return (hba->scsi_host_added && scsi_host_busy(hba->host)) ||
+ ufshcd_has_pending_tasks(hba);
}
static const struct ufs_dev_quirk ufs_fixups[] = {
@@ -679,7 +680,8 @@ static void ufshcd_print_host_state(struct ufs_hba *hba)
dev_err(hba->dev, "UFS Host state=%d\n", hba->ufshcd_state);
dev_err(hba->dev, "%d outstanding reqs, tasks=0x%lx\n",
- scsi_host_busy(hba->host), hba->outstanding_tasks);
+ hba->scsi_host_added ? scsi_host_busy(hba->host) : 0,
+ hba->outstanding_tasks);
dev_err(hba->dev, "saved_err=0x%x, saved_uic_err=0x%x\n",
hba->saved_err, hba->saved_uic_err);
dev_err(hba->dev, "Device power mode=%d, UIC link state=%d\n",
@@ -3032,7 +3034,8 @@ static int ufshcd_init_cmd_priv(struct Scsi_Host *host, struct scsi_cmnd *cmd)
*
* Return: 0 for success, non-zero in case of failure.
*/
-static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
+static enum scsi_qc_status ufshcd_queuecommand(struct Scsi_Host *host,
+ struct scsi_cmnd *cmd)
{
struct ufs_hba *hba = shost_priv(host);
int tag = scsi_cmd_to_rq(cmd)->tag;
@@ -3112,8 +3115,8 @@ out:
return err;
}
-static int ufshcd_queue_reserved_command(struct Scsi_Host *host,
- struct scsi_cmnd *cmd)
+static enum scsi_qc_status ufshcd_queue_reserved_command(struct Scsi_Host *host,
+ struct scsi_cmnd *cmd)
{
struct ufshcd_lrb *lrbp = scsi_cmd_priv(cmd);
struct request *rq = scsi_cmd_to_rq(cmd);
@@ -9319,6 +9322,7 @@ static const struct scsi_host_template ufshcd_driver_template = {
.max_segment_size = PRDT_DATA_BYTE_COUNT_MAX,
.max_sectors = SZ_1M / SECTOR_SIZE,
.max_host_blocked = 1,
+ .host_tagset = true,
.track_queue_depth = 1,
.skip_settle_delay = 1,
.sdev_groups = ufshcd_driver_groups,
@@ -9995,6 +9999,8 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
if (req_dev_pwr_mode == UFS_ACTIVE_PWR_MODE &&
req_link_state == UIC_LINK_ACTIVE_STATE) {
+ ufshcd_disable_auto_bkops(hba);
+ flush_work(&hba->eeh_work);
goto vops_suspend;
}
@@ -10529,9 +10535,8 @@ int ufshcd_runtime_resume(struct device *dev)
EXPORT_SYMBOL(ufshcd_runtime_resume);
#endif /* CONFIG_PM */
-static void ufshcd_wl_shutdown(struct device *dev)
+static void ufshcd_wl_shutdown(struct scsi_device *sdev)
{
- struct scsi_device *sdev = to_scsi_device(dev);
struct ufs_hba *hba = shost_priv(sdev->host);
down(&hba->host_sem);
@@ -11138,9 +11143,9 @@ static int ufshcd_wl_poweroff(struct device *dev)
}
#endif
-static int ufshcd_wl_probe(struct device *dev)
+static int ufshcd_wl_probe(struct scsi_device *sdev)
{
- struct scsi_device *sdev = to_scsi_device(dev);
+ struct device *dev = &sdev->sdev_gendev;
if (!is_device_wlun(sdev))
return -ENODEV;
@@ -11152,10 +11157,11 @@ static int ufshcd_wl_probe(struct device *dev)
return 0;
}
-static int ufshcd_wl_remove(struct device *dev)
+static void ufshcd_wl_remove(struct scsi_device *sdev)
{
+ struct device *dev = &sdev->sdev_gendev;
+
pm_runtime_forbid(dev);
- return 0;
}
static const struct dev_pm_ops ufshcd_wl_pm_ops = {
@@ -11228,12 +11234,12 @@ static void ufshcd_check_header_layout(void)
* Hence register a scsi driver for ufs wluns only.
*/
static struct scsi_driver ufs_dev_wlun_template = {
+ .probe = ufshcd_wl_probe,
+ .remove = ufshcd_wl_remove,
+ .shutdown = ufshcd_wl_shutdown,
.gendrv = {
.name = "ufs_device_wlun",
- .probe = ufshcd_wl_probe,
- .remove = ufshcd_wl_remove,
.pm = &ufshcd_wl_pm_ops,
- .shutdown = ufshcd_wl_shutdown,
},
};
@@ -11245,7 +11251,7 @@ static int __init ufshcd_core_init(void)
ufs_debugfs_init();
- ret = scsi_register_driver(&ufs_dev_wlun_template.gendrv);
+ ret = scsi_register_driver(&ufs_dev_wlun_template);
if (ret)
ufs_debugfs_exit();
return ret;
@@ -11254,7 +11260,7 @@ static int __init ufshcd_core_init(void)
static void __exit ufshcd_core_exit(void)
{
ufs_debugfs_exit();
- scsi_unregister_driver(&ufs_dev_wlun_template.gendrv);
+ scsi_unregister_driver(&ufs_dev_wlun_template);
}
module_init(ufshcd_core_init);
diff --git a/drivers/ufs/host/Kconfig b/drivers/ufs/host/Kconfig
index 7d5117b2dab4..964ae70e7390 100644
--- a/drivers/ufs/host/Kconfig
+++ b/drivers/ufs/host/Kconfig
@@ -72,6 +72,7 @@ config SCSI_UFS_QCOM
config SCSI_UFS_MEDIATEK
tristate "Mediatek specific hooks to UFS controller platform driver"
depends on SCSI_UFSHCD_PLATFORM && ARCH_MEDIATEK
+ depends on PM
depends on RESET_CONTROLLER
select PHY_MTK_UFS
select RESET_TI_SYSCON
diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c
index 70d195179eba..76fee3a79c77 100644
--- a/drivers/ufs/host/ufs-exynos.c
+++ b/drivers/ufs/host/ufs-exynos.c
@@ -1568,12 +1568,17 @@ static void exynos_ufs_pre_hibern8(struct ufs_hba *hba, enum uic_cmd_dme cmd)
{
struct exynos_ufs *ufs = ufshcd_get_variant(hba);
struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr;
+ static const union phy_notify phystate = {
+ .ufs_state = PHY_UFS_HIBERN8_EXIT
+ };
if (cmd == UIC_CMD_DME_HIBER_EXIT) {
if (ufs->opts & EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL)
exynos_ufs_disable_auto_ctrl_hcc(ufs);
exynos_ufs_ungate_clks(ufs);
+ phy_notify_state(ufs->phy, phystate);
+
if (ufs->opts & EXYNOS_UFS_OPT_USE_SW_HIBERN8_TIMER) {
static const unsigned int granularity_tbl[] = {
1, 4, 8, 16, 32, 100
@@ -1600,12 +1605,17 @@ static void exynos_ufs_pre_hibern8(struct ufs_hba *hba, enum uic_cmd_dme cmd)
static void exynos_ufs_post_hibern8(struct ufs_hba *hba, enum uic_cmd_dme cmd)
{
struct exynos_ufs *ufs = ufshcd_get_variant(hba);
+ static const union phy_notify phystate = {
+ .ufs_state = PHY_UFS_HIBERN8_ENTER
+ };
if (cmd == UIC_CMD_DME_HIBER_ENTER) {
ufs->entry_hibern8_t = ktime_get();
exynos_ufs_gate_clks(ufs);
if (ufs->opts & EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL)
exynos_ufs_enable_auto_ctrl_hcc(ufs);
+
+ phy_notify_state(ufs->phy, phystate);
}
}
diff --git a/drivers/ufs/host/ufs-mediatek-trace.h b/drivers/ufs/host/ufs-mediatek-trace.h
index b5f2ec314074..0df8ac843379 100644
--- a/drivers/ufs/host/ufs-mediatek-trace.h
+++ b/drivers/ufs/host/ufs-mediatek-trace.h
@@ -33,19 +33,19 @@ TRACE_EVENT(ufs_mtk_clk_scale,
TP_ARGS(name, scale_up, clk_rate),
TP_STRUCT__entry(
- __field(const char*, name)
+ __string(name, name)
__field(bool, scale_up)
__field(unsigned long, clk_rate)
),
TP_fast_assign(
- __entry->name = name;
+ __assign_str(name);
__entry->scale_up = scale_up;
__entry->clk_rate = clk_rate;
),
TP_printk("ufs: clk (%s) scaled %s @ %lu",
- __entry->name,
+ __get_str(name),
__entry->scale_up ? "up" : "down",
__entry->clk_rate)
);
diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c
index 66b11cc0703b..b3daaa07e925 100644
--- a/drivers/ufs/host/ufs-mediatek.c
+++ b/drivers/ufs/host/ufs-mediatek.c
@@ -2437,7 +2437,6 @@ static void ufs_mtk_remove(struct platform_device *pdev)
ufshcd_pltfrm_remove(pdev);
}
-#ifdef CONFIG_PM_SLEEP
static int ufs_mtk_system_suspend(struct device *dev)
{
struct ufs_hba *hba = dev_get_drvdata(dev);
@@ -2484,9 +2483,7 @@ out:
return ret;
}
-#endif
-#ifdef CONFIG_PM
static int ufs_mtk_runtime_suspend(struct device *dev)
{
struct ufs_hba *hba = dev_get_drvdata(dev);
@@ -2525,13 +2522,10 @@ static int ufs_mtk_runtime_resume(struct device *dev)
return ufshcd_runtime_resume(dev);
}
-#endif
static const struct dev_pm_ops ufs_mtk_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(ufs_mtk_system_suspend,
- ufs_mtk_system_resume)
- SET_RUNTIME_PM_OPS(ufs_mtk_runtime_suspend,
- ufs_mtk_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(ufs_mtk_system_suspend, ufs_mtk_system_resume)
+ RUNTIME_PM_OPS(ufs_mtk_runtime_suspend, ufs_mtk_runtime_resume, NULL)
.prepare = ufshcd_suspend_prepare,
.complete = ufshcd_resume_complete,
};
@@ -2541,7 +2535,7 @@ static struct platform_driver ufs_mtk_pltform = {
.remove = ufs_mtk_remove,
.driver = {
.name = "ufshcd-mtk",
- .pm = &ufs_mtk_pm_ops,
+ .pm = pm_ptr(&ufs_mtk_pm_ops),
.of_match_table = ufs_mtk_of_match,
},
};
diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
index 8ebee0cc5313..375fd24ba458 100644
--- a/drivers/ufs/host/ufs-qcom.c
+++ b/drivers/ufs/host/ufs-qcom.c
@@ -14,6 +14,7 @@
#include <linux/of.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
#include <linux/reset-controller.h>
#include <linux/time.h>
#include <linux/unaligned.h>
@@ -619,6 +620,27 @@ static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba,
return err;
}
+static int ufs_qcom_fw_managed_hce_enable_notify(struct ufs_hba *hba,
+ enum ufs_notify_change_status status)
+{
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+
+ switch (status) {
+ case PRE_CHANGE:
+ ufs_qcom_select_unipro_mode(host);
+ break;
+ case POST_CHANGE:
+ ufs_qcom_enable_hw_clk_gating(hba);
+ ufs_qcom_ice_enable(host);
+ break;
+ default:
+ dev_err(hba->dev, "Invalid status %d\n", status);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/**
* ufs_qcom_cfg_timers - Configure ufs qcom cfg timers
*
@@ -789,6 +811,33 @@ static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
return ufs_qcom_ice_resume(host);
}
+static int ufs_qcom_fw_managed_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op,
+ enum ufs_notify_change_status status)
+{
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+
+ if (status == PRE_CHANGE)
+ return 0;
+
+ pm_runtime_put_sync(hba->dev);
+
+ return ufs_qcom_ice_suspend(host);
+}
+
+static int ufs_qcom_fw_managed_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
+{
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+ int err;
+
+ err = pm_runtime_resume_and_get(hba->dev);
+ if (err) {
+ dev_err(hba->dev, "PM runtime resume failed: %d\n", err);
+ return err;
+ }
+
+ return ufs_qcom_ice_resume(host);
+}
+
static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_qcom_host *host, bool enable)
{
if (host->dev_ref_clk_ctrl_mmio &&
@@ -1421,6 +1470,54 @@ static void ufs_qcom_exit(struct ufs_hba *hba)
phy_exit(host->generic_phy);
}
+static int ufs_qcom_fw_managed_init(struct ufs_hba *hba)
+{
+ struct device *dev = hba->dev;
+ struct ufs_qcom_host *host;
+ int err;
+
+ host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
+ if (!host)
+ return -ENOMEM;
+
+ host->hba = hba;
+ ufshcd_set_variant(hba, host);
+
+ ufs_qcom_get_controller_revision(hba, &host->hw_ver.major,
+ &host->hw_ver.minor, &host->hw_ver.step);
+
+ err = ufs_qcom_ice_init(host);
+ if (err)
+ goto out_variant_clear;
+
+ ufs_qcom_get_default_testbus_cfg(host);
+ err = ufs_qcom_testbus_config(host);
+ if (err)
+ /* Failure is non-fatal */
+ dev_warn(dev, "Failed to configure the testbus %d\n", err);
+
+ hba->caps |= UFSHCD_CAP_WB_EN;
+
+ ufs_qcom_advertise_quirks(hba);
+ host->hba->quirks &= ~UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH;
+
+ hba->spm_lvl = hba->rpm_lvl = hba->pm_lvl_min = UFS_PM_LVL_5;
+
+ ufs_qcom_set_host_params(hba);
+ ufs_qcom_parse_gear_limits(hba);
+
+ return 0;
+
+out_variant_clear:
+ ufshcd_set_variant(hba, NULL);
+ return err;
+}
+
+static void ufs_qcom_fw_managed_exit(struct ufs_hba *hba)
+{
+ pm_runtime_put_sync(hba->dev);
+}
+
/**
* ufs_qcom_set_clk_40ns_cycles - Configure 40ns clk cycles
*
@@ -1950,6 +2047,37 @@ static int ufs_qcom_device_reset(struct ufs_hba *hba)
return 0;
}
+/**
+ * ufs_qcom_fw_managed_device_reset - Reset UFS device under FW-managed design
+ * @hba: pointer to UFS host bus adapter
+ *
+ * In the firmware-managed reset model, the power domain is powered on by genpd
+ * before the UFS controller driver probes. For subsequent resets (such as
+ * suspend/resume or recovery), the UFS driver must explicitly invoke PM runtime
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+static int ufs_qcom_fw_managed_device_reset(struct ufs_hba *hba)
+{
+ static bool is_boot = true;
+ int err;
+
+ /* Skip reset on cold boot; perform it on subsequent calls */
+ if (is_boot) {
+ is_boot = false;
+ return 0;
+ }
+
+ pm_runtime_put_sync(hba->dev);
+ err = pm_runtime_resume_and_get(hba->dev);
+ if (err < 0) {
+ dev_err(hba->dev, "PM runtime resume failed: %d\n", err);
+ return err;
+ }
+
+ return 0;
+}
+
static void ufs_qcom_config_scaling_param(struct ufs_hba *hba,
struct devfreq_dev_profile *p,
struct devfreq_simple_ondemand_data *d)
@@ -2229,6 +2357,20 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = {
.freq_to_gear_speed = ufs_qcom_freq_to_gear_speed,
};
+static const struct ufs_hba_variant_ops ufs_hba_qcom_sa8255p_vops = {
+ .name = "qcom-sa8255p",
+ .init = ufs_qcom_fw_managed_init,
+ .exit = ufs_qcom_fw_managed_exit,
+ .hce_enable_notify = ufs_qcom_fw_managed_hce_enable_notify,
+ .pwr_change_notify = ufs_qcom_pwr_change_notify,
+ .apply_dev_quirks = ufs_qcom_apply_dev_quirks,
+ .fixup_dev_quirks = ufs_qcom_fixup_dev_quirks,
+ .suspend = ufs_qcom_fw_managed_suspend,
+ .resume = ufs_qcom_fw_managed_resume,
+ .dbg_register_dump = ufs_qcom_dump_dbg_regs,
+ .device_reset = ufs_qcom_fw_managed_device_reset,
+};
+
/**
* ufs_qcom_probe - probe routine of the driver
* @pdev: pointer to Platform device handle
@@ -2239,9 +2381,16 @@ static int ufs_qcom_probe(struct platform_device *pdev)
{
int err;
struct device *dev = &pdev->dev;
+ const struct ufs_hba_variant_ops *vops;
+ const struct ufs_qcom_drvdata *drvdata = device_get_match_data(dev);
+
+ if (drvdata && drvdata->vops)
+ vops = drvdata->vops;
+ else
+ vops = &ufs_hba_qcom_vops;
/* Perform generic probe */
- err = ufshcd_pltfrm_init(pdev, &ufs_hba_qcom_vops);
+ err = ufshcd_pltfrm_init(pdev, vops);
if (err)
return dev_err_probe(dev, err, "ufshcd_pltfrm_init() failed\n");
@@ -2269,10 +2418,15 @@ static const struct ufs_qcom_drvdata ufs_qcom_sm8550_drvdata = {
.no_phy_retention = true,
};
+static const struct ufs_qcom_drvdata ufs_qcom_sa8255p_drvdata = {
+ .vops = &ufs_hba_qcom_sa8255p_vops
+};
+
static const struct of_device_id ufs_qcom_of_match[] __maybe_unused = {
{ .compatible = "qcom,ufshc" },
{ .compatible = "qcom,sm8550-ufshc", .data = &ufs_qcom_sm8550_drvdata },
{ .compatible = "qcom,sm8650-ufshc", .data = &ufs_qcom_sm8550_drvdata },
+ { .compatible = "qcom,sa8255p-ufshc", .data = &ufs_qcom_sa8255p_drvdata },
{},
};
MODULE_DEVICE_TABLE(of, ufs_qcom_of_match);
diff --git a/drivers/ufs/host/ufs-qcom.h b/drivers/ufs/host/ufs-qcom.h
index 380d02333d38..1111ab34da01 100644
--- a/drivers/ufs/host/ufs-qcom.h
+++ b/drivers/ufs/host/ufs-qcom.h
@@ -313,6 +313,7 @@ struct ufs_qcom_host {
struct ufs_qcom_drvdata {
enum ufshcd_quirks quirks;
bool no_phy_retention;
+ const struct ufs_hba_variant_ops *vops;
};
static inline u32
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index 934ec5310fb9..82859374f302 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -355,8 +355,8 @@ static int mts_scsi_host_reset(struct scsi_cmnd *srb)
return result ? FAILED : SUCCESS;
}
-static int
-mts_scsi_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *srb);
+static enum scsi_qc_status mts_scsi_queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *srb);
static void mts_transfer_cleanup( struct urb *transfer );
static void mts_do_sg(struct urb * transfer);
@@ -559,7 +559,7 @@ mts_build_transfer_context(struct scsi_cmnd *srb, struct mts_desc* desc)
desc->context.data_pipe = pipe;
}
-static int mts_scsi_queuecommand_lck(struct scsi_cmnd *srb)
+static enum scsi_qc_status mts_scsi_queuecommand_lck(struct scsi_cmnd *srb)
{
mts_scsi_cmnd_callback callback = scsi_done;
struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]);
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index d2f476e48d0c..97de28e85562 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -357,7 +357,7 @@ static int target_alloc(struct scsi_target *starget)
/* queue a command */
/* This is always called with scsi_lock(host) held */
-static int queuecommand_lck(struct scsi_cmnd *srb)
+static enum scsi_qc_status queuecommand_lck(struct scsi_cmnd *srb)
{
void (*done)(struct scsi_cmnd *) = scsi_done;
struct us_data *us = host_to_us(srb->device->host);
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 73b1981cb1d5..ac3c0b919fdd 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -636,7 +636,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
return 0;
}
-static int uas_queuecommand_lck(struct scsi_cmnd *cmnd)
+static enum scsi_qc_status uas_queuecommand_lck(struct scsi_cmnd *cmnd)
{
struct scsi_device *sdev = cmnd->device;
struct uas_dev_info *devinfo = sdev->hostdata;
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 39534fafa36a..44117814d672 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -1150,7 +1150,8 @@ extern int ata_scsi_ioctl(struct scsi_device *dev, unsigned int cmd,
#else
#define ATA_SCSI_COMPAT_IOCTL /* empty */
#endif
-extern int ata_scsi_queuecmd(struct Scsi_Host *h, struct scsi_cmnd *cmd);
+extern enum scsi_qc_status ata_scsi_queuecmd(struct Scsi_Host *h,
+ struct scsi_cmnd *cmd);
#if IS_REACHABLE(CONFIG_ATA)
bool ata_scsi_dma_need_drain(struct request *rq);
#else
diff --git a/include/linux/transport_class.h b/include/linux/transport_class.h
index 9c2e03104461..b1f53fd5cfa3 100644
--- a/include/linux/transport_class.h
+++ b/include/linux/transport_class.h
@@ -56,6 +56,7 @@ struct anon_transport_class cls = { \
struct transport_container {
struct attribute_container ac;
const struct attribute_group *statistics;
+ const struct attribute_group *encryption;
};
#define attribute_container_to_transport_container(x) \
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 183d9fd50d2d..be0ffe1e3395 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -959,7 +959,8 @@ void fc_fcp_destroy(struct fc_lport *);
/*
* SCSI INTERACTION LAYER
*****************************/
-int fc_queuecommand(struct Scsi_Host *, struct scsi_cmnd *);
+enum scsi_qc_status fc_queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *cmnd);
int fc_eh_abort(struct scsi_cmnd *);
int fc_eh_device_reset(struct scsi_cmnd *);
int fc_eh_host_reset(struct scsi_cmnd *);
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index 7282555adfd5..3d765c77bcd9 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -392,7 +392,8 @@ extern int iscsi_eh_abort(struct scsi_cmnd *sc);
extern int iscsi_eh_recover_target(struct scsi_cmnd *sc);
extern int iscsi_eh_session_reset(struct scsi_cmnd *sc);
extern int iscsi_eh_device_reset(struct scsi_cmnd *sc);
-extern int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc);
+extern enum scsi_qc_status iscsi_queuecommand(struct Scsi_Host *host,
+ struct scsi_cmnd *sc);
extern enum scsi_timeout_action iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc);
/*
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index a0635b128d7a..e76f5744941b 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -689,7 +689,8 @@ extern void sas_suspend_ha(struct sas_ha_struct *sas_ha);
int sas_phy_reset(struct sas_phy *phy, int hard_reset);
int sas_phy_enable(struct sas_phy *phy, int enable);
-extern int sas_queuecommand(struct Scsi_Host *, struct scsi_cmnd *);
+extern enum scsi_qc_status sas_queuecommand(struct Scsi_Host *host,
+ struct scsi_cmnd *cmd);
extern int sas_target_alloc(struct scsi_target *);
int sas_sdev_configure(struct scsi_device *dev, struct queue_limits *lim);
extern int sas_change_queue_depth(struct scsi_device *, int new_depth);
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 96b350366670..08ac3200b4a4 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -106,12 +106,15 @@ enum scsi_disposition {
};
/*
- * Midlevel queue return values.
+ * Status values returned by the .queuecommand() callback if a command has not
+ * been queued.
*/
-#define SCSI_MLQUEUE_HOST_BUSY 0x1055
-#define SCSI_MLQUEUE_DEVICE_BUSY 0x1056
-#define SCSI_MLQUEUE_EH_RETRY 0x1057
-#define SCSI_MLQUEUE_TARGET_BUSY 0x1058
+enum scsi_qc_status {
+ SCSI_MLQUEUE_HOST_BUSY = 0x1055,
+ SCSI_MLQUEUE_DEVICE_BUSY = 0x1056,
+ SCSI_MLQUEUE_EH_RETRY = 0x1057,
+ SCSI_MLQUEUE_TARGET_BUSY = 0x1058,
+};
/*
* Use these to separate status msg and our bytes
diff --git a/include/scsi/scsi_driver.h b/include/scsi/scsi_driver.h
index c0e89996bdb3..249cea724abd 100644
--- a/include/scsi/scsi_driver.h
+++ b/include/scsi/scsi_driver.h
@@ -12,6 +12,9 @@ struct request;
struct scsi_driver {
struct device_driver gendrv;
+ int (*probe)(struct scsi_device *);
+ void (*remove)(struct scsi_device *);
+ void (*shutdown)(struct scsi_device *);
int (*resume)(struct device *);
void (*rescan)(struct device *);
blk_status_t (*init_command)(struct scsi_cmnd *);
@@ -25,9 +28,9 @@ struct scsi_driver {
#define scsi_register_driver(drv) \
__scsi_register_driver(drv, THIS_MODULE)
-int __scsi_register_driver(struct device_driver *, struct module *);
+int __scsi_register_driver(struct scsi_driver *, struct module *);
#define scsi_unregister_driver(drv) \
- driver_unregister(drv);
+ driver_unregister(&(drv)->gendrv);
extern int scsi_register_interface(struct class_interface *);
#define scsi_unregister_interface(intf) \
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index e87cf7eadd26..f6e12565a81d 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -84,13 +84,15 @@ struct scsi_host_template {
*
* STATUS: REQUIRED
*/
- int (* queuecommand)(struct Scsi_Host *, struct scsi_cmnd *);
+ enum scsi_qc_status (*queuecommand)(struct Scsi_Host *,
+ struct scsi_cmnd *);
/*
* Queue a reserved command (BLK_MQ_REQ_RESERVED). The .queuecommand()
* documentation also applies to the .queue_reserved_command() callback.
*/
- int (*queue_reserved_command)(struct Scsi_Host *, struct scsi_cmnd *);
+ enum scsi_qc_status (*queue_reserved_command)(struct Scsi_Host *,
+ struct scsi_cmnd *);
/*
* The commit_rqs function is used to trigger a hardware
@@ -525,10 +527,12 @@ struct scsi_host_template {
*
*/
#define DEF_SCSI_QCMD(func_name) \
- int func_name(struct Scsi_Host *shost, struct scsi_cmnd *cmd) \
+ enum scsi_qc_status func_name(struct Scsi_Host *shost, \
+ struct scsi_cmnd *cmd) \
{ \
unsigned long irq_flags; \
- int rc; \
+ enum scsi_qc_status rc; \
+ \
spin_lock_irqsave(shost->host_lock, irq_flags); \
rc = func_name##_lck(cmd); \
spin_unlock_irqrestore(shost->host_lock, irq_flags); \
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index b908aacfef48..9f30625aa0d3 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -317,6 +317,15 @@ struct fc_fpin_stats {
u64 cn_device_specific;
};
+#define FC_RPORT_ENCRYPTION_STATUS_MAX_LEN 14
+/*
+ * Encryption Information
+ */
+struct fc_encryption_info {
+ /* Encryption Status */
+ u8 status;
+};
+
/* Macro for use in defining Remote Port attributes */
#define FC_RPORT_ATTR(_name,_mode,_show,_store) \
struct device_attribute dev_attr_rport_##_name = \
@@ -364,6 +373,7 @@ struct fc_rport { /* aka fc_starget_attrs */
u64 port_name;
u32 port_id;
u32 roles;
+ struct fc_encryption_info enc_info;
enum fc_port_state port_state; /* Will only be ONLINE or UNKNOWN */
u32 scsi_target_id;
u32 fast_io_fail_tmo;
@@ -691,6 +701,8 @@ struct fc_function_template {
struct fc_host_statistics * (*get_fc_host_stats)(struct Scsi_Host *);
void (*reset_fc_host_stats)(struct Scsi_Host *);
+ struct fc_encryption_info * (*get_fc_rport_enc_info)(struct fc_rport *);
+
int (*issue_fc_host_lip)(struct Scsi_Host *);
void (*dev_loss_tmo_callbk)(struct fc_rport *);
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 7016d93fa383..b62d5fcce950 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -108,6 +108,9 @@
#define SE_MODE_PAGE_BUF 512
#define SE_SENSE_BUF 96
+/* Peripheral Device Text Identification Information */
+#define PD_TEXT_ID_INFO_LEN 256
+
enum target_submit_type {
/* Use the fabric driver's default submission type */
TARGET_FABRIC_DEFAULT_SUBMIT,
@@ -348,6 +351,7 @@ struct t10_wwn {
struct se_device *t10_dev;
struct config_group t10_wwn_group;
struct list_head t10_vpd_list;
+ char pd_text_id_info[PD_TEXT_ID_INFO_LEN];
};
struct t10_pr_registration {
diff --git a/include/uapi/scsi/scsi_bsg_ufs.h b/include/uapi/scsi/scsi_bsg_ufs.h
index 8c29e498ef98..06f88d1b1876 100644
--- a/include/uapi/scsi/scsi_bsg_ufs.h
+++ b/include/uapi/scsi/scsi_bsg_ufs.h
@@ -94,16 +94,15 @@ struct utp_upiu_header {
};
/**
- * struct utp_upiu_query - upiu request buffer structure for
- * query request.
- * @opcode: command to perform B-0
- * @idn: a value that indicates the particular type of data B-1
- * @index: Index to further identify data B-2
- * @selector: Index to further identify data B-3
+ * struct utp_upiu_query - QUERY REQUEST UPIU structure.
+ * @opcode: query function to perform B-0
+ * @idn: descriptor or attribute identification number B-1
+ * @index: Index that further identifies which data to access B-2
+ * @selector: Index that further identifies which data to access B-3
* @reserved_osf: spec reserved field B-4,5
- * @length: number of descriptor bytes to read/write B-6,7
- * @value: Attribute value to be written DW-5
- * @reserved: spec reserved DW-6,7
+ * @length: number of descriptor bytes to read or write B-6,7
+ * @value: if @opcode == UPIU_QUERY_OPCODE_WRITE_ATTR, the value to be written B-6,7
+ * @reserved: reserved for future use DW-6,7
*/
struct utp_upiu_query {
__u8 opcode;
diff --git a/include/ufs/ufs.h b/include/ufs/ufs.h
index ab8f6c07b5a2..602aa34c9822 100644
--- a/include/ufs/ufs.h
+++ b/include/ufs/ufs.h
@@ -21,6 +21,7 @@
* in this header file of the size of struct utp_upiu_header.
*/
static_assert(sizeof(struct utp_upiu_header) == 12);
+static_assert(sizeof(struct utp_upiu_query) == 20);
#define GENERAL_UPIU_REQUEST_SIZE (sizeof(struct utp_upiu_req))
#define QUERY_DESC_MAX_SIZE 255
@@ -561,7 +562,7 @@ enum ufs_dev_pwr_mode {
#define UFS_WB_BUF_REMAIN_PERCENT(val) ((val) / 10)
/**
- * struct utp_cmd_rsp - Response UPIU structure
+ * struct utp_cmd_rsp - RESPONSE UPIU structure
* @residual_transfer_count: Residual transfer count DW-3
* @reserved: Reserved double words DW-4 to DW-7
* @sense_data_len: Sense data length DW-8 U16
@@ -574,6 +575,8 @@ struct utp_cmd_rsp {
u8 sense_data[UFS_SENSE_SIZE];
};
+static_assert(sizeof(struct utp_cmd_rsp) == 40);
+
/**
* struct utp_upiu_rsp - general upiu response structure
* @header: UPIU header structure DW-0 to DW-2
diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
index 19154228780b..8563b6648976 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -834,6 +834,7 @@ enum ufshcd_mcq_opr {
* @uic_link_state: active state of the link to the UFS device.
* @rpm_lvl: desired UFS power management level during runtime PM.
* @spm_lvl: desired UFS power management level during system PM.
+ * @pm_lvl_min: minimum supported power management level.
* @pm_op_in_progress: whether or not a PM operation is in progress.
* @ahit: value of Auto-Hibernate Idle Timer register.
* @outstanding_tasks: Bits representing outstanding task requests
@@ -972,6 +973,7 @@ struct ufs_hba {
enum ufs_pm_level rpm_lvl;
/* Desired UFS power management level during system PM */
enum ufs_pm_level spm_lvl;
+ enum ufs_pm_level pm_lvl_min;
int pm_op_in_progress;
/* Auto-Hibernate Idle Timer register value */
@@ -1342,17 +1344,13 @@ static inline void *ufshcd_get_variant(struct ufs_hba *hba)
return hba->priv;
}
-#ifdef CONFIG_PM
extern int ufshcd_runtime_suspend(struct device *dev);
extern int ufshcd_runtime_resume(struct device *dev);
-#endif
-#ifdef CONFIG_PM_SLEEP
extern int ufshcd_system_suspend(struct device *dev);
extern int ufshcd_system_resume(struct device *dev);
extern int ufshcd_system_freeze(struct device *dev);
extern int ufshcd_system_thaw(struct device *dev);
extern int ufshcd_system_restore(struct device *dev);
-#endif
extern int ufshcd_dme_reset(struct ufs_hba *hba);
extern int ufshcd_dme_enable(struct ufs_hba *hba);
diff --git a/include/ufs/ufshci.h b/include/ufs/ufshci.h
index d36df24242a3..806fdaf52bd9 100644
--- a/include/ufs/ufshci.h
+++ b/include/ufs/ufshci.h
@@ -288,6 +288,7 @@ enum {
/* REG_UFS_MEM_CFG - Global Config Registers 300h */
#define MCQ_MODE_SELECT BIT(0)
+#define ESI_ENABLE BIT(1)
/* CQISy - CQ y Interrupt Status Register */
#define UFSHCD_MCQ_CQIS_TAIL_ENT_PUSH_STS 0x1