aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/stable/sysfs-driver-ib_srp25
-rw-r--r--Documentation/scsi/libsas.txt82
-rw-r--r--Documentation/scsi/scsi_mid_low_api.txt20
-rw-r--r--Documentation/scsi/wd719x.txt21
-rw-r--r--MAINTAINERS17
-rw-r--r--arch/m68k/atari/config.c27
-rw-r--r--arch/m68k/atari/stdma.c61
-rw-r--r--arch/m68k/include/asm/atari_stdma.h4
-rw-r--r--arch/m68k/include/asm/macintosh.h4
-rw-r--r--arch/m68k/mac/config.c146
-rw-r--r--arch/m68k/sun3/config.c60
-rw-r--r--drivers/ata/libata-scsi.c17
-rw-r--r--drivers/ata/sata_nv.c2
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.c3
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c1076
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.h75
-rw-r--r--drivers/message/fusion/mptscsih.c12
-rw-r--r--drivers/message/fusion/mptscsih.h3
-rw-r--r--drivers/misc/eeprom/eeprom_93cx6.c62
-rw-r--r--drivers/s390/scsi/zfcp_aux.c6
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c32
-rw-r--r--drivers/s390/scsi/zfcp_def.h3
-rw-r--r--drivers/s390/scsi/zfcp_erp.c7
-rw-r--r--drivers/s390/scsi/zfcp_ext.h1
-rw-r--r--drivers/s390/scsi/zfcp_fc.c52
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c3
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c24
-rw-r--r--drivers/s390/scsi/zfcp_sysfs.c66
-rw-r--r--drivers/scsi/3w-9xxx.c15
-rw-r--r--drivers/scsi/3w-sas.c15
-rw-r--r--drivers/scsi/3w-xxxx.c15
-rw-r--r--drivers/scsi/53c700.c19
-rw-r--r--drivers/scsi/BusLogic.c4
-rw-r--r--drivers/scsi/Kconfig18
-rw-r--r--drivers/scsi/Makefile3
-rw-r--r--drivers/scsi/NCR5380.c295
-rw-r--r--drivers/scsi/NCR5380.h78
-rw-r--r--drivers/scsi/aacraid/linit.c18
-rw-r--r--drivers/scsi/advansys.c8
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c4
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c4
-rw-r--r--drivers/scsi/aic94xx/aic94xx.h2
-rw-r--r--drivers/scsi/aic94xx/aic94xx_hwi.c3
-rw-r--r--drivers/scsi/aic94xx/aic94xx_init.c12
-rw-r--r--drivers/scsi/aic94xx/aic94xx_task.c13
-rw-r--r--drivers/scsi/am53c974.c586
-rw-r--r--drivers/scsi/arcmsr/arcmsr_hba.c9
-rw-r--r--drivers/scsi/arm/cumana_1.c18
-rw-r--r--drivers/scsi/arm/oak.c23
-rw-r--r--drivers/scsi/atari_NCR5380.c981
-rw-r--r--drivers/scsi/atari_scsi.c673
-rw-r--r--drivers/scsi/atari_scsi.h60
-rw-r--r--drivers/scsi/be2iscsi/be_main.c4
-rw-r--r--drivers/scsi/bfa/bfad_debugfs.c30
-rw-r--r--drivers/scsi/bfa/bfad_im.c4
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_fcoe.c6
-rw-r--r--drivers/scsi/bnx2i/bnx2i_iscsi.c3
-rw-r--r--drivers/scsi/csiostor/csio_scsi.c2
-rw-r--r--drivers/scsi/cxgbi/cxgb3i/cxgb3i.c3
-rw-r--r--drivers/scsi/cxgbi/cxgb4i/cxgb4i.c3
-rw-r--r--drivers/scsi/dmx3191d.c31
-rw-r--r--drivers/scsi/dpt_i2o.c2
-rw-r--r--drivers/scsi/dtc.c85
-rw-r--r--drivers/scsi/dtc.h26
-rw-r--r--drivers/scsi/eata.c6
-rw-r--r--drivers/scsi/esas2r/esas2r.h1
-rw-r--r--drivers/scsi/esas2r/esas2r_ioctl.c22
-rw-r--r--drivers/scsi/esas2r/esas2r_main.c11
-rw-r--r--drivers/scsi/esp_scsi.c411
-rw-r--r--drivers/scsi/esp_scsi.h22
-rw-r--r--drivers/scsi/fcoe/fcoe.c3
-rw-r--r--drivers/scsi/fnic/fnic.h2
-rw-r--r--drivers/scsi/fnic/fnic_fcs.c5
-rw-r--r--drivers/scsi/fnic/fnic_main.c18
-rw-r--r--drivers/scsi/fnic/fnic_scsi.c32
-rw-r--r--drivers/scsi/fnic/fnic_trace.c4
-rw-r--r--drivers/scsi/g_NCR5380.c224
-rw-r--r--drivers/scsi/g_NCR5380.h26
-rw-r--r--drivers/scsi/hpsa.c509
-rw-r--r--drivers/scsi/hpsa.h33
-rw-r--r--drivers/scsi/hpsa_cmd.h34
-rw-r--r--drivers/scsi/hptiop.c8
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c10
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c10
-rw-r--r--drivers/scsi/ipr.c116
-rw-r--r--drivers/scsi/ipr.h2
-rw-r--r--drivers/scsi/ips.c2
-rw-r--r--drivers/scsi/isci/init.c3
-rw-r--r--drivers/scsi/isci/task.c147
-rw-r--r--drivers/scsi/isci/task.h1
-rw-r--r--drivers/scsi/iscsi_tcp.c3
-rw-r--r--drivers/scsi/libfc/fc_fcp.c27
-rw-r--r--drivers/scsi/libiscsi.c19
-rw-r--r--drivers/scsi/libsas/sas_ata.c9
-rw-r--r--drivers/scsi/libsas/sas_expander.c2
-rw-r--r--drivers/scsi/libsas/sas_init.c21
-rw-r--r--drivers/scsi/libsas/sas_internal.h2
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c203
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c113
-rw-r--r--drivers/scsi/mac_scsi.c552
-rw-r--r--drivers/scsi/mac_scsi.h74
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.c23
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h23
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c163
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fp.c33
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.c112
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.h18
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c46
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_scsih.c48
-rw-r--r--drivers/scsi/mvsas/mv_init.c23
-rw-r--r--drivers/scsi/mvsas/mv_sas.c109
-rw-r--r--drivers/scsi/mvsas/mv_sas.h10
-rw-r--r--drivers/scsi/ncr53c8xx.c2
-rw-r--r--drivers/scsi/pas16.c106
-rw-r--r--drivers/scsi/pas16.h21
-rw-r--r--drivers/scsi/pm8001/pm8001_init.c3
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.c22
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.h3
-rw-r--r--drivers/scsi/pmcraid.c12
-rw-r--r--drivers/scsi/qla1280.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_nx2.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c58
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c18
-rw-r--r--drivers/scsi/scsi.c41
-rw-r--r--drivers/scsi/scsi_debug.c1982
-rw-r--r--drivers/scsi/scsi_error.c15
-rw-r--r--drivers/scsi/scsi_scan.c2
-rw-r--r--drivers/scsi/scsi_sysfs.c5
-rw-r--r--drivers/scsi/storvsc_drv.c2
-rw-r--r--drivers/scsi/sun3_NCR5380.c2932
-rw-r--r--drivers/scsi/sun3_scsi.c512
-rw-r--r--drivers/scsi/sun3_scsi.h84
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c2
-rw-r--r--drivers/scsi/t128.c83
-rw-r--r--drivers/scsi/t128.h23
-rw-r--r--drivers/scsi/tmscsim.c2626
-rw-r--r--drivers/scsi/tmscsim.h551
-rw-r--r--drivers/scsi/u14-34f.c10
-rw-r--r--drivers/scsi/ufs/ufshcd.c25
-rw-r--r--drivers/scsi/virtio_scsi.c38
-rw-r--r--drivers/scsi/vmw_pvscsi.c32
-rw-r--r--drivers/scsi/wd7000.c1
-rw-r--r--drivers/scsi/wd719x.c996
-rw-r--r--drivers/scsi/wd719x.h249
-rw-r--r--drivers/target/loopback/tcm_loop.c28
-rw-r--r--drivers/usb/storage/uas.c2
-rw-r--r--include/linux/eeprom_93cx6.h4
-rw-r--r--include/linux/libata.h4
-rw-r--r--include/scsi/libfc.h1
-rw-r--r--include/scsi/libiscsi.h2
-rw-r--r--include/scsi/libsas.h17
-rw-r--r--include/scsi/scsi_device.h2
-rw-r--r--include/scsi/scsi_host.h15
154 files changed, 7004 insertions, 11816 deletions
diff --git a/Documentation/ABI/stable/sysfs-driver-ib_srp b/Documentation/ABI/stable/sysfs-driver-ib_srp
index b9688de8455b..7049a2b50359 100644
--- a/Documentation/ABI/stable/sysfs-driver-ib_srp
+++ b/Documentation/ABI/stable/sysfs-driver-ib_srp
@@ -55,12 +55,12 @@ Description: Interface for making ib_srp connect to a new target.
only safe with partial memory descriptor list support enabled
(allow_ext_sg=1).
* comp_vector, a number in the range 0..n-1 specifying the
- MSI-X completion vector. Some HCA's allocate multiple (n)
- MSI-X vectors per HCA port. If the IRQ affinity masks of
- these interrupts have been configured such that each MSI-X
- interrupt is handled by a different CPU then the comp_vector
- parameter can be used to spread the SRP completion workload
- over multiple CPU's.
+ MSI-X completion vector of the first RDMA channel. Some
+ HCA's allocate multiple (n) MSI-X vectors per HCA port. If
+ the IRQ affinity masks of these interrupts have been
+ configured such that each MSI-X interrupt is handled by a
+ different CPU then the comp_vector parameter can be used to
+ spread the SRP completion workload over multiple CPU's.
* tl_retry_count, a number in the range 2..7 specifying the
IB RC retry count.
* queue_size, the maximum number of commands that the
@@ -88,6 +88,13 @@ Description: Whether ib_srp is allowed to include a partial memory
descriptor list in an SRP_CMD when communicating with an SRP
target.
+What: /sys/class/scsi_host/host<n>/ch_count
+Date: April 1, 2015
+KernelVersion: 3.19
+Contact: linux-rdma@vger.kernel.org
+Description: Number of RDMA channels used for communication with the SRP
+ target.
+
What: /sys/class/scsi_host/host<n>/cmd_sg_entries
Date: May 19, 2011
KernelVersion: 2.6.39
@@ -95,6 +102,12 @@ Contact: linux-rdma@vger.kernel.org
Description: Maximum number of data buffer descriptors that may be sent to
the target in a single SRP_CMD request.
+What: /sys/class/scsi_host/host<n>/comp_vector
+Date: September 2, 2013
+KernelVersion: 3.11
+Contact: linux-rdma@vger.kernel.org
+Description: Completion vector used for the first RDMA channel.
+
What: /sys/class/scsi_host/host<n>/dgid
Date: June 17, 2006
KernelVersion: 2.6.17
diff --git a/Documentation/scsi/libsas.txt b/Documentation/scsi/libsas.txt
index 3cc9c7843e15..8cac6492aade 100644
--- a/Documentation/scsi/libsas.txt
+++ b/Documentation/scsi/libsas.txt
@@ -226,9 +226,6 @@ static int register_sas_ha(struct my_sas_ha *my_ha)
my_ha->sas_ha.lldd_dev_found = my_dev_found;
my_ha->sas_ha.lldd_dev_gone = my_dev_gone;
- my_ha->sas_ha.lldd_max_execute_num = lldd_max_execute_num; (1)
-
- my_ha->sas_ha.lldd_queue_size = ha_can_queue;
my_ha->sas_ha.lldd_execute_task = my_execute_task;
my_ha->sas_ha.lldd_abort_task = my_abort_task;
@@ -247,28 +244,6 @@ static int register_sas_ha(struct my_sas_ha *my_ha)
return sas_register_ha(&my_ha->sas_ha);
}
-(1) This is normally a LLDD parameter, something of the
-lines of a task collector. What it tells the SAS Layer is
-whether the SAS layer should run in Direct Mode (default:
-value 0 or 1) or Task Collector Mode (value greater than 1).
-
-In Direct Mode, the SAS Layer calls Execute Task as soon as
-it has a command to send to the SDS, _and_ this is a single
-command, i.e. not linked.
-
-Some hardware (e.g. aic94xx) has the capability to DMA more
-than one task at a time (interrupt) from host memory. Task
-Collector Mode is an optional feature for HAs which support
-this in their hardware. (Again, it is completely optional
-even if your hardware supports it.)
-
-In Task Collector Mode, the SAS Layer would do _natural_
-coalescing of tasks and at the appropriate moment it would
-call your driver to DMA more than one task in a single HA
-interrupt. DMBS may want to use this by insmod/modprobe
-setting the lldd_max_execute_num to something greater than
-1.
-
(2) SAS 1.1 does not define I_T Nexus Reset TMF.
Events
@@ -325,71 +300,22 @@ PHYE_SPINUP_HOLD -- SATA is present, COMWAKE not sent.
The Execute Command SCSI RPC:
- int (*lldd_execute_task)(struct sas_task *, int num,
- unsigned long gfp_flags);
+ int (*lldd_execute_task)(struct sas_task *, gfp_t gfp_flags);
-Used to queue a task to the SAS LLDD. @task is the tasks to
-be executed. @num should be the number of tasks being
-queued at this function call (they are linked listed via
-task::list), @gfp_mask should be the gfp_mask defining the
-context of the caller.
+Used to queue a task to the SAS LLDD. @task is the task to be executed.
+@gfp_mask is the gfp_mask defining the context of the caller.
This function should implement the Execute Command SCSI RPC,
-or if you're sending a SCSI Task as linked commands, you
-should also use this function.
-That is, when lldd_execute_task() is called, the command(s)
+That is, when lldd_execute_task() is called, the command
go out on the transport *immediately*. There is *no*
queuing of any sort and at any level in a SAS LLDD.
-The use of task::list is two-fold, one for linked commands,
-the other discussed below.
-
-It is possible to queue up more than one task at a time, by
-initializing the list element of struct sas_task, and
-passing the number of tasks enlisted in this manner in num.
-
Returns: -SAS_QUEUE_FULL, -ENOMEM, nothing was queued;
0, the task(s) were queued.
-If you want to pass num > 1, then either
-A) you're the only caller of this function and keep track
- of what you've queued to the LLDD, or
-B) you know what you're doing and have a strategy of
- retrying.
-
-As opposed to queuing one task at a time (function call),
-batch queuing of tasks, by having num > 1, greatly
-simplifies LLDD code, sequencer code, and _hardware design_,
-and has some performance advantages in certain situations
-(DBMS).
-
-The LLDD advertises if it can take more than one command at
-a time at lldd_execute_task(), by setting the
-lldd_max_execute_num parameter (controlled by "collector"
-module parameter in aic94xx SAS LLDD).
-
-You should leave this to the default 1, unless you know what
-you're doing.
-
-This is a function of the LLDD, to which the SAS layer can
-cater to.
-
-int lldd_queue_size
- The host adapter's queue size. This is the maximum
-number of commands the lldd can have pending to domain
-devices on behalf of all upper layers submitting through
-lldd_execute_task().
-
-You really want to set this to something (much) larger than
-1.
-
-This _really_ has absolutely nothing to do with queuing.
-There is no queuing in SAS LLDDs.
-
struct sas_task {
dev -- the device this task is destined to
- list -- must be initialized (INIT_LIST_HEAD)
task_proto -- _one_ of enum sas_proto
scatter -- pointer to scatter gather list array
num_scatter -- number of elements in scatter
diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt
index bee7d86b9dcc..731bc4f4c5e6 100644
--- a/Documentation/scsi/scsi_mid_low_api.txt
+++ b/Documentation/scsi/scsi_mid_low_api.txt
@@ -149,7 +149,7 @@ scsi_add_host() ---->
scsi_scan_host() -------+
|
slave_alloc()
- slave_configure() --> scsi_adjust_queue_depth()
+ slave_configure() --> scsi_change_queue_depth()
|
slave_alloc()
slave_configure()
@@ -159,7 +159,7 @@ scsi_scan_host() -------+
------------------------------------------------------------
If the LLD wants to adjust the default queue settings, it can invoke
-scsi_adjust_queue_depth() in its slave_configure() routine.
+scsi_change_queue_depth() in its slave_configure() routine.
*** For scsi devices that the mid level tries to scan but do not
respond, a slave_alloc(), slave_destroy() pair is called.
@@ -203,7 +203,7 @@ LLD mid level LLD
scsi_add_device() ------+
|
slave_alloc()
- slave_configure() [--> scsi_adjust_queue_depth()]
+ slave_configure() [--> scsi_change_queue_depth()]
------------------------------------------------------------
In a similar fashion, an LLD may become aware that a SCSI device has been
@@ -261,7 +261,7 @@ init_this_scsi_driver() ----+
| scsi_register()
|
slave_alloc()
- slave_configure() --> scsi_adjust_queue_depth()
+ slave_configure() --> scsi_change_queue_depth()
slave_alloc() ***
slave_destroy() ***
|
@@ -271,7 +271,7 @@ init_this_scsi_driver() ----+
slave_destroy() ***
------------------------------------------------------------
-The mid level invokes scsi_adjust_queue_depth() with "cmd_per_lun" for that
+The mid level invokes scsi_change_queue_depth() with "cmd_per_lun" for that
host as the queue length. These settings can be overridden by a
slave_configure() supplied by the LLD.
@@ -368,7 +368,7 @@ names all start with "scsi_".
Summary:
scsi_add_device - creates new scsi device (lu) instance
scsi_add_host - perform sysfs registration and set up transport class
- scsi_adjust_queue_depth - change the queue depth on a SCSI device
+ scsi_change_queue_depth - change the queue depth on a SCSI device
scsi_bios_ptable - return copy of block device's partition table
scsi_block_requests - prevent further commands being queued to given host
scsi_host_alloc - return a new scsi_host instance whose refcount==1
@@ -436,7 +436,7 @@ int scsi_add_host(struct Scsi_Host *shost, struct device * dev)
/**
- * scsi_adjust_queue_depth - allow LLD to change queue depth on a SCSI device
+ * scsi_change_queue_depth - allow LLD to change queue depth on a SCSI device
* @sdev: pointer to SCSI device to change queue depth on
* @tags Number of tags allowed if tagged queuing enabled,
* or number of commands the LLD can queue up
@@ -453,7 +453,7 @@ int scsi_add_host(struct Scsi_Host *shost, struct device * dev)
* Defined in: drivers/scsi/scsi.c [see source code for more notes]
*
**/
-void scsi_adjust_queue_depth(struct scsi_device *sdev, int tags)
+int scsi_change_queue_depth(struct scsi_device *sdev, int tags)
/**
@@ -1214,7 +1214,7 @@ of interest:
for disk firmware uploads.
cmd_per_lun - maximum number of commands that can be queued on devices
controlled by the host. Overridden by LLD calls to
- scsi_adjust_queue_depth().
+ scsi_change_queue_depth().
unchecked_isa_dma - 1=>only use bottom 16 MB of ram (ISA DMA addressing
restriction), 0=>can use full 32 bit (or better) DMA
address space
@@ -1254,7 +1254,7 @@ struct scsi_cmnd
Instances of this structure convey SCSI commands to the LLD and responses
back to the mid level. The SCSI mid level will ensure that no more SCSI
commands become queued against the LLD than are indicated by
-scsi_adjust_queue_depth() (or struct Scsi_Host::cmd_per_lun). There will
+scsi_change_queue_depth() (or struct Scsi_Host::cmd_per_lun). There will
be at least one instance of struct scsi_cmnd available for each SCSI device.
Members of interest:
cmnd - array containing SCSI command
diff --git a/Documentation/scsi/wd719x.txt b/Documentation/scsi/wd719x.txt
new file mode 100644
index 000000000000..0816b0220238
--- /dev/null
+++ b/Documentation/scsi/wd719x.txt
@@ -0,0 +1,21 @@
+Driver for Western Digital WD7193, WD7197 and WD7296 SCSI cards
+---------------------------------------------------------------
+
+The card requires firmware that can be cut out of the Windows NT driver that
+can be downloaded from WD at:
+http://support.wdc.com/product/download.asp?groupid=801&sid=27&lang=en
+
+There is no license anywhere in the file or on the page - so the firmware
+probably cannot be added to linux-firmware.
+
+This script downloads and extracts the firmware, creating wd719x-risc.bin and
+d719x-wcs.bin files. Put them in /lib/firmware/.
+
+#!/bin/sh
+wget http://support.wdc.com/download/archive/pciscsi.exe
+lha xi pciscsi.exe pci-scsi.exe
+lha xi pci-scsi.exe nt/wd7296a.sys
+rm pci-scsi.exe
+dd if=wd7296a.sys of=wd719x-risc.bin bs=1 skip=5760 count=14336
+dd if=wd7296a.sys of=wd719x-wcs.bin bs=1 skip=20096 count=514
+rm wd7296a.sys
diff --git a/MAINTAINERS b/MAINTAINERS
index 0ff630de8a6d..7a95dc1a8de6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2862,11 +2862,10 @@ F: Documentation/networking/dmfe.txt
F: drivers/net/ethernet/dec/tulip/dmfe.c
DC390/AM53C974 SCSI driver
-M: Kurt Garloff <garloff@suse.de>
-W: http://www.garloff.de/kurt/linux/dc390/
-M: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+M: Hannes Reinecke <hare@suse.de>
+L: linux-scsi@vger.kernel.org
S: Maintained
-F: drivers/scsi/tmscsim.*
+F: drivers/scsi/am53c974.c
DC395x SCSI driver
M: Oliver Neukum <oliver@neukum.org>
@@ -5991,10 +5990,13 @@ W: http://linuxtv.org
S: Odd Fixes
F: drivers/media/parport/pms*
-MEGARAID SCSI DRIVERS
-M: Neela Syam Kolli <megaraidlinux@lsi.com>
+MEGARAID SCSI/SAS DRIVERS
+M: Kashyap Desai <kashyap.desai@avagotech.com>
+M: Sumit Saxena <sumit.saxena@avagotech.com>
+M: Uday Lingala <uday.lingala@avagotech.com>
+L: megaraidlinux.pdl@avagotech.com
L: linux-scsi@vger.kernel.org
-W: http://megaraid.lsilogic.com
+W: http://www.lsi.com
S: Maintained
F: Documentation/scsi/megaraid.txt
F: drivers/scsi/megaraid.*
@@ -6305,7 +6307,6 @@ F: drivers/scsi/g_NCR5380.*
F: drivers/scsi/g_NCR5380_mmio.c
F: drivers/scsi/mac_scsi.*
F: drivers/scsi/pas16.*
-F: drivers/scsi/sun3_NCR5380.c
F: drivers/scsi/sun3_scsi.*
F: drivers/scsi/sun3_scsi_vme.c
F: drivers/scsi/t128.*
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index 01a62161b08a..192b00f098f4 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -858,6 +858,24 @@ static struct platform_device *atari_netusbee_devices[] __initdata = {
};
#endif /* CONFIG_ATARI_ETHERNEC */
+#ifdef CONFIG_ATARI_SCSI
+static const struct resource atari_scsi_st_rsrc[] __initconst = {
+ {
+ .flags = IORESOURCE_IRQ,
+ .start = IRQ_MFP_FSCSI,
+ .end = IRQ_MFP_FSCSI,
+ },
+};
+
+static const struct resource atari_scsi_tt_rsrc[] __initconst = {
+ {
+ .flags = IORESOURCE_IRQ,
+ .start = IRQ_TT_MFP_SCSI,
+ .end = IRQ_TT_MFP_SCSI,
+ },
+};
+#endif
+
int __init atari_platform_init(void)
{
int rv = 0;
@@ -892,6 +910,15 @@ int __init atari_platform_init(void)
}
#endif
+#ifdef CONFIG_ATARI_SCSI
+ if (ATARIHW_PRESENT(ST_SCSI))
+ platform_device_register_simple("atari_scsi", -1,
+ atari_scsi_st_rsrc, ARRAY_SIZE(atari_scsi_st_rsrc));
+ else if (ATARIHW_PRESENT(TT_SCSI))
+ platform_device_register_simple("atari_scsi", -1,
+ atari_scsi_tt_rsrc, ARRAY_SIZE(atari_scsi_tt_rsrc));
+#endif
+
return rv;
}
diff --git a/arch/m68k/atari/stdma.c b/arch/m68k/atari/stdma.c
index ddbf43ca8858..e5a66596b116 100644
--- a/arch/m68k/atari/stdma.c
+++ b/arch/m68k/atari/stdma.c
@@ -59,6 +59,31 @@ static irqreturn_t stdma_int (int irq, void *dummy);
/************************* End of Prototypes **************************/
+/**
+ * stdma_try_lock - attempt to acquire ST DMA interrupt "lock"
+ * @handler: interrupt handler to use after acquisition
+ *
+ * Returns !0 if lock was acquired; otherwise 0.
+ */
+
+int stdma_try_lock(irq_handler_t handler, void *data)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ if (stdma_locked) {
+ local_irq_restore(flags);
+ return 0;
+ }
+
+ stdma_locked = 1;
+ stdma_isr = handler;
+ stdma_isr_data = data;
+ local_irq_restore(flags);
+ return 1;
+}
+EXPORT_SYMBOL(stdma_try_lock);
+
/*
* Function: void stdma_lock( isrfunc isr, void *data )
@@ -78,19 +103,10 @@ static irqreturn_t stdma_int (int irq, void *dummy);
void stdma_lock(irq_handler_t handler, void *data)
{
- unsigned long flags;
-
- local_irq_save(flags); /* protect lock */
-
/* Since the DMA is used for file system purposes, we
have to sleep uninterruptible (there may be locked
buffers) */
- wait_event(stdma_wait, !stdma_locked);
-
- stdma_locked = 1;
- stdma_isr = handler;
- stdma_isr_data = data;
- local_irq_restore(flags);
+ wait_event(stdma_wait, stdma_try_lock(handler, data));
}
EXPORT_SYMBOL(stdma_lock);
@@ -122,22 +138,25 @@ void stdma_release(void)
EXPORT_SYMBOL(stdma_release);
-/*
- * Function: int stdma_others_waiting( void )
- *
- * Purpose: Check if someone waits for the ST-DMA lock.
- *
- * Inputs: none
- *
- * Returns: 0 if no one is waiting, != 0 otherwise
+/**
+ * stdma_is_locked_by - allow lock holder to check whether it needs to release.
+ * @handler: interrupt handler previously used to acquire lock.
*
+ * Returns !0 if locked for the given handler; 0 otherwise.
*/
-int stdma_others_waiting(void)
+int stdma_is_locked_by(irq_handler_t handler)
{
- return waitqueue_active(&stdma_wait);
+ unsigned long flags;
+ int result;
+
+ local_irq_save(flags);
+ result = stdma_locked && (stdma_isr == handler);
+ local_irq_restore(flags);
+
+ return result;
}
-EXPORT_SYMBOL(stdma_others_waiting);
+EXPORT_SYMBOL(stdma_is_locked_by);
/*
diff --git a/arch/m68k/include/asm/atari_stdma.h b/arch/m68k/include/asm/atari_stdma.h
index 8e389b7fa70c..d24e34d870dc 100644
--- a/arch/m68k/include/asm/atari_stdma.h
+++ b/arch/m68k/include/asm/atari_stdma.h
@@ -8,11 +8,11 @@
/***************************** Prototypes *****************************/
+int stdma_try_lock(irq_handler_t, void *);
void stdma_lock(irq_handler_t handler, void *data);
void stdma_release( void );
-int stdma_others_waiting( void );
int stdma_islocked( void );
-void *stdma_locked_by( void );
+int stdma_is_locked_by(irq_handler_t);
void stdma_init( void );
/************************* End of Prototypes **************************/
diff --git a/arch/m68k/include/asm/macintosh.h b/arch/m68k/include/asm/macintosh.h
index d323b2c2d07d..29c7c6c3a5f2 100644
--- a/arch/m68k/include/asm/macintosh.h
+++ b/arch/m68k/include/asm/macintosh.h
@@ -53,6 +53,10 @@ struct mac_model
#define MAC_SCSI_QUADRA 2
#define MAC_SCSI_QUADRA2 3
#define MAC_SCSI_QUADRA3 4
+#define MAC_SCSI_IIFX 5
+#define MAC_SCSI_DUO 6
+#define MAC_SCSI_CCL 7
+#define MAC_SCSI_LATE 8
#define MAC_IDE_NONE 0
#define MAC_IDE_QUADRA 1
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index a471eab1a4dd..e9c3756139fc 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -278,7 +278,7 @@ static struct mac_model mac_data_table[] = {
.name = "IIfx",
.adb_type = MAC_ADB_IOP,
.via_type = MAC_VIA_IICI,
- .scsi_type = MAC_SCSI_OLD,
+ .scsi_type = MAC_SCSI_IIFX,
.scc_type = MAC_SCC_IOP,
.nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_IOP,
@@ -329,7 +329,7 @@ static struct mac_model mac_data_table[] = {
.name = "Color Classic",
.adb_type = MAC_ADB_CUDA,
.via_type = MAC_VIA_IICI,
- .scsi_type = MAC_SCSI_OLD,
+ .scsi_type = MAC_SCSI_CCL,
.scc_type = MAC_SCC_II,
.nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
@@ -338,7 +338,7 @@ static struct mac_model mac_data_table[] = {
.name = "Color Classic II",
.adb_type = MAC_ADB_CUDA,
.via_type = MAC_VIA_IICI,
- .scsi_type = MAC_SCSI_OLD,
+ .scsi_type = MAC_SCSI_CCL,
.scc_type = MAC_SCC_II,
.nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
@@ -526,7 +526,7 @@ static struct mac_model mac_data_table[] = {
.name = "Performa 520",
.adb_type = MAC_ADB_CUDA,
.via_type = MAC_VIA_IICI,
- .scsi_type = MAC_SCSI_OLD,
+ .scsi_type = MAC_SCSI_CCL,
.scc_type = MAC_SCC_II,
.nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
@@ -535,7 +535,7 @@ static struct mac_model mac_data_table[] = {
.name = "Performa 550",
.adb_type = MAC_ADB_CUDA,
.via_type = MAC_VIA_IICI,
- .scsi_type = MAC_SCSI_OLD,
+ .scsi_type = MAC_SCSI_CCL,
.scc_type = MAC_SCC_II,
.nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
@@ -567,7 +567,7 @@ static struct mac_model mac_data_table[] = {
.name = "TV",
.adb_type = MAC_ADB_CUDA,
.via_type = MAC_VIA_IICI,
- .scsi_type = MAC_SCSI_OLD,
+ .scsi_type = MAC_SCSI_CCL,
.scc_type = MAC_SCC_II,
.nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
@@ -712,7 +712,7 @@ static struct mac_model mac_data_table[] = {
.name = "PowerBook 190",
.adb_type = MAC_ADB_PB2,
.via_type = MAC_VIA_QUADRA,
- .scsi_type = MAC_SCSI_OLD,
+ .scsi_type = MAC_SCSI_LATE,
.ide_type = MAC_IDE_BABOON,
.scc_type = MAC_SCC_QUADRA,
.nubus_type = MAC_NUBUS,
@@ -722,7 +722,7 @@ static struct mac_model mac_data_table[] = {
.name = "PowerBook 520",
.adb_type = MAC_ADB_PB2,
.via_type = MAC_VIA_QUADRA,
- .scsi_type = MAC_SCSI_OLD,
+ .scsi_type = MAC_SCSI_LATE,
.scc_type = MAC_SCC_QUADRA,
.ether_type = MAC_ETHER_SONIC,
.nubus_type = MAC_NUBUS,
@@ -740,7 +740,7 @@ static struct mac_model mac_data_table[] = {
.name = "PowerBook Duo 210",
.adb_type = MAC_ADB_PB2,
.via_type = MAC_VIA_IICI,
- .scsi_type = MAC_SCSI_OLD,
+ .scsi_type = MAC_SCSI_DUO,
.scc_type = MAC_SCC_QUADRA,
.nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
@@ -749,7 +749,7 @@ static struct mac_model mac_data_table[] = {
.name = "PowerBook Duo 230",
.adb_type = MAC_ADB_PB2,
.via_type = MAC_VIA_IICI,
- .scsi_type = MAC_SCSI_OLD,
+ .scsi_type = MAC_SCSI_DUO,
.scc_type = MAC_SCC_QUADRA,
.nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
@@ -758,7 +758,7 @@ static struct mac_model mac_data_table[] = {
.name = "PowerBook Duo 250",
.adb_type = MAC_ADB_PB2,
.via_type = MAC_VIA_IICI,
- .scsi_type = MAC_SCSI_OLD,
+ .scsi_type = MAC_SCSI_DUO,
.scc_type = MAC_SCC_QUADRA,
.nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
@@ -767,7 +767,7 @@ static struct mac_model mac_data_table[] = {
.name = "PowerBook Duo 270c",
.adb_type = MAC_ADB_PB2,
.via_type = MAC_VIA_IICI,
- .scsi_type = MAC_SCSI_OLD,
+ .scsi_type = MAC_SCSI_DUO,
.scc_type = MAC_SCC_QUADRA,
.nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
@@ -776,7 +776,7 @@ static struct mac_model mac_data_table[] = {
.name = "PowerBook Duo 280",
.adb_type = MAC_ADB_PB2,
.via_type = MAC_VIA_IICI,
- .scsi_type = MAC_SCSI_OLD,
+ .scsi_type = MAC_SCSI_DUO,
.scc_type = MAC_SCC_QUADRA,
.nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
@@ -785,7 +785,7 @@ static struct mac_model mac_data_table[] = {
.name = "PowerBook Duo 280c",
.adb_type = MAC_ADB_PB2,
.via_type = MAC_VIA_IICI,
- .scsi_type = MAC_SCSI_OLD,
+ .scsi_type = MAC_SCSI_DUO,
.scc_type = MAC_SCC_QUADRA,
.nubus_type = MAC_NUBUS,
.floppy_type = MAC_FLOPPY_SWIM_ADDR2,
@@ -929,6 +929,70 @@ static struct platform_device swim_pdev = {
.resource = &swim_rsrc,
};
+static const struct resource mac_scsi_iifx_rsrc[] __initconst = {
+ {
+ .flags = IORESOURCE_IRQ,
+ .start = IRQ_MAC_SCSI,
+ .end = IRQ_MAC_SCSI,
+ }, {
+ .flags = IORESOURCE_MEM,
+ .start = 0x50008000,
+ .end = 0x50009FFF,
+ },
+};
+
+static const struct resource mac_scsi_duo_rsrc[] __initconst = {
+ {
+ .flags = IORESOURCE_MEM,
+ .start = 0xFEE02000,
+ .end = 0xFEE03FFF,
+ },
+};
+
+static const struct resource mac_scsi_old_rsrc[] __initconst = {
+ {
+ .flags = IORESOURCE_IRQ,
+ .start = IRQ_MAC_SCSI,
+ .end = IRQ_MAC_SCSI,
+ }, {
+ .flags = IORESOURCE_MEM,
+ .start = 0x50010000,
+ .end = 0x50011FFF,
+ }, {
+ .flags = IORESOURCE_MEM,
+ .start = 0x50006000,
+ .end = 0x50007FFF,
+ },
+};
+
+static const struct resource mac_scsi_late_rsrc[] __initconst = {
+ {
+ .flags = IORESOURCE_IRQ,
+ .start = IRQ_MAC_SCSI,
+ .end = IRQ_MAC_SCSI,
+ }, {
+ .flags = IORESOURCE_MEM,
+ .start = 0x50010000,
+ .end = 0x50011FFF,
+ },
+};
+
+static const struct resource mac_scsi_ccl_rsrc[] __initconst = {
+ {
+ .flags = IORESOURCE_IRQ,
+ .start = IRQ_MAC_SCSI,
+ .end = IRQ_MAC_SCSI,
+ }, {
+ .flags = IORESOURCE_MEM,
+ .start = 0x50F10000,
+ .end = 0x50F11FFF,
+ }, {
+ .flags = IORESOURCE_MEM,
+ .start = 0x50F06000,
+ .end = 0x50F07FFF,
+ },
+};
+
static struct platform_device esp_0_pdev = {
.name = "mac_esp",
.id = 0,
@@ -1000,6 +1064,60 @@ int __init mac_platform_init(void)
(macintosh_config->ident == MAC_MODEL_Q950))
platform_device_register(&esp_1_pdev);
break;
+ case MAC_SCSI_IIFX:
+ /* Addresses from The Guide to Mac Family Hardware.
+ * $5000 8000 - $5000 9FFF: SCSI DMA
+ * $5000 C000 - $5000 DFFF: Alternate SCSI (DMA)
+ * $5000 E000 - $5000 FFFF: Alternate SCSI (Hsk)
+ * The SCSI DMA custom IC embeds the 53C80 core. mac_scsi does
+ * not make use of its DMA or hardware handshaking logic.
+ */
+ platform_device_register_simple("mac_scsi", 0,
+ mac_scsi_iifx_rsrc, ARRAY_SIZE(mac_scsi_iifx_rsrc));
+ break;
+ case MAC_SCSI_DUO:
+ /* Addresses from the Duo Dock II Developer Note.
+ * $FEE0 2000 - $FEE0 3FFF: normal mode
+ * $FEE0 4000 - $FEE0 5FFF: pseudo DMA without /DRQ
+ * $FEE0 6000 - $FEE0 7FFF: pseudo DMA with /DRQ
+ * The NetBSD code indicates that both 5380 chips share
+ * an IRQ (?) which would need careful handling (see mac_esp).
+ */
+ platform_device_register_simple("mac_scsi", 1,
+ mac_scsi_duo_rsrc, ARRAY_SIZE(mac_scsi_duo_rsrc));
+ /* fall through */
+ case MAC_SCSI_OLD:
+ /* Addresses from Developer Notes for Duo System,
+ * PowerBook 180 & 160, 140 & 170, Macintosh IIsi
+ * and also from The Guide to Mac Family Hardware for
+ * SE/30, II, IIx, IIcx, IIci.
+ * $5000 6000 - $5000 7FFF: pseudo-DMA with /DRQ
+ * $5001 0000 - $5001 1FFF: normal mode
+ * $5001 2000 - $5001 3FFF: pseudo-DMA without /DRQ
+ * GMFH says that $5000 0000 - $50FF FFFF "wraps
+ * $5000 0000 - $5001 FFFF eight times" (!)
+ * mess.org says IIci and Color Classic do not alias
+ * I/O address space.
+ */
+ platform_device_register_simple("mac_scsi", 0,
+ mac_scsi_old_rsrc, ARRAY_SIZE(mac_scsi_old_rsrc));
+ break;
+ case MAC_SCSI_LATE:
+ /* PDMA logic in 68040 PowerBooks is somehow different to
+ * '030 models. It's probably more like Quadras (see mac_esp).
+ */
+ platform_device_register_simple("mac_scsi", 0,
+ mac_scsi_late_rsrc, ARRAY_SIZE(mac_scsi_late_rsrc));
+ break;
+ case MAC_SCSI_CCL:
+ /* Addresses from the Color Classic Developer Note.
+ * $50F0 6000 - $50F0 7FFF: SCSI handshake
+ * $50F1 0000 - $50F1 1FFF: SCSI
+ * $50F1 2000 - $50F1 3FFF: SCSI DMA
+ */
+ platform_device_register_simple("mac_scsi", 0,
+ mac_scsi_ccl_rsrc, ARRAY_SIZE(mac_scsi_ccl_rsrc));
+ break;
}
/*
diff --git a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c
index f59ec58083f8..a8b942bf7163 100644
--- a/arch/m68k/sun3/config.c
+++ b/arch/m68k/sun3/config.c
@@ -16,6 +16,7 @@
#include <linux/console.h>
#include <linux/init.h>
#include <linux/bootmem.h>
+#include <linux/platform_device.h>
#include <asm/oplib.h>
#include <asm/setup.h>
@@ -27,6 +28,7 @@
#include <asm/sun3mmu.h>
#include <asm/rtc.h>
#include <asm/machdep.h>
+#include <asm/machines.h>
#include <asm/idprom.h>
#include <asm/intersil.h>
#include <asm/irq.h>
@@ -169,3 +171,61 @@ static void __init sun3_sched_init(irq_handler_t timer_routine)
intersil_clear();
}
+#ifdef CONFIG_SUN3_SCSI
+
+static const struct resource sun3_scsi_vme_rsrc[] __initconst = {
+ {
+ .flags = IORESOURCE_IRQ,
+ .start = SUN3_VEC_VMESCSI0,
+ .end = SUN3_VEC_VMESCSI0,
+ }, {
+ .flags = IORESOURCE_MEM,
+ .start = 0xff200000,
+ .end = 0xff200021,
+ }, {
+ .flags = IORESOURCE_IRQ,
+ .start = SUN3_VEC_VMESCSI1,
+ .end = SUN3_VEC_VMESCSI1,
+ }, {
+ .flags = IORESOURCE_MEM,
+ .start = 0xff204000,
+ .end = 0xff204021,
+ },
+};
+
+/*
+ * Int: level 2 autovector
+ * IO: type 1, base 0x00140000, 5 bits phys space: A<4..0>
+ */
+static const struct resource sun3_scsi_rsrc[] __initconst = {
+ {
+ .flags = IORESOURCE_IRQ,
+ .start = 2,
+ .end = 2,
+ }, {
+ .flags = IORESOURCE_MEM,
+ .start = 0x00140000,
+ .end = 0x0014001f,
+ },
+};
+
+int __init sun3_platform_init(void)
+{
+ switch (idprom->id_machtype) {
+ case SM_SUN3 | SM_3_160:
+ case SM_SUN3 | SM_3_260:
+ platform_device_register_simple("sun3_scsi_vme", -1,
+ sun3_scsi_vme_rsrc, ARRAY_SIZE(sun3_scsi_vme_rsrc));
+ break;
+ case SM_SUN3 | SM_3_50:
+ case SM_SUN3 | SM_3_60:
+ platform_device_register_simple("sun3_scsi", -1,
+ sun3_scsi_rsrc, ARRAY_SIZE(sun3_scsi_rsrc));
+ break;
+ }
+ return 0;
+}
+
+arch_initcall(sun3_platform_init);
+
+#endif
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index fc6a60abe518..dd45c6a03e5d 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1164,7 +1164,7 @@ static int ata_scsi_dev_config(struct scsi_device *sdev,
depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
depth = min(ATA_MAX_QUEUE - 1, depth);
- scsi_adjust_queue_depth(sdev, depth);
+ scsi_change_queue_depth(sdev, depth);
}
blk_queue_flush_queueable(q, false);
@@ -1243,21 +1243,17 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev)
* @ap: ATA port to which the device change the queue depth
* @sdev: SCSI device to configure queue depth for
* @queue_depth: new queue depth
- * @reason: calling context
*
* libsas and libata have different approaches for associating a sdev to
* its ata_port.
*
*/
int __ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev,
- int queue_depth, int reason)
+ int queue_depth)
{
struct ata_device *dev;
unsigned long flags;
- if (reason != SCSI_QDEPTH_DEFAULT)
- return -EOPNOTSUPP;
-
if (queue_depth < 1 || queue_depth == sdev->queue_depth)
return sdev->queue_depth;
@@ -1282,15 +1278,13 @@ int __ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev,
if (sdev->queue_depth == queue_depth)
return -EINVAL;
- scsi_adjust_queue_depth(sdev, queue_depth);
- return queue_depth;
+ return scsi_change_queue_depth(sdev, queue_depth);
}
/**
* ata_scsi_change_queue_depth - SCSI callback for queue depth config
* @sdev: SCSI device to configure queue depth for
* @queue_depth: new queue depth
- * @reason: calling context
*
* This is libata standard hostt->change_queue_depth callback.
* SCSI will call into this callback when user tries to set queue
@@ -1302,12 +1296,11 @@ int __ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev,
* RETURNS:
* Newly configured queue depth.
*/
-int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth,
- int reason)
+int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth)
{
struct ata_port *ap = ata_shost_to_port(sdev->host);
- return __ata_change_queue_depth(ap, sdev, queue_depth, reason);
+ return __ata_change_queue_depth(ap, sdev, queue_depth);
}
/**
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index cdf99fac139a..1db6f5ce5e89 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -1951,7 +1951,7 @@ static int nv_swncq_slave_config(struct scsi_device *sdev)
ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
if (strncmp(model_num, "Maxtor", 6) == 0) {
- ata_scsi_change_queue_depth(sdev, 1, SCSI_QDEPTH_DEFAULT);
+ ata_scsi_change_queue_depth(sdev, 1);
ata_dev_notice(dev, "Disabling SWNCQ mode (depth %x)\n",
sdev->queue_depth);
}
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index f42ab14105ac..20ca6a619476 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -911,7 +911,7 @@ static struct scsi_host_template iscsi_iser_sht = {
.module = THIS_MODULE,
.name = "iSCSI Initiator over iSER",
.queuecommand = iscsi_queuecommand,
- .change_queue_depth = iscsi_change_queue_depth,
+ .change_queue_depth = scsi_change_queue_depth,
.sg_tablesize = ISCSI_ISER_SG_TABLESIZE,
.max_sectors = 1024,
.cmd_per_lun = ISER_DEF_CMD_PER_LUN,
@@ -922,6 +922,7 @@ static struct scsi_host_template iscsi_iser_sht = {
.use_clustering = DISABLE_CLUSTERING,
.proc_name = "iscsi_iser",
.this_id = -1,
+ .track_queue_depth = 1,
};
static struct iscsi_transport iscsi_iser_transport = {
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 023a66f5ca14..5461924c9f10 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -123,10 +123,15 @@ MODULE_PARM_DESC(dev_loss_tmo,
" if fast_io_fail_tmo has not been set. \"off\" means that"
" this functionality is disabled.");
+static unsigned ch_count;
+module_param(ch_count, uint, 0444);
+MODULE_PARM_DESC(ch_count,
+ "Number of RDMA channels to use for communication with an SRP target. Using more than one channel improves performance if the HCA supports multiple completion vectors. The default value is the minimum of four times the number of online CPU sockets and the number of completion vectors supported by the HCA.");
+
static void srp_add_one(struct ib_device *device);
static void srp_remove_one(struct ib_device *device);
-static void srp_recv_completion(struct ib_cq *cq, void *target_ptr);
-static void srp_send_completion(struct ib_cq *cq, void *target_ptr);
+static void srp_recv_completion(struct ib_cq *cq, void *ch_ptr);
+static void srp_send_completion(struct ib_cq *cq, void *ch_ptr);
static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event);
static struct scsi_transport_template *ib_srp_transport_template;
@@ -262,7 +267,7 @@ static int srp_init_qp(struct srp_target_port *target,
ret = ib_find_pkey(target->srp_host->srp_dev->dev,
target->srp_host->port,
- be16_to_cpu(target->path.pkey),
+ be16_to_cpu(target->pkey),
&attr->pkey_index);
if (ret)
goto out;
@@ -283,18 +288,23 @@ out:
return ret;
}
-static int srp_new_cm_id(struct srp_target_port *target)
+static int srp_new_cm_id(struct srp_rdma_ch *ch)
{
+ struct srp_target_port *target = ch->target;
struct ib_cm_id *new_cm_id;
new_cm_id = ib_create_cm_id(target->srp_host->srp_dev->dev,
- srp_cm_handler, target);
+ srp_cm_handler, ch);
if (IS_ERR(new_cm_id))
return PTR_ERR(new_cm_id);
- if (target->cm_id)
- ib_destroy_cm_id(target->cm_id);
- target->cm_id = new_cm_id;
+ if (ch->cm_id)
+ ib_destroy_cm_id(ch->cm_id);
+ ch->cm_id = new_cm_id;
+ ch->path.sgid = target->sgid;
+ ch->path.dgid = target->orig_dgid;
+ ch->path.pkey = target->pkey;
+ ch->path.service_id = target->service_id;
return 0;
}
@@ -443,8 +453,44 @@ static struct srp_fr_pool *srp_alloc_fr_pool(struct srp_target_port *target)
dev->max_pages_per_mr);
}
-static int srp_create_target_ib(struct srp_target_port *target)
+/**
+ * srp_destroy_qp() - destroy an RDMA queue pair
+ * @ch: SRP RDMA channel.
+ *
+ * Change a queue pair into the error state and wait until all receive
+ * completions have been processed before destroying it. This avoids that
+ * the receive completion handler can access the queue pair while it is
+ * being destroyed.
+ */
+static void srp_destroy_qp(struct srp_rdma_ch *ch)
{
+ struct srp_target_port *target = ch->target;
+ static struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR };
+ static struct ib_recv_wr wr = { .wr_id = SRP_LAST_WR_ID };
+ struct ib_recv_wr *bad_wr;
+ int ret;
+
+ /* Destroying a QP and reusing ch->done is only safe if not connected */
+ WARN_ON_ONCE(target->connected);
+
+ ret = ib_modify_qp(ch->qp, &attr, IB_QP_STATE);
+ WARN_ONCE(ret, "ib_cm_init_qp_attr() returned %d\n", ret);
+ if (ret)
+ goto out;
+
+ init_completion(&ch->done);
+ ret = ib_post_recv(ch->qp, &wr, &bad_wr);
+ WARN_ONCE(ret, "ib_post_recv() returned %d\n", ret);
+ if (ret == 0)
+ wait_for_completion(&ch->done);
+
+out:
+ ib_destroy_qp(ch->qp);
+}
+
+static int srp_create_ch_ib(struct srp_rdma_ch *ch)
+{
+ struct srp_target_port *target = ch->target;
struct srp_device *dev = target->srp_host->srp_dev;
struct ib_qp_init_attr *init_attr;
struct ib_cq *recv_cq, *send_cq;
@@ -458,15 +504,16 @@ static int srp_create_target_ib(struct srp_target_port *target)
if (!init_attr)
return -ENOMEM;
- recv_cq = ib_create_cq(dev->dev, srp_recv_completion, NULL, target,
- target->queue_size, target->comp_vector);
+ /* + 1 for SRP_LAST_WR_ID */
+ recv_cq = ib_create_cq(dev->dev, srp_recv_completion, NULL, ch,
+ target->queue_size + 1, ch->comp_vector);
if (IS_ERR(recv_cq)) {
ret = PTR_ERR(recv_cq);
goto err;
}
- send_cq = ib_create_cq(dev->dev, srp_send_completion, NULL, target,
- m * target->queue_size, target->comp_vector);
+ send_cq = ib_create_cq(dev->dev, srp_send_completion, NULL, ch,
+ m * target->queue_size, ch->comp_vector);
if (IS_ERR(send_cq)) {
ret = PTR_ERR(send_cq);
goto err_recv_cq;
@@ -476,7 +523,7 @@ static int srp_create_target_ib(struct srp_target_port *target)
init_attr->event_handler = srp_qp_event;
init_attr->cap.max_send_wr = m * target->queue_size;
- init_attr->cap.max_recv_wr = target->queue_size;
+ init_attr->cap.max_recv_wr = target->queue_size + 1;
init_attr->cap.max_recv_sge = 1;
init_attr->cap.max_send_sge = 1;
init_attr->sq_sig_type = IB_SIGNAL_REQ_WR;
@@ -502,9 +549,9 @@ static int srp_create_target_ib(struct srp_target_port *target)
"FR pool allocation failed (%d)\n", ret);
goto err_qp;
}
- if (target->fr_pool)
- srp_destroy_fr_pool(target->fr_pool);
- target->fr_pool = fr_pool;
+ if (ch->fr_pool)
+ srp_destroy_fr_pool(ch->fr_pool);
+ ch->fr_pool = fr_pool;
} else if (!dev->use_fast_reg && dev->has_fmr) {
fmr_pool = srp_alloc_fmr_pool(target);
if (IS_ERR(fmr_pool)) {
@@ -513,21 +560,21 @@ static int srp_create_target_ib(struct srp_target_port *target)
"FMR pool allocation failed (%d)\n", ret);
goto err_qp;
}
- if (target->fmr_pool)
- ib_destroy_fmr_pool(target->fmr_pool);
- target->fmr_pool = fmr_pool;
+ if (ch->fmr_pool)
+ ib_destroy_fmr_pool(ch->fmr_pool);
+ ch->fmr_pool = fmr_pool;
}
- if (target->qp)
- ib_destroy_qp(target->qp);
- if (target->recv_cq)
- ib_destroy_cq(target->recv_cq);
- if (target->send_cq)
- ib_destroy_cq(target->send_cq);
+ if (ch->qp)
+ srp_destroy_qp(ch);
+ if (ch->recv_cq)
+ ib_destroy_cq(ch->recv_cq);
+ if (ch->send_cq)
+ ib_destroy_cq(ch->send_cq);
- target->qp = qp;
- target->recv_cq = recv_cq;
- target->send_cq = send_cq;
+ ch->qp = qp;
+ ch->recv_cq = recv_cq;
+ ch->send_cq = send_cq;
kfree(init_attr);
return 0;
@@ -548,93 +595,117 @@ err:
/*
* Note: this function may be called without srp_alloc_iu_bufs() having been
- * invoked. Hence the target->[rt]x_ring checks.
+ * invoked. Hence the ch->[rt]x_ring checks.
*/
-static void srp_free_target_ib(struct srp_target_port *target)
+static void srp_free_ch_ib(struct srp_target_port *target,
+ struct srp_rdma_ch *ch)
{
struct srp_device *dev = target->srp_host->srp_dev;
int i;
+ if (!ch->target)
+ return;
+
+ if (ch->cm_id) {
+ ib_destroy_cm_id(ch->cm_id);
+ ch->cm_id = NULL;
+ }
+
+ /* If srp_new_cm_id() succeeded but srp_create_ch_ib() not, return. */
+ if (!ch->qp)
+ return;
+
if (dev->use_fast_reg) {
- if (target->fr_pool)
- srp_destroy_fr_pool(target->fr_pool);
+ if (ch->fr_pool)
+ srp_destroy_fr_pool(ch->fr_pool);
} else {
- if (target->fmr_pool)
- ib_destroy_fmr_pool(target->fmr_pool);
+ if (ch->fmr_pool)
+ ib_destroy_fmr_pool(ch->fmr_pool);
}
- ib_destroy_qp(target->qp);
- ib_destroy_cq(target->send_cq);
- ib_destroy_cq(target->recv_cq);
+ srp_destroy_qp(ch);
+ ib_destroy_cq(ch->send_cq);
+ ib_destroy_cq(ch->recv_cq);
- target->qp = NULL;
- target->send_cq = target->recv_cq = NULL;
+ /*
+ * Avoid that the SCSI error handler tries to use this channel after
+ * it has been freed. The SCSI error handler can namely continue
+ * trying to perform recovery actions after scsi_remove_host()
+ * returned.
+ */
+ ch->target = NULL;
+
+ ch->qp = NULL;
+ ch->send_cq = ch->recv_cq = NULL;
- if (target->rx_ring) {
+ if (ch->rx_ring) {
for (i = 0; i < target->queue_size; ++i)
- srp_free_iu(target->srp_host, target->rx_ring[i]);
- kfree(target->rx_ring);
- target->rx_ring = NULL;
+ srp_free_iu(target->srp_host, ch->rx_ring[i]);
+ kfree(ch->rx_ring);
+ ch->rx_ring = NULL;
}
- if (target->tx_ring) {
+ if (ch->tx_ring) {
for (i = 0; i < target->queue_size; ++i)
- srp_free_iu(target->srp_host, target->tx_ring[i]);
- kfree(target->tx_ring);
- target->tx_ring = NULL;
+ srp_free_iu(target->srp_host, ch->tx_ring[i]);
+ kfree(ch->tx_ring);
+ ch->tx_ring = NULL;
}
}
static void srp_path_rec_completion(int status,
struct ib_sa_path_rec *pathrec,
- void *target_ptr)
+ void *ch_ptr)
{
- struct srp_target_port *target = target_ptr;
+ struct srp_rdma_ch *ch = ch_ptr;
+ struct srp_target_port *target = ch->target;
- target->status = status;
+ ch->status = status;
if (status)
shost_printk(KERN_ERR, target->scsi_host,
PFX "Got failed path rec status %d\n", status);
else
- target->path = *pathrec;
- complete(&target->done);
+ ch->path = *pathrec;
+ complete(&ch->done);
}
-static int srp_lookup_path(struct srp_target_port *target)
+static int srp_lookup_path(struct srp_rdma_ch *ch)
{
+ struct srp_target_port *target = ch->target;
int ret;
- target->path.numb_path = 1;
-
- init_completion(&target->done);
-
- target->path_query_id = ib_sa_path_rec_get(&srp_sa_client,
- target->srp_host->srp_dev->dev,
- target->srp_host->port,
- &target->path,
- IB_SA_PATH_REC_SERVICE_ID |
- IB_SA_PATH_REC_DGID |
- IB_SA_PATH_REC_SGID |
- IB_SA_PATH_REC_NUMB_PATH |
- IB_SA_PATH_REC_PKEY,
- SRP_PATH_REC_TIMEOUT_MS,
- GFP_KERNEL,
- srp_path_rec_completion,
- target, &target->path_query);
- if (target->path_query_id < 0)
- return target->path_query_id;
-
- ret = wait_for_completion_interruptible(&target->done);
+ ch->path.numb_path = 1;
+
+ init_completion(&ch->done);
+
+ ch->path_query_id = ib_sa_path_rec_get(&srp_sa_client,
+ target->srp_host->srp_dev->dev,
+ target->srp_host->port,
+ &ch->path,
+ IB_SA_PATH_REC_SERVICE_ID |
+ IB_SA_PATH_REC_DGID |
+ IB_SA_PATH_REC_SGID |
+ IB_SA_PATH_REC_NUMB_PATH |
+ IB_SA_PATH_REC_PKEY,
+ SRP_PATH_REC_TIMEOUT_MS,
+ GFP_KERNEL,
+ srp_path_rec_completion,
+ ch, &ch->path_query);
+ if (ch->path_query_id < 0)
+ return ch->path_query_id;
+
+ ret = wait_for_completion_interruptible(&ch->done);
if (ret < 0)
return ret;
- if (target->status < 0)
+ if (ch->status < 0)
shost_printk(KERN_WARNING, target->scsi_host,
PFX "Path record query failed\n");
- return target->status;
+ return ch->status;
}
-static int srp_send_req(struct srp_target_port *target)
+static int srp_send_req(struct srp_rdma_ch *ch, bool multich)
{
+ struct srp_target_port *target = ch->target;
struct {
struct ib_cm_req_param param;
struct srp_login_req priv;
@@ -645,11 +716,11 @@ static int srp_send_req(struct srp_target_port *target)
if (!req)
return -ENOMEM;
- req->param.primary_path = &target->path;
+ req->param.primary_path = &ch->path;
req->param.alternate_path = NULL;
req->param.service_id = target->service_id;
- req->param.qp_num = target->qp->qp_num;
- req->param.qp_type = target->qp->qp_type;
+ req->param.qp_num = ch->qp->qp_num;
+ req->param.qp_type = ch->qp->qp_type;
req->param.private_data = &req->priv;
req->param.private_data_len = sizeof req->priv;
req->param.flow_control = 1;
@@ -673,6 +744,8 @@ static int srp_send_req(struct srp_target_port *target)
req->priv.req_it_iu_len = cpu_to_be32(target->max_iu_len);
req->priv.req_buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT |
SRP_BUF_FORMAT_INDIRECT);
+ req->priv.req_flags = (multich ? SRP_MULTICHAN_MULTI :
+ SRP_MULTICHAN_SINGLE);
/*
* In the published SRP specification (draft rev. 16a), the
* port identifier format is 8 bytes of ID extension followed
@@ -684,7 +757,7 @@ static int srp_send_req(struct srp_target_port *target)
*/
if (target->io_class == SRP_REV10_IB_IO_CLASS) {
memcpy(req->priv.initiator_port_id,
- &target->path.sgid.global.interface_id, 8);
+ &target->sgid.global.interface_id, 8);
memcpy(req->priv.initiator_port_id + 8,
&target->initiator_ext, 8);
memcpy(req->priv.target_port_id, &target->ioc_guid, 8);
@@ -693,7 +766,7 @@ static int srp_send_req(struct srp_target_port *target)
memcpy(req->priv.initiator_port_id,
&target->initiator_ext, 8);
memcpy(req->priv.initiator_port_id + 8,
- &target->path.sgid.global.interface_id, 8);
+ &target->sgid.global.interface_id, 8);
memcpy(req->priv.target_port_id, &target->id_ext, 8);
memcpy(req->priv.target_port_id + 8, &target->ioc_guid, 8);
}
@@ -713,7 +786,7 @@ static int srp_send_req(struct srp_target_port *target)
&target->srp_host->srp_dev->dev->node_guid, 8);
}
- status = ib_send_cm_req(target->cm_id, &req->param);
+ status = ib_send_cm_req(ch->cm_id, &req->param);
kfree(req);
@@ -754,28 +827,35 @@ static bool srp_change_conn_state(struct srp_target_port *target,
static void srp_disconnect_target(struct srp_target_port *target)
{
+ struct srp_rdma_ch *ch;
+ int i;
+
if (srp_change_conn_state(target, false)) {
/* XXX should send SRP_I_LOGOUT request */
- if (ib_send_cm_dreq(target->cm_id, NULL, 0)) {
- shost_printk(KERN_DEBUG, target->scsi_host,
- PFX "Sending CM DREQ failed\n");
+ for (i = 0; i < target->ch_count; i++) {
+ ch = &target->ch[i];
+ if (ch->cm_id && ib_send_cm_dreq(ch->cm_id, NULL, 0)) {
+ shost_printk(KERN_DEBUG, target->scsi_host,
+ PFX "Sending CM DREQ failed\n");
+ }
}
}
}
-static void srp_free_req_data(struct srp_target_port *target)
+static void srp_free_req_data(struct srp_target_port *target,
+ struct srp_rdma_ch *ch)
{
struct srp_device *dev = target->srp_host->srp_dev;
struct ib_device *ibdev = dev->dev;
struct srp_request *req;
int i;
- if (!target->req_ring)
+ if (!ch->target || !ch->req_ring)
return;
for (i = 0; i < target->req_ring_size; ++i) {
- req = &target->req_ring[i];
+ req = &ch->req_ring[i];
if (dev->use_fast_reg)
kfree(req->fr_list);
else
@@ -789,12 +869,13 @@ static void srp_free_req_data(struct srp_target_port *target)
kfree(req->indirect_desc);
}
- kfree(target->req_ring);
- target->req_ring = NULL;
+ kfree(ch->req_ring);
+ ch->req_ring = NULL;
}
-static int srp_alloc_req_data(struct srp_target_port *target)
+static int srp_alloc_req_data(struct srp_rdma_ch *ch)
{
+ struct srp_target_port *target = ch->target;
struct srp_device *srp_dev = target->srp_host->srp_dev;
struct ib_device *ibdev = srp_dev->dev;
struct srp_request *req;
@@ -802,15 +883,13 @@ static int srp_alloc_req_data(struct srp_target_port *target)
dma_addr_t dma_addr;
int i, ret = -ENOMEM;
- INIT_LIST_HEAD(&target->free_reqs);
-
- target->req_ring = kzalloc(target->req_ring_size *
- sizeof(*target->req_ring), GFP_KERNEL);
- if (!target->req_ring)
+ ch->req_ring = kcalloc(target->req_ring_size, sizeof(*ch->req_ring),
+ GFP_KERNEL);
+ if (!ch->req_ring)
goto out;
for (i = 0; i < target->req_ring_size; ++i) {
- req = &target->req_ring[i];
+ req = &ch->req_ring[i];
mr_list = kmalloc(target->cmd_sg_cnt * sizeof(void *),
GFP_KERNEL);
if (!mr_list)
@@ -834,8 +913,6 @@ static int srp_alloc_req_data(struct srp_target_port *target)
goto out;
req->indirect_dma_addr = dma_addr;
- req->index = i;
- list_add_tail(&req->list, &target->free_reqs);
}
ret = 0;
@@ -860,6 +937,9 @@ static void srp_del_scsi_host_attr(struct Scsi_Host *shost)
static void srp_remove_target(struct srp_target_port *target)
{
+ struct srp_rdma_ch *ch;
+ int i;
+
WARN_ON_ONCE(target->state != SRP_TARGET_REMOVED);
srp_del_scsi_host_attr(target->scsi_host);
@@ -868,11 +948,18 @@ static void srp_remove_target(struct srp_target_port *target)
scsi_remove_host(target->scsi_host);
srp_stop_rport_timers(target->rport);
srp_disconnect_target(target);
- ib_destroy_cm_id(target->cm_id);
- srp_free_target_ib(target);
+ for (i = 0; i < target->ch_count; i++) {
+ ch = &target->ch[i];
+ srp_free_ch_ib(target, ch);
+ }
cancel_work_sync(&target->tl_err_work);
srp_rport_put(target->rport);
- srp_free_req_data(target);
+ for (i = 0; i < target->ch_count; i++) {
+ ch = &target->ch[i];
+ srp_free_req_data(target, ch);
+ }
+ kfree(target->ch);
+ target->ch = NULL;
spin_lock(&target->srp_host->target_lock);
list_del(&target->list);
@@ -898,25 +985,25 @@ static void srp_rport_delete(struct srp_rport *rport)
srp_queue_remove_work(target);
}
-static int srp_connect_target(struct srp_target_port *target)
+static int srp_connect_ch(struct srp_rdma_ch *ch, bool multich)
{
- int retries = 3;
+ struct srp_target_port *target = ch->target;
int ret;
- WARN_ON_ONCE(target->connected);
+ WARN_ON_ONCE(!multich && target->connected);
target->qp_in_error = false;
- ret = srp_lookup_path(target);
+ ret = srp_lookup_path(ch);
if (ret)
return ret;
while (1) {
- init_completion(&target->done);
- ret = srp_send_req(target);
+ init_completion(&ch->done);
+ ret = srp_send_req(ch, multich);
if (ret)
return ret;
- ret = wait_for_completion_interruptible(&target->done);
+ ret = wait_for_completion_interruptible(&ch->done);
if (ret < 0)
return ret;
@@ -926,13 +1013,13 @@ static int srp_connect_target(struct srp_target_port *target)
* back, or SRP_DLID_REDIRECT if we get a lid/qp
* redirect REJ back.
*/
- switch (target->status) {
+ switch (ch->status) {
case 0:
srp_change_conn_state(target, true);
return 0;
case SRP_PORT_REDIRECT:
- ret = srp_lookup_path(target);
+ ret = srp_lookup_path(ch);
if (ret)
return ret;
break;
@@ -941,27 +1028,18 @@ static int srp_connect_target(struct srp_target_port *target)
break;
case SRP_STALE_CONN:
- /* Our current CM id was stale, and is now in timewait.
- * Try to reconnect with a new one.
- */
- if (!retries-- || srp_new_cm_id(target)) {
- shost_printk(KERN_ERR, target->scsi_host, PFX
- "giving up on stale connection\n");
- target->status = -ECONNRESET;
- return target->status;
- }
-
shost_printk(KERN_ERR, target->scsi_host, PFX
- "retrying stale connection\n");
- break;
+ "giving up on stale connection\n");
+ ch->status = -ECONNRESET;
+ return ch->status;
default:
- return target->status;
+ return ch->status;
}
}
}
-static int srp_inv_rkey(struct srp_target_port *target, u32 rkey)
+static int srp_inv_rkey(struct srp_rdma_ch *ch, u32 rkey)
{
struct ib_send_wr *bad_wr;
struct ib_send_wr wr = {
@@ -973,13 +1051,14 @@ static int srp_inv_rkey(struct srp_target_port *target, u32 rkey)
.ex.invalidate_rkey = rkey,
};
- return ib_post_send(target->qp, &wr, &bad_wr);
+ return ib_post_send(ch->qp, &wr, &bad_wr);
}
static void srp_unmap_data(struct scsi_cmnd *scmnd,
- struct srp_target_port *target,
+ struct srp_rdma_ch *ch,
struct srp_request *req)
{
+ struct srp_target_port *target = ch->target;
struct srp_device *dev = target->srp_host->srp_dev;
struct ib_device *ibdev = dev->dev;
int i, res;
@@ -993,7 +1072,7 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd,
struct srp_fr_desc **pfr;
for (i = req->nmdesc, pfr = req->fr_list; i > 0; i--, pfr++) {
- res = srp_inv_rkey(target, (*pfr)->mr->rkey);
+ res = srp_inv_rkey(ch, (*pfr)->mr->rkey);
if (res < 0) {
shost_printk(KERN_ERR, target->scsi_host, PFX
"Queueing INV WR for rkey %#x failed (%d)\n",
@@ -1003,7 +1082,7 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd,
}
}
if (req->nmdesc)
- srp_fr_pool_put(target->fr_pool, req->fr_list,
+ srp_fr_pool_put(ch->fr_pool, req->fr_list,
req->nmdesc);
} else {
struct ib_pool_fmr **pfmr;
@@ -1018,7 +1097,7 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd,
/**
* srp_claim_req - Take ownership of the scmnd associated with a request.
- * @target: SRP target port.
+ * @ch: SRP RDMA channel.
* @req: SRP request.
* @sdev: If not NULL, only take ownership for this SCSI device.
* @scmnd: If NULL, take ownership of @req->scmnd. If not NULL, only take
@@ -1027,14 +1106,14 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd,
* Return value:
* Either NULL or a pointer to the SCSI command the caller became owner of.
*/
-static struct scsi_cmnd *srp_claim_req(struct srp_target_port *target,
+static struct scsi_cmnd *srp_claim_req(struct srp_rdma_ch *ch,
struct srp_request *req,
struct scsi_device *sdev,
struct scsi_cmnd *scmnd)
{
unsigned long flags;
- spin_lock_irqsave(&target->lock, flags);
+ spin_lock_irqsave(&ch->lock, flags);
if (req->scmnd &&
(!sdev || req->scmnd->device == sdev) &&
(!scmnd || req->scmnd == scmnd)) {
@@ -1043,40 +1122,37 @@ static struct scsi_cmnd *srp_claim_req(struct srp_target_port *target,
} else {
scmnd = NULL;
}
- spin_unlock_irqrestore(&target->lock, flags);
+ spin_unlock_irqrestore(&ch->lock, flags);
return scmnd;
}
/**
* srp_free_req() - Unmap data and add request to the free request list.
- * @target: SRP target port.
+ * @ch: SRP RDMA channel.
* @req: Request to be freed.
* @scmnd: SCSI command associated with @req.
* @req_lim_delta: Amount to be added to @target->req_lim.
*/
-static void srp_free_req(struct srp_target_port *target,
- struct srp_request *req, struct scsi_cmnd *scmnd,
- s32 req_lim_delta)
+static void srp_free_req(struct srp_rdma_ch *ch, struct srp_request *req,
+ struct scsi_cmnd *scmnd, s32 req_lim_delta)
{
unsigned long flags;
- srp_unmap_data(scmnd, target, req);
+ srp_unmap_data(scmnd, ch, req);
- spin_lock_irqsave(&target->lock, flags);
- target->req_lim += req_lim_delta;
- list_add_tail(&req->list, &target->free_reqs);
- spin_unlock_irqrestore(&target->lock, flags);
+ spin_lock_irqsave(&ch->lock, flags);
+ ch->req_lim += req_lim_delta;
+ spin_unlock_irqrestore(&ch->lock, flags);
}
-static void srp_finish_req(struct srp_target_port *target,
- struct srp_request *req, struct scsi_device *sdev,
- int result)
+static void srp_finish_req(struct srp_rdma_ch *ch, struct srp_request *req,
+ struct scsi_device *sdev, int result)
{
- struct scsi_cmnd *scmnd = srp_claim_req(target, req, sdev, NULL);
+ struct scsi_cmnd *scmnd = srp_claim_req(ch, req, sdev, NULL);
if (scmnd) {
- srp_free_req(target, req, scmnd, 0);
+ srp_free_req(ch, req, scmnd, 0);
scmnd->result = result;
scmnd->scsi_done(scmnd);
}
@@ -1085,9 +1161,10 @@ static void srp_finish_req(struct srp_target_port *target,
static void srp_terminate_io(struct srp_rport *rport)
{
struct srp_target_port *target = rport->lld_data;
+ struct srp_rdma_ch *ch;
struct Scsi_Host *shost = target->scsi_host;
struct scsi_device *sdev;
- int i;
+ int i, j;
/*
* Invoking srp_terminate_io() while srp_queuecommand() is running
@@ -1096,9 +1173,15 @@ static void srp_terminate_io(struct srp_rport *rport)
shost_for_each_device(sdev, shost)
WARN_ON_ONCE(sdev->request_queue->request_fn_active);
- for (i = 0; i < target->req_ring_size; ++i) {
- struct srp_request *req = &target->req_ring[i];
- srp_finish_req(target, req, NULL, DID_TRANSPORT_FAILFAST << 16);
+ for (i = 0; i < target->ch_count; i++) {
+ ch = &target->ch[i];
+
+ for (j = 0; j < target->req_ring_size; ++j) {
+ struct srp_request *req = &ch->req_ring[j];
+
+ srp_finish_req(ch, req, NULL,
+ DID_TRANSPORT_FAILFAST << 16);
+ }
}
}
@@ -1114,34 +1197,61 @@ static void srp_terminate_io(struct srp_rport *rport)
static int srp_rport_reconnect(struct srp_rport *rport)
{
struct srp_target_port *target = rport->lld_data;
- int i, ret;
+ struct srp_rdma_ch *ch;
+ int i, j, ret = 0;
+ bool multich = false;
srp_disconnect_target(target);
+
+ if (target->state == SRP_TARGET_SCANNING)
+ return -ENODEV;
+
/*
* Now get a new local CM ID so that we avoid confusing the target in
* case things are really fouled up. Doing so also ensures that all CM
* callbacks will have finished before a new QP is allocated.
*/
- ret = srp_new_cm_id(target);
-
- for (i = 0; i < target->req_ring_size; ++i) {
- struct srp_request *req = &target->req_ring[i];
- srp_finish_req(target, req, NULL, DID_RESET << 16);
+ for (i = 0; i < target->ch_count; i++) {
+ ch = &target->ch[i];
+ if (!ch->target)
+ break;
+ ret += srp_new_cm_id(ch);
}
+ for (i = 0; i < target->ch_count; i++) {
+ ch = &target->ch[i];
+ if (!ch->target)
+ break;
+ for (j = 0; j < target->req_ring_size; ++j) {
+ struct srp_request *req = &ch->req_ring[j];
- /*
- * Whether or not creating a new CM ID succeeded, create a new
- * QP. This guarantees that all callback functions for the old QP have
- * finished before any send requests are posted on the new QP.
- */
- ret += srp_create_target_ib(target);
-
- INIT_LIST_HEAD(&target->free_tx);
- for (i = 0; i < target->queue_size; ++i)
- list_add(&target->tx_ring[i]->list, &target->free_tx);
+ srp_finish_req(ch, req, NULL, DID_RESET << 16);
+ }
+ }
+ for (i = 0; i < target->ch_count; i++) {
+ ch = &target->ch[i];
+ if (!ch->target)
+ break;
+ /*
+ * Whether or not creating a new CM ID succeeded, create a new
+ * QP. This guarantees that all completion callback function
+ * invocations have finished before request resetting starts.
+ */
+ ret += srp_create_ch_ib(ch);
- if (ret == 0)
- ret = srp_connect_target(target);
+ INIT_LIST_HEAD(&ch->free_tx);
+ for (j = 0; j < target->queue_size; ++j)
+ list_add(&ch->tx_ring[j]->list, &ch->free_tx);
+ }
+ for (i = 0; i < target->ch_count; i++) {
+ ch = &target->ch[i];
+ if (ret || !ch->target) {
+ if (i > 1)
+ ret = 0;
+ break;
+ }
+ ret = srp_connect_ch(ch, multich);
+ multich = true;
+ }
if (ret == 0)
shost_printk(KERN_INFO, target->scsi_host,
@@ -1165,12 +1275,12 @@ static void srp_map_desc(struct srp_map_state *state, dma_addr_t dma_addr,
}
static int srp_map_finish_fmr(struct srp_map_state *state,
- struct srp_target_port *target)
+ struct srp_rdma_ch *ch)
{
struct ib_pool_fmr *fmr;
u64 io_addr = 0;
- fmr = ib_fmr_pool_map_phys(target->fmr_pool, state->pages,
+ fmr = ib_fmr_pool_map_phys(ch->fmr_pool, state->pages,
state->npages, io_addr);
if (IS_ERR(fmr))
return PTR_ERR(fmr);
@@ -1184,15 +1294,16 @@ static int srp_map_finish_fmr(struct srp_map_state *state,
}
static int srp_map_finish_fr(struct srp_map_state *state,
- struct srp_target_port *target)
+ struct srp_rdma_ch *ch)
{
+ struct srp_target_port *target = ch->target;
struct srp_device *dev = target->srp_host->srp_dev;
struct ib_send_wr *bad_wr;
struct ib_send_wr wr;
struct srp_fr_desc *desc;
u32 rkey;
- desc = srp_fr_pool_get(target->fr_pool);
+ desc = srp_fr_pool_get(ch->fr_pool);
if (!desc)
return -ENOMEM;
@@ -1221,12 +1332,13 @@ static int srp_map_finish_fr(struct srp_map_state *state,
srp_map_desc(state, state->base_dma_addr, state->dma_len,
desc->mr->rkey);
- return ib_post_send(target->qp, &wr, &bad_wr);
+ return ib_post_send(ch->qp, &wr, &bad_wr);
}
static int srp_finish_mapping(struct srp_map_state *state,
- struct srp_target_port *target)
+ struct srp_rdma_ch *ch)
{
+ struct srp_target_port *target = ch->target;
int ret = 0;
if (state->npages == 0)
@@ -1237,8 +1349,8 @@ static int srp_finish_mapping(struct srp_map_state *state,
target->rkey);
else
ret = target->srp_host->srp_dev->use_fast_reg ?
- srp_map_finish_fr(state, target) :
- srp_map_finish_fmr(state, target);
+ srp_map_finish_fr(state, ch) :
+ srp_map_finish_fmr(state, ch);
if (ret == 0) {
state->npages = 0;
@@ -1258,10 +1370,11 @@ static void srp_map_update_start(struct srp_map_state *state,
}
static int srp_map_sg_entry(struct srp_map_state *state,
- struct srp_target_port *target,
+ struct srp_rdma_ch *ch,
struct scatterlist *sg, int sg_index,
bool use_mr)
{
+ struct srp_target_port *target = ch->target;
struct srp_device *dev = target->srp_host->srp_dev;
struct ib_device *ibdev = dev->dev;
dma_addr_t dma_addr = ib_sg_dma_address(ibdev, sg);
@@ -1290,7 +1403,7 @@ static int srp_map_sg_entry(struct srp_map_state *state,
*/
if ((!dev->use_fast_reg && dma_addr & ~dev->mr_page_mask) ||
dma_len > dev->mr_max_size) {
- ret = srp_finish_mapping(state, target);
+ ret = srp_finish_mapping(state, ch);
if (ret)
return ret;
@@ -1311,7 +1424,7 @@ static int srp_map_sg_entry(struct srp_map_state *state,
while (dma_len) {
unsigned offset = dma_addr & ~dev->mr_page_mask;
if (state->npages == dev->max_pages_per_mr || offset != 0) {
- ret = srp_finish_mapping(state, target);
+ ret = srp_finish_mapping(state, ch);
if (ret)
return ret;
@@ -1335,17 +1448,18 @@ static int srp_map_sg_entry(struct srp_map_state *state,
*/
ret = 0;
if (len != dev->mr_page_size) {
- ret = srp_finish_mapping(state, target);
+ ret = srp_finish_mapping(state, ch);
if (!ret)
srp_map_update_start(state, NULL, 0, 0);
}
return ret;
}
-static int srp_map_sg(struct srp_map_state *state,
- struct srp_target_port *target, struct srp_request *req,
- struct scatterlist *scat, int count)
+static int srp_map_sg(struct srp_map_state *state, struct srp_rdma_ch *ch,
+ struct srp_request *req, struct scatterlist *scat,
+ int count)
{
+ struct srp_target_port *target = ch->target;
struct srp_device *dev = target->srp_host->srp_dev;
struct ib_device *ibdev = dev->dev;
struct scatterlist *sg;
@@ -1356,14 +1470,14 @@ static int srp_map_sg(struct srp_map_state *state,
state->pages = req->map_page;
if (dev->use_fast_reg) {
state->next_fr = req->fr_list;
- use_mr = !!target->fr_pool;
+ use_mr = !!ch->fr_pool;
} else {
state->next_fmr = req->fmr_list;
- use_mr = !!target->fmr_pool;
+ use_mr = !!ch->fmr_pool;
}
for_each_sg(scat, sg, count, i) {
- if (srp_map_sg_entry(state, target, sg, i, use_mr)) {
+ if (srp_map_sg_entry(state, ch, sg, i, use_mr)) {
/*
* Memory registration failed, so backtrack to the
* first unmapped entry and continue on without using
@@ -1385,7 +1499,7 @@ backtrack:
}
}
- if (use_mr && srp_finish_mapping(state, target))
+ if (use_mr && srp_finish_mapping(state, ch))
goto backtrack;
req->nmdesc = state->nmdesc;
@@ -1393,9 +1507,10 @@ backtrack:
return 0;
}
-static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
+static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
struct srp_request *req)
{
+ struct srp_target_port *target = ch->target;
struct scatterlist *scat;
struct srp_cmd *cmd = req->cmd->buf;
int len, nents, count;
@@ -1457,7 +1572,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
target->indirect_size, DMA_TO_DEVICE);
memset(&state, 0, sizeof(state));
- srp_map_sg(&state, target, req, scat, count);
+ srp_map_sg(&state, ch, req, scat, count);
/* We've mapped the request, now pull as much of the indirect
* descriptor table as we can into the command buffer. If this
@@ -1518,20 +1633,20 @@ map_complete:
/*
* Return an IU and possible credit to the free pool
*/
-static void srp_put_tx_iu(struct srp_target_port *target, struct srp_iu *iu,
+static void srp_put_tx_iu(struct srp_rdma_ch *ch, struct srp_iu *iu,
enum srp_iu_type iu_type)
{
unsigned long flags;
- spin_lock_irqsave(&target->lock, flags);
- list_add(&iu->list, &target->free_tx);
+ spin_lock_irqsave(&ch->lock, flags);
+ list_add(&iu->list, &ch->free_tx);
if (iu_type != SRP_IU_RSP)
- ++target->req_lim;
- spin_unlock_irqrestore(&target->lock, flags);
+ ++ch->req_lim;
+ spin_unlock_irqrestore(&ch->lock, flags);
}
/*
- * Must be called with target->lock held to protect req_lim and free_tx.
+ * Must be called with ch->lock held to protect req_lim and free_tx.
* If IU is not sent, it must be returned using srp_put_tx_iu().
*
* Note:
@@ -1543,35 +1658,36 @@ static void srp_put_tx_iu(struct srp_target_port *target, struct srp_iu *iu,
* - SRP_IU_RSP: 1, since a conforming SRP target never sends more than
* one unanswered SRP request to an initiator.
*/
-static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target,
+static struct srp_iu *__srp_get_tx_iu(struct srp_rdma_ch *ch,
enum srp_iu_type iu_type)
{
+ struct srp_target_port *target = ch->target;
s32 rsv = (iu_type == SRP_IU_TSK_MGMT) ? 0 : SRP_TSK_MGMT_SQ_SIZE;
struct srp_iu *iu;
- srp_send_completion(target->send_cq, target);
+ srp_send_completion(ch->send_cq, ch);
- if (list_empty(&target->free_tx))
+ if (list_empty(&ch->free_tx))
return NULL;
/* Initiator responses to target requests do not consume credits */
if (iu_type != SRP_IU_RSP) {
- if (target->req_lim <= rsv) {
+ if (ch->req_lim <= rsv) {
++target->zero_req_lim;
return NULL;
}
- --target->req_lim;
+ --ch->req_lim;
}
- iu = list_first_entry(&target->free_tx, struct srp_iu, list);
+ iu = list_first_entry(&ch->free_tx, struct srp_iu, list);
list_del(&iu->list);
return iu;
}
-static int srp_post_send(struct srp_target_port *target,
- struct srp_iu *iu, int len)
+static int srp_post_send(struct srp_rdma_ch *ch, struct srp_iu *iu, int len)
{
+ struct srp_target_port *target = ch->target;
struct ib_sge list;
struct ib_send_wr wr, *bad_wr;
@@ -1586,11 +1702,12 @@ static int srp_post_send(struct srp_target_port *target,
wr.opcode = IB_WR_SEND;
wr.send_flags = IB_SEND_SIGNALED;
- return ib_post_send(target->qp, &wr, &bad_wr);
+ return ib_post_send(ch->qp, &wr, &bad_wr);
}
-static int srp_post_recv(struct srp_target_port *target, struct srp_iu *iu)
+static int srp_post_recv(struct srp_rdma_ch *ch, struct srp_iu *iu)
{
+ struct srp_target_port *target = ch->target;
struct ib_recv_wr wr, *bad_wr;
struct ib_sge list;
@@ -1603,35 +1720,39 @@ static int srp_post_recv(struct srp_target_port *target, struct srp_iu *iu)
wr.sg_list = &list;
wr.num_sge = 1;
- return ib_post_recv(target->qp, &wr, &bad_wr);
+ return ib_post_recv(ch->qp, &wr, &bad_wr);
}
-static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
+static void srp_process_rsp(struct srp_rdma_ch *ch, struct srp_rsp *rsp)
{
+ struct srp_target_port *target = ch->target;
struct srp_request *req;
struct scsi_cmnd *scmnd;
unsigned long flags;
if (unlikely(rsp->tag & SRP_TAG_TSK_MGMT)) {
- spin_lock_irqsave(&target->lock, flags);
- target->req_lim += be32_to_cpu(rsp->req_lim_delta);
- spin_unlock_irqrestore(&target->lock, flags);
+ spin_lock_irqsave(&ch->lock, flags);
+ ch->req_lim += be32_to_cpu(rsp->req_lim_delta);
+ spin_unlock_irqrestore(&ch->lock, flags);
- target->tsk_mgmt_status = -1;
+ ch->tsk_mgmt_status = -1;
if (be32_to_cpu(rsp->resp_data_len) >= 4)
- target->tsk_mgmt_status = rsp->data[3];
- complete(&target->tsk_mgmt_done);
+ ch->tsk_mgmt_status = rsp->data[3];
+ complete(&ch->tsk_mgmt_done);
} else {
- req = &target->req_ring[rsp->tag];
- scmnd = srp_claim_req(target, req, NULL, NULL);
+ scmnd = scsi_host_find_tag(target->scsi_host, rsp->tag);
+ if (scmnd) {
+ req = (void *)scmnd->host_scribble;
+ scmnd = srp_claim_req(ch, req, NULL, scmnd);
+ }
if (!scmnd) {
shost_printk(KERN_ERR, target->scsi_host,
- "Null scmnd for RSP w/tag %016llx\n",
- (unsigned long long) rsp->tag);
+ "Null scmnd for RSP w/tag %#016llx received on ch %td / QP %#x\n",
+ rsp->tag, ch - target->ch, ch->qp->qp_num);
- spin_lock_irqsave(&target->lock, flags);
- target->req_lim += be32_to_cpu(rsp->req_lim_delta);
- spin_unlock_irqrestore(&target->lock, flags);
+ spin_lock_irqsave(&ch->lock, flags);
+ ch->req_lim += be32_to_cpu(rsp->req_lim_delta);
+ spin_unlock_irqrestore(&ch->lock, flags);
return;
}
@@ -1653,7 +1774,7 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
else if (unlikely(rsp->flags & SRP_RSP_FLAG_DOOVER))
scsi_set_resid(scmnd, -be32_to_cpu(rsp->data_out_res_cnt));
- srp_free_req(target, req, scmnd,
+ srp_free_req(ch, req, scmnd,
be32_to_cpu(rsp->req_lim_delta));
scmnd->host_scribble = NULL;
@@ -1661,18 +1782,19 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
}
}
-static int srp_response_common(struct srp_target_port *target, s32 req_delta,
+static int srp_response_common(struct srp_rdma_ch *ch, s32 req_delta,
void *rsp, int len)
{
+ struct srp_target_port *target = ch->target;
struct ib_device *dev = target->srp_host->srp_dev->dev;
unsigned long flags;
struct srp_iu *iu;
int err;
- spin_lock_irqsave(&target->lock, flags);
- target->req_lim += req_delta;
- iu = __srp_get_tx_iu(target, SRP_IU_RSP);
- spin_unlock_irqrestore(&target->lock, flags);
+ spin_lock_irqsave(&ch->lock, flags);
+ ch->req_lim += req_delta;
+ iu = __srp_get_tx_iu(ch, SRP_IU_RSP);
+ spin_unlock_irqrestore(&ch->lock, flags);
if (!iu) {
shost_printk(KERN_ERR, target->scsi_host, PFX
@@ -1684,17 +1806,17 @@ static int srp_response_common(struct srp_target_port *target, s32 req_delta,
memcpy(iu->buf, rsp, len);
ib_dma_sync_single_for_device(dev, iu->dma, len, DMA_TO_DEVICE);
- err = srp_post_send(target, iu, len);
+ err = srp_post_send(ch, iu, len);
if (err) {
shost_printk(KERN_ERR, target->scsi_host, PFX
"unable to post response: %d\n", err);
- srp_put_tx_iu(target, iu, SRP_IU_RSP);
+ srp_put_tx_iu(ch, iu, SRP_IU_RSP);
}
return err;
}
-static void srp_process_cred_req(struct srp_target_port *target,
+static void srp_process_cred_req(struct srp_rdma_ch *ch,
struct srp_cred_req *req)
{
struct srp_cred_rsp rsp = {
@@ -1703,14 +1825,15 @@ static void srp_process_cred_req(struct srp_target_port *target,
};
s32 delta = be32_to_cpu(req->req_lim_delta);
- if (srp_response_common(target, delta, &rsp, sizeof rsp))
- shost_printk(KERN_ERR, target->scsi_host, PFX
+ if (srp_response_common(ch, delta, &rsp, sizeof(rsp)))
+ shost_printk(KERN_ERR, ch->target->scsi_host, PFX
"problems processing SRP_CRED_REQ\n");
}
-static void srp_process_aer_req(struct srp_target_port *target,
+static void srp_process_aer_req(struct srp_rdma_ch *ch,
struct srp_aer_req *req)
{
+ struct srp_target_port *target = ch->target;
struct srp_aer_rsp rsp = {
.opcode = SRP_AER_RSP,
.tag = req->tag,
@@ -1720,19 +1843,20 @@ static void srp_process_aer_req(struct srp_target_port *target,
shost_printk(KERN_ERR, target->scsi_host, PFX
"ignoring AER for LUN %llu\n", be64_to_cpu(req->lun));
- if (srp_response_common(target, delta, &rsp, sizeof rsp))
+ if (srp_response_common(ch, delta, &rsp, sizeof(rsp)))
shost_printk(KERN_ERR, target->scsi_host, PFX
"problems processing SRP_AER_REQ\n");
}
-static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
+static void srp_handle_recv(struct srp_rdma_ch *ch, struct ib_wc *wc)
{
+ struct srp_target_port *target = ch->target;
struct ib_device *dev = target->srp_host->srp_dev->dev;
struct srp_iu *iu = (struct srp_iu *) (uintptr_t) wc->wr_id;
int res;
u8 opcode;
- ib_dma_sync_single_for_cpu(dev, iu->dma, target->max_ti_iu_len,
+ ib_dma_sync_single_for_cpu(dev, iu->dma, ch->max_ti_iu_len,
DMA_FROM_DEVICE);
opcode = *(u8 *) iu->buf;
@@ -1746,15 +1870,15 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
switch (opcode) {
case SRP_RSP:
- srp_process_rsp(target, iu->buf);
+ srp_process_rsp(ch, iu->buf);
break;
case SRP_CRED_REQ:
- srp_process_cred_req(target, iu->buf);
+ srp_process_cred_req(ch, iu->buf);
break;
case SRP_AER_REQ:
- srp_process_aer_req(target, iu->buf);
+ srp_process_aer_req(ch, iu->buf);
break;
case SRP_T_LOGOUT:
@@ -1769,10 +1893,10 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
break;
}
- ib_dma_sync_single_for_device(dev, iu->dma, target->max_ti_iu_len,
+ ib_dma_sync_single_for_device(dev, iu->dma, ch->max_ti_iu_len,
DMA_FROM_DEVICE);
- res = srp_post_recv(target, iu);
+ res = srp_post_recv(ch, iu);
if (res != 0)
shost_printk(KERN_ERR, target->scsi_host,
PFX "Recv failed with error code %d\n", res);
@@ -1795,8 +1919,15 @@ static void srp_tl_err_work(struct work_struct *work)
}
static void srp_handle_qp_err(u64 wr_id, enum ib_wc_status wc_status,
- bool send_err, struct srp_target_port *target)
+ bool send_err, struct srp_rdma_ch *ch)
{
+ struct srp_target_port *target = ch->target;
+
+ if (wr_id == SRP_LAST_WR_ID) {
+ complete(&ch->done);
+ return;
+ }
+
if (target->connected && !target->qp_in_error) {
if (wr_id & LOCAL_INV_WR_ID_MASK) {
shost_printk(KERN_ERR, target->scsi_host, PFX
@@ -1817,33 +1948,33 @@ static void srp_handle_qp_err(u64 wr_id, enum ib_wc_status wc_status,
target->qp_in_error = true;
}
-static void srp_recv_completion(struct ib_cq *cq, void *target_ptr)
+static void srp_recv_completion(struct ib_cq *cq, void *ch_ptr)
{
- struct srp_target_port *target = target_ptr;
+ struct srp_rdma_ch *ch = ch_ptr;
struct ib_wc wc;
ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
while (ib_poll_cq(cq, 1, &wc) > 0) {
if (likely(wc.status == IB_WC_SUCCESS)) {
- srp_handle_recv(target, &wc);
+ srp_handle_recv(ch, &wc);
} else {
- srp_handle_qp_err(wc.wr_id, wc.status, false, target);
+ srp_handle_qp_err(wc.wr_id, wc.status, false, ch);
}
}
}
-static void srp_send_completion(struct ib_cq *cq, void *target_ptr)
+static void srp_send_completion(struct ib_cq *cq, void *ch_ptr)
{
- struct srp_target_port *target = target_ptr;
+ struct srp_rdma_ch *ch = ch_ptr;
struct ib_wc wc;
struct srp_iu *iu;
while (ib_poll_cq(cq, 1, &wc) > 0) {
if (likely(wc.status == IB_WC_SUCCESS)) {
iu = (struct srp_iu *) (uintptr_t) wc.wr_id;
- list_add(&iu->list, &target->free_tx);
+ list_add(&iu->list, &ch->free_tx);
} else {
- srp_handle_qp_err(wc.wr_id, wc.status, true, target);
+ srp_handle_qp_err(wc.wr_id, wc.status, true, ch);
}
}
}
@@ -1852,11 +1983,14 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
{
struct srp_target_port *target = host_to_target(shost);
struct srp_rport *rport = target->rport;
+ struct srp_rdma_ch *ch;
struct srp_request *req;
struct srp_iu *iu;
struct srp_cmd *cmd;
struct ib_device *dev;
unsigned long flags;
+ u32 tag;
+ u16 idx;
int len, ret;
const bool in_scsi_eh = !in_interrupt() && current == shost->ehandler;
@@ -1873,15 +2007,22 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
if (unlikely(scmnd->result))
goto err;
- spin_lock_irqsave(&target->lock, flags);
- iu = __srp_get_tx_iu(target, SRP_IU_CMD);
- if (!iu)
- goto err_unlock;
+ WARN_ON_ONCE(scmnd->request->tag < 0);
+ tag = blk_mq_unique_tag(scmnd->request);
+ ch = &target->ch[blk_mq_unique_tag_to_hwq(tag)];
+ idx = blk_mq_unique_tag_to_tag(tag);
+ WARN_ONCE(idx >= target->req_ring_size, "%s: tag %#x: idx %d >= %d\n",
+ dev_name(&shost->shost_gendev), tag, idx,
+ target->req_ring_size);
- req = list_first_entry(&target->free_reqs, struct srp_request, list);
- list_del(&req->list);
- spin_unlock_irqrestore(&target->lock, flags);
+ spin_lock_irqsave(&ch->lock, flags);
+ iu = __srp_get_tx_iu(ch, SRP_IU_CMD);
+ spin_unlock_irqrestore(&ch->lock, flags);
+ if (!iu)
+ goto err;
+
+ req = &ch->req_ring[idx];
dev = target->srp_host->srp_dev->dev;
ib_dma_sync_single_for_cpu(dev, iu->dma, target->max_iu_len,
DMA_TO_DEVICE);
@@ -1893,13 +2034,13 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
cmd->opcode = SRP_CMD;
cmd->lun = cpu_to_be64((u64) scmnd->device->lun << 48);
- cmd->tag = req->index;
+ cmd->tag = tag;
memcpy(cmd->cdb, scmnd->cmnd, scmnd->cmd_len);
req->scmnd = scmnd;
req->cmd = iu;
- len = srp_map_data(scmnd, target, req);
+ len = srp_map_data(scmnd, ch, req);
if (len < 0) {
shost_printk(KERN_ERR, target->scsi_host,
PFX "Failed to map data (%d)\n", len);
@@ -1917,7 +2058,7 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
ib_dma_sync_single_for_device(dev, iu->dma, target->max_iu_len,
DMA_TO_DEVICE);
- if (srp_post_send(target, iu, len)) {
+ if (srp_post_send(ch, iu, len)) {
shost_printk(KERN_ERR, target->scsi_host, PFX "Send failed\n");
goto err_unmap;
}
@@ -1931,10 +2072,10 @@ unlock_rport:
return ret;
err_unmap:
- srp_unmap_data(scmnd, target, req);
+ srp_unmap_data(scmnd, ch, req);
err_iu:
- srp_put_tx_iu(target, iu, SRP_IU_CMD);
+ srp_put_tx_iu(ch, iu, SRP_IU_CMD);
/*
* Avoid that the loops that iterate over the request ring can
@@ -1942,12 +2083,6 @@ err_iu:
*/
req->scmnd = NULL;
- spin_lock_irqsave(&target->lock, flags);
- list_add(&req->list, &target->free_reqs);
-
-err_unlock:
- spin_unlock_irqrestore(&target->lock, flags);
-
err:
if (scmnd->result) {
scmnd->scsi_done(scmnd);
@@ -1961,53 +2096,54 @@ err:
/*
* Note: the resources allocated in this function are freed in
- * srp_free_target_ib().
+ * srp_free_ch_ib().
*/
-static int srp_alloc_iu_bufs(struct srp_target_port *target)
+static int srp_alloc_iu_bufs(struct srp_rdma_ch *ch)
{
+ struct srp_target_port *target = ch->target;
int i;
- target->rx_ring = kzalloc(target->queue_size * sizeof(*target->rx_ring),
- GFP_KERNEL);
- if (!target->rx_ring)
+ ch->rx_ring = kcalloc(target->queue_size, sizeof(*ch->rx_ring),
+ GFP_KERNEL);
+ if (!ch->rx_ring)
goto err_no_ring;
- target->tx_ring = kzalloc(target->queue_size * sizeof(*target->tx_ring),
- GFP_KERNEL);
- if (!target->tx_ring)
+ ch->tx_ring = kcalloc(target->queue_size, sizeof(*ch->tx_ring),
+ GFP_KERNEL);
+ if (!ch->tx_ring)
goto err_no_ring;
for (i = 0; i < target->queue_size; ++i) {
- target->rx_ring[i] = srp_alloc_iu(target->srp_host,
- target->max_ti_iu_len,
- GFP_KERNEL, DMA_FROM_DEVICE);
- if (!target->rx_ring[i])
+ ch->rx_ring[i] = srp_alloc_iu(target->srp_host,
+ ch->max_ti_iu_len,
+ GFP_KERNEL, DMA_FROM_DEVICE);
+ if (!ch->rx_ring[i])
goto err;
}
for (i = 0; i < target->queue_size; ++i) {
- target->tx_ring[i] = srp_alloc_iu(target->srp_host,
- target->max_iu_len,
- GFP_KERNEL, DMA_TO_DEVICE);
- if (!target->tx_ring[i])
+ ch->tx_ring[i] = srp_alloc_iu(target->srp_host,
+ target->max_iu_len,
+ GFP_KERNEL, DMA_TO_DEVICE);
+ if (!ch->tx_ring[i])
goto err;
- list_add(&target->tx_ring[i]->list, &target->free_tx);
+ list_add(&ch->tx_ring[i]->list, &ch->free_tx);
}
return 0;
err:
for (i = 0; i < target->queue_size; ++i) {
- srp_free_iu(target->srp_host, target->rx_ring[i]);
- srp_free_iu(target->srp_host, target->tx_ring[i]);
+ srp_free_iu(target->srp_host, ch->rx_ring[i]);
+ srp_free_iu(target->srp_host, ch->tx_ring[i]);
}
err_no_ring:
- kfree(target->tx_ring);
- target->tx_ring = NULL;
- kfree(target->rx_ring);
- target->rx_ring = NULL;
+ kfree(ch->tx_ring);
+ ch->tx_ring = NULL;
+ kfree(ch->rx_ring);
+ ch->rx_ring = NULL;
return -ENOMEM;
}
@@ -2041,23 +2177,24 @@ static uint32_t srp_compute_rq_tmo(struct ib_qp_attr *qp_attr, int attr_mask)
static void srp_cm_rep_handler(struct ib_cm_id *cm_id,
struct srp_login_rsp *lrsp,
- struct srp_target_port *target)
+ struct srp_rdma_ch *ch)
{
+ struct srp_target_port *target = ch->target;
struct ib_qp_attr *qp_attr = NULL;
int attr_mask = 0;
int ret;
int i;
if (lrsp->opcode == SRP_LOGIN_RSP) {
- target->max_ti_iu_len = be32_to_cpu(lrsp->max_ti_iu_len);
- target->req_lim = be32_to_cpu(lrsp->req_lim_delta);
+ ch->max_ti_iu_len = be32_to_cpu(lrsp->max_ti_iu_len);
+ ch->req_lim = be32_to_cpu(lrsp->req_lim_delta);
/*
* Reserve credits for task management so we don't
* bounce requests back to the SCSI mid-layer.
*/
target->scsi_host->can_queue
- = min(target->req_lim - SRP_TSK_MGMT_SQ_SIZE,
+ = min(ch->req_lim - SRP_TSK_MGMT_SQ_SIZE,
target->scsi_host->can_queue);
target->scsi_host->cmd_per_lun
= min_t(int, target->scsi_host->can_queue,
@@ -2069,8 +2206,8 @@ static void srp_cm_rep_handler(struct ib_cm_id *cm_id,
goto error;
}
- if (!target->rx_ring) {
- ret = srp_alloc_iu_bufs(target);
+ if (!ch->rx_ring) {
+ ret = srp_alloc_iu_bufs(ch);
if (ret)
goto error;
}
@@ -2085,13 +2222,14 @@ static void srp_cm_rep_handler(struct ib_cm_id *cm_id,
if (ret)
goto error_free;
- ret = ib_modify_qp(target->qp, qp_attr, attr_mask);
+ ret = ib_modify_qp(ch->qp, qp_attr, attr_mask);
if (ret)
goto error_free;
for (i = 0; i < target->queue_size; i++) {
- struct srp_iu *iu = target->rx_ring[i];
- ret = srp_post_recv(target, iu);
+ struct srp_iu *iu = ch->rx_ring[i];
+
+ ret = srp_post_recv(ch, iu);
if (ret)
goto error_free;
}
@@ -2103,7 +2241,7 @@ static void srp_cm_rep_handler(struct ib_cm_id *cm_id,
target->rq_tmo_jiffies = srp_compute_rq_tmo(qp_attr, attr_mask);
- ret = ib_modify_qp(target->qp, qp_attr, attr_mask);
+ ret = ib_modify_qp(ch->qp, qp_attr, attr_mask);
if (ret)
goto error_free;
@@ -2113,13 +2251,14 @@ error_free:
kfree(qp_attr);
error:
- target->status = ret;
+ ch->status = ret;
}
static void srp_cm_rej_handler(struct ib_cm_id *cm_id,
struct ib_cm_event *event,
- struct srp_target_port *target)
+ struct srp_rdma_ch *ch)
{
+ struct srp_target_port *target = ch->target;
struct Scsi_Host *shost = target->scsi_host;
struct ib_class_port_info *cpi;
int opcode;
@@ -2127,12 +2266,12 @@ static void srp_cm_rej_handler(struct ib_cm_id *cm_id,
switch (event->param.rej_rcvd.reason) {
case IB_CM_REJ_PORT_CM_REDIRECT:
cpi = event->param.rej_rcvd.ari;
- target->path.dlid = cpi->redirect_lid;
- target->path.pkey = cpi->redirect_pkey;
+ ch->path.dlid = cpi->redirect_lid;
+ ch->path.pkey = cpi->redirect_pkey;
cm_id->remote_cm_qpn = be32_to_cpu(cpi->redirect_qp) & 0x00ffffff;
- memcpy(target->path.dgid.raw, cpi->redirect_gid, 16);
+ memcpy(ch->path.dgid.raw, cpi->redirect_gid, 16);
- target->status = target->path.dlid ?
+ ch->status = ch->path.dlid ?
SRP_DLID_REDIRECT : SRP_PORT_REDIRECT;
break;
@@ -2143,26 +2282,26 @@ static void srp_cm_rej_handler(struct ib_cm_id *cm_id,
* reject reason code 25 when they mean 24
* (port redirect).
*/
- memcpy(target->path.dgid.raw,
+ memcpy(ch->path.dgid.raw,
event->param.rej_rcvd.ari, 16);
shost_printk(KERN_DEBUG, shost,
PFX "Topspin/Cisco redirect to target port GID %016llx%016llx\n",
- (unsigned long long) be64_to_cpu(target->path.dgid.global.subnet_prefix),
- (unsigned long long) be64_to_cpu(target->path.dgid.global.interface_id));
+ be64_to_cpu(ch->path.dgid.global.subnet_prefix),
+ be64_to_cpu(ch->path.dgid.global.interface_id));
- target->status = SRP_PORT_REDIRECT;
+ ch->status = SRP_PORT_REDIRECT;
} else {
shost_printk(KERN_WARNING, shost,
" REJ reason: IB_CM_REJ_PORT_REDIRECT\n");
- target->status = -ECONNRESET;
+ ch->status = -ECONNRESET;
}
break;
case IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID:
shost_printk(KERN_WARNING, shost,
" REJ reason: IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID\n");
- target->status = -ECONNRESET;
+ ch->status = -ECONNRESET;
break;
case IB_CM_REJ_CONSUMER_DEFINED:
@@ -2177,30 +2316,31 @@ static void srp_cm_rej_handler(struct ib_cm_id *cm_id,
else
shost_printk(KERN_WARNING, shost, PFX
"SRP LOGIN from %pI6 to %pI6 REJECTED, reason 0x%08x\n",
- target->path.sgid.raw,
- target->orig_dgid, reason);
+ target->sgid.raw,
+ target->orig_dgid.raw, reason);
} else
shost_printk(KERN_WARNING, shost,
" REJ reason: IB_CM_REJ_CONSUMER_DEFINED,"
" opcode 0x%02x\n", opcode);
- target->status = -ECONNRESET;
+ ch->status = -ECONNRESET;
break;
case IB_CM_REJ_STALE_CONN:
shost_printk(KERN_WARNING, shost, " REJ reason: stale connection\n");
- target->status = SRP_STALE_CONN;
+ ch->status = SRP_STALE_CONN;
break;
default:
shost_printk(KERN_WARNING, shost, " REJ reason 0x%x\n",
event->param.rej_rcvd.reason);
- target->status = -ECONNRESET;
+ ch->status = -ECONNRESET;
}
}
static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
{
- struct srp_target_port *target = cm_id->context;
+ struct srp_rdma_ch *ch = cm_id->context;
+ struct srp_target_port *target = ch->target;
int comp = 0;
switch (event->event) {
@@ -2208,19 +2348,19 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
shost_printk(KERN_DEBUG, target->scsi_host,
PFX "Sending CM REQ failed\n");
comp = 1;
- target->status = -ECONNRESET;
+ ch->status = -ECONNRESET;
break;
case IB_CM_REP_RECEIVED:
comp = 1;
- srp_cm_rep_handler(cm_id, event->private_data, target);
+ srp_cm_rep_handler(cm_id, event->private_data, ch);
break;
case IB_CM_REJ_RECEIVED:
shost_printk(KERN_DEBUG, target->scsi_host, PFX "REJ received\n");
comp = 1;
- srp_cm_rej_handler(cm_id, event, target);
+ srp_cm_rej_handler(cm_id, event, ch);
break;
case IB_CM_DREQ_RECEIVED:
@@ -2238,7 +2378,7 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
PFX "connection closed\n");
comp = 1;
- target->status = 0;
+ ch->status = 0;
break;
case IB_CM_MRA_RECEIVED:
@@ -2253,7 +2393,7 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
}
if (comp)
- complete(&target->done);
+ complete(&ch->done);
return 0;
}
@@ -2262,34 +2402,21 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
* srp_change_queue_depth - setting device queue depth
* @sdev: scsi device struct
* @qdepth: requested queue depth
- * @reason: SCSI_QDEPTH_DEFAULT/SCSI_QDEPTH_QFULL/SCSI_QDEPTH_RAMP_UP
- * (see include/scsi/scsi_host.h for definition)
*
* Returns queue depth.
*/
static int
-srp_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
+srp_change_queue_depth(struct scsi_device *sdev, int qdepth)
{
- struct Scsi_Host *shost = sdev->host;
- int max_depth;
- if (reason == SCSI_QDEPTH_DEFAULT || reason == SCSI_QDEPTH_RAMP_UP) {
- max_depth = shost->can_queue;
- if (!sdev->tagged_supported)
- max_depth = 1;
- if (qdepth > max_depth)
- qdepth = max_depth;
- scsi_adjust_queue_depth(sdev, qdepth);
- } else if (reason == SCSI_QDEPTH_QFULL)
- scsi_track_queue_full(sdev, qdepth);
- else
- return -EOPNOTSUPP;
-
- return sdev->queue_depth;
+ if (!sdev->tagged_supported)
+ qdepth = 1;
+ return scsi_change_queue_depth(sdev, qdepth);
}
-static int srp_send_tsk_mgmt(struct srp_target_port *target,
- u64 req_tag, unsigned int lun, u8 func)
+static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag,
+ unsigned int lun, u8 func)
{
+ struct srp_target_port *target = ch->target;
struct srp_rport *rport = target->rport;
struct ib_device *dev = target->srp_host->srp_dev->dev;
struct srp_iu *iu;
@@ -2298,16 +2425,16 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target,
if (!target->connected || target->qp_in_error)
return -1;
- init_completion(&target->tsk_mgmt_done);
+ init_completion(&ch->tsk_mgmt_done);
/*
- * Lock the rport mutex to avoid that srp_create_target_ib() is
+ * Lock the rport mutex to avoid that srp_create_ch_ib() is
* invoked while a task management function is being sent.
*/
mutex_lock(&rport->mutex);
- spin_lock_irq(&target->lock);
- iu = __srp_get_tx_iu(target, SRP_IU_TSK_MGMT);
- spin_unlock_irq(&target->lock);
+ spin_lock_irq(&ch->lock);
+ iu = __srp_get_tx_iu(ch, SRP_IU_TSK_MGMT);
+ spin_unlock_irq(&ch->lock);
if (!iu) {
mutex_unlock(&rport->mutex);
@@ -2328,15 +2455,15 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target,
ib_dma_sync_single_for_device(dev, iu->dma, sizeof *tsk_mgmt,
DMA_TO_DEVICE);
- if (srp_post_send(target, iu, sizeof *tsk_mgmt)) {
- srp_put_tx_iu(target, iu, SRP_IU_TSK_MGMT);
+ if (srp_post_send(ch, iu, sizeof(*tsk_mgmt))) {
+ srp_put_tx_iu(ch, iu, SRP_IU_TSK_MGMT);
mutex_unlock(&rport->mutex);
return -1;
}
mutex_unlock(&rport->mutex);
- if (!wait_for_completion_timeout(&target->tsk_mgmt_done,
+ if (!wait_for_completion_timeout(&ch->tsk_mgmt_done,
msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS)))
return -1;
@@ -2347,20 +2474,32 @@ static int srp_abort(struct scsi_cmnd *scmnd)
{
struct srp_target_port *target = host_to_target(scmnd->device->host);
struct srp_request *req = (struct srp_request *) scmnd->host_scribble;
+ u32 tag;
+ u16 ch_idx;
+ struct srp_rdma_ch *ch;
int ret;
shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n");
- if (!req || !srp_claim_req(target, req, NULL, scmnd))
+ if (!req)
+ return SUCCESS;
+ tag = blk_mq_unique_tag(scmnd->request);
+ ch_idx = blk_mq_unique_tag_to_hwq(tag);
+ if (WARN_ON_ONCE(ch_idx >= target->ch_count))
return SUCCESS;
- if (srp_send_tsk_mgmt(target, req->index, scmnd->device->lun,
+ ch = &target->ch[ch_idx];
+ if (!srp_claim_req(ch, req, NULL, scmnd))
+ return SUCCESS;
+ shost_printk(KERN_ERR, target->scsi_host,
+ "Sending SRP abort for tag %#x\n", tag);
+ if (srp_send_tsk_mgmt(ch, tag, scmnd->device->lun,
SRP_TSK_ABORT_TASK) == 0)
ret = SUCCESS;
else if (target->rport->state == SRP_RPORT_LOST)
ret = FAST_IO_FAIL;
else
ret = FAILED;
- srp_free_req(target, req, scmnd, 0);
+ srp_free_req(ch, req, scmnd, 0);
scmnd->result = DID_ABORT << 16;
scmnd->scsi_done(scmnd);
@@ -2370,19 +2509,25 @@ static int srp_abort(struct scsi_cmnd *scmnd)
static int srp_reset_device(struct scsi_cmnd *scmnd)
{
struct srp_target_port *target = host_to_target(scmnd->device->host);
+ struct srp_rdma_ch *ch;
int i;
shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n");
- if (srp_send_tsk_mgmt(target, SRP_TAG_NO_REQ, scmnd->device->lun,
+ ch = &target->ch[0];
+ if (srp_send_tsk_mgmt(ch, SRP_TAG_NO_REQ, scmnd->device->lun,
SRP_TSK_LUN_RESET))
return FAILED;
- if (target->tsk_mgmt_status)
+ if (ch->tsk_mgmt_status)
return FAILED;
- for (i = 0; i < target->req_ring_size; ++i) {
- struct srp_request *req = &target->req_ring[i];
- srp_finish_req(target, req, scmnd->device, DID_RESET << 16);
+ for (i = 0; i < target->ch_count; i++) {
+ ch = &target->ch[i];
+ for (i = 0; i < target->req_ring_size; ++i) {
+ struct srp_request *req = &ch->req_ring[i];
+
+ srp_finish_req(ch, req, scmnd->device, DID_RESET << 16);
+ }
}
return SUCCESS;
@@ -2444,7 +2589,7 @@ static ssize_t show_pkey(struct device *dev, struct device_attribute *attr,
{
struct srp_target_port *target = host_to_target(class_to_shost(dev));
- return sprintf(buf, "0x%04x\n", be16_to_cpu(target->path.pkey));
+ return sprintf(buf, "0x%04x\n", be16_to_cpu(target->pkey));
}
static ssize_t show_sgid(struct device *dev, struct device_attribute *attr,
@@ -2452,15 +2597,16 @@ static ssize_t show_sgid(struct device *dev, struct device_attribute *attr,
{
struct srp_target_port *target = host_to_target(class_to_shost(dev));
- return sprintf(buf, "%pI6\n", target->path.sgid.raw);
+ return sprintf(buf, "%pI6\n", target->sgid.raw);
}
static ssize_t show_dgid(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct srp_target_port *target = host_to_target(class_to_shost(dev));
+ struct srp_rdma_ch *ch = &target->ch[0];
- return sprintf(buf, "%pI6\n", target->path.dgid.raw);
+ return sprintf(buf, "%pI6\n", ch->path.dgid.raw);
}
static ssize_t show_orig_dgid(struct device *dev,
@@ -2468,15 +2614,21 @@ static ssize_t show_orig_dgid(struct device *dev,
{
struct srp_target_port *target = host_to_target(class_to_shost(dev));
- return sprintf(buf, "%pI6\n", target->orig_dgid);
+ return sprintf(buf, "%pI6\n", target->orig_dgid.raw);
}
static ssize_t show_req_lim(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct srp_target_port *target = host_to_target(class_to_shost(dev));
+ struct srp_rdma_ch *ch;
+ int i, req_lim = INT_MAX;
- return sprintf(buf, "%d\n", target->req_lim);
+ for (i = 0; i < target->ch_count; i++) {
+ ch = &target->ch[i];
+ req_lim = min(req_lim, ch->req_lim);
+ }
+ return sprintf(buf, "%d\n", req_lim);
}
static ssize_t show_zero_req_lim(struct device *dev,
@@ -2503,6 +2655,14 @@ static ssize_t show_local_ib_device(struct device *dev,
return sprintf(buf, "%s\n", target->srp_host->srp_dev->dev->name);
}
+static ssize_t show_ch_count(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct srp_target_port *target = host_to_target(class_to_shost(dev));
+
+ return sprintf(buf, "%d\n", target->ch_count);
+}
+
static ssize_t show_comp_vector(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -2546,6 +2706,7 @@ static DEVICE_ATTR(req_lim, S_IRUGO, show_req_lim, NULL);
static DEVICE_ATTR(zero_req_lim, S_IRUGO, show_zero_req_lim, NULL);
static DEVICE_ATTR(local_ib_port, S_IRUGO, show_local_ib_port, NULL);
static DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL);
+static DEVICE_ATTR(ch_count, S_IRUGO, show_ch_count, NULL);
static DEVICE_ATTR(comp_vector, S_IRUGO, show_comp_vector, NULL);
static DEVICE_ATTR(tl_retry_count, S_IRUGO, show_tl_retry_count, NULL);
static DEVICE_ATTR(cmd_sg_entries, S_IRUGO, show_cmd_sg_entries, NULL);
@@ -2563,6 +2724,7 @@ static struct device_attribute *srp_host_attrs[] = {
&dev_attr_zero_req_lim,
&dev_attr_local_ib_port,
&dev_attr_local_ib_device,
+ &dev_attr_ch_count,
&dev_attr_comp_vector,
&dev_attr_tl_retry_count,
&dev_attr_cmd_sg_entries,
@@ -2588,14 +2750,28 @@ static struct scsi_host_template srp_template = {
.this_id = -1,
.cmd_per_lun = SRP_DEFAULT_CMD_SQ_SIZE,
.use_clustering = ENABLE_CLUSTERING,
- .shost_attrs = srp_host_attrs
+ .shost_attrs = srp_host_attrs,
+ .use_blk_tags = 1,
+ .track_queue_depth = 1,
};
+static int srp_sdev_count(struct Scsi_Host *host)
+{
+ struct scsi_device *sdev;
+ int c = 0;
+
+ shost_for_each_device(sdev, host)
+ c++;
+
+ return c;
+}
+
static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
{
struct srp_rport_identifiers ids;
struct srp_rport *rport;
+ target->state = SRP_TARGET_SCANNING;
sprintf(target->target_name, "SRP.T10:%016llX",
(unsigned long long) be64_to_cpu(target->id_ext));
@@ -2618,11 +2794,26 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
list_add_tail(&target->list, &host->target_list);
spin_unlock(&host->target_lock);
- target->state = SRP_TARGET_LIVE;
-
scsi_scan_target(&target->scsi_host->shost_gendev,
0, target->scsi_id, SCAN_WILD_CARD, 0);
+ if (!target->connected || target->qp_in_error) {
+ shost_printk(KERN_INFO, target->scsi_host,
+ PFX "SCSI scan failed - removing SCSI host\n");
+ srp_queue_remove_work(target);
+ goto out;
+ }
+
+ pr_debug(PFX "%s: SCSI scan succeeded - detected %d LUNs\n",
+ dev_name(&target->scsi_host->shost_gendev),
+ srp_sdev_count(target->scsi_host));
+
+ spin_lock_irq(&target->lock);
+ if (target->state == SRP_TARGET_SCANNING)
+ target->state = SRP_TARGET_LIVE;
+ spin_unlock_irq(&target->lock);
+
+out:
return 0;
}
@@ -2779,11 +2970,15 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target)
}
for (i = 0; i < 16; ++i) {
- strlcpy(dgid, p + i * 2, 3);
- target->path.dgid.raw[i] = simple_strtoul(dgid, NULL, 16);
+ strlcpy(dgid, p + i * 2, sizeof(dgid));
+ if (sscanf(dgid, "%hhx",
+ &target->orig_dgid.raw[i]) < 1) {
+ ret = -EINVAL;
+ kfree(p);
+ goto out;
+ }
}
kfree(p);
- memcpy(target->orig_dgid, target->path.dgid.raw, 16);
break;
case SRP_OPT_PKEY:
@@ -2791,7 +2986,7 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target)
pr_warn("bad P_Key parameter '%s'\n", p);
goto out;
}
- target->path.pkey = cpu_to_be16(token);
+ target->pkey = cpu_to_be16(token);
break;
case SRP_OPT_SERVICE_ID:
@@ -2801,7 +2996,6 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target)
goto out;
}
target->service_id = cpu_to_be64(simple_strtoull(p, NULL, 16));
- target->path.service_id = target->service_id;
kfree(p);
break;
@@ -2938,9 +3132,11 @@ static ssize_t srp_create_target(struct device *dev,
container_of(dev, struct srp_host, dev);
struct Scsi_Host *target_host;
struct srp_target_port *target;
+ struct srp_rdma_ch *ch;
struct srp_device *srp_dev = host->srp_dev;
struct ib_device *ibdev = srp_dev->dev;
- int ret;
+ int ret, node_idx, node, cpu, i;
+ bool multich = false;
target_host = scsi_host_alloc(&srp_template,
sizeof (struct srp_target_port));
@@ -2966,12 +3162,22 @@ static ssize_t srp_create_target(struct device *dev,
target->tl_retry_count = 7;
target->queue_size = SRP_DEFAULT_QUEUE_SIZE;
+ /*
+ * Avoid that the SCSI host can be removed by srp_remove_target()
+ * before this function returns.
+ */
+ scsi_host_get(target->scsi_host);
+
mutex_lock(&host->add_target_mutex);
ret = srp_parse_options(buf, target);
if (ret)
goto err;
+ ret = scsi_init_shared_tag_map(target_host, target_host->can_queue);
+ if (ret)
+ goto err;
+
target->req_ring_size = target->queue_size - SRP_TSK_MGMT_SQ_SIZE;
if (!srp_conn_unique(target->srp_host, target)) {
@@ -3000,59 +3206,115 @@ static ssize_t srp_create_target(struct device *dev,
INIT_WORK(&target->tl_err_work, srp_tl_err_work);
INIT_WORK(&target->remove_work, srp_remove_work);
spin_lock_init(&target->lock);
- INIT_LIST_HEAD(&target->free_tx);
- ret = srp_alloc_req_data(target);
+ ret = ib_query_gid(ibdev, host->port, 0, &target->sgid);
if (ret)
- goto err_free_mem;
+ goto err;
- ret = ib_query_gid(ibdev, host->port, 0, &target->path.sgid);
- if (ret)
- goto err_free_mem;
+ ret = -ENOMEM;
+ target->ch_count = max_t(unsigned, num_online_nodes(),
+ min(ch_count ? :
+ min(4 * num_online_nodes(),
+ ibdev->num_comp_vectors),
+ num_online_cpus()));
+ target->ch = kcalloc(target->ch_count, sizeof(*target->ch),
+ GFP_KERNEL);
+ if (!target->ch)
+ goto err;
- ret = srp_create_target_ib(target);
- if (ret)
- goto err_free_mem;
+ node_idx = 0;
+ for_each_online_node(node) {
+ const int ch_start = (node_idx * target->ch_count /
+ num_online_nodes());
+ const int ch_end = ((node_idx + 1) * target->ch_count /
+ num_online_nodes());
+ const int cv_start = (node_idx * ibdev->num_comp_vectors /
+ num_online_nodes() + target->comp_vector)
+ % ibdev->num_comp_vectors;
+ const int cv_end = ((node_idx + 1) * ibdev->num_comp_vectors /
+ num_online_nodes() + target->comp_vector)
+ % ibdev->num_comp_vectors;
+ int cpu_idx = 0;
+
+ for_each_online_cpu(cpu) {
+ if (cpu_to_node(cpu) != node)
+ continue;
+ if (ch_start + cpu_idx >= ch_end)
+ continue;
+ ch = &target->ch[ch_start + cpu_idx];
+ ch->target = target;
+ ch->comp_vector = cv_start == cv_end ? cv_start :
+ cv_start + cpu_idx % (cv_end - cv_start);
+ spin_lock_init(&ch->lock);
+ INIT_LIST_HEAD(&ch->free_tx);
+ ret = srp_new_cm_id(ch);
+ if (ret)
+ goto err_disconnect;
- ret = srp_new_cm_id(target);
- if (ret)
- goto err_free_ib;
+ ret = srp_create_ch_ib(ch);
+ if (ret)
+ goto err_disconnect;
- ret = srp_connect_target(target);
- if (ret) {
- shost_printk(KERN_ERR, target->scsi_host,
- PFX "Connection failed\n");
- goto err_cm_id;
+ ret = srp_alloc_req_data(ch);
+ if (ret)
+ goto err_disconnect;
+
+ ret = srp_connect_ch(ch, multich);
+ if (ret) {
+ shost_printk(KERN_ERR, target->scsi_host,
+ PFX "Connection %d/%d failed\n",
+ ch_start + cpu_idx,
+ target->ch_count);
+ if (node_idx == 0 && cpu_idx == 0) {
+ goto err_disconnect;
+ } else {
+ srp_free_ch_ib(target, ch);
+ srp_free_req_data(target, ch);
+ target->ch_count = ch - target->ch;
+ break;
+ }
+ }
+
+ multich = true;
+ cpu_idx++;
+ }
+ node_idx++;
}
+ target->scsi_host->nr_hw_queues = target->ch_count;
+
ret = srp_add_target(host, target);
if (ret)
goto err_disconnect;
- shost_printk(KERN_DEBUG, target->scsi_host, PFX
- "new target: id_ext %016llx ioc_guid %016llx pkey %04x service_id %016llx sgid %pI6 dgid %pI6\n",
- be64_to_cpu(target->id_ext),
- be64_to_cpu(target->ioc_guid),
- be16_to_cpu(target->path.pkey),
- be64_to_cpu(target->service_id),
- target->path.sgid.raw, target->path.dgid.raw);
+ if (target->state != SRP_TARGET_REMOVED) {
+ shost_printk(KERN_DEBUG, target->scsi_host, PFX
+ "new target: id_ext %016llx ioc_guid %016llx pkey %04x service_id %016llx sgid %pI6 dgid %pI6\n",
+ be64_to_cpu(target->id_ext),
+ be64_to_cpu(target->ioc_guid),
+ be16_to_cpu(target->pkey),
+ be64_to_cpu(target->service_id),
+ target->sgid.raw, target->orig_dgid.raw);
+ }
ret = count;
out:
mutex_unlock(&host->add_target_mutex);
+
+ scsi_host_put(target->scsi_host);
+
return ret;
err_disconnect:
srp_disconnect_target(target);
-err_cm_id:
- ib_destroy_cm_id(target->cm_id);
-
-err_free_ib:
- srp_free_target_ib(target);
+ for (i = 0; i < target->ch_count; i++) {
+ ch = &target->ch[i];
+ srp_free_ch_ib(target, ch);
+ srp_free_req_data(target, ch);
+ }
-err_free_mem:
- srp_free_req_data(target);
+ kfree(target->ch);
err:
scsi_host_put(target_host);
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index e46ecb15aa0d..a611556406ac 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -70,9 +70,12 @@ enum {
LOCAL_INV_WR_ID_MASK = 1,
FAST_REG_WR_ID_MASK = 2,
+
+ SRP_LAST_WR_ID = 0xfffffffcU,
};
enum srp_target_state {
+ SRP_TARGET_SCANNING,
SRP_TARGET_LIVE,
SRP_TARGET_REMOVED,
};
@@ -115,7 +118,6 @@ struct srp_host {
};
struct srp_request {
- struct list_head list;
struct scsi_cmnd *scmnd;
struct srp_iu *cmd;
union {
@@ -126,24 +128,62 @@ struct srp_request {
struct srp_direct_buf *indirect_desc;
dma_addr_t indirect_dma_addr;
short nmdesc;
- short index;
};
-struct srp_target_port {
+/**
+ * struct srp_rdma_ch
+ * @comp_vector: Completion vector used by this RDMA channel.
+ */
+struct srp_rdma_ch {
/* These are RW in the hot path, and commonly used together */
struct list_head free_tx;
- struct list_head free_reqs;
spinlock_t lock;
s32 req_lim;
/* These are read-only in the hot path */
- struct ib_cq *send_cq ____cacheline_aligned_in_smp;
+ struct srp_target_port *target ____cacheline_aligned_in_smp;
+ struct ib_cq *send_cq;
struct ib_cq *recv_cq;
struct ib_qp *qp;
union {
struct ib_fmr_pool *fmr_pool;
struct srp_fr_pool *fr_pool;
};
+
+ /* Everything above this point is used in the hot path of
+ * command processing. Try to keep them packed into cachelines.
+ */
+
+ struct completion done;
+ int status;
+
+ struct ib_sa_path_rec path;
+ struct ib_sa_query *path_query;
+ int path_query_id;
+
+ struct ib_cm_id *cm_id;
+ struct srp_iu **tx_ring;
+ struct srp_iu **rx_ring;
+ struct srp_request *req_ring;
+ int max_ti_iu_len;
+ int comp_vector;
+
+ struct completion tsk_mgmt_done;
+ u8 tsk_mgmt_status;
+};
+
+/**
+ * struct srp_target_port
+ * @comp_vector: Completion vector used by the first RDMA channel created for
+ * this target port.
+ */
+struct srp_target_port {
+ /* read and written in the hot path */
+ spinlock_t lock;
+
+ /* read only in the hot path */
+ struct srp_rdma_ch *ch;
+ u32 ch_count;
u32 lkey;
u32 rkey;
enum srp_target_state state;
@@ -152,10 +192,8 @@ struct srp_target_port {
unsigned int indirect_size;
bool allow_ext_sg;
- /* Everything above this point is used in the hot path of
- * command processing. Try to keep them packed into cachelines.
- */
-
+ /* other member variables */
+ union ib_gid sgid;
__be64 id_ext;
__be64 ioc_guid;
__be64 service_id;
@@ -172,34 +210,19 @@ struct srp_target_port {
int comp_vector;
int tl_retry_count;
- struct ib_sa_path_rec path;
- __be16 orig_dgid[8];
- struct ib_sa_query *path_query;
- int path_query_id;
+ union ib_gid orig_dgid;
+ __be16 pkey;
u32 rq_tmo_jiffies;
bool connected;
- struct ib_cm_id *cm_id;
-
- int max_ti_iu_len;
-
int zero_req_lim;
- struct srp_iu **tx_ring;
- struct srp_iu **rx_ring;
- struct srp_request *req_ring;
-
struct work_struct tl_err_work;
struct work_struct remove_work;
struct list_head list;
- struct completion done;
- int status;
bool qp_in_error;
-
- struct completion tsk_mgmt_done;
- u8 tsk_mgmt_status;
};
struct srp_iu {
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index dee06d6f0b68..6c9fc11efb87 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -2311,12 +2311,11 @@ mptscsih_slave_destroy(struct scsi_device *sdev)
* mptscsih_change_queue_depth - This function will set a devices queue depth
* @sdev: per scsi_device pointer
* @qdepth: requested queue depth
- * @reason: calling context
*
* Adding support for new 'change_queue_depth' api.
*/
int
-mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
+mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
{
MPT_SCSI_HOST *hd = shost_priv(sdev->host);
VirtTarget *vtarget;
@@ -2327,9 +2326,6 @@ mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
starget = scsi_target(sdev);
vtarget = starget->hostdata;
- if (reason != SCSI_QDEPTH_DEFAULT)
- return -EOPNOTSUPP;
-
if (ioc->bus_type == SPI) {
if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
max_depth = 1;
@@ -2347,8 +2343,7 @@ mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
if (qdepth > max_depth)
qdepth = max_depth;
- scsi_adjust_queue_depth(sdev, qdepth);
- return sdev->queue_depth;
+ return scsi_change_queue_depth(sdev, qdepth);
}
/*
@@ -2392,8 +2387,7 @@ mptscsih_slave_configure(struct scsi_device *sdev)
ioc->name, vtarget->negoFlags, vtarget->maxOffset,
vtarget->minSyncFactor));
- mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH,
- SCSI_QDEPTH_DEFAULT);
+ mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"tagged %d, simple %d\n",
ioc->name,sdev->tagged_supported, sdev->simple_tags));
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index e1b1a198a62a..2baeefd9be7a 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -128,8 +128,7 @@ extern int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_F
extern int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
-extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth,
- int reason);
+extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id);
extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id);
extern struct device_attribute *mptscsih_host_attrs[];
diff --git a/drivers/misc/eeprom/eeprom_93cx6.c b/drivers/misc/eeprom/eeprom_93cx6.c
index 0ff4b02177be..0cf2c9d676be 100644
--- a/drivers/misc/eeprom/eeprom_93cx6.c
+++ b/drivers/misc/eeprom/eeprom_93cx6.c
@@ -170,7 +170,7 @@ static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom,
}
/**
- * eeprom_93cx6_read - Read multiple words from eeprom
+ * eeprom_93cx6_read - Read a word from eeprom
* @eeprom: Pointer to eeprom structure
* @word: Word index from where we should start reading
* @data: target pointer where the information will have to be stored
@@ -235,6 +235,66 @@ void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word,
EXPORT_SYMBOL_GPL(eeprom_93cx6_multiread);
/**
+ * eeprom_93cx6_readb - Read a byte from eeprom
+ * @eeprom: Pointer to eeprom structure
+ * @word: Byte index from where we should start reading
+ * @data: target pointer where the information will have to be stored
+ *
+ * This function will read a byte of the eeprom data
+ * into the given data pointer.
+ */
+void eeprom_93cx6_readb(struct eeprom_93cx6 *eeprom, const u8 byte,
+ u8 *data)
+{
+ u16 command;
+ u16 tmp;
+
+ /*
+ * Initialize the eeprom register
+ */
+ eeprom_93cx6_startup(eeprom);
+
+ /*
+ * Select the read opcode and the byte to be read.
+ */
+ command = (PCI_EEPROM_READ_OPCODE << (eeprom->width + 1)) | byte;
+ eeprom_93cx6_write_bits(eeprom, command,
+ PCI_EEPROM_WIDTH_OPCODE + eeprom->width + 1);
+
+ /*
+ * Read the requested 8 bits.
+ */
+ eeprom_93cx6_read_bits(eeprom, &tmp, 8);
+ *data = tmp & 0xff;
+
+ /*
+ * Cleanup eeprom register.
+ */
+ eeprom_93cx6_cleanup(eeprom);
+}
+EXPORT_SYMBOL_GPL(eeprom_93cx6_readb);
+
+/**
+ * eeprom_93cx6_multireadb - Read multiple bytes from eeprom
+ * @eeprom: Pointer to eeprom structure
+ * @byte: Index from where we should start reading
+ * @data: target pointer where the information will have to be stored
+ * @words: Number of bytes that should be read.
+ *
+ * This function will read all requested bytes from the eeprom,
+ * this is done by calling eeprom_93cx6_readb() multiple times.
+ */
+void eeprom_93cx6_multireadb(struct eeprom_93cx6 *eeprom, const u8 byte,
+ u8 *data, const u16 bytes)
+{
+ unsigned int i;
+
+ for (i = 0; i < bytes; i++)
+ eeprom_93cx6_readb(eeprom, byte + i, &data[i]);
+}
+EXPORT_SYMBOL_GPL(eeprom_93cx6_multireadb);
+
+/**
* eeprom_93cx6_wren - set the write enable state
* @eeprom: Pointer to eeprom structure
* @enable: true to enable writes, otherwise disable writes
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 8004b071a9f2..01a73395a017 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -353,9 +353,11 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
adapter->ccw_device = ccw_device;
INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler);
- INIT_WORK(&adapter->scan_work, zfcp_fc_scan_ports);
+ INIT_DELAYED_WORK(&adapter->scan_work, zfcp_fc_scan_ports);
INIT_WORK(&adapter->ns_up_work, zfcp_fc_sym_name_update);
+ adapter->next_port_scan = jiffies;
+
if (zfcp_qdio_setup(adapter))
goto failed;
@@ -420,7 +422,7 @@ void zfcp_adapter_unregister(struct zfcp_adapter *adapter)
{
struct ccw_device *cdev = adapter->ccw_device;
- cancel_work_sync(&adapter->scan_work);
+ cancel_delayed_work_sync(&adapter->scan_work);
cancel_work_sync(&adapter->stat_work);
cancel_work_sync(&adapter->ns_up_work);
zfcp_destroy_adapter_work_queue(adapter);
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index f9879d400d0e..54c7b48fdb46 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -56,8 +56,22 @@ static int zfcp_ccw_activate(struct ccw_device *cdev, int clear, char *tag)
zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
tag);
+
+ /*
+ * We want to scan ports here, with some random backoff and without
+ * rate limit. Recovery has already scheduled a port scan for us,
+ * but with both random delay and rate limit. Nevertheless we get
+ * what we want here by flushing the scheduled work after sleeping
+ * an equivalent random time.
+ * Let the port scan random delay elapse first. If recovery finishes
+ * up to that point in time, that would be perfect for both recovery
+ * and port scan. If not, i.e. recovery takes ages, there was no
+ * point in waiting a random delay on top of the time consumed by
+ * recovery.
+ */
+ msleep(zfcp_fc_port_scan_backoff());
zfcp_erp_wait(adapter);
- flush_work(&adapter->scan_work); /* ok to call even if nothing queued */
+ flush_delayed_work(&adapter->scan_work);
zfcp_ccw_adapter_put(adapter);
@@ -162,11 +176,19 @@ static int zfcp_ccw_set_online(struct ccw_device *cdev)
adapter->req_no = 0;
zfcp_ccw_activate(cdev, 0, "ccsonl1");
- /* scan for remote ports
- either at the end of any successful adapter recovery
- or only after the adapter recovery for setting a device online */
+
+ /*
+ * We want to scan ports here, always, with some random delay and
+ * without rate limit - basically what zfcp_ccw_activate() has
+ * achieved for us. Not quite! That port scan depended on
+ * !no_auto_port_rescan. So let's cover the no_auto_port_rescan
+ * case here to make sure a port scan is done unconditionally.
+ * Since zfcp_ccw_activate() has waited the desired random time,
+ * we can immediately schedule and flush a port scan for the
+ * remaining cases.
+ */
zfcp_fc_inverse_conditional_port_scan(adapter);
- flush_work(&adapter->scan_work); /* ok to call even if nothing queued */
+ flush_delayed_work(&adapter->scan_work);
zfcp_ccw_adapter_put(adapter);
return 0;
}
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index d91173f326c5..b8e853e53546 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -186,12 +186,13 @@ struct zfcp_adapter {
struct fc_host_statistics *fc_stats;
struct fsf_qtcb_bottom_port *stats_reset_data;
unsigned long stats_reset;
- struct work_struct scan_work;
+ struct delayed_work scan_work;
struct work_struct ns_up_work;
struct service_level service_level;
struct workqueue_struct *work_queue;
struct device_dma_parameters dma_parms;
struct zfcp_fc_events events;
+ unsigned long next_port_scan;
};
struct zfcp_port {
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index c82fe65c4128..2c5d4567d1da 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -821,11 +821,6 @@ static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *act)
return ZFCP_ERP_CONTINUES;
}
-static void zfcp_erp_port_strategy_clearstati(struct zfcp_port *port)
-{
- atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, &port->status);
-}
-
static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
{
struct zfcp_port *port = erp_action->port;
@@ -833,7 +828,6 @@ static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
switch (erp_action->step) {
case ZFCP_ERP_STEP_UNINITIALIZED:
- zfcp_erp_port_strategy_clearstati(port);
if ((status & ZFCP_STATUS_PORT_PHYS_OPEN) &&
(status & ZFCP_STATUS_COMMON_OPEN))
return zfcp_erp_port_forced_strategy_close(erp_action);
@@ -933,7 +927,6 @@ static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action)
switch (erp_action->step) {
case ZFCP_ERP_STEP_UNINITIALIZED:
- zfcp_erp_port_strategy_clearstati(port);
if (p_status & ZFCP_STATUS_COMMON_OPEN)
return zfcp_erp_port_strategy_close(erp_action);
break;
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index a9c570a09b85..5b500652572b 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -85,6 +85,7 @@ extern void zfcp_fc_gs_destroy(struct zfcp_adapter *);
extern int zfcp_fc_exec_bsg_job(struct fc_bsg_job *);
extern int zfcp_fc_timeout_bsg_job(struct fc_bsg_job *);
extern void zfcp_fc_sym_name_update(struct work_struct *);
+extern unsigned int zfcp_fc_port_scan_backoff(void);
extern void zfcp_fc_conditional_port_scan(struct zfcp_adapter *);
extern void zfcp_fc_inverse_conditional_port_scan(struct zfcp_adapter *);
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index ca28e1c66115..25d49f32ca63 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -12,6 +12,7 @@
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/utsname.h>
+#include <linux/random.h>
#include <scsi/fc/fc_els.h>
#include <scsi/libfc.h>
#include "zfcp_ext.h"
@@ -31,12 +32,54 @@ module_param_named(no_auto_port_rescan, no_auto_port_rescan, bool, 0600);
MODULE_PARM_DESC(no_auto_port_rescan,
"no automatic port_rescan (default off)");
+static unsigned int port_scan_backoff = 500;
+module_param(port_scan_backoff, uint, 0600);
+MODULE_PARM_DESC(port_scan_backoff,
+ "upper limit of port scan random backoff in msecs (default 500)");
+
+static unsigned int port_scan_ratelimit = 60000;
+module_param(port_scan_ratelimit, uint, 0600);
+MODULE_PARM_DESC(port_scan_ratelimit,
+ "minimum interval between port scans in msecs (default 60000)");
+
+unsigned int zfcp_fc_port_scan_backoff(void)
+{
+ if (!port_scan_backoff)
+ return 0;
+ return get_random_int() % port_scan_backoff;
+}
+
+static void zfcp_fc_port_scan_time(struct zfcp_adapter *adapter)
+{
+ unsigned long interval = msecs_to_jiffies(port_scan_ratelimit);
+ unsigned long backoff = msecs_to_jiffies(zfcp_fc_port_scan_backoff());
+
+ adapter->next_port_scan = jiffies + interval + backoff;
+}
+
+static void zfcp_fc_port_scan(struct zfcp_adapter *adapter)
+{
+ unsigned long now = jiffies;
+ unsigned long next = adapter->next_port_scan;
+ unsigned long delay = 0, max;
+
+ /* delay only needed within waiting period */
+ if (time_before(now, next)) {
+ delay = next - now;
+ /* paranoia: never ever delay scans longer than specified */
+ max = msecs_to_jiffies(port_scan_ratelimit + port_scan_backoff);
+ delay = min(delay, max);
+ }
+
+ queue_delayed_work(adapter->work_queue, &adapter->scan_work, delay);
+}
+
void zfcp_fc_conditional_port_scan(struct zfcp_adapter *adapter)
{
if (no_auto_port_rescan)
return;
- queue_work(adapter->work_queue, &adapter->scan_work);
+ zfcp_fc_port_scan(adapter);
}
void zfcp_fc_inverse_conditional_port_scan(struct zfcp_adapter *adapter)
@@ -44,7 +87,7 @@ void zfcp_fc_inverse_conditional_port_scan(struct zfcp_adapter *adapter)
if (!no_auto_port_rescan)
return;
- queue_work(adapter->work_queue, &adapter->scan_work);
+ zfcp_fc_port_scan(adapter);
}
/**
@@ -680,12 +723,15 @@ static int zfcp_fc_eval_gpn_ft(struct zfcp_fc_req *fc_req,
*/
void zfcp_fc_scan_ports(struct work_struct *work)
{
- struct zfcp_adapter *adapter = container_of(work, struct zfcp_adapter,
+ struct delayed_work *dw = to_delayed_work(work);
+ struct zfcp_adapter *adapter = container_of(dw, struct zfcp_adapter,
scan_work);
int ret, i;
struct zfcp_fc_req *fc_req;
int chain, max_entries, buf_num, max_bytes;
+ zfcp_fc_port_scan_time(adapter);
+
chain = adapter->adapter_features & FSF_FEATURE_ELS_CT_CHAINED_SBALS;
buf_num = chain ? ZFCP_FC_GPN_FT_NUM_BUFS : 1;
max_entries = chain ? ZFCP_FC_GPN_FT_MAX_ENT : ZFCP_FC_GPN_FT_ENT_PAGE;
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 0fe8d5d95119..21ec5e2f584c 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -1396,8 +1396,7 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
port->handle = header->port_handle;
atomic_set_mask(ZFCP_STATUS_COMMON_OPEN |
ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
- atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
- ZFCP_STATUS_COMMON_ACCESS_BOXED,
+ atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED,
&port->status);
/* check whether D_ID has changed during open */
/*
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index b5dfa51f396f..75f4bfc2b98a 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -32,25 +32,6 @@ static bool allow_lun_scan = 1;
module_param(allow_lun_scan, bool, 0600);
MODULE_PARM_DESC(allow_lun_scan, "For NPIV, scan and attach all storage LUNs");
-static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth,
- int reason)
-{
- switch (reason) {
- case SCSI_QDEPTH_DEFAULT:
- scsi_adjust_queue_depth(sdev, depth);
- break;
- case SCSI_QDEPTH_QFULL:
- scsi_track_queue_full(sdev, depth);
- break;
- case SCSI_QDEPTH_RAMP_UP:
- scsi_adjust_queue_depth(sdev, depth);
- break;
- default:
- return -EOPNOTSUPP;
- }
- return sdev->queue_depth;
-}
-
static void zfcp_scsi_slave_destroy(struct scsi_device *sdev)
{
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
@@ -66,7 +47,7 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdev)
static int zfcp_scsi_slave_configure(struct scsi_device *sdp)
{
if (sdp->tagged_supported)
- scsi_adjust_queue_depth(sdp, default_depth);
+ scsi_change_queue_depth(sdp, default_depth);
return 0;
}
@@ -305,7 +286,7 @@ static struct scsi_host_template zfcp_scsi_host_template = {
.slave_alloc = zfcp_scsi_slave_alloc,
.slave_configure = zfcp_scsi_slave_configure,
.slave_destroy = zfcp_scsi_slave_destroy,
- .change_queue_depth = zfcp_scsi_change_queue_depth,
+ .change_queue_depth = scsi_change_queue_depth,
.proc_name = "zfcp",
.can_queue = 4096,
.this_id = -1,
@@ -320,6 +301,7 @@ static struct scsi_host_template zfcp_scsi_host_template = {
.use_clustering = 1,
.shost_attrs = zfcp_sysfs_shost_attrs,
.sdev_attrs = zfcp_sysfs_sdev_attrs,
+ .track_queue_depth = 1,
};
/**
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
index 672b57219e11..96a0be13e841 100644
--- a/drivers/s390/scsi/zfcp_sysfs.c
+++ b/drivers/s390/scsi/zfcp_sysfs.c
@@ -73,9 +73,7 @@ ZFCP_DEFINE_ATTR(zfcp_port, port, status, "0x%08x\n",
ZFCP_DEFINE_ATTR(zfcp_port, port, in_recovery, "%d\n",
(atomic_read(&port->status) &
ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
-ZFCP_DEFINE_ATTR(zfcp_port, port, access_denied, "%d\n",
- (atomic_read(&port->status) &
- ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
+ZFCP_DEFINE_ATTR_CONST(port, access_denied, "%d\n", 0);
ZFCP_DEFINE_ATTR(zfcp_unit, unit, status, "0x%08x\n",
zfcp_unit_sdev_status(unit));
@@ -223,9 +221,13 @@ static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev,
if (!adapter)
return -ENODEV;
- /* sync the user-space- with the kernel-invocation of scan_work */
- queue_work(adapter->work_queue, &adapter->scan_work);
- flush_work(&adapter->scan_work);
+ /*
+ * Users wish is our command: immediately schedule and flush a
+ * worker to conduct a synchronous port scan, that is, neither
+ * a random delay nor a rate limit is applied here.
+ */
+ queue_delayed_work(adapter->work_queue, &adapter->scan_work, 0);
+ flush_delayed_work(&adapter->scan_work);
zfcp_ccw_adapter_put(adapter);
return (ssize_t) count;
@@ -439,16 +441,15 @@ static ssize_t zfcp_sysfs_scsi_##_name##_show(struct device *dev, \
{ \
struct scsi_device *sdev = to_scsi_device(dev); \
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); \
- struct zfcp_port *port = zfcp_sdev->port; \
\
return sprintf(buf, _format, _value); \
} \
static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_scsi_##_name##_show, NULL);
ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n",
- dev_name(&port->adapter->ccw_device->dev));
+ dev_name(&zfcp_sdev->port->adapter->ccw_device->dev));
ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n",
- (unsigned long long) port->wwpn);
+ (unsigned long long) zfcp_sdev->port->wwpn);
static ssize_t zfcp_sysfs_scsi_fcp_lun_show(struct device *dev,
struct device_attribute *attr,
@@ -460,6 +461,49 @@ static ssize_t zfcp_sysfs_scsi_fcp_lun_show(struct device *dev,
}
static DEVICE_ATTR(fcp_lun, S_IRUGO, zfcp_sysfs_scsi_fcp_lun_show, NULL);
+ZFCP_DEFINE_SCSI_ATTR(zfcp_access_denied, "%d\n",
+ (atomic_read(&zfcp_sdev->status) &
+ ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
+
+static ssize_t zfcp_sysfs_scsi_zfcp_failed_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ unsigned int status = atomic_read(&sdev_to_zfcp(sdev)->status);
+ unsigned int failed = status & ZFCP_STATUS_COMMON_ERP_FAILED ? 1 : 0;
+
+ return sprintf(buf, "%d\n", failed);
+}
+
+static ssize_t zfcp_sysfs_scsi_zfcp_failed_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ unsigned long val;
+
+ if (kstrtoul(buf, 0, &val) || val != 0)
+ return -EINVAL;
+
+ zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_RUNNING);
+ zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
+ "syufai3");
+ zfcp_erp_wait(sdev_to_zfcp(sdev)->port->adapter);
+
+ return count;
+}
+static DEVICE_ATTR(zfcp_failed, S_IWUSR | S_IRUGO,
+ zfcp_sysfs_scsi_zfcp_failed_show,
+ zfcp_sysfs_scsi_zfcp_failed_store);
+
+ZFCP_DEFINE_SCSI_ATTR(zfcp_in_recovery, "%d\n",
+ (atomic_read(&zfcp_sdev->status) &
+ ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
+
+ZFCP_DEFINE_SCSI_ATTR(zfcp_status, "0x%08x\n",
+ atomic_read(&zfcp_sdev->status));
+
struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
&dev_attr_fcp_lun,
&dev_attr_wwpn,
@@ -467,6 +511,10 @@ struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
&dev_attr_read_latency,
&dev_attr_write_latency,
&dev_attr_cmd_latency,
+ &dev_attr_zfcp_access_denied,
+ &dev_attr_zfcp_failed,
+ &dev_attr_zfcp_in_recovery,
+ &dev_attr_zfcp_status,
NULL
};
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 02021f5ca866..cd4129ff7ae4 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -189,19 +189,6 @@ static ssize_t twa_show_stats(struct device *dev,
return len;
} /* End twa_show_stats() */
-/* This function will set a devices queue depth */
-static int twa_change_queue_depth(struct scsi_device *sdev, int queue_depth,
- int reason)
-{
- if (reason != SCSI_QDEPTH_DEFAULT)
- return -EOPNOTSUPP;
-
- if (queue_depth > TW_Q_LENGTH-2)
- queue_depth = TW_Q_LENGTH-2;
- scsi_adjust_queue_depth(sdev, queue_depth);
- return queue_depth;
-} /* End twa_change_queue_depth() */
-
/* Create sysfs 'stats' entry */
static struct device_attribute twa_host_stats_attr = {
.attr = {
@@ -2016,7 +2003,7 @@ static struct scsi_host_template driver_template = {
.queuecommand = twa_scsi_queue,
.eh_host_reset_handler = twa_scsi_eh_reset,
.bios_param = twa_scsi_biosparam,
- .change_queue_depth = twa_change_queue_depth,
+ .change_queue_depth = scsi_change_queue_depth,
.can_queue = TW_Q_LENGTH-2,
.slave_configure = twa_slave_configure,
.this_id = -1,
diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c
index ac0c2544a470..2361772d5909 100644
--- a/drivers/scsi/3w-sas.c
+++ b/drivers/scsi/3w-sas.c
@@ -191,19 +191,6 @@ static ssize_t twl_show_stats(struct device *dev,
return len;
} /* End twl_show_stats() */
-/* This function will set a devices queue depth */
-static int twl_change_queue_depth(struct scsi_device *sdev, int queue_depth,
- int reason)
-{
- if (reason != SCSI_QDEPTH_DEFAULT)
- return -EOPNOTSUPP;
-
- if (queue_depth > TW_Q_LENGTH-2)
- queue_depth = TW_Q_LENGTH-2;
- scsi_adjust_queue_depth(sdev, queue_depth);
- return queue_depth;
-} /* End twl_change_queue_depth() */
-
/* stats sysfs attribute initializer */
static struct device_attribute twl_host_stats_attr = {
.attr = {
@@ -1590,7 +1577,7 @@ static struct scsi_host_template driver_template = {
.queuecommand = twl_scsi_queue,
.eh_host_reset_handler = twl_scsi_eh_reset,
.bios_param = twl_scsi_biosparam,
- .change_queue_depth = twl_change_queue_depth,
+ .change_queue_depth = scsi_change_queue_depth,
.can_queue = TW_Q_LENGTH-2,
.slave_configure = twl_slave_configure,
.this_id = -1,
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 1ec9ad92b6c3..c75f2048319f 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -523,19 +523,6 @@ static ssize_t tw_show_stats(struct device *dev, struct device_attribute *attr,
return len;
} /* End tw_show_stats() */
-/* This function will set a devices queue depth */
-static int tw_change_queue_depth(struct scsi_device *sdev, int queue_depth,
- int reason)
-{
- if (reason != SCSI_QDEPTH_DEFAULT)
- return -EOPNOTSUPP;
-
- if (queue_depth > TW_Q_LENGTH-2)
- queue_depth = TW_Q_LENGTH-2;
- scsi_adjust_queue_depth(sdev, queue_depth);
- return queue_depth;
-} /* End tw_change_queue_depth() */
-
/* Create sysfs 'stats' entry */
static struct device_attribute tw_host_stats_attr = {
.attr = {
@@ -2270,7 +2257,7 @@ static struct scsi_host_template driver_template = {
.queuecommand = tw_scsi_queue,
.eh_host_reset_handler = tw_scsi_eh_reset,
.bios_param = tw_scsi_biosparam,
- .change_queue_depth = tw_change_queue_depth,
+ .change_queue_depth = scsi_change_queue_depth,
.can_queue = TW_Q_LENGTH-2,
.slave_configure = tw_slave_configure,
.this_id = -1,
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index d7557b932113..aa915da2a5e5 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -175,7 +175,7 @@ STATIC void NCR_700_chip_reset(struct Scsi_Host *host);
STATIC int NCR_700_slave_alloc(struct scsi_device *SDpnt);
STATIC int NCR_700_slave_configure(struct scsi_device *SDpnt);
STATIC void NCR_700_slave_destroy(struct scsi_device *SDpnt);
-static int NCR_700_change_queue_depth(struct scsi_device *SDpnt, int depth, int reason);
+static int NCR_700_change_queue_depth(struct scsi_device *SDpnt, int depth);
static int NCR_700_change_queue_type(struct scsi_device *SDpnt, int depth);
STATIC struct device_attribute *NCR_700_dev_attrs[];
@@ -904,7 +904,7 @@ process_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata
hostdata->tag_negotiated &= ~(1<<scmd_id(SCp));
SCp->device->tagged_supported = 0;
- scsi_adjust_queue_depth(SCp->device, host->cmd_per_lun);
+ scsi_change_queue_depth(SCp->device, host->cmd_per_lun);
scsi_set_tag_type(SCp->device, 0);
} else {
shost_printk(KERN_WARNING, host,
@@ -2052,7 +2052,7 @@ NCR_700_slave_configure(struct scsi_device *SDp)
/* to do here: allocate memory; build a queue_full list */
if(SDp->tagged_supported) {
- scsi_adjust_queue_depth(SDp, NCR_700_DEFAULT_TAGS);
+ scsi_change_queue_depth(SDp, NCR_700_DEFAULT_TAGS);
NCR_700_set_tag_neg_state(SDp, NCR_700_START_TAG_NEGOTIATION);
}
@@ -2075,16 +2075,11 @@ NCR_700_slave_destroy(struct scsi_device *SDp)
}
static int
-NCR_700_change_queue_depth(struct scsi_device *SDp, int depth, int reason)
+NCR_700_change_queue_depth(struct scsi_device *SDp, int depth)
{
- if (reason != SCSI_QDEPTH_DEFAULT)
- return -EOPNOTSUPP;
-
if (depth > NCR_700_MAX_TAGS)
depth = NCR_700_MAX_TAGS;
-
- scsi_adjust_queue_depth(SDp, depth);
- return depth;
+ return scsi_change_queue_depth(SDp, depth);
}
static int NCR_700_change_queue_type(struct scsi_device *SDp, int tag_type)
@@ -2105,12 +2100,12 @@ static int NCR_700_change_queue_type(struct scsi_device *SDp, int tag_type)
if (!tag_type) {
/* shift back to the default unqueued number of commands
* (the user can still raise this) */
- scsi_adjust_queue_depth(SDp, SDp->host->cmd_per_lun);
+ scsi_change_queue_depth(SDp, SDp->host->cmd_per_lun);
hostdata->tag_negotiated &= ~(1 << sdev_id(SDp));
} else {
/* Here, we cleared the negotiation flag above, so this
* will force the driver to renegotiate */
- scsi_adjust_queue_depth(SDp, SDp->queue_depth);
+ scsi_change_queue_depth(SDp, SDp->queue_depth);
if (change_tag)
NCR_700_set_tag_neg_state(SDp, NCR_700_START_TAG_NEGOTIATION);
}
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index 5aa476b6b8a8..8d66a6469e29 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -2327,12 +2327,12 @@ static int blogic_slaveconfig(struct scsi_device *dev)
if (qdepth == 0)
qdepth = BLOGIC_MAX_AUTO_TAG_DEPTH;
adapter->qdepth[tgt_id] = qdepth;
- scsi_adjust_queue_depth(dev, qdepth);
+ scsi_change_queue_depth(dev, qdepth);
} else {
adapter->tagq_ok &= ~(1 << tgt_id);
qdepth = adapter->untag_qdepth;
adapter->qdepth[tgt_id] = qdepth;
- scsi_adjust_queue_depth(dev, qdepth);
+ scsi_change_queue_depth(dev, qdepth);
}
qdepth = 0;
for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 3a820f61ce65..86cf3d671eb9 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1341,13 +1341,15 @@ config SCSI_DC395x
To compile this driver as a module, choose M here: the
module will be called dc395x.
-config SCSI_DC390T
- tristate "Tekram DC390(T) and Am53/79C974 SCSI support"
+config SCSI_AM53C974
+ tristate "Tekram DC390(T) and Am53/79C974 SCSI support (new driver)"
depends on PCI && SCSI
+ select SCSI_SPI_ATTRS
---help---
This driver supports PCI SCSI host adapters based on the Am53C974A
chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard
PCscsi/PCnet (Am53/79C974) solutions.
+ This is a new implementation base on the generic esp_scsi driver.
Documentation can be found in <file:Documentation/scsi/tmscsim.txt>.
@@ -1355,7 +1357,7 @@ config SCSI_DC390T
based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those.
To compile this driver as a module, choose M here: the
- module will be called tmscsim.
+ module will be called am53c974.
config SCSI_T128
tristate "Trantor T128/T128F/T228 SCSI support"
@@ -1451,6 +1453,14 @@ config SCSI_NSP32
To compile this driver as a module, choose M here: the
module will be called nsp32.
+config SCSI_WD719X
+ tristate "Western Digital WD7193/7197/7296 support"
+ depends on PCI && SCSI
+ select EEPROM_93CX6
+ ---help---
+ This is a driver for Western Digital WD7193, WD7197 and WD7296 PCI
+ SCSI controllers (based on WD33C296A chip).
+
config SCSI_DEBUG
tristate "SCSI debugging host simulator"
depends on SCSI
@@ -1615,7 +1625,7 @@ config ATARI_SCSI_RESET_BOOT
that leave the devices with SCSI operations partway completed.
config MAC_SCSI
- bool "Macintosh NCR5380 SCSI"
+ tristate "Macintosh NCR5380 SCSI"
depends on MAC && SCSI=y
select SCSI_SPI_ATTRS
help
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 59f1ce6df2d6..58158f11ed7b 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -100,7 +100,7 @@ obj-$(CONFIG_SCSI_EATA_PIO) += eata_pio.o
obj-$(CONFIG_SCSI_7000FASST) += wd7000.o
obj-$(CONFIG_SCSI_EATA) += eata.o
obj-$(CONFIG_SCSI_DC395x) += dc395x.o
-obj-$(CONFIG_SCSI_DC390T) += tmscsim.o
+obj-$(CONFIG_SCSI_AM53C974) += esp_scsi.o am53c974.o
obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o
obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/
obj-$(CONFIG_MEGARAID_SAS) += megaraid/
@@ -143,6 +143,7 @@ obj-$(CONFIG_SCSI_VIRTIO) += virtio_scsi.o
obj-$(CONFIG_VMWARE_PVSCSI) += vmw_pvscsi.o
obj-$(CONFIG_XEN_SCSI_FRONTEND) += xen-scsifront.o
obj-$(CONFIG_HYPERV_STORAGE) += hv_storvsc.o
+obj-$(CONFIG_SCSI_WD719X) += wd719x.o
obj-$(CONFIG_ARM) += arm/
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index 296c6f53605a..36244d63def2 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -11,8 +11,6 @@
* drew@colorado.edu
* +1 (303) 666-5836
*
- * DISTRIBUTION RELEASE 6.
- *
* For more information, please consult
*
* NCR 5380 Family
@@ -279,7 +277,7 @@ static void do_reset(struct Scsi_Host *host);
* Set up the internal fields in the SCSI command.
*/
-static __inline__ void initialize_SCp(Scsi_Cmnd * cmd)
+static inline void initialize_SCp(struct scsi_cmnd *cmd)
{
/*
* Initialize the Scsi Pointer field so that all of the commands in the
@@ -574,12 +572,12 @@ static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance,
int trying_irqs, i, mask;
NCR5380_setup(instance);
- for (trying_irqs = i = 0, mask = 1; i < 16; ++i, mask <<= 1)
+ for (trying_irqs = 0, i = 1, mask = 2; i < 16; ++i, mask <<= 1)
if ((mask & possible) && (request_irq(i, &probe_intr, 0, "NCR-probe", NULL) == 0))
trying_irqs |= mask;
timeout = jiffies + (250 * HZ / 1000);
- probe_irq = SCSI_IRQ_NONE;
+ probe_irq = NO_IRQ;
/*
* A interrupt is triggered whenever BSY = false, SEL = true
@@ -596,13 +594,13 @@ static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance,
NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL);
- while (probe_irq == SCSI_IRQ_NONE && time_before(jiffies, timeout))
+ while (probe_irq == NO_IRQ && time_before(jiffies, timeout))
schedule_timeout_uninterruptible(1);
NCR5380_write(SELECT_ENABLE_REG, 0);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- for (i = 0, mask = 1; i < 16; ++i, mask <<= 1)
+ for (i = 1, mask = 2; i < 16; ++i, mask <<= 1)
if (trying_irqs & mask)
free_irq(i, NULL);
@@ -610,50 +608,70 @@ static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance,
}
/**
- * NCR58380_print_options - show options
- * @instance: unused for now
+ * NCR58380_info - report driver and host information
+ * @instance: relevant scsi host instance
*
- * Called by probe code indicating the NCR5380 driver options that
- * were selected. At some point this will switch to runtime options
- * read from the adapter in question
+ * For use as the host template info() handler.
*
* Locks: none
*/
-static void __init __maybe_unused
-NCR5380_print_options(struct Scsi_Host *instance)
+static const char *NCR5380_info(struct Scsi_Host *instance)
{
- printk(" generic options"
-#ifdef AUTOPROBE_IRQ
- " AUTOPROBE_IRQ"
+ struct NCR5380_hostdata *hostdata = shost_priv(instance);
+
+ return hostdata->info;
+}
+
+static void prepare_info(struct Scsi_Host *instance)
+{
+ struct NCR5380_hostdata *hostdata = shost_priv(instance);
+
+ snprintf(hostdata->info, sizeof(hostdata->info),
+ "%s, io_port 0x%lx, n_io_port %d, "
+ "base 0x%lx, irq %d, "
+ "can_queue %d, cmd_per_lun %d, "
+ "sg_tablesize %d, this_id %d, "
+ "flags { %s%s%s}, "
+#if defined(USLEEP_POLL) && defined(USLEEP_WAITLONG)
+ "USLEEP_POLL %d, USLEEP_WAITLONG %d, "
+#endif
+ "options { %s} ",
+ instance->hostt->name, instance->io_port, instance->n_io_port,
+ instance->base, instance->irq,
+ instance->can_queue, instance->cmd_per_lun,
+ instance->sg_tablesize, instance->this_id,
+ hostdata->flags & FLAG_NCR53C400 ? "NCR53C400 " : "",
+ hostdata->flags & FLAG_DTC3181E ? "DTC3181E " : "",
+ hostdata->flags & FLAG_NO_PSEUDO_DMA ? "NO_PSEUDO_DMA " : "",
+#if defined(USLEEP_POLL) && defined(USLEEP_WAITLONG)
+ USLEEP_POLL, USLEEP_WAITLONG,
#endif
-#ifdef AUTOSENSE
- " AUTOSENSE"
+#ifdef AUTOPROBE_IRQ
+ "AUTOPROBE_IRQ "
#endif
#ifdef DIFFERENTIAL
- " DIFFERENTIAL"
+ "DIFFERENTIAL "
#endif
#ifdef REAL_DMA
- " REAL DMA"
+ "REAL_DMA "
#endif
#ifdef REAL_DMA_POLL
- " REAL DMA POLL"
+ "REAL_DMA_POLL "
#endif
#ifdef PARITY
- " PARITY"
+ "PARITY "
#endif
#ifdef PSEUDO_DMA
- " PSEUDO DMA"
+ "PSEUDO_DMA "
#endif
#ifdef UNSAFE
- " UNSAFE "
+ "UNSAFE "
#endif
- );
- printk(" USLEEP, USLEEP_POLL=%d USLEEP_SLEEP=%d", USLEEP_POLL, USLEEP_SLEEP);
- printk(" generic release=%d", NCR5380_PUBLIC_RELEASE);
- if (((struct NCR5380_hostdata *) instance->hostdata)->flags & FLAG_NCR53C400) {
- printk(" ncr53c400 release=%d", NCR53C400_PUBLIC_RELEASE);
- }
+#ifdef NCR53C400
+ "NCR53C400 "
+#endif
+ "");
}
/**
@@ -672,6 +690,7 @@ static void NCR5380_print_status(struct Scsi_Host *instance)
NCR5380_dprint_phase(NDEBUG_ANY, instance);
}
+#ifdef PSEUDO_DMA
/******************************************/
/*
* /proc/scsi/[dtc pas16 t128 generic]/[0-ASC_NUM_BOARD_SUPPORTED]
@@ -689,19 +708,18 @@ static void NCR5380_print_status(struct Scsi_Host *instance)
static int __maybe_unused NCR5380_write_info(struct Scsi_Host *instance,
char *buffer, int length)
{
-#ifdef DTC_PUBLIC_RELEASE
- dtc_wmaxi = dtc_maxi = 0;
-#endif
-#ifdef PAS16_PUBLIC_RELEASE
- pas_wmaxi = pas_maxi = 0;
-#endif
- return (-ENOSYS); /* Currently this is a no-op */
+ struct NCR5380_hostdata *hostdata = shost_priv(instance);
+
+ hostdata->spin_max_r = 0;
+ hostdata->spin_max_w = 0;
+ return 0;
}
+#endif
#undef SPRINTF
#define SPRINTF(args...) seq_printf(m, ## args)
static
-void lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, struct seq_file *m);
+void lprint_Scsi_Cmnd(struct scsi_cmnd *cmd, struct seq_file *m);
static
void lprint_command(unsigned char *cmd, struct seq_file *m);
static
@@ -711,56 +729,31 @@ static int __maybe_unused NCR5380_show_info(struct seq_file *m,
struct Scsi_Host *instance)
{
struct NCR5380_hostdata *hostdata;
- Scsi_Cmnd *ptr;
+ struct scsi_cmnd *ptr;
hostdata = (struct NCR5380_hostdata *) instance->hostdata;
- SPRINTF("NCR5380 core release=%d. ", NCR5380_PUBLIC_RELEASE);
- if (((struct NCR5380_hostdata *) instance->hostdata)->flags & FLAG_NCR53C400)
- SPRINTF("ncr53c400 release=%d. ", NCR53C400_PUBLIC_RELEASE);
-#ifdef DTC_PUBLIC_RELEASE
- SPRINTF("DTC 3180/3280 release %d", DTC_PUBLIC_RELEASE);
-#endif
-#ifdef T128_PUBLIC_RELEASE
- SPRINTF("T128 release %d", T128_PUBLIC_RELEASE);
-#endif
-#ifdef GENERIC_NCR5380_PUBLIC_RELEASE
- SPRINTF("Generic5380 release %d", GENERIC_NCR5380_PUBLIC_RELEASE);
-#endif
-#ifdef PAS16_PUBLIC_RELEASE
- SPRINTF("PAS16 release=%d", PAS16_PUBLIC_RELEASE);
-#endif
-
- SPRINTF("\nBase Addr: 0x%05lX ", (long) instance->base);
- SPRINTF("io_port: %04x ", (int) instance->io_port);
- if (instance->irq == SCSI_IRQ_NONE)
- SPRINTF("IRQ: None.\n");
- else
- SPRINTF("IRQ: %d.\n", instance->irq);
-
-#ifdef DTC_PUBLIC_RELEASE
- SPRINTF("Highwater I/O busy_spin_counts -- write: %d read: %d\n", dtc_wmaxi, dtc_maxi);
-#endif
-#ifdef PAS16_PUBLIC_RELEASE
- SPRINTF("Highwater I/O busy_spin_counts -- write: %d read: %d\n", pas_wmaxi, pas_maxi);
+#ifdef PSEUDO_DMA
+ SPRINTF("Highwater I/O busy spin counts: write %d, read %d\n",
+ hostdata->spin_max_w, hostdata->spin_max_r);
#endif
spin_lock_irq(instance->host_lock);
if (!hostdata->connected)
SPRINTF("scsi%d: no currently connected command\n", instance->host_no);
else
- lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected, m);
+ lprint_Scsi_Cmnd((struct scsi_cmnd *) hostdata->connected, m);
SPRINTF("scsi%d: issue_queue\n", instance->host_no);
- for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
+ for (ptr = (struct scsi_cmnd *) hostdata->issue_queue; ptr; ptr = (struct scsi_cmnd *) ptr->host_scribble)
lprint_Scsi_Cmnd(ptr, m);
SPRINTF("scsi%d: disconnected_queue\n", instance->host_no);
- for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
+ for (ptr = (struct scsi_cmnd *) hostdata->disconnected_queue; ptr; ptr = (struct scsi_cmnd *) ptr->host_scribble)
lprint_Scsi_Cmnd(ptr, m);
spin_unlock_irq(instance->host_lock);
return 0;
}
-static void lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, struct seq_file *m)
+static void lprint_Scsi_Cmnd(struct scsi_cmnd *cmd, struct seq_file *m)
{
SPRINTF("scsi%d : destination target %d, lun %llu\n", cmd->device->host->host_no, cmd->device->id, cmd->device->lun);
SPRINTF(" command = ");
@@ -836,18 +829,6 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags)
INIT_DELAYED_WORK(&hostdata->coroutine, NCR5380_main);
-#ifdef NCR5380_STATS
- for (i = 0; i < 8; ++i) {
- hostdata->time_read[i] = 0;
- hostdata->time_write[i] = 0;
- hostdata->bytes_read[i] = 0;
- hostdata->bytes_write[i] = 0;
- }
- hostdata->timebase = 0;
- hostdata->pendingw = 0;
- hostdata->pendingr = 0;
-#endif
-
/* The CHECK code seems to break the 53C400. Will check it later maybe */
if (flags & FLAG_NCR53C400)
hostdata->flags = FLAG_HAS_LAST_BYTE_SENT | flags;
@@ -857,11 +838,7 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags)
hostdata->host = instance;
hostdata->time_expires = 0;
-#ifndef AUTOSENSE
- if ((instance->cmd_per_lun > 1) || instance->can_queue > 1)
- printk(KERN_WARNING "scsi%d : WARNING : support for multiple outstanding commands enabled\n" " without AUTOSENSE option, contingent allegiance conditions may\n"
- " be incorrectly cleared.\n", instance->host_no);
-#endif /* def AUTOSENSE */
+ prepare_info(instance);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
NCR5380_write(MODE_REG, MR_BASE);
@@ -935,11 +912,11 @@ static void NCR5380_exit(struct Scsi_Host *instance)
* Locks: host lock taken by caller
*/
-static int NCR5380_queue_command_lck(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
+static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd, void (*done) (struct scsi_cmnd *))
{
struct Scsi_Host *instance = cmd->device->host;
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
- Scsi_Cmnd *tmp;
+ struct scsi_cmnd *tmp;
#if (NDEBUG & NDEBUG_NO_WRITE)
switch (cmd->cmnd[0]) {
@@ -952,25 +929,6 @@ static int NCR5380_queue_command_lck(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)
}
#endif /* (NDEBUG & NDEBUG_NO_WRITE) */
-#ifdef NCR5380_STATS
- switch (cmd->cmnd[0]) {
- case WRITE:
- case WRITE_6:
- case WRITE_10:
- hostdata->time_write[cmd->device->id] -= (jiffies - hostdata->timebase);
- hostdata->bytes_write[cmd->device->id] += scsi_bufflen(cmd);
- hostdata->pendingw++;
- break;
- case READ:
- case READ_6:
- case READ_10:
- hostdata->time_read[cmd->device->id] -= (jiffies - hostdata->timebase);
- hostdata->bytes_read[cmd->device->id] += scsi_bufflen(cmd);
- hostdata->pendingr++;
- break;
- }
-#endif
-
/*
* We use the host_scribble field as a pointer to the next command
* in a queue
@@ -992,7 +950,7 @@ static int NCR5380_queue_command_lck(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)
cmd->host_scribble = (unsigned char *) hostdata->issue_queue;
hostdata->issue_queue = cmd;
} else {
- for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp->host_scribble; tmp = (Scsi_Cmnd *) tmp->host_scribble);
+ for (tmp = (struct scsi_cmnd *) hostdata->issue_queue; tmp->host_scribble; tmp = (struct scsi_cmnd *) tmp->host_scribble);
LIST(cmd, tmp);
tmp->host_scribble = (unsigned char *) cmd;
}
@@ -1023,7 +981,7 @@ static void NCR5380_main(struct work_struct *work)
struct NCR5380_hostdata *hostdata =
container_of(work, struct NCR5380_hostdata, coroutine.work);
struct Scsi_Host *instance = hostdata->host;
- Scsi_Cmnd *tmp, *prev;
+ struct scsi_cmnd *tmp, *prev;
int done;
spin_lock_irq(instance->host_lock);
@@ -1036,7 +994,7 @@ static void NCR5380_main(struct work_struct *work)
* Search through the issue_queue for a command destined
* for a target that's not busy.
*/
- for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble)
+ for (tmp = (struct scsi_cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = (struct scsi_cmnd *) tmp->host_scribble)
{
if (prev != tmp)
dprintk(NDEBUG_LISTS, "MAIN tmp=%p target=%d busy=%d lun=%llu\n", tmp, tmp->device->id, hostdata->busy[tmp->device->id], tmp->device->lun);
@@ -1048,7 +1006,7 @@ static void NCR5380_main(struct work_struct *work)
prev->host_scribble = tmp->host_scribble;
} else {
REMOVE(-1, hostdata->issue_queue, tmp, tmp->host_scribble);
- hostdata->issue_queue = (Scsi_Cmnd *) tmp->host_scribble;
+ hostdata->issue_queue = (struct scsi_cmnd *) tmp->host_scribble;
}
tmp->host_scribble = NULL;
@@ -1073,14 +1031,14 @@ static void NCR5380_main(struct work_struct *work)
hostdata->selecting = NULL;
/* RvC: have to preset this to indicate a new command is being performed */
- if (!NCR5380_select(instance, tmp,
- /*
- * REQUEST SENSE commands are issued without tagged
- * queueing, even on SCSI-II devices because the
- * contingent allegiance condition exists for the
- * entire unit.
- */
- (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : TAG_NEXT)) {
+ /*
+ * REQUEST SENSE commands are issued without tagged
+ * queueing, even on SCSI-II devices because the
+ * contingent allegiance condition exists for the
+ * entire unit.
+ */
+
+ if (!NCR5380_select(instance, tmp)) {
break;
} else {
LIST(tmp, hostdata->issue_queue);
@@ -1095,9 +1053,9 @@ static void NCR5380_main(struct work_struct *work)
/* exited locked */
} /* if (!hostdata->connected) */
if (hostdata->selecting) {
- tmp = (Scsi_Cmnd *) hostdata->selecting;
+ tmp = (struct scsi_cmnd *) hostdata->selecting;
/* Selection will drop and retake the lock */
- if (!NCR5380_select(instance, tmp, (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : TAG_NEXT)) {
+ if (!NCR5380_select(instance, tmp)) {
/* Ok ?? */
} else {
/* RvC: device failed, so we wait a long time
@@ -1216,47 +1174,16 @@ static irqreturn_t NCR5380_intr(int dummy, void *dev_id)
#endif
-/**
- * collect_stats - collect stats on a scsi command
- * @hostdata: adapter
- * @cmd: command being issued
- *
- * Update the statistical data by parsing the command in question
- */
-
-static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd)
-{
-#ifdef NCR5380_STATS
- switch (cmd->cmnd[0]) {
- case WRITE:
- case WRITE_6:
- case WRITE_10:
- hostdata->time_write[scmd_id(cmd)] += (jiffies - hostdata->timebase);
- hostdata->pendingw--;
- break;
- case READ:
- case READ_6:
- case READ_10:
- hostdata->time_read[scmd_id(cmd)] += (jiffies - hostdata->timebase);
- hostdata->pendingr--;
- break;
- }
-#endif
-}
-
-
/*
- * Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd,
- * int tag);
+ * Function : int NCR5380_select(struct Scsi_Host *instance,
+ * struct scsi_cmnd *cmd)
*
* Purpose : establishes I_T_L or I_T_L_Q nexus for new or existing command,
* including ARBITRATION, SELECTION, and initial message out for
* IDENTIFY and queue messages.
*
* Inputs : instance - instantiation of the 5380 driver on which this
- * target lives, cmd - SCSI command to execute, tag - set to TAG_NEXT for
- * new tag, TAG_NONE for untagged queueing, otherwise set to the tag for
- * the command that is presently connected.
+ * target lives, cmd - SCSI command to execute.
*
* Returns : -1 if selection could not execute for some reason,
* 0 if selection succeeded or failed because the target
@@ -1278,7 +1205,7 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd)
* Locks: caller holds hostdata lock in IRQ mode
*/
-static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
+static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
{
NCR5380_local_declare();
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
@@ -1476,7 +1403,6 @@ part2:
return -1;
}
cmd->result = DID_BAD_TARGET << 16;
- collect_stats(hostdata, cmd);
cmd->scsi_done(cmd);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
dprintk(NDEBUG_SELECTION, "scsi%d : target did not respond within 250ms\n", instance->host_no);
@@ -1513,7 +1439,7 @@ part2:
}
dprintk(NDEBUG_SELECTION, "scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->device->id);
- tmp[0] = IDENTIFY(((instance->irq == SCSI_IRQ_NONE) ? 0 : 1), cmd->device->lun);
+ tmp[0] = IDENTIFY(((instance->irq == NO_IRQ) ? 0 : 1), cmd->device->lun);
len = 1;
cmd->tag = 0;
@@ -2086,7 +2012,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
#endif
unsigned char *data;
unsigned char phase, tmp, extended_msg[10], old_phase = 0xff;
- Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected;
+ struct scsi_cmnd *cmd = (struct scsi_cmnd *) hostdata->connected;
/* RvC: we need to set the end of the polling time */
unsigned long poll_time = jiffies + USLEEP_POLL;
@@ -2228,7 +2154,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
cmd->next_link->tag = cmd->tag;
cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
dprintk(NDEBUG_LINKED, "scsi%d : target %d lun %llu linked request done, calling scsi_done().\n", instance->host_no, cmd->device->id, cmd->device->lun);
- collect_stats(hostdata, cmd);
cmd->scsi_done(cmd);
cmd = hostdata->connected;
break;
@@ -2263,7 +2188,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
else if (status_byte(cmd->SCp.Status) != GOOD)
cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
-#ifdef AUTOSENSE
if ((cmd->cmnd[0] == REQUEST_SENSE) &&
hostdata->ses.cmd_len) {
scsi_eh_restore_cmnd(cmd, &hostdata->ses);
@@ -2278,12 +2202,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
LIST(cmd, hostdata->issue_queue);
cmd->host_scribble = (unsigned char *)
hostdata->issue_queue;
- hostdata->issue_queue = (Scsi_Cmnd *) cmd;
+ hostdata->issue_queue = (struct scsi_cmnd *) cmd;
dprintk(NDEBUG_QUEUES, "scsi%d : REQUEST SENSE added to head of issue queue\n", instance->host_no);
- } else
-#endif /* def AUTOSENSE */
- {
- collect_stats(hostdata, cmd);
+ } else {
cmd->scsi_done(cmd);
}
@@ -2430,7 +2351,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xFF));
hostdata->connected = NULL;
cmd->result = DID_ERROR << 16;
- collect_stats(hostdata, cmd);
cmd->scsi_done(cmd);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
return;
@@ -2479,7 +2399,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
* Function : void NCR5380_reselect (struct Scsi_Host *instance)
*
* Purpose : does reselection, initializing the instance->connected
- * field to point to the Scsi_Cmnd for which the I_T_L or I_T_L_Q
+ * field to point to the scsi_cmnd for which the I_T_L or I_T_L_Q
* nexus has been reestablished,
*
* Inputs : instance - this instance of the NCR5380.
@@ -2496,7 +2416,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
int len;
unsigned char msg[3];
unsigned char *data;
- Scsi_Cmnd *tmp = NULL, *prev;
+ struct scsi_cmnd *tmp = NULL, *prev;
int abort = 0;
NCR5380_setup(instance);
@@ -2562,7 +2482,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
*/
- for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble)
+ for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue, prev = NULL; tmp; prev = tmp, tmp = (struct scsi_cmnd *) tmp->host_scribble)
if ((target_mask == (1 << tmp->device->id)) && (lun == (u8)tmp->device->lun)
) {
if (prev) {
@@ -2570,7 +2490,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
prev->host_scribble = tmp->host_scribble;
} else {
REMOVE(-1, hostdata->disconnected_queue, tmp, tmp->host_scribble);
- hostdata->disconnected_queue = (Scsi_Cmnd *) tmp->host_scribble;
+ hostdata->disconnected_queue = (struct scsi_cmnd *) tmp->host_scribble;
}
tmp->host_scribble = NULL;
break;
@@ -2601,7 +2521,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
*
* Inputs : instance - this instance of the NCR5380.
*
- * Returns : pointer to the Scsi_Cmnd structure for which the I_T_L
+ * Returns : pointer to the scsi_cmnd structure for which the I_T_L
* nexus has been reestablished, on failure NULL is returned.
*/
@@ -2643,11 +2563,11 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) {
#endif /* def REAL_DMA */
/*
- * Function : int NCR5380_abort (Scsi_Cmnd *cmd)
+ * Function : int NCR5380_abort (struct scsi_cmnd *cmd)
*
* Purpose : abort a command
*
- * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the
+ * Inputs : cmd - the scsi_cmnd to abort, code - code to set the
* host byte of the result field to, if zero DID_ABORTED is
* used.
*
@@ -2661,11 +2581,12 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) {
* Locks: host lock taken by caller
*/
-static int NCR5380_abort(Scsi_Cmnd * cmd) {
+static int NCR5380_abort(struct scsi_cmnd *cmd)
+{
NCR5380_local_declare();
struct Scsi_Host *instance = cmd->device->host;
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
- Scsi_Cmnd *tmp, **prev;
+ struct scsi_cmnd *tmp, **prev;
scmd_printk(KERN_WARNING, cmd, "aborting command\n");
@@ -2713,10 +2634,10 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) {
*/
dprintk(NDEBUG_ABORT, "scsi%d : abort going into loop.\n", instance->host_no);
- for (prev = (Scsi_Cmnd **) & (hostdata->issue_queue), tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp; prev = (Scsi_Cmnd **) & (tmp->host_scribble), tmp = (Scsi_Cmnd *) tmp->host_scribble)
+ for (prev = (struct scsi_cmnd **) &(hostdata->issue_queue), tmp = (struct scsi_cmnd *) hostdata->issue_queue; tmp; prev = (struct scsi_cmnd **) &(tmp->host_scribble), tmp = (struct scsi_cmnd *) tmp->host_scribble)
if (cmd == tmp) {
REMOVE(5, *prev, tmp, tmp->host_scribble);
- (*prev) = (Scsi_Cmnd *) tmp->host_scribble;
+ (*prev) = (struct scsi_cmnd *) tmp->host_scribble;
tmp->host_scribble = NULL;
tmp->result = DID_ABORT << 16;
dprintk(NDEBUG_ABORT, "scsi%d : abort removed command from issue queue.\n", instance->host_no);
@@ -2769,20 +2690,20 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) {
* it from the disconnected queue.
*/
- for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp; tmp = (Scsi_Cmnd *) tmp->host_scribble)
+ for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue; tmp; tmp = (struct scsi_cmnd *) tmp->host_scribble)
if (cmd == tmp) {
dprintk(NDEBUG_ABORT, "scsi%d : aborting disconnected command.\n", instance->host_no);
- if (NCR5380_select(instance, cmd, (int) cmd->tag))
+ if (NCR5380_select(instance, cmd))
return FAILED;
dprintk(NDEBUG_ABORT, "scsi%d : nexus reestablished.\n", instance->host_no);
do_abort(instance);
- for (prev = (Scsi_Cmnd **) & (hostdata->disconnected_queue), tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp; prev = (Scsi_Cmnd **) & (tmp->host_scribble), tmp = (Scsi_Cmnd *) tmp->host_scribble)
+ for (prev = (struct scsi_cmnd **) &(hostdata->disconnected_queue), tmp = (struct scsi_cmnd *) hostdata->disconnected_queue; tmp; prev = (struct scsi_cmnd **) &(tmp->host_scribble), tmp = (struct scsi_cmnd *) tmp->host_scribble)
if (cmd == tmp) {
REMOVE(5, *prev, tmp, tmp->host_scribble);
- *prev = (Scsi_Cmnd *) tmp->host_scribble;
+ *prev = (struct scsi_cmnd *) tmp->host_scribble;
tmp->host_scribble = NULL;
tmp->result = DID_ABORT << 16;
tmp->scsi_done(tmp);
@@ -2805,7 +2726,7 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) {
/*
- * Function : int NCR5380_bus_reset (Scsi_Cmnd *cmd)
+ * Function : int NCR5380_bus_reset (struct scsi_cmnd *cmd)
*
* Purpose : reset the SCSI bus.
*
@@ -2814,7 +2735,7 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) {
* Locks: host lock taken by caller
*/
-static int NCR5380_bus_reset(Scsi_Cmnd * cmd)
+static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
{
struct Scsi_Host *instance = cmd->device->host;
diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
index c79ddfa6f53c..162112dd1bf8 100644
--- a/drivers/scsi/NCR5380.h
+++ b/drivers/scsi/NCR5380.h
@@ -7,8 +7,6 @@
* drew@colorado.edu
* +1 (303) 666-5836
*
- * DISTRIBUTION RELEASE 7
- *
* For more information, please consult
*
* NCR 5380 Family
@@ -25,13 +23,7 @@
#define NCR5380_H
#include <linux/interrupt.h>
-
-#ifdef AUTOSENSE
#include <scsi/scsi_eh.h>
-#endif
-
-#define NCR5380_PUBLIC_RELEASE 7
-#define NCR53C400_PUBLIC_RELEASE 2
#define NDEBUG_ARBITRATION 0x1
#define NDEBUG_AUTOSENSE 0x2
@@ -224,33 +216,44 @@
#define DISCONNECT_LONG 2
/*
- * These are "special" values for the tag parameter passed to NCR5380_select.
+ * "Special" value for the (unsigned char) command tag, to indicate
+ * I_T_L nexus instead of I_T_L_Q.
*/
-#define TAG_NEXT -1 /* Use next free tag */
-#define TAG_NONE -2 /*
- * Establish I_T_L nexus instead of I_T_L_Q
- * even on SCSI-II devices.
- */
+#define TAG_NONE 0xff
/*
* These are "special" values for the irq and dma_channel fields of the
* Scsi_Host structure
*/
-#define SCSI_IRQ_NONE 255
#define DMA_NONE 255
#define IRQ_AUTO 254
#define DMA_AUTO 254
#define PORT_AUTO 0xffff /* autoprobe io port for 53c400a */
+#ifndef NO_IRQ
+#define NO_IRQ 0
+#endif
+
#define FLAG_HAS_LAST_BYTE_SENT 1 /* NCR53c81 or better */
#define FLAG_CHECK_LAST_BYTE_SENT 2 /* Only test once */
#define FLAG_NCR53C400 4 /* NCR53c400 */
#define FLAG_NO_PSEUDO_DMA 8 /* Inhibit DMA */
#define FLAG_DTC3181E 16 /* DTC3181E */
+#define FLAG_LATE_DMA_SETUP 32 /* Setup NCR before DMA H/W */
+#define FLAG_TAGGED_QUEUING 64 /* as X3T9.2 spelled it */
#ifndef ASM
+
+#ifdef SUPPORT_TAGS
+struct tag_alloc {
+ DECLARE_BITMAP(allocated, MAX_TAGS);
+ int nr_allocated;
+ int queue_size;
+};
+#endif
+
struct NCR5380_hostdata {
NCR5380_implementation_fields; /* implementation specific */
struct Scsi_Host *host; /* Host backpointer */
@@ -263,9 +266,9 @@ struct NCR5380_hostdata {
volatile int dma_len; /* requested length of DMA */
#endif
volatile unsigned char last_message; /* last message OUT */
- volatile Scsi_Cmnd *connected; /* currently connected command */
- volatile Scsi_Cmnd *issue_queue; /* waiting to be issued */
- volatile Scsi_Cmnd *disconnected_queue; /* waiting for reconnect */
+ volatile struct scsi_cmnd *connected; /* currently connected command */
+ volatile struct scsi_cmnd *issue_queue; /* waiting to be issued */
+ volatile struct scsi_cmnd *disconnected_queue; /* waiting for reconnect */
volatile int restart_select; /* we have disconnected,
used to restart
NCR5380_select() */
@@ -273,19 +276,21 @@ struct NCR5380_hostdata {
int flags;
unsigned long time_expires; /* in jiffies, set prior to sleeping */
int select_time; /* timer in select for target response */
- volatile Scsi_Cmnd *selecting;
+ volatile struct scsi_cmnd *selecting;
struct delayed_work coroutine; /* our co-routine */
-#ifdef NCR5380_STATS
- unsigned timebase; /* Base for time calcs */
- long time_read[8]; /* time to do reads */
- long time_write[8]; /* time to do writes */
- unsigned long bytes_read[8]; /* bytes read */
- unsigned long bytes_write[8]; /* bytes written */
- unsigned pendingr;
- unsigned pendingw;
-#endif
-#ifdef AUTOSENSE
struct scsi_eh_save ses;
+ char info[256];
+ int read_overruns; /* number of bytes to cut from a
+ * transfer to handle chip overruns */
+ int retain_dma_intr;
+ struct work_struct main_task;
+ volatile int main_running;
+#ifdef SUPPORT_TAGS
+ struct tag_alloc TagAlloc[8][8]; /* 8 targets and 8 LUNs */
+#endif
+#ifdef PSEUDO_DMA
+ unsigned spin_max_r;
+ unsigned spin_max_w;
#endif
};
@@ -296,7 +301,8 @@ struct NCR5380_hostdata {
#endif
#define dprintk(flg, fmt, ...) \
- do { if ((NDEBUG) & (flg)) pr_debug(fmt, ## __VA_ARGS__); } while (0)
+ do { if ((NDEBUG) & (flg)) \
+ printk(KERN_DEBUG fmt, ## __VA_ARGS__); } while (0)
#if NDEBUG
#define NCR5380_dprint(flg, arg) \
@@ -320,17 +326,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance);
static irqreturn_t NCR5380_intr(int irq, void *dev_id);
#endif
static void NCR5380_main(struct work_struct *work);
-static void __maybe_unused NCR5380_print_options(struct Scsi_Host *instance);
-static int NCR5380_abort(Scsi_Cmnd * cmd);
-static int NCR5380_bus_reset(Scsi_Cmnd * cmd);
-static int NCR5380_queue_command(struct Scsi_Host *, struct scsi_cmnd *);
-static int __maybe_unused NCR5380_show_info(struct seq_file *,
- struct Scsi_Host *);
-static int __maybe_unused NCR5380_write_info(struct Scsi_Host *instance,
- char *buffer, int length);
-
+static const char *NCR5380_info(struct Scsi_Host *instance);
static void NCR5380_reselect(struct Scsi_Host *instance);
-static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag);
+static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd);
#if defined(PSEUDO_DMA) || defined(REAL_DMA) || defined(REAL_DMA_POLL)
static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data);
#endif
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 4c340d88c33d..fdcdf9f781bc 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -462,9 +462,9 @@ static int aac_slave_configure(struct scsi_device *sdev)
depth = 256;
else if (depth < 2)
depth = 2;
- scsi_adjust_queue_depth(sdev, depth);
+ scsi_change_queue_depth(sdev, depth);
} else
- scsi_adjust_queue_depth(sdev, 1);
+ scsi_change_queue_depth(sdev, 1);
return 0;
}
@@ -478,12 +478,8 @@ static int aac_slave_configure(struct scsi_device *sdev)
* total capacity and the queue depth supported by the target device.
*/
-static int aac_change_queue_depth(struct scsi_device *sdev, int depth,
- int reason)
+static int aac_change_queue_depth(struct scsi_device *sdev, int depth)
{
- if (reason != SCSI_QDEPTH_DEFAULT)
- return -EOPNOTSUPP;
-
if (sdev->tagged_supported && (sdev->type == TYPE_DISK) &&
(sdev_channel(sdev) == CONTAINER_CHANNEL)) {
struct scsi_device * dev;
@@ -504,10 +500,10 @@ static int aac_change_queue_depth(struct scsi_device *sdev, int depth,
depth = 256;
else if (depth < 2)
depth = 2;
- scsi_adjust_queue_depth(sdev, depth);
- } else
- scsi_adjust_queue_depth(sdev, 1);
- return sdev->queue_depth;
+ return scsi_change_queue_depth(sdev, depth);
+ }
+
+ return scsi_change_queue_depth(sdev, 1);
}
static ssize_t aac_show_raid_level(struct device *dev, struct device_attribute *attr, char *buf)
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index ae4840e4c1c5..6719a3390ebd 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -7706,7 +7706,7 @@ advansys_narrow_slave_configure(struct scsi_device *sdev, ASC_DVC_VAR *asc_dvc)
asc_dvc->cfg->can_tagged_qng |= tid_bit;
asc_dvc->use_tagged_qng |= tid_bit;
}
- scsi_adjust_queue_depth(sdev,
+ scsi_change_queue_depth(sdev,
asc_dvc->max_dvc_qng[sdev->id]);
}
} else {
@@ -7847,10 +7847,8 @@ advansys_wide_slave_configure(struct scsi_device *sdev, ADV_DVC_VAR *adv_dvc)
}
}
- if ((adv_dvc->tagqng_able & tidmask) && sdev->tagged_supported) {
- scsi_adjust_queue_depth(sdev,
- adv_dvc->max_dvc_qng);
- }
+ if ((adv_dvc->tagqng_able & tidmask) && sdev->tagged_supported)
+ scsi_change_queue_depth(sdev, adv_dvc->max_dvc_qng);
}
/*
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 80cb4fd7caaa..d5c7b193d8d3 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -1470,7 +1470,7 @@ ahd_platform_set_tags(struct ahd_softc *ahd, struct scsi_device *sdev,
switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) {
case AHD_DEV_Q_BASIC:
case AHD_DEV_Q_TAGGED:
- scsi_adjust_queue_depth(sdev,
+ scsi_change_queue_depth(sdev,
dev->openings + dev->active);
break;
default:
@@ -1480,7 +1480,7 @@ ahd_platform_set_tags(struct ahd_softc *ahd, struct scsi_device *sdev,
* serially on the controller/device. This should
* remove some latency.
*/
- scsi_adjust_queue_depth(sdev, 1);
+ scsi_change_queue_depth(sdev, 1);
break;
}
}
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index a6a27d5398dd..88360116dbcb 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -1336,7 +1336,7 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct scsi_device *sdev,
switch ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED))) {
case AHC_DEV_Q_BASIC:
case AHC_DEV_Q_TAGGED:
- scsi_adjust_queue_depth(sdev,
+ scsi_change_queue_depth(sdev,
dev->openings + dev->active);
default:
/*
@@ -1345,7 +1345,7 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct scsi_device *sdev,
* serially on the controller/device. This should
* remove some latency.
*/
- scsi_adjust_queue_depth(sdev, 2);
+ scsi_change_queue_depth(sdev, 2);
break;
}
}
diff --git a/drivers/scsi/aic94xx/aic94xx.h b/drivers/scsi/aic94xx/aic94xx.h
index 66cda669b417..26d4ad9ede2e 100644
--- a/drivers/scsi/aic94xx/aic94xx.h
+++ b/drivers/scsi/aic94xx/aic94xx.h
@@ -78,7 +78,7 @@ void asd_dev_gone(struct domain_device *dev);
void asd_invalidate_edb(struct asd_ascb *ascb, int edb_id);
-int asd_execute_task(struct sas_task *, int num, gfp_t gfp_flags);
+int asd_execute_task(struct sas_task *task, gfp_t gfp_flags);
void asd_set_dmamode(struct domain_device *dev);
diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c
index 4df867e07b20..9f636a34d595 100644
--- a/drivers/scsi/aic94xx/aic94xx_hwi.c
+++ b/drivers/scsi/aic94xx/aic94xx_hwi.c
@@ -1200,8 +1200,7 @@ static void asd_start_scb_timers(struct list_head *list)
* Case A: we can send the whole batch at once. Increment "pending"
* in the beginning of this function, when it is checked, in order to
* eliminate races when this function is called by multiple processes.
- * Case B: should never happen if the managing layer considers
- * lldd_queue_size.
+ * Case B: should never happen.
*/
int asd_post_ascb_list(struct asd_ha_struct *asd_ha, struct asd_ascb *ascb,
int num)
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index 579dc2f460c4..14fc018436c2 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -49,14 +49,6 @@ MODULE_PARM_DESC(use_msi, "\n"
"\tEnable(1) or disable(0) using PCI MSI.\n"
"\tDefault: 0");
-static int lldd_max_execute_num = 0;
-module_param_named(collector, lldd_max_execute_num, int, S_IRUGO);
-MODULE_PARM_DESC(collector, "\n"
- "\tIf greater than one, tells the SAS Layer to run in Task Collector\n"
- "\tMode. If 1 or 0, tells the SAS Layer to run in Direct Mode.\n"
- "\tThe aic94xx SAS LLDD supports both modes.\n"
- "\tDefault: 0 (Direct Mode).\n");
-
static struct scsi_transport_template *aic94xx_transport_template;
static int asd_scan_finished(struct Scsi_Host *, unsigned long);
static void asd_scan_start(struct Scsi_Host *);
@@ -84,6 +76,7 @@ static struct scsi_host_template aic94xx_sht = {
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
.use_blk_tags = 1,
+ .track_queue_depth = 1,
};
static int asd_map_memio(struct asd_ha_struct *asd_ha)
@@ -710,9 +703,6 @@ static int asd_register_sas_ha(struct asd_ha_struct *asd_ha)
asd_ha->sas_ha.sas_port= sas_ports;
asd_ha->sas_ha.num_phys= ASD_MAX_PHYS;
- asd_ha->sas_ha.lldd_queue_size = asd_ha->seq.can_queue;
- asd_ha->sas_ha.lldd_max_execute_num = lldd_max_execute_num;
-
return sas_register_ha(&asd_ha->sas_ha);
}
diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c
index 59b86e260ce9..5ff1ce7ba1f4 100644
--- a/drivers/scsi/aic94xx/aic94xx_task.c
+++ b/drivers/scsi/aic94xx/aic94xx_task.c
@@ -543,8 +543,7 @@ static int asd_can_queue(struct asd_ha_struct *asd_ha, int num)
return res;
}
-int asd_execute_task(struct sas_task *task, const int num,
- gfp_t gfp_flags)
+int asd_execute_task(struct sas_task *task, gfp_t gfp_flags)
{
int res = 0;
LIST_HEAD(alist);
@@ -553,11 +552,11 @@ int asd_execute_task(struct sas_task *task, const int num,
struct asd_ha_struct *asd_ha = task->dev->port->ha->lldd_ha;
unsigned long flags;
- res = asd_can_queue(asd_ha, num);
+ res = asd_can_queue(asd_ha, 1);
if (res)
return res;
- res = num;
+ res = 1;
ascb = asd_ascb_alloc_list(asd_ha, &res, gfp_flags);
if (res) {
res = -ENOMEM;
@@ -568,7 +567,7 @@ int asd_execute_task(struct sas_task *task, const int num,
list_for_each_entry(a, &alist, list) {
a->uldd_task = t;
t->lldd_task = a;
- t = list_entry(t->list.next, struct sas_task, list);
+ break;
}
list_for_each_entry(a, &alist, list) {
t = a->uldd_task;
@@ -601,7 +600,7 @@ int asd_execute_task(struct sas_task *task, const int num,
}
list_del_init(&alist);
- res = asd_post_ascb_list(asd_ha, ascb, num);
+ res = asd_post_ascb_list(asd_ha, ascb, 1);
if (unlikely(res)) {
a = NULL;
__list_add(&alist, ascb->list.prev, &ascb->list);
@@ -639,6 +638,6 @@ out_err_unmap:
out_err:
if (ascb)
asd_ascb_free_list(ascb);
- asd_can_dequeue(asd_ha, num);
+ asd_can_dequeue(asd_ha, 1);
return res;
}
diff --git a/drivers/scsi/am53c974.c b/drivers/scsi/am53c974.c
new file mode 100644
index 000000000000..aa3e2c7cd83c
--- /dev/null
+++ b/drivers/scsi/am53c974.c
@@ -0,0 +1,586 @@
+/*
+ * AMD am53c974 driver.
+ * Copyright (c) 2014 Hannes Reinecke, SUSE Linux GmbH
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+
+#include <scsi/scsi_host.h>
+
+#include "esp_scsi.h"
+
+#define DRV_MODULE_NAME "am53c974"
+#define DRV_MODULE_VERSION "1.00"
+
+static bool am53c974_debug;
+static bool am53c974_fenab = true;
+
+#define esp_dma_log(f, a...) \
+ do { \
+ if (am53c974_debug) \
+ shost_printk(KERN_DEBUG, esp->host, f, ##a); \
+ } while (0)
+
+#define ESP_DMA_CMD 0x10
+#define ESP_DMA_STC 0x11
+#define ESP_DMA_SPA 0x12
+#define ESP_DMA_WBC 0x13
+#define ESP_DMA_WAC 0x14
+#define ESP_DMA_STATUS 0x15
+#define ESP_DMA_SMDLA 0x16
+#define ESP_DMA_WMAC 0x17
+
+#define ESP_DMA_CMD_IDLE 0x00
+#define ESP_DMA_CMD_BLAST 0x01
+#define ESP_DMA_CMD_ABORT 0x02
+#define ESP_DMA_CMD_START 0x03
+#define ESP_DMA_CMD_MASK 0x03
+#define ESP_DMA_CMD_DIAG 0x04
+#define ESP_DMA_CMD_MDL 0x10
+#define ESP_DMA_CMD_INTE_P 0x20
+#define ESP_DMA_CMD_INTE_D 0x40
+#define ESP_DMA_CMD_DIR 0x80
+
+#define ESP_DMA_STAT_PWDN 0x01
+#define ESP_DMA_STAT_ERROR 0x02
+#define ESP_DMA_STAT_ABORT 0x04
+#define ESP_DMA_STAT_DONE 0x08
+#define ESP_DMA_STAT_SCSIINT 0x10
+#define ESP_DMA_STAT_BCMPLT 0x20
+
+/* EEPROM is accessed with 16-bit values */
+#define DC390_EEPROM_READ 0x80
+#define DC390_EEPROM_LEN 0x40
+
+/*
+ * DC390 EEPROM
+ *
+ * 8 * 4 bytes of per-device options
+ * followed by HBA specific options
+ */
+
+/* Per-device options */
+#define DC390_EE_MODE1 0x00
+#define DC390_EE_SPEED 0x01
+
+/* HBA-specific options */
+#define DC390_EE_ADAPT_SCSI_ID 0x40
+#define DC390_EE_MODE2 0x41
+#define DC390_EE_DELAY 0x42
+#define DC390_EE_TAG_CMD_NUM 0x43
+
+#define DC390_EE_MODE1_PARITY_CHK 0x01
+#define DC390_EE_MODE1_SYNC_NEGO 0x02
+#define DC390_EE_MODE1_EN_DISC 0x04
+#define DC390_EE_MODE1_SEND_START 0x08
+#define DC390_EE_MODE1_TCQ 0x10
+
+#define DC390_EE_MODE2_MORE_2DRV 0x01
+#define DC390_EE_MODE2_GREATER_1G 0x02
+#define DC390_EE_MODE2_RST_SCSI_BUS 0x04
+#define DC390_EE_MODE2_ACTIVE_NEGATION 0x08
+#define DC390_EE_MODE2_NO_SEEK 0x10
+#define DC390_EE_MODE2_LUN_CHECK 0x20
+
+struct pci_esp_priv {
+ struct esp *esp;
+ u8 dma_status;
+};
+
+static void pci_esp_dma_drain(struct esp *esp);
+
+static inline struct pci_esp_priv *pci_esp_get_priv(struct esp *esp)
+{
+ struct pci_dev *pdev = esp->dev;
+
+ return pci_get_drvdata(pdev);
+}
+
+static void pci_esp_write8(struct esp *esp, u8 val, unsigned long reg)
+{
+ iowrite8(val, esp->regs + (reg * 4UL));
+}
+
+static u8 pci_esp_read8(struct esp *esp, unsigned long reg)
+{
+ return ioread8(esp->regs + (reg * 4UL));
+}
+
+static void pci_esp_write32(struct esp *esp, u32 val, unsigned long reg)
+{
+ return iowrite32(val, esp->regs + (reg * 4UL));
+}
+
+static dma_addr_t pci_esp_map_single(struct esp *esp, void *buf,
+ size_t sz, int dir)
+{
+ return pci_map_single(esp->dev, buf, sz, dir);
+}
+
+static int pci_esp_map_sg(struct esp *esp, struct scatterlist *sg,
+ int num_sg, int dir)
+{
+ return pci_map_sg(esp->dev, sg, num_sg, dir);
+}
+
+static void pci_esp_unmap_single(struct esp *esp, dma_addr_t addr,
+ size_t sz, int dir)
+{
+ pci_unmap_single(esp->dev, addr, sz, dir);
+}
+
+static void pci_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
+ int num_sg, int dir)
+{
+ pci_unmap_sg(esp->dev, sg, num_sg, dir);
+}
+
+static int pci_esp_irq_pending(struct esp *esp)
+{
+ struct pci_esp_priv *pep = pci_esp_get_priv(esp);
+
+ pep->dma_status = pci_esp_read8(esp, ESP_DMA_STATUS);
+ esp_dma_log("dma intr dreg[%02x]\n", pep->dma_status);
+
+ if (pep->dma_status & (ESP_DMA_STAT_ERROR |
+ ESP_DMA_STAT_ABORT |
+ ESP_DMA_STAT_DONE |
+ ESP_DMA_STAT_SCSIINT))
+ return 1;
+
+ return 0;
+}
+
+static void pci_esp_reset_dma(struct esp *esp)
+{
+ /* Nothing to do ? */
+}
+
+static void pci_esp_dma_drain(struct esp *esp)
+{
+ u8 resid;
+ int lim = 1000;
+
+
+ if ((esp->sreg & ESP_STAT_PMASK) == ESP_DOP ||
+ (esp->sreg & ESP_STAT_PMASK) == ESP_DIP)
+ /* Data-In or Data-Out, nothing to be done */
+ return;
+
+ while (--lim > 0) {
+ resid = pci_esp_read8(esp, ESP_FFLAGS) & ESP_FF_FBYTES;
+ if (resid <= 1)
+ break;
+ cpu_relax();
+ }
+ if (resid > 1) {
+ /* FIFO not cleared */
+ shost_printk(KERN_INFO, esp->host,
+ "FIFO not cleared, %d bytes left\n",
+ resid);
+ }
+
+ /*
+ * When there is a residual BCMPLT will never be set
+ * (obviously). But we still have to issue the BLAST
+ * command, otherwise the data will not being transferred.
+ * But we'll never know when the BLAST operation is
+ * finished. So check for some time and give up eventually.
+ */
+ lim = 1000;
+ pci_esp_write8(esp, ESP_DMA_CMD_DIR | ESP_DMA_CMD_BLAST, ESP_DMA_CMD);
+ while (pci_esp_read8(esp, ESP_DMA_STATUS) & ESP_DMA_STAT_BCMPLT) {
+ if (--lim == 0)
+ break;
+ cpu_relax();
+ }
+ pci_esp_write8(esp, ESP_DMA_CMD_DIR | ESP_DMA_CMD_IDLE, ESP_DMA_CMD);
+ esp_dma_log("DMA blast done (%d tries, %d bytes left)\n", lim, resid);
+ /* BLAST residual handling is currently untested */
+ if (WARN_ON_ONCE(resid == 1)) {
+ struct esp_cmd_entry *ent = esp->active_cmd;
+
+ ent->flags |= ESP_CMD_FLAG_RESIDUAL;
+ }
+}
+
+static void pci_esp_dma_invalidate(struct esp *esp)
+{
+ struct pci_esp_priv *pep = pci_esp_get_priv(esp);
+
+ esp_dma_log("invalidate DMA\n");
+
+ pci_esp_write8(esp, ESP_DMA_CMD_IDLE, ESP_DMA_CMD);
+ pep->dma_status = 0;
+}
+
+static int pci_esp_dma_error(struct esp *esp)
+{
+ struct pci_esp_priv *pep = pci_esp_get_priv(esp);
+
+ if (pep->dma_status & ESP_DMA_STAT_ERROR) {
+ u8 dma_cmd = pci_esp_read8(esp, ESP_DMA_CMD);
+
+ if ((dma_cmd & ESP_DMA_CMD_MASK) == ESP_DMA_CMD_START)
+ pci_esp_write8(esp, ESP_DMA_CMD_ABORT, ESP_DMA_CMD);
+
+ return 1;
+ }
+ if (pep->dma_status & ESP_DMA_STAT_ABORT) {
+ pci_esp_write8(esp, ESP_DMA_CMD_IDLE, ESP_DMA_CMD);
+ pep->dma_status = pci_esp_read8(esp, ESP_DMA_CMD);
+ return 1;
+ }
+ return 0;
+}
+
+static void pci_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
+ u32 dma_count, int write, u8 cmd)
+{
+ struct pci_esp_priv *pep = pci_esp_get_priv(esp);
+ u32 val = 0;
+
+ BUG_ON(!(cmd & ESP_CMD_DMA));
+
+ pep->dma_status = 0;
+
+ /* Set DMA engine to IDLE */
+ if (write)
+ /* DMA write direction logic is inverted */
+ val |= ESP_DMA_CMD_DIR;
+ pci_esp_write8(esp, ESP_DMA_CMD_IDLE | val, ESP_DMA_CMD);
+
+ pci_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
+ pci_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
+ if (esp->config2 & ESP_CONFIG2_FENAB)
+ pci_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI);
+
+ pci_esp_write32(esp, esp_count, ESP_DMA_STC);
+ pci_esp_write32(esp, addr, ESP_DMA_SPA);
+
+ esp_dma_log("start dma addr[%x] count[%d:%d]\n",
+ addr, esp_count, dma_count);
+
+ scsi_esp_cmd(esp, cmd);
+ /* Send DMA Start command */
+ pci_esp_write8(esp, ESP_DMA_CMD_START | val, ESP_DMA_CMD);
+}
+
+static u32 pci_esp_dma_length_limit(struct esp *esp, u32 dma_addr, u32 dma_len)
+{
+ int dma_limit = 16;
+ u32 base, end;
+
+ /*
+ * If CONFIG2_FENAB is set we can
+ * handle up to 24 bit addresses
+ */
+ if (esp->config2 & ESP_CONFIG2_FENAB)
+ dma_limit = 24;
+
+ if (dma_len > (1U << dma_limit))
+ dma_len = (1U << dma_limit);
+
+ /*
+ * Prevent crossing a 24-bit address boundary.
+ */
+ base = dma_addr & ((1U << 24) - 1U);
+ end = base + dma_len;
+ if (end > (1U << 24))
+ end = (1U <<24);
+ dma_len = end - base;
+
+ return dma_len;
+}
+
+static const struct esp_driver_ops pci_esp_ops = {
+ .esp_write8 = pci_esp_write8,
+ .esp_read8 = pci_esp_read8,
+ .map_single = pci_esp_map_single,
+ .map_sg = pci_esp_map_sg,
+ .unmap_single = pci_esp_unmap_single,
+ .unmap_sg = pci_esp_unmap_sg,
+ .irq_pending = pci_esp_irq_pending,
+ .reset_dma = pci_esp_reset_dma,
+ .dma_drain = pci_esp_dma_drain,
+ .dma_invalidate = pci_esp_dma_invalidate,
+ .send_dma_cmd = pci_esp_send_dma_cmd,
+ .dma_error = pci_esp_dma_error,
+ .dma_length_limit = pci_esp_dma_length_limit,
+};
+
+/*
+ * Read DC-390 eeprom
+ */
+static void dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cmd)
+{
+ u8 carry_flag = 1, j = 0x80, bval;
+ int i;
+
+ for (i = 0; i < 9; i++) {
+ if (carry_flag) {
+ pci_write_config_byte(pdev, 0x80, 0x40);
+ bval = 0xc0;
+ } else
+ bval = 0x80;
+
+ udelay(160);
+ pci_write_config_byte(pdev, 0x80, bval);
+ udelay(160);
+ pci_write_config_byte(pdev, 0x80, 0);
+ udelay(160);
+
+ carry_flag = (cmd & j) ? 1 : 0;
+ j >>= 1;
+ }
+}
+
+static u16 dc390_eeprom_get_data(struct pci_dev *pdev)
+{
+ int i;
+ u16 wval = 0;
+ u8 bval;
+
+ for (i = 0; i < 16; i++) {
+ wval <<= 1;
+
+ pci_write_config_byte(pdev, 0x80, 0x80);
+ udelay(160);
+ pci_write_config_byte(pdev, 0x80, 0x40);
+ udelay(160);
+ pci_read_config_byte(pdev, 0x00, &bval);
+
+ if (bval == 0x22)
+ wval |= 1;
+ }
+
+ return wval;
+}
+
+static void dc390_read_eeprom(struct pci_dev *pdev, u16 *ptr)
+{
+ u8 cmd = DC390_EEPROM_READ, i;
+
+ for (i = 0; i < DC390_EEPROM_LEN; i++) {
+ pci_write_config_byte(pdev, 0xc0, 0);
+ udelay(160);
+
+ dc390_eeprom_prepare_read(pdev, cmd++);
+ *ptr++ = dc390_eeprom_get_data(pdev);
+
+ pci_write_config_byte(pdev, 0x80, 0);
+ pci_write_config_byte(pdev, 0x80, 0);
+ udelay(160);
+ }
+}
+
+static void dc390_check_eeprom(struct esp *esp)
+{
+ u8 EEbuf[128];
+ u16 *ptr = (u16 *)EEbuf, wval = 0;
+ int i;
+
+ dc390_read_eeprom((struct pci_dev *)esp->dev, ptr);
+
+ for (i = 0; i < DC390_EEPROM_LEN; i++, ptr++)
+ wval += *ptr;
+
+ /* no Tekram EEprom found */
+ if (wval != 0x1234) {
+ struct pci_dev *pdev = esp->dev;
+ dev_printk(KERN_INFO, &pdev->dev,
+ "No valid Tekram EEprom found\n");
+ return;
+ }
+ esp->scsi_id = EEbuf[DC390_EE_ADAPT_SCSI_ID];
+ esp->num_tags = 2 << EEbuf[DC390_EE_TAG_CMD_NUM];
+ if (EEbuf[DC390_EE_MODE2] & DC390_EE_MODE2_ACTIVE_NEGATION)
+ esp->config4 |= ESP_CONFIG4_RADE | ESP_CONFIG4_RAE;
+}
+
+static int pci_esp_probe_one(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ struct scsi_host_template *hostt = &scsi_esp_template;
+ int err = -ENODEV;
+ struct Scsi_Host *shost;
+ struct esp *esp;
+ struct pci_esp_priv *pep;
+
+ if (pci_enable_device(pdev)) {
+ dev_printk(KERN_INFO, &pdev->dev, "cannot enable device\n");
+ return -ENODEV;
+ }
+
+ if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+ dev_printk(KERN_INFO, &pdev->dev,
+ "failed to set 32bit DMA mask\n");
+ goto fail_disable_device;
+ }
+
+ shost = scsi_host_alloc(hostt, sizeof(struct esp));
+ if (!shost) {
+ dev_printk(KERN_INFO, &pdev->dev,
+ "failed to allocate scsi host\n");
+ err = -ENOMEM;
+ goto fail_disable_device;
+ }
+
+ pep = kzalloc(sizeof(struct pci_esp_priv), GFP_KERNEL);
+ if (!pep) {
+ dev_printk(KERN_INFO, &pdev->dev,
+ "failed to allocate esp_priv\n");
+ err = -ENOMEM;
+ goto fail_host_alloc;
+ }
+
+ esp = shost_priv(shost);
+ esp->host = shost;
+ esp->dev = pdev;
+ esp->ops = &pci_esp_ops;
+ /*
+ * The am53c974 HBA has a design flaw of generating
+ * spurious DMA completion interrupts when using
+ * DMA for command submission.
+ */
+ esp->flags |= ESP_FLAG_USE_FIFO;
+ /*
+ * Enable CONFIG2_FENAB to allow for large DMA transfers
+ */
+ if (am53c974_fenab)
+ esp->config2 |= ESP_CONFIG2_FENAB;
+
+ pep->esp = esp;
+
+ if (pci_request_regions(pdev, DRV_MODULE_NAME)) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "pci memory selection failed\n");
+ goto fail_priv_alloc;
+ }
+
+ esp->regs = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
+ if (!esp->regs) {
+ dev_printk(KERN_ERR, &pdev->dev, "pci I/O map failed\n");
+ err = -EINVAL;
+ goto fail_release_regions;
+ }
+ esp->dma_regs = esp->regs;
+
+ pci_set_master(pdev);
+
+ esp->command_block = pci_alloc_consistent(pdev, 16,
+ &esp->command_block_dma);
+ if (!esp->command_block) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "failed to allocate command block\n");
+ err = -ENOMEM;
+ goto fail_unmap_regs;
+ }
+
+ err = request_irq(pdev->irq, scsi_esp_intr, IRQF_SHARED,
+ DRV_MODULE_NAME, esp);
+ if (err < 0) {
+ dev_printk(KERN_ERR, &pdev->dev, "failed to register IRQ\n");
+ goto fail_unmap_command_block;
+ }
+
+ esp->scsi_id = 7;
+ dc390_check_eeprom(esp);
+
+ shost->this_id = esp->scsi_id;
+ shost->max_id = 8;
+ shost->irq = pdev->irq;
+ shost->io_port = pci_resource_start(pdev, 0);
+ shost->n_io_port = pci_resource_len(pdev, 0);
+ shost->unique_id = shost->io_port;
+ esp->scsi_id_mask = (1 << esp->scsi_id);
+ /* Assume 40MHz clock */
+ esp->cfreq = 40000000;
+
+ pci_set_drvdata(pdev, pep);
+
+ err = scsi_esp_register(esp, &pdev->dev);
+ if (err)
+ goto fail_free_irq;
+
+ return 0;
+
+fail_free_irq:
+ free_irq(pdev->irq, esp);
+fail_unmap_command_block:
+ pci_free_consistent(pdev, 16, esp->command_block,
+ esp->command_block_dma);
+fail_unmap_regs:
+ pci_iounmap(pdev, esp->regs);
+fail_release_regions:
+ pci_release_regions(pdev);
+fail_priv_alloc:
+ kfree(pep);
+fail_host_alloc:
+ scsi_host_put(shost);
+fail_disable_device:
+ pci_disable_device(pdev);
+
+ return err;
+}
+
+static void pci_esp_remove_one(struct pci_dev *pdev)
+{
+ struct pci_esp_priv *pep = pci_get_drvdata(pdev);
+ struct esp *esp = pep->esp;
+
+ scsi_esp_unregister(esp);
+ free_irq(pdev->irq, esp);
+ pci_free_consistent(pdev, 16, esp->command_block,
+ esp->command_block_dma);
+ pci_iounmap(pdev, esp->regs);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ kfree(pep);
+
+ scsi_host_put(esp->host);
+}
+
+static struct pci_device_id am53c974_pci_tbl[] = {
+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_SCSI,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(pci, am53c974_pci_tbl);
+
+static struct pci_driver am53c974_driver = {
+ .name = DRV_MODULE_NAME,
+ .id_table = am53c974_pci_tbl,
+ .probe = pci_esp_probe_one,
+ .remove = pci_esp_remove_one,
+};
+
+static int __init am53c974_module_init(void)
+{
+ return pci_register_driver(&am53c974_driver);
+}
+
+static void __exit am53c974_module_exit(void)
+{
+ pci_unregister_driver(&am53c974_driver);
+}
+
+MODULE_DESCRIPTION("AM53C974 SCSI driver");
+MODULE_AUTHOR("Hannes Reinecke <hare@suse.de>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_ALIAS("tmscsim");
+
+module_param(am53c974_debug, bool, 0644);
+MODULE_PARM_DESC(am53c974_debug, "Enable debugging");
+
+module_param(am53c974_fenab, bool, 0444);
+MODULE_PARM_DESC(am53c974_fenab, "Enable 24-bit DMA transfer sizes");
+
+module_init(am53c974_module_init);
+module_exit(am53c974_module_exit);
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index 209f77162d06..914c39f9f388 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -114,16 +114,11 @@ static void arcmsr_hardware_reset(struct AdapterControlBlock *acb);
static const char *arcmsr_info(struct Scsi_Host *);
static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb);
static void arcmsr_free_irq(struct pci_dev *, struct AdapterControlBlock *);
-static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev,
- int queue_depth, int reason)
+static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, int queue_depth)
{
- if (reason != SCSI_QDEPTH_DEFAULT)
- return -EOPNOTSUPP;
-
if (queue_depth > ARCMSR_MAX_CMD_PERLUN)
queue_depth = ARCMSR_MAX_CMD_PERLUN;
- scsi_adjust_queue_depth(sdev, queue_depth);
- return queue_depth;
+ return scsi_change_queue_depth(sdev, queue_depth);
}
static struct scsi_host_template arcmsr_scsi_host_template = {
diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c
index 8ef810a4476e..d28d6c0f18c0 100644
--- a/drivers/scsi/arm/cumana_1.c
+++ b/drivers/scsi/arm/cumana_1.c
@@ -13,16 +13,12 @@
#include <asm/ecard.h>
#include <asm/io.h>
-#include "../scsi.h"
#include <scsi/scsi_host.h>
#include <scsi/scsicam.h>
-#define AUTOSENSE
#define PSEUDO_DMA
-#define CUMANASCSI_PUBLIC_RELEASE 1
-
#define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata)
#define NCR5380_local_declare() struct Scsi_Host *_instance
#define NCR5380_setup(instance) _instance = instance
@@ -30,6 +26,7 @@
#define NCR5380_write(reg, value) cumanascsi_write(_instance, reg, value)
#define NCR5380_intr cumanascsi_intr
#define NCR5380_queue_command cumanascsi_queue_command
+#define NCR5380_info cumanascsi_info
#define NCR5380_implementation_fields \
unsigned ctrl; \
@@ -42,11 +39,6 @@ void cumanascsi_setup(char *str, int *ints)
{
}
-const char *cumanascsi_info(struct Scsi_Host *spnt)
-{
- return "";
-}
-
#define CTRL 0x16fc
#define STAT 0x2004
#define L(v) (((v)<<16)|((v) & 0x0000ffff))
@@ -267,14 +259,6 @@ static int cumanascsi1_probe(struct expansion_card *ec,
goto out_unmap;
}
- printk("scsi%d: at port 0x%08lx irq %d",
- host->host_no, host->io_port, host->irq);
- printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
- host->can_queue, host->cmd_per_lun, CUMANASCSI_PUBLIC_RELEASE);
- printk("\nscsi%d:", host->host_no);
- NCR5380_print_options(host);
- printk("\n");
-
ret = scsi_add_host(host, &ec->dev);
if (ret)
goto out_free_irq;
diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c
index 188e734c7ff0..7c6fa1479c9c 100644
--- a/drivers/scsi/arm/oak.c
+++ b/drivers/scsi/arm/oak.c
@@ -14,13 +14,9 @@
#include <asm/ecard.h>
#include <asm/io.h>
-#include "../scsi.h"
#include <scsi/scsi_host.h>
-#define AUTOSENSE
/*#define PSEUDO_DMA*/
-
-#define OAKSCSI_PUBLIC_RELEASE 1
#define DONT_USE_INTR
#define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata)
@@ -29,10 +25,9 @@
#define NCR5380_read(reg) readb(_base + ((reg) << 2))
#define NCR5380_write(reg, value) writeb(value, _base + ((reg) << 2))
-#define NCR5380_intr oakscsi_intr
#define NCR5380_queue_command oakscsi_queue_command
+#define NCR5380_info oakscsi_info
#define NCR5380_show_info oakscsi_show_info
-#define NCR5380_write_info oakscsi_write_info
#define NCR5380_implementation_fields \
void __iomem *base
@@ -42,11 +37,6 @@
#undef START_DMA_INITIATOR_RECEIVE_REG
#define START_DMA_INITIATOR_RECEIVE_REG (128 + 7)
-const char * oakscsi_info (struct Scsi_Host *spnt)
-{
- return "";
-}
-
#define STAT ((128 + 16) << 2)
#define DATA ((128 + 8) << 2)
@@ -114,7 +104,6 @@ printk("reading %p len %d\n", addr, len);
static struct scsi_host_template oakscsi_template = {
.module = THIS_MODULE,
.show_info = oakscsi_show_info,
- .write_info = oakscsi_write_info,
.name = "Oak 16-bit SCSI",
.info = oakscsi_info,
.queuecommand = oakscsi_queue_command,
@@ -150,19 +139,11 @@ static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
goto unreg;
}
- host->irq = IRQ_NONE;
+ host->irq = NO_IRQ;
host->n_io_port = 255;
NCR5380_init(host, 0);
- printk("scsi%d: at port 0x%08lx irqs disabled",
- host->host_no, host->io_port);
- printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
- host->can_queue, host->cmd_per_lun, OAKSCSI_PUBLIC_RELEASE);
- printk("\nscsi%d:", host->host_no);
- NCR5380_print_options(host);
- printk("\n");
-
ret = scsi_add_host(host, &ec->dev);
if (ret)
goto out_unmap;
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
index 11e93025b87a..6daed6b386d4 100644
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -11,8 +11,6 @@
* drew@colorado.edu
* +1 (303) 666-5836
*
- * DISTRIBUTION RELEASE 6.
- *
* For more information, please consult
*
* NCR 5380 Family
@@ -73,6 +71,9 @@
* 1. Test linked command handling code after Eric is ready with
* the high level code.
*/
+
+/* Adapted for the sun3 by Sam Creasey. */
+
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_transport_spi.h>
@@ -103,27 +104,7 @@
/*
* Design
- * Issues :
- *
- * The other Linux SCSI drivers were written when Linux was Intel PC-only,
- * and specifically for each board rather than each chip. This makes their
- * adaptation to platforms like the Mac (Some of which use NCR5380's)
- * more difficult than it has to be.
*
- * Also, many of the SCSI drivers were written before the command queuing
- * routines were implemented, meaning their implementations of queued
- * commands were hacked on rather than designed in from the start.
- *
- * When I designed the Linux SCSI drivers I figured that
- * while having two different SCSI boards in a system might be useful
- * for debugging things, two of the same type wouldn't be used.
- * Well, I was wrong and a number of users have mailed me about running
- * multiple high-performance SCSI boards in a server.
- *
- * Finally, when I get questions from users, I have no idea what
- * revision of my driver they are running.
- *
- * This driver attempts to address these problems :
* This is a generic 5380 driver. To use it on a different platform,
* one simply writes appropriate system specific macros (ie, data
* transfer - some PC's will use the I/O bus, 68K's must use
@@ -138,17 +119,6 @@
* allowing multiple commands to propagate all the way to a SCSI-II device
* while a command is already executing.
*
- * To solve the multiple-boards-in-the-same-system problem,
- * there is a separate instance structure for each instance
- * of a 5380 in the system. So, multiple NCR5380 drivers will
- * be able to coexist with appropriate changes to the high level
- * SCSI code.
- *
- * A NCR5380_PUBLIC_REVISION macro is provided, with the release
- * number (updated for each public release) printed by the
- * NCR5380_print_options command, which should be called from the
- * wrapper detect function, so that I know what release of the driver
- * users are using.
*
* Issues specific to the NCR5380 :
*
@@ -173,19 +143,17 @@
* Architecture :
*
* At the heart of the design is a coroutine, NCR5380_main,
- * which is started when not running by the interrupt handler,
- * timer, and queue command function. It attempts to establish
- * I_T_L or I_T_L_Q nexuses by removing the commands from the
- * issue queue and calling NCR5380_select() if a nexus
- * is not established.
+ * which is started from a workqueue for each NCR5380 host in the
+ * system. It attempts to establish I_T_L or I_T_L_Q nexuses by
+ * removing the commands from the issue queue and calling
+ * NCR5380_select() if a nexus is not established.
*
* Once a nexus is established, the NCR5380_information_transfer()
* phase goes through the various phases as instructed by the target.
* if the target goes into MSG IN and sends a DISCONNECT message,
* the command structure is placed into the per instance disconnected
- * queue, and NCR5380_main tries to find more work. If USLEEP
- * was defined, and the target is idle for too long, the system
- * will try to sleep.
+ * queue, and NCR5380_main tries to find more work. If the target is
+ * idle for too long, the system will try to sleep.
*
* If a command has disconnected, eventually an interrupt will trigger,
* calling NCR5380_intr() which will in turn call NCR5380_reselect
@@ -211,6 +179,9 @@
* AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
* for commands that return with a CHECK CONDITION status.
*
+ * DIFFERENTIAL - if defined, NCR53c81 chips will use external differential
+ * transceivers.
+ *
* LINKED - if defined, linked commands are supported.
*
* REAL_DMA - if defined, REAL DMA is used during the data transfer phases.
@@ -223,6 +194,9 @@
*
* NCR5380_write(register, value) - write to the specific register
*
+ * NCR5380_implementation_fields - additional fields needed for this
+ * specific implementation of the NCR5380
+ *
* Either real DMA *or* pseudo DMA may be implemented
* REAL functions :
* NCR5380_REAL_DMA should be defined if real DMA is to be used.
@@ -241,40 +215,21 @@
* NCR5380_pwrite(instance, src, count)
* NCR5380_pread(instance, dst, count);
*
- * If nothing specific to this implementation needs doing (ie, with external
- * hardware), you must also define
- *
- * NCR5380_queue_command
- * NCR5380_reset
- * NCR5380_abort
- * NCR5380_proc_info
- *
- * to be the global entry points into the specific driver, ie
- * #define NCR5380_queue_command t128_queue_command.
- *
- * If this is not done, the routines will be defined as static functions
- * with the NCR5380* names and the user must provide a globally
- * accessible wrapper function.
- *
* The generic driver is initialized by calling NCR5380_init(instance),
* after setting the appropriate host specific fields and ID. If the
* driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance,
- * possible) function may be used. Before the specific driver initialization
- * code finishes, NCR5380_print_options should be called.
+ * possible) function may be used.
*/
-static struct Scsi_Host *first_instance = NULL;
-static struct scsi_host_template *the_template = NULL;
-
/* Macros ease life... :-) */
#define SETUP_HOSTDATA(in) \
struct NCR5380_hostdata *hostdata = \
(struct NCR5380_hostdata *)(in)->hostdata
#define HOSTDATA(in) ((struct NCR5380_hostdata *)(in)->hostdata)
-#define NEXT(cmd) ((Scsi_Cmnd *)(cmd)->host_scribble)
+#define NEXT(cmd) ((struct scsi_cmnd *)(cmd)->host_scribble)
#define SET_NEXT(cmd,next) ((cmd)->host_scribble = (void *)(next))
-#define NEXTADDR(cmd) ((Scsi_Cmnd **)&(cmd)->host_scribble)
+#define NEXTADDR(cmd) ((struct scsi_cmnd **)&(cmd)->host_scribble)
#define HOSTNO instance->host_no
#define H_NO(cmd) (cmd)->device->host->host_no
@@ -316,30 +271,17 @@ static struct scsi_host_template *the_template = NULL;
* important: the tag bit must be cleared before 'nr_allocated' is decreased.
*/
-/* -1 for TAG_NONE is not possible with unsigned char cmd->tag */
-#undef TAG_NONE
-#define TAG_NONE 0xff
-
-typedef struct {
- DECLARE_BITMAP(allocated, MAX_TAGS);
- int nr_allocated;
- int queue_size;
-} TAG_ALLOC;
-
-static TAG_ALLOC TagAlloc[8][8]; /* 8 targets and 8 LUNs */
-
-
-static void __init init_tags(void)
+static void __init init_tags(struct NCR5380_hostdata *hostdata)
{
int target, lun;
- TAG_ALLOC *ta;
+ struct tag_alloc *ta;
- if (!setup_use_tagged_queuing)
+ if (!(hostdata->flags & FLAG_TAGGED_QUEUING))
return;
for (target = 0; target < 8; ++target) {
for (lun = 0; lun < 8; ++lun) {
- ta = &TagAlloc[target][lun];
+ ta = &hostdata->TagAlloc[target][lun];
bitmap_zero(ta->allocated, MAX_TAGS);
ta->nr_allocated = 0;
/* At the beginning, assume the maximum queue size we could
@@ -359,7 +301,7 @@ static void __init init_tags(void)
* conditions.
*/
-static int is_lun_busy(Scsi_Cmnd *cmd, int should_be_tagged)
+static int is_lun_busy(struct scsi_cmnd *cmd, int should_be_tagged)
{
u8 lun = cmd->device->lun;
SETUP_HOSTDATA(cmd->device->host);
@@ -367,10 +309,11 @@ static int is_lun_busy(Scsi_Cmnd *cmd, int should_be_tagged)
if (hostdata->busy[cmd->device->id] & (1 << lun))
return 1;
if (!should_be_tagged ||
- !setup_use_tagged_queuing || !cmd->device->tagged_supported)
+ !(hostdata->flags & FLAG_TAGGED_QUEUING) ||
+ !cmd->device->tagged_supported)
return 0;
- if (TagAlloc[cmd->device->id][lun].nr_allocated >=
- TagAlloc[cmd->device->id][lun].queue_size) {
+ if (hostdata->TagAlloc[scmd_id(cmd)][lun].nr_allocated >=
+ hostdata->TagAlloc[scmd_id(cmd)][lun].queue_size) {
dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d: no free tags\n",
H_NO(cmd), cmd->device->id, lun);
return 1;
@@ -384,7 +327,7 @@ static int is_lun_busy(Scsi_Cmnd *cmd, int should_be_tagged)
* untagged.
*/
-static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged)
+static void cmd_get_tag(struct scsi_cmnd *cmd, int should_be_tagged)
{
u8 lun = cmd->device->lun;
SETUP_HOSTDATA(cmd->device->host);
@@ -393,13 +336,14 @@ static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged)
* an untagged command.
*/
if (!should_be_tagged ||
- !setup_use_tagged_queuing || !cmd->device->tagged_supported) {
+ !(hostdata->flags & FLAG_TAGGED_QUEUING) ||
+ !cmd->device->tagged_supported) {
cmd->tag = TAG_NONE;
hostdata->busy[cmd->device->id] |= (1 << lun);
dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d now allocated by untagged "
"command\n", H_NO(cmd), cmd->device->id, lun);
} else {
- TAG_ALLOC *ta = &TagAlloc[cmd->device->id][lun];
+ struct tag_alloc *ta = &hostdata->TagAlloc[scmd_id(cmd)][lun];
cmd->tag = find_first_zero_bit(ta->allocated, MAX_TAGS);
set_bit(cmd->tag, ta->allocated);
@@ -416,7 +360,7 @@ static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged)
* unlock the LUN.
*/
-static void cmd_free_tag(Scsi_Cmnd *cmd)
+static void cmd_free_tag(struct scsi_cmnd *cmd)
{
u8 lun = cmd->device->lun;
SETUP_HOSTDATA(cmd->device->host);
@@ -429,7 +373,7 @@ static void cmd_free_tag(Scsi_Cmnd *cmd)
printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n",
H_NO(cmd), cmd->tag);
} else {
- TAG_ALLOC *ta = &TagAlloc[cmd->device->id][lun];
+ struct tag_alloc *ta = &hostdata->TagAlloc[scmd_id(cmd)][lun];
clear_bit(cmd->tag, ta->allocated);
ta->nr_allocated--;
dprintk(NDEBUG_TAGS, "scsi%d: freed tag %d for target %d lun %d\n",
@@ -438,17 +382,17 @@ static void cmd_free_tag(Scsi_Cmnd *cmd)
}
-static void free_all_tags(void)
+static void free_all_tags(struct NCR5380_hostdata *hostdata)
{
int target, lun;
- TAG_ALLOC *ta;
+ struct tag_alloc *ta;
- if (!setup_use_tagged_queuing)
+ if (!(hostdata->flags & FLAG_TAGGED_QUEUING))
return;
for (target = 0; target < 8; ++target) {
for (lun = 0; lun < 8; ++lun) {
- ta = &TagAlloc[target][lun];
+ ta = &hostdata->TagAlloc[target][lun];
bitmap_zero(ta->allocated, MAX_TAGS);
ta->nr_allocated = 0;
}
@@ -459,19 +403,20 @@ static void free_all_tags(void)
/*
- * Function: void merge_contiguous_buffers( Scsi_Cmnd *cmd )
+ * Function: void merge_contiguous_buffers( struct scsi_cmnd *cmd )
*
* Purpose: Try to merge several scatter-gather requests into one DMA
* transfer. This is possible if the scatter buffers lie on
* physical contiguous addresses.
*
- * Parameters: Scsi_Cmnd *cmd
+ * Parameters: struct scsi_cmnd *cmd
* The command to work on. The first scatter buffer's data are
* assumed to be already transferred into ptr/this_residual.
*/
-static void merge_contiguous_buffers(Scsi_Cmnd *cmd)
+static void merge_contiguous_buffers(struct scsi_cmnd *cmd)
{
+#if !defined(CONFIG_SUN3)
unsigned long endaddr;
#if (NDEBUG & NDEBUG_MERGING)
unsigned long oldlen = cmd->SCp.this_residual;
@@ -496,18 +441,17 @@ static void merge_contiguous_buffers(Scsi_Cmnd *cmd)
dprintk(NDEBUG_MERGING, "merged %d buffers from %p, new length %08x\n",
cnt, cmd->SCp.ptr, cmd->SCp.this_residual);
#endif
+#endif /* !defined(CONFIG_SUN3) */
}
-/*
- * Function : void initialize_SCp(Scsi_Cmnd *cmd)
+/**
+ * initialize_SCp - init the scsi pointer field
+ * @cmd: command block to set up
*
- * Purpose : initialize the saved data pointers for cmd to point to the
- * start of the buffer.
- *
- * Inputs : cmd - Scsi_Cmnd structure to have pointers reset.
+ * Set up the internal fields in the SCSI command.
*/
-static inline void initialize_SCp(Scsi_Cmnd *cmd)
+static inline void initialize_SCp(struct scsi_cmnd *cmd)
{
/*
* Initialize the Scsi Pointer field so that all of the commands in the
@@ -557,12 +501,11 @@ static struct {
{0, NULL}
};
-/*
- * Function : void NCR5380_print(struct Scsi_Host *instance)
+/**
+ * NCR5380_print - print scsi bus signals
+ * @instance: adapter state to dump
*
- * Purpose : print the SCSI bus signals for debugging purposes
- *
- * Input : instance - which NCR5380
+ * Print the SCSI bus signals for debugging purposes
*/
static void NCR5380_print(struct Scsi_Host *instance)
@@ -605,12 +548,13 @@ static struct {
{PHASE_UNKNOWN, "UNKNOWN"}
};
-/*
- * Function : void NCR5380_print_phase(struct Scsi_Host *instance)
+/**
+ * NCR5380_print_phase - show SCSI phase
+ * @instance: adapter to dump
*
- * Purpose : print the current SCSI phase for debugging purposes
+ * Print the current SCSI phase for debugging purposes
*
- * Input : instance - which NCR5380
+ * Locks: none
*/
static void NCR5380_print_phase(struct Scsi_Host *instance)
@@ -648,71 +592,75 @@ static void NCR5380_print_phase(struct Scsi_Host *instance)
#include <linux/workqueue.h>
#include <linux/interrupt.h>
-static volatile int main_running;
-static DECLARE_WORK(NCR5380_tqueue, NCR5380_main);
-
-static inline void queue_main(void)
+static inline void queue_main(struct NCR5380_hostdata *hostdata)
{
- if (!main_running) {
+ if (!hostdata->main_running) {
/* If in interrupt and NCR5380_main() not already running,
queue it on the 'immediate' task queue, to be processed
immediately after the current interrupt processing has
finished. */
- schedule_work(&NCR5380_tqueue);
+ schedule_work(&hostdata->main_task);
}
/* else: nothing to do: the running NCR5380_main() will pick up
any newly queued command. */
}
-
-static inline void NCR5380_all_init(void)
-{
- static int done = 0;
- if (!done) {
- dprintk(NDEBUG_INIT, "scsi : NCR5380_all_init()\n");
- done = 1;
- }
-}
-
-
-/*
- * Function : void NCR58380_print_options (struct Scsi_Host *instance)
+/**
+ * NCR58380_info - report driver and host information
+ * @instance: relevant scsi host instance
*
- * Purpose : called by probe code indicating the NCR5380 driver
- * options that were selected.
+ * For use as the host template info() handler.
*
- * Inputs : instance, pointer to this instance. Unused.
+ * Locks: none
*/
-static void __init NCR5380_print_options(struct Scsi_Host *instance)
+static const char *NCR5380_info(struct Scsi_Host *instance)
+{
+ struct NCR5380_hostdata *hostdata = shost_priv(instance);
+
+ return hostdata->info;
+}
+
+static void prepare_info(struct Scsi_Host *instance)
{
- printk(" generic options"
-#ifdef AUTOSENSE
- " AUTOSENSE"
+ struct NCR5380_hostdata *hostdata = shost_priv(instance);
+
+ snprintf(hostdata->info, sizeof(hostdata->info),
+ "%s, io_port 0x%lx, n_io_port %d, "
+ "base 0x%lx, irq %d, "
+ "can_queue %d, cmd_per_lun %d, "
+ "sg_tablesize %d, this_id %d, "
+ "flags { %s}, "
+ "options { %s} ",
+ instance->hostt->name, instance->io_port, instance->n_io_port,
+ instance->base, instance->irq,
+ instance->can_queue, instance->cmd_per_lun,
+ instance->sg_tablesize, instance->this_id,
+ hostdata->flags & FLAG_TAGGED_QUEUING ? "TAGGED_QUEUING " : "",
+#ifdef DIFFERENTIAL
+ "DIFFERENTIAL "
#endif
#ifdef REAL_DMA
- " REAL DMA"
+ "REAL_DMA "
#endif
#ifdef PARITY
- " PARITY"
+ "PARITY "
#endif
#ifdef SUPPORT_TAGS
- " SCSI-2 TAGGED QUEUING"
+ "SUPPORT_TAGS "
#endif
- );
- printk(" generic release=%d", NCR5380_PUBLIC_RELEASE);
+ "");
}
-/*
- * Function : void NCR5380_print_status (struct Scsi_Host *instance)
+/**
+ * NCR5380_print_status - dump controller info
+ * @instance: controller to dump
*
- * Purpose : print commands in the various queues, called from
- * NCR5380_abort and NCR5380_debug to aid debugging.
- *
- * Inputs : instance, pointer to this instance.
+ * Print commands in the various queues, called from NCR5380_abort
+ * to aid debugging.
*/
-static void lprint_Scsi_Cmnd(Scsi_Cmnd *cmd)
+static void lprint_Scsi_Cmnd(struct scsi_cmnd *cmd)
{
int i, s;
unsigned char *command;
@@ -729,7 +677,7 @@ static void lprint_Scsi_Cmnd(Scsi_Cmnd *cmd)
static void NCR5380_print_status(struct Scsi_Host *instance)
{
struct NCR5380_hostdata *hostdata;
- Scsi_Cmnd *ptr;
+ struct scsi_cmnd *ptr;
unsigned long flags;
NCR5380_dprint(NDEBUG_ANY, instance);
@@ -737,20 +685,19 @@ static void NCR5380_print_status(struct Scsi_Host *instance)
hostdata = (struct NCR5380_hostdata *)instance->hostdata;
- printk("\nNCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
local_irq_save(flags);
printk("NCR5380: coroutine is%s running.\n",
- main_running ? "" : "n't");
+ hostdata->main_running ? "" : "n't");
if (!hostdata->connected)
printk("scsi%d: no currently connected command\n", HOSTNO);
else
- lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected);
+ lprint_Scsi_Cmnd((struct scsi_cmnd *) hostdata->connected);
printk("scsi%d: issue_queue\n", HOSTNO);
- for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr))
+ for (ptr = (struct scsi_cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr))
lprint_Scsi_Cmnd(ptr);
printk("scsi%d: disconnected_queue\n", HOSTNO);
- for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
+ for (ptr = (struct scsi_cmnd *) hostdata->disconnected_queue; ptr;
ptr = NEXT(ptr))
lprint_Scsi_Cmnd(ptr);
@@ -758,7 +705,7 @@ static void NCR5380_print_status(struct Scsi_Host *instance)
printk("\n");
}
-static void show_Scsi_Cmnd(Scsi_Cmnd *cmd, struct seq_file *m)
+static void show_Scsi_Cmnd(struct scsi_cmnd *cmd, struct seq_file *m)
{
int i, s;
unsigned char *command;
@@ -772,28 +719,28 @@ static void show_Scsi_Cmnd(Scsi_Cmnd *cmd, struct seq_file *m)
seq_printf(m, "\n");
}
-static int NCR5380_show_info(struct seq_file *m, struct Scsi_Host *instance)
+static int __maybe_unused NCR5380_show_info(struct seq_file *m,
+ struct Scsi_Host *instance)
{
struct NCR5380_hostdata *hostdata;
- Scsi_Cmnd *ptr;
+ struct scsi_cmnd *ptr;
unsigned long flags;
hostdata = (struct NCR5380_hostdata *)instance->hostdata;
- seq_printf(m, "NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
local_irq_save(flags);
seq_printf(m, "NCR5380: coroutine is%s running.\n",
- main_running ? "" : "n't");
+ hostdata->main_running ? "" : "n't");
if (!hostdata->connected)
seq_printf(m, "scsi%d: no currently connected command\n", HOSTNO);
else
- show_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected, m);
+ show_Scsi_Cmnd((struct scsi_cmnd *) hostdata->connected, m);
seq_printf(m, "scsi%d: issue_queue\n", HOSTNO);
- for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr))
+ for (ptr = (struct scsi_cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr))
show_Scsi_Cmnd(ptr, m);
seq_printf(m, "scsi%d: disconnected_queue\n", HOSTNO);
- for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
+ for (ptr = (struct scsi_cmnd *) hostdata->disconnected_queue; ptr;
ptr = NEXT(ptr))
show_Scsi_Cmnd(ptr, m);
@@ -801,16 +748,18 @@ static int NCR5380_show_info(struct seq_file *m, struct Scsi_Host *instance)
return 0;
}
-/*
- * Function : void NCR5380_init (struct Scsi_Host *instance)
+/**
+ * NCR5380_init - initialise an NCR5380
+ * @instance: adapter to configure
+ * @flags: control flags
*
- * Purpose : initializes *instance and corresponding 5380 chip.
- *
- * Inputs : instance - instantiation of the 5380 driver.
+ * Initializes *instance and corresponding 5380 chip,
+ * with flags OR'd into the initial flags value.
*
* Notes : I assume that the host, hostno, and id bits have been
- * set correctly. I don't care about the irq and other fields.
+ * set correctly. I don't care about the irq and other fields.
*
+ * Returns 0 for success
*/
static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
@@ -818,8 +767,7 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
int i;
SETUP_HOSTDATA(instance);
- NCR5380_all_init();
-
+ hostdata->host = instance;
hostdata->aborted = 0;
hostdata->id_mask = 1 << instance->this_id;
hostdata->id_higher_mask = 0;
@@ -829,7 +777,7 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
for (i = 0; i < 8; ++i)
hostdata->busy[i] = 0;
#ifdef SUPPORT_TAGS
- init_tags();
+ init_tags(hostdata);
#endif
#if defined (REAL_DMA)
hostdata->dma_len = 0;
@@ -838,19 +786,11 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
hostdata->connected = NULL;
hostdata->issue_queue = NULL;
hostdata->disconnected_queue = NULL;
- hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT;
+ hostdata->flags = flags;
- if (!the_template) {
- the_template = instance->hostt;
- first_instance = instance;
- }
+ INIT_WORK(&hostdata->main_task, NCR5380_main);
-#ifndef AUTOSENSE
- if ((instance->cmd_per_lun > 1) || (instance->can_queue > 1))
- printk("scsi%d: WARNING : support for multiple outstanding commands enabled\n"
- " without AUTOSENSE option, contingent allegiance conditions may\n"
- " be incorrectly cleared.\n", HOSTNO);
-#endif /* def AUTOSENSE */
+ prepare_info(instance);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
NCR5380_write(MODE_REG, MR_BASE);
@@ -860,33 +800,35 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
return 0;
}
+/**
+ * NCR5380_exit - remove an NCR5380
+ * @instance: adapter to remove
+ *
+ * Assumes that no more work can be queued (e.g. by NCR5380_intr).
+ */
+
static void NCR5380_exit(struct Scsi_Host *instance)
{
- /* Empty, as we didn't schedule any delayed work */
+ struct NCR5380_hostdata *hostdata = shost_priv(instance);
+
+ cancel_work_sync(&hostdata->main_task);
}
-/*
- * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd,
- * void (*done)(Scsi_Cmnd *))
- *
- * Purpose : enqueues a SCSI command
- *
- * Inputs : cmd - SCSI command, done - function called on completion, with
- * a pointer to the command descriptor.
- *
- * Returns : 0
- *
- * Side effects :
- * cmd is added to the per instance issue_queue, with minor
- * twiddling done to the host specific fields of cmd. If the
- * main coroutine is not running, it is restarted.
+/**
+ * NCR5380_queue_command - queue a command
+ * @instance: the relevant SCSI adapter
+ * @cmd: SCSI command
*
+ * cmd is added to the per instance issue_queue, with minor
+ * twiddling done to the host specific fields of cmd. If the
+ * main coroutine is not running, it is restarted.
*/
-static int NCR5380_queue_command_lck(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
+static int NCR5380_queue_command(struct Scsi_Host *instance,
+ struct scsi_cmnd *cmd)
{
- SETUP_HOSTDATA(cmd->device->host);
- Scsi_Cmnd *tmp;
+ struct NCR5380_hostdata *hostdata = shost_priv(instance);
+ struct scsi_cmnd *tmp;
unsigned long flags;
#if (NDEBUG & NDEBUG_NO_WRITE)
@@ -896,47 +838,17 @@ static int NCR5380_queue_command_lck(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
printk(KERN_NOTICE "scsi%d: WRITE attempted with NO_WRITE debugging flag set\n",
H_NO(cmd));
cmd->result = (DID_ERROR << 16);
- done(cmd);
+ cmd->scsi_done(cmd);
return 0;
}
#endif /* (NDEBUG & NDEBUG_NO_WRITE) */
-#ifdef NCR5380_STATS
-# if 0
- if (!hostdata->connected && !hostdata->issue_queue &&
- !hostdata->disconnected_queue) {
- hostdata->timebase = jiffies;
- }
-# endif
-# ifdef NCR5380_STAT_LIMIT
- if (scsi_bufflen(cmd) > NCR5380_STAT_LIMIT)
-# endif
- switch (cmd->cmnd[0]) {
- case WRITE:
- case WRITE_6:
- case WRITE_10:
- hostdata->time_write[cmd->device->id] -= (jiffies - hostdata->timebase);
- hostdata->bytes_write[cmd->device->id] += scsi_bufflen(cmd);
- hostdata->pendingw++;
- break;
- case READ:
- case READ_6:
- case READ_10:
- hostdata->time_read[cmd->device->id] -= (jiffies - hostdata->timebase);
- hostdata->bytes_read[cmd->device->id] += scsi_bufflen(cmd);
- hostdata->pendingr++;
- break;
- }
-#endif
-
/*
* We use the host_scribble field as a pointer to the next command
* in a queue
*/
SET_NEXT(cmd, NULL);
- cmd->scsi_done = done;
-
cmd->result = 0;
/*
@@ -946,7 +858,6 @@ static int NCR5380_queue_command_lck(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
* sense data is only guaranteed to be valid while the condition exists.
*/
- local_irq_save(flags);
/* ++guenther: now that the issue queue is being set up, we can lock ST-DMA.
* Otherwise a running NCR5380_main may steal the lock.
* Lock before actually inserting due to fairness reasons explained in
@@ -959,17 +870,24 @@ static int NCR5380_queue_command_lck(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
* because also a timer int can trigger an abort or reset, which would
* alter queues and touch the lock.
*/
- if (!IS_A_TT()) {
- /* perhaps stop command timer here */
- falcon_get_lock();
- /* perhaps restart command timer here */
- }
+ if (!NCR5380_acquire_dma_irq(instance))
+ return SCSI_MLQUEUE_HOST_BUSY;
+
+ local_irq_save(flags);
+
+ /*
+ * Insert the cmd into the issue queue. Note that REQUEST SENSE
+ * commands are added to the head of the queue since any command will
+ * clear the contingent allegiance condition that exists and the
+ * sense data is only guaranteed to be valid while the condition exists.
+ */
+
if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
LIST(cmd, hostdata->issue_queue);
SET_NEXT(cmd, hostdata->issue_queue);
hostdata->issue_queue = cmd;
} else {
- for (tmp = (Scsi_Cmnd *)hostdata->issue_queue;
+ for (tmp = (struct scsi_cmnd *)hostdata->issue_queue;
NEXT(tmp); tmp = NEXT(tmp))
;
LIST(cmd, tmp);
@@ -987,32 +905,42 @@ static int NCR5380_queue_command_lck(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
* If we're not in an interrupt, we can call NCR5380_main()
* unconditionally, because it cannot be already running.
*/
- if (in_interrupt() || ((flags >> 8) & 7) >= 6)
- queue_main();
+ if (in_interrupt() || irqs_disabled())
+ queue_main(hostdata);
else
- NCR5380_main(NULL);
+ NCR5380_main(&hostdata->main_task);
return 0;
}
-static DEF_SCSI_QCMD(NCR5380_queue_command)
+static inline void maybe_release_dma_irq(struct Scsi_Host *instance)
+{
+ struct NCR5380_hostdata *hostdata = shost_priv(instance);
+
+ /* Caller does the locking needed to set & test these data atomically */
+ if (!hostdata->disconnected_queue &&
+ !hostdata->issue_queue &&
+ !hostdata->connected &&
+ !hostdata->retain_dma_intr)
+ NCR5380_release_dma_irq(instance);
+}
-/*
- * Function : NCR5380_main (void)
+/**
+ * NCR5380_main - NCR state machines
*
- * Purpose : NCR5380_main is a coroutine that runs as long as more work can
- * be done on the NCR5380 host adapters in a system. Both
- * NCR5380_queue_command() and NCR5380_intr() will try to start it
- * in case it is not running.
+ * NCR5380_main is a coroutine that runs as long as more work can
+ * be done on the NCR5380 host adapters in a system. Both
+ * NCR5380_queue_command() and NCR5380_intr() will try to start it
+ * in case it is not running.
*
- * NOTE : NCR5380_main exits with interrupts *disabled*, the caller should
- * reenable them. This prevents reentrancy and kernel stack overflow.
+ * Locks: called as its own thread with no locks held.
*/
static void NCR5380_main(struct work_struct *work)
{
- Scsi_Cmnd *tmp, *prev;
- struct Scsi_Host *instance = first_instance;
- struct NCR5380_hostdata *hostdata = HOSTDATA(instance);
+ struct NCR5380_hostdata *hostdata =
+ container_of(work, struct NCR5380_hostdata, main_task);
+ struct Scsi_Host *instance = hostdata->host;
+ struct scsi_cmnd *tmp, *prev;
int done;
unsigned long flags;
@@ -1037,9 +965,9 @@ static void NCR5380_main(struct work_struct *work)
'main_running' is set here, and queues/executes main via the
task queue, it doesn't do any harm, just this instance of main
won't find any work left to do. */
- if (main_running)
+ if (hostdata->main_running)
return;
- main_running = 1;
+ hostdata->main_running = 1;
local_save_flags(flags);
do {
@@ -1053,7 +981,7 @@ static void NCR5380_main(struct work_struct *work)
* for a target that's not busy.
*/
#if (NDEBUG & NDEBUG_LISTS)
- for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL;
+ for (tmp = (struct scsi_cmnd *) hostdata->issue_queue, prev = NULL;
tmp && (tmp != prev); prev = tmp, tmp = NEXT(tmp))
;
/*printk("%p ", tmp);*/
@@ -1061,16 +989,14 @@ static void NCR5380_main(struct work_struct *work)
printk(" LOOP\n");
/* else printk("\n"); */
#endif
- for (tmp = (Scsi_Cmnd *) hostdata->issue_queue,
+ for (tmp = (struct scsi_cmnd *) hostdata->issue_queue,
prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp)) {
u8 lun = tmp->device->lun;
-#if (NDEBUG & NDEBUG_LISTS)
- if (prev != tmp)
- printk("MAIN tmp=%p target=%d busy=%d lun=%llu\n",
- tmp, tmp->device->id, hostdata->busy[tmp->device->id],
- lun);
-#endif
+ dprintk(NDEBUG_LISTS,
+ "MAIN tmp=%p target=%d busy=%d lun=%d\n",
+ tmp, scmd_id(tmp), hostdata->busy[scmd_id(tmp)],
+ lun);
/* When we find one, remove it from the issue queue. */
/* ++guenther: possible race with Falcon locking */
if (
@@ -1090,7 +1016,7 @@ static void NCR5380_main(struct work_struct *work)
hostdata->issue_queue = NEXT(tmp);
}
SET_NEXT(tmp, NULL);
- falcon_dont_release++;
+ hostdata->retain_dma_intr++;
/* reenable interrupts after finding one */
local_irq_restore(flags);
@@ -1117,12 +1043,12 @@ static void NCR5380_main(struct work_struct *work)
#ifdef SUPPORT_TAGS
cmd_get_tag(tmp, tmp->cmnd[0] != REQUEST_SENSE);
#endif
- if (!NCR5380_select(instance, tmp,
- (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE :
- TAG_NEXT)) {
- falcon_dont_release--;
+ if (!NCR5380_select(instance, tmp)) {
+ local_irq_disable();
+ hostdata->retain_dma_intr--;
/* release if target did not response! */
- falcon_release_lock_if_possible(hostdata);
+ maybe_release_dma_irq(instance);
+ local_irq_restore(flags);
break;
} else {
local_irq_disable();
@@ -1132,7 +1058,7 @@ static void NCR5380_main(struct work_struct *work)
#ifdef SUPPORT_TAGS
cmd_free_tag(tmp);
#endif
- falcon_dont_release--;
+ hostdata->retain_dma_intr--;
local_irq_restore(flags);
dprintk(NDEBUG_MAIN, "scsi%d: main(): select() failed, "
"returned to issue_queue\n", HOSTNO);
@@ -1160,7 +1086,7 @@ static void NCR5380_main(struct work_struct *work)
/* Better allow ints _after_ 'main_running' has been cleared, else
an interrupt could believe we'll pick up the work it left for
us, but we won't see it anymore here... */
- main_running = 0;
+ hostdata->main_running = 0;
local_irq_restore(flags);
}
@@ -1179,9 +1105,11 @@ static void NCR5380_main(struct work_struct *work)
static void NCR5380_dma_complete(struct Scsi_Host *instance)
{
SETUP_HOSTDATA(instance);
- int transfered, saved_data = 0, overrun = 0, cnt, toPIO;
- unsigned char **data, p;
+ int transferred;
+ unsigned char **data;
volatile int *count;
+ int saved_data = 0, overrun = 0;
+ unsigned char p;
if (!hostdata->connected) {
printk(KERN_WARNING "scsi%d: received end of DMA interrupt with "
@@ -1189,7 +1117,7 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance)
return;
}
- if (atari_read_overruns) {
+ if (hostdata->read_overruns) {
p = hostdata->connected->SCp.phase;
if (p & SR_IO) {
udelay(10);
@@ -1207,21 +1135,41 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance)
HOSTNO, NCR5380_read(BUS_AND_STATUS_REG),
NCR5380_read(STATUS_REG));
+#if defined(CONFIG_SUN3)
+ if ((sun3scsi_dma_finish(rq_data_dir(hostdata->connected->request)))) {
+ pr_err("scsi%d: overrun in UDC counter -- not prepared to deal with this!\n",
+ instance->host_no);
+ BUG();
+ }
+
+ /* make sure we're not stuck in a data phase */
+ if ((NCR5380_read(BUS_AND_STATUS_REG) & (BASR_PHASE_MATCH | BASR_ACK)) ==
+ (BASR_PHASE_MATCH | BASR_ACK)) {
+ pr_err("scsi%d: BASR %02x\n", instance->host_no,
+ NCR5380_read(BUS_AND_STATUS_REG));
+ pr_err("scsi%d: bus stuck in data phase -- probably a single byte overrun!\n",
+ instance->host_no);
+ BUG();
+ }
+#endif
+
(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
NCR5380_write(MODE_REG, MR_BASE);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- transfered = hostdata->dma_len - NCR5380_dma_residual(instance);
+ transferred = hostdata->dma_len - NCR5380_dma_residual(instance);
hostdata->dma_len = 0;
data = (unsigned char **)&hostdata->connected->SCp.ptr;
count = &hostdata->connected->SCp.this_residual;
- *data += transfered;
- *count -= transfered;
+ *data += transferred;
+ *count -= transferred;
+
+ if (hostdata->read_overruns) {
+ int cnt, toPIO;
- if (atari_read_overruns) {
if ((NCR5380_read(STATUS_REG) & PHASE_MASK) == p && (p & SR_IO)) {
- cnt = toPIO = atari_read_overruns;
+ cnt = toPIO = hostdata->read_overruns;
if (overrun) {
dprintk(NDEBUG_DMA, "Got an input overrun, using saved byte\n");
*(*data)++ = saved_data;
@@ -1238,20 +1186,19 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance)
#endif /* REAL_DMA */
-/*
- * Function : void NCR5380_intr (int irq)
- *
- * Purpose : handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
- * from the disconnected queue, and restarting NCR5380_main()
- * as required.
- *
- * Inputs : int irq, irq that caused this interrupt.
+/**
+ * NCR5380_intr - generic NCR5380 irq handler
+ * @irq: interrupt number
+ * @dev_id: device info
*
+ * Handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
+ * from the disconnected queue, and restarting NCR5380_main()
+ * as required.
*/
static irqreturn_t NCR5380_intr(int irq, void *dev_id)
{
- struct Scsi_Host *instance = first_instance;
+ struct Scsi_Host *instance = dev_id;
int done = 1, handled = 0;
unsigned char basr;
@@ -1265,7 +1212,6 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id)
NCR5380_dprint(NDEBUG_INTR, instance);
if ((NCR5380_read(STATUS_REG) & (SR_SEL|SR_IO)) == (SR_SEL|SR_IO)) {
done = 0;
- ENABLE_IRQ();
dprintk(NDEBUG_INTR, "scsi%d: SEL interrupt\n", HOSTNO);
NCR5380_reselect(instance);
(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
@@ -1295,17 +1241,19 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id)
dprintk(NDEBUG_INTR, "scsi%d: PHASE MISM or EOP interrupt\n", HOSTNO);
NCR5380_dma_complete( instance );
done = 0;
- ENABLE_IRQ();
} else
#endif /* REAL_DMA */
{
/* MS: Ignore unknown phase mismatch interrupts (caused by EOP interrupt) */
if (basr & BASR_PHASE_MATCH)
- printk(KERN_NOTICE "scsi%d: unknown interrupt, "
+ dprintk(NDEBUG_INTR, "scsi%d: unknown interrupt, "
"BASR 0x%x, MR 0x%x, SR 0x%x\n",
HOSTNO, basr, NCR5380_read(MODE_REG),
NCR5380_read(STATUS_REG));
(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+#ifdef SUN3_SCSI_VME
+ dregs->csr |= CSR_DMA_ENABLE;
+#endif
}
} /* if !(SELECTION || PARITY) */
handled = 1;
@@ -1314,53 +1262,29 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id)
"BASR 0x%X, MR 0x%X, SR 0x%x\n", HOSTNO, basr,
NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG));
(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+#ifdef SUN3_SCSI_VME
+ dregs->csr |= CSR_DMA_ENABLE;
+#endif
}
if (!done) {
dprintk(NDEBUG_INTR, "scsi%d: in int routine, calling main\n", HOSTNO);
/* Put a call to NCR5380_main() on the queue... */
- queue_main();
+ queue_main(shost_priv(instance));
}
return IRQ_RETVAL(handled);
}
-#ifdef NCR5380_STATS
-static void collect_stats(struct NCR5380_hostdata* hostdata, Scsi_Cmnd *cmd)
-{
-# ifdef NCR5380_STAT_LIMIT
- if (scsi_bufflen(cmd) > NCR5380_STAT_LIMIT)
-# endif
- switch (cmd->cmnd[0]) {
- case WRITE:
- case WRITE_6:
- case WRITE_10:
- hostdata->time_write[cmd->device->id] += (jiffies - hostdata->timebase);
- /*hostdata->bytes_write[cmd->device->id] += scsi_bufflen(cmd);*/
- hostdata->pendingw--;
- break;
- case READ:
- case READ_6:
- case READ_10:
- hostdata->time_read[cmd->device->id] += (jiffies - hostdata->timebase);
- /*hostdata->bytes_read[cmd->device->id] += scsi_bufflen(cmd);*/
- hostdata->pendingr--;
- break;
- }
-}
-#endif
-
/*
- * Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd,
- * int tag);
+ * Function : int NCR5380_select(struct Scsi_Host *instance,
+ * struct scsi_cmnd *cmd)
*
* Purpose : establishes I_T_L or I_T_L_Q nexus for new or existing command,
* including ARBITRATION, SELECTION, and initial message out for
* IDENTIFY and queue messages.
*
* Inputs : instance - instantiation of the 5380 driver on which this
- * target lives, cmd - SCSI command to execute, tag - set to TAG_NEXT for
- * new tag, TAG_NONE for untagged queueing, otherwise set to the tag for
- * the command that is presently connected.
+ * target lives, cmd - SCSI command to execute.
*
* Returns : -1 if selection could not execute for some reason,
* 0 if selection succeeded or failed because the target
@@ -1380,7 +1304,7 @@ static void collect_stats(struct NCR5380_hostdata* hostdata, Scsi_Cmnd *cmd)
* cmd->result host byte set to DID_BAD_TARGET.
*/
-static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
+static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
{
SETUP_HOSTDATA(instance);
unsigned char tmp[3], phase;
@@ -1562,7 +1486,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
* selection.
*/
- timeout = jiffies + 25;
+ timeout = jiffies + (250 * HZ / 1000);
/*
* XXX very interesting - we're seeing a bounce where the BSY we
@@ -1616,9 +1540,6 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
return -1;
}
cmd->result = DID_BAD_TARGET << 16;
-#ifdef NCR5380_STATS
- collect_stats(hostdata, cmd);
-#endif
#ifdef SUPPORT_TAGS
cmd_free_tag(cmd);
#endif
@@ -1676,6 +1597,9 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
#ifndef SUPPORT_TAGS
hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
#endif
+#ifdef SUN3_SCSI_VME
+ dregs->csr |= CSR_INTR;
+#endif
initialize_SCp(cmd);
@@ -1826,7 +1750,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance,
* Returns : 0 on success, -1 on failure.
*/
-static int do_abort(struct Scsi_Host *host)
+static int do_abort(struct Scsi_Host *instance)
{
unsigned char tmp, *msgptr, phase;
int len;
@@ -1861,7 +1785,7 @@ static int do_abort(struct Scsi_Host *host)
msgptr = &tmp;
len = 1;
phase = PHASE_MSGOUT;
- NCR5380_transfer_pio(host, &phase, &len, &msgptr);
+ NCR5380_transfer_pio(instance, &phase, &len, &msgptr);
/*
* If we got here, and the command completed successfully,
@@ -1899,17 +1823,62 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
SETUP_HOSTDATA(instance);
register int c = *count;
register unsigned char p = *phase;
+ unsigned long flags;
+
+#if defined(CONFIG_SUN3)
+ /* sanity check */
+ if (!sun3_dma_setup_done) {
+ pr_err("scsi%d: transfer_dma without setup!\n",
+ instance->host_no);
+ BUG();
+ }
+ hostdata->dma_len = c;
+
+ dprintk(NDEBUG_DMA, "scsi%d: initializing DMA for %s, %d bytes %s %p\n",
+ instance->host_no, (p & SR_IO) ? "reading" : "writing",
+ c, (p & SR_IO) ? "to" : "from", *data);
+
+ /* netbsd turns off ints here, why not be safe and do it too */
+ local_irq_save(flags);
+
+ /* send start chain */
+ sun3scsi_dma_start(c, *data);
+
+ if (p & SR_IO) {
+ NCR5380_write(TARGET_COMMAND_REG, 1);
+ NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+ NCR5380_write(INITIATOR_COMMAND_REG, 0);
+ NCR5380_write(MODE_REG,
+ (NCR5380_read(MODE_REG) | MR_DMA_MODE | MR_ENABLE_EOP_INTR));
+ NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);
+ } else {
+ NCR5380_write(TARGET_COMMAND_REG, 0);
+ NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_DATA);
+ NCR5380_write(MODE_REG,
+ (NCR5380_read(MODE_REG) | MR_DMA_MODE | MR_ENABLE_EOP_INTR));
+ NCR5380_write(START_DMA_SEND_REG, 0);
+ }
+
+#ifdef SUN3_SCSI_VME
+ dregs->csr |= CSR_DMA_ENABLE;
+#endif
+
+ local_irq_restore(flags);
+
+ sun3_dma_active = 1;
+
+#else /* !defined(CONFIG_SUN3) */
register unsigned char *d = *data;
unsigned char tmp;
- unsigned long flags;
if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) {
*phase = tmp;
return -1;
}
- if (atari_read_overruns && (p & SR_IO))
- c -= atari_read_overruns;
+ if (hostdata->read_overruns && (p & SR_IO))
+ c -= hostdata->read_overruns;
dprintk(NDEBUG_DMA, "scsi%d: initializing DMA for %s, %d bytes %s %p\n",
HOSTNO, (p & SR_IO) ? "reading" : "writing",
@@ -1921,7 +1890,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY);
#endif /* def REAL_DMA */
- if (IS_A_TT()) {
+ if (!(hostdata->flags & FLAG_LATE_DMA_SETUP)) {
/* On the Medusa, it is a must to initialize the DMA before
* starting the NCR. This is also the cleaner way for the TT.
*/
@@ -1939,7 +1908,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
NCR5380_write(START_DMA_SEND_REG, 0);
}
- if (!IS_A_TT()) {
+ if (hostdata->flags & FLAG_LATE_DMA_SETUP) {
/* On the Falcon, the DMA setup must be done after the last */
/* NCR access, else the DMA setup gets trashed!
*/
@@ -1949,6 +1918,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
NCR5380_dma_write_setup(instance, d, c);
local_irq_restore(flags);
}
+#endif /* !defined(CONFIG_SUN3) */
+
return 0;
}
#endif /* defined(REAL_DMA) */
@@ -1982,7 +1953,11 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
#endif
unsigned char *data;
unsigned char phase, tmp, extended_msg[10], old_phase = 0xff;
- Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected;
+ struct scsi_cmnd *cmd = (struct scsi_cmnd *) hostdata->connected;
+
+#ifdef SUN3_SCSI_VME
+ dregs->csr |= CSR_INTR;
+#endif
while (1) {
tmp = NCR5380_read(STATUS_REG);
@@ -1993,6 +1968,33 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
old_phase = phase;
NCR5380_dprint_phase(NDEBUG_INFORMATION, instance);
}
+#if defined(CONFIG_SUN3)
+ if (phase == PHASE_CMDOUT) {
+#if defined(REAL_DMA)
+ void *d;
+ unsigned long count;
+
+ if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
+ count = cmd->SCp.buffer->length;
+ d = sg_virt(cmd->SCp.buffer);
+ } else {
+ count = cmd->SCp.this_residual;
+ d = cmd->SCp.ptr;
+ }
+ /* this command setup for dma yet? */
+ if ((count >= DMA_MIN_SIZE) && (sun3_dma_setup_done != cmd)) {
+ if (cmd->request->cmd_type == REQ_TYPE_FS) {
+ sun3scsi_dma_setup(d, count,
+ rq_data_dir(cmd->request));
+ sun3_dma_setup_done = cmd;
+ }
+ }
+#endif
+#ifdef SUN3_SCSI_VME
+ dregs->csr |= CSR_INTR;
+#endif
+ }
+#endif /* CONFIG_SUN3 */
if (sink && (phase != PHASE_MSGOUT)) {
NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
@@ -2054,8 +2056,11 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
*/
#if defined(REAL_DMA)
- if (!cmd->device->borken &&
- (transfersize = NCR5380_dma_xfer_len(instance,cmd,phase)) > 31) {
+ if (
+#if !defined(CONFIG_SUN3)
+ !cmd->device->borken &&
+#endif
+ (transfersize = NCR5380_dma_xfer_len(instance, cmd, phase)) >= DMA_MIN_SIZE) {
len = transfersize;
cmd->SCp.phase = phase;
if (NCR5380_transfer_dma(instance, &phase,
@@ -2064,9 +2069,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
* If the watchdog timer fires, all future
* accesses to this device will use the
* polled-IO. */
- printk(KERN_NOTICE "scsi%d: switching target %d "
- "lun %llu to slow handshake\n", HOSTNO,
- cmd->device->id, cmd->device->lun);
+ scmd_printk(KERN_INFO, cmd,
+ "switching to slow handshake\n");
cmd->device->borken = 1;
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
ICR_ASSERT_ATN);
@@ -2092,6 +2096,11 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
NCR5380_transfer_pio(instance, &phase,
(int *)&cmd->SCp.this_residual,
(unsigned char **)&cmd->SCp.ptr);
+#if defined(CONFIG_SUN3) && defined(REAL_DMA)
+ /* if we had intended to dma that command clear it */
+ if (sun3_dma_setup_done == cmd)
+ sun3_dma_setup_done = NULL;
+#endif
break;
case PHASE_MSGIN:
len = 1;
@@ -2145,9 +2154,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %llu linked request "
"done, calling scsi_done().\n",
HOSTNO, cmd->device->id, cmd->device->lun);
-#ifdef NCR5380_STATS
- collect_stats(hostdata, cmd);
-#endif
cmd->scsi_done(cmd);
cmd = hostdata->connected;
break;
@@ -2156,11 +2162,12 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
case COMMAND_COMPLETE:
/* Accept message by clearing ACK */
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- /* ++guenther: possible race with Falcon locking */
- falcon_dont_release++;
- hostdata->connected = NULL;
dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d, lun %llu "
"completed\n", HOSTNO, cmd->device->id, cmd->device->lun);
+
+ local_irq_save(flags);
+ hostdata->retain_dma_intr++;
+ hostdata->connected = NULL;
#ifdef SUPPORT_TAGS
cmd_free_tag(cmd);
if (status_byte(cmd->SCp.Status) == QUEUE_FULL) {
@@ -2172,7 +2179,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
*/
/* ++Andreas: the mid level code knows about
QUEUE_FULL now. */
- TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
+ struct tag_alloc *ta = &hostdata->TagAlloc[scmd_id(cmd)][cmd->device->lun];
dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %llu returned "
"QUEUE_FULL after %d commands\n",
HOSTNO, cmd->device->id, cmd->device->lun,
@@ -2207,7 +2214,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
else if (status_byte(cmd->SCp.Status) != GOOD)
cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
-#ifdef AUTOSENSE
if ((cmd->cmnd[0] == REQUEST_SENSE) &&
hostdata->ses.cmd_len) {
scsi_eh_restore_cmnd(cmd, &hostdata->ses);
@@ -2220,22 +2226,17 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
dprintk(NDEBUG_AUTOSENSE, "scsi%d: performing request sense\n", HOSTNO);
- local_irq_save(flags);
LIST(cmd,hostdata->issue_queue);
SET_NEXT(cmd, hostdata->issue_queue);
- hostdata->issue_queue = (Scsi_Cmnd *) cmd;
- local_irq_restore(flags);
+ hostdata->issue_queue = (struct scsi_cmnd *) cmd;
dprintk(NDEBUG_QUEUES, "scsi%d: REQUEST SENSE added to head of "
"issue queue\n", H_NO(cmd));
- } else
-#endif /* def AUTOSENSE */
- {
-#ifdef NCR5380_STATS
- collect_stats(hostdata, cmd);
-#endif
+ } else {
cmd->scsi_done(cmd);
}
+ local_irq_restore(flags);
+
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
/*
* Restore phase bits to 0 so an interrupted selection,
@@ -2246,12 +2247,14 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
barrier();
- falcon_dont_release--;
+ local_irq_save(flags);
+ hostdata->retain_dma_intr--;
/* ++roman: For Falcon SCSI, release the lock on the
* ST-DMA here if no other commands are waiting on the
* disconnected queue.
*/
- falcon_release_lock_if_possible(hostdata);
+ maybe_release_dma_irq(instance);
+ local_irq_restore(flags);
return;
case MESSAGE_REJECT:
/* Accept message by clearing ACK */
@@ -2303,6 +2306,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
/* Wait for bus free to avoid nasty timeouts */
while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
barrier();
+#ifdef SUN3_SCSI_VME
+ dregs->csr |= CSR_DMA_ENABLE;
+#endif
return;
/*
* The SCSI data pointer is *IMPLICITLY* saved on a disconnect
@@ -2384,20 +2390,18 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
*/
default:
if (!tmp) {
- printk(KERN_DEBUG "scsi%d: rejecting message ", HOSTNO);
+ printk(KERN_INFO "scsi%d: rejecting message ",
+ instance->host_no);
spi_print_msg(extended_msg);
printk("\n");
} else if (tmp != EXTENDED_MESSAGE)
- printk(KERN_DEBUG "scsi%d: rejecting unknown "
- "message %02x from target %d, lun %llu\n",
- HOSTNO, tmp, cmd->device->id, cmd->device->lun);
+ scmd_printk(KERN_INFO, cmd,
+ "rejecting unknown message %02x\n",
+ tmp);
else
- printk(KERN_DEBUG "scsi%d: rejecting unknown "
- "extended message "
- "code %02x, length %d from target %d, lun %llu\n",
- HOSTNO, extended_msg[1], extended_msg[0],
- cmd->device->id, cmd->device->lun);
-
+ scmd_printk(KERN_INFO, cmd,
+ "rejecting unknown extended message code %02x, length %d\n",
+ extended_msg[1], extended_msg[0]);
msgout = MESSAGE_REJECT;
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
@@ -2410,6 +2414,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
hostdata->last_message = msgout;
NCR5380_transfer_pio(instance, &phase, &len, &data);
if (msgout == ABORT) {
+ local_irq_save(flags);
#ifdef SUPPORT_TAGS
cmd_free_tag(cmd);
#else
@@ -2417,12 +2422,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
#endif
hostdata->connected = NULL;
cmd->result = DID_ERROR << 16;
-#ifdef NCR5380_STATS
- collect_stats(hostdata, cmd);
-#endif
- cmd->scsi_done(cmd);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
- falcon_release_lock_if_possible(hostdata);
+ maybe_release_dma_irq(instance);
+ local_irq_restore(flags);
+ cmd->scsi_done(cmd);
return;
}
msgout = NOP;
@@ -2455,7 +2458,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
* Function : void NCR5380_reselect (struct Scsi_Host *instance)
*
* Purpose : does reselection, initializing the instance->connected
- * field to point to the Scsi_Cmnd for which the I_T_L or I_T_L_Q
+ * field to point to the scsi_cmnd for which the I_T_L or I_T_L_Q
* nexus has been reestablished,
*
* Inputs : instance - this instance of the NCR5380.
@@ -2463,19 +2466,21 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
*/
+/* it might eventually prove necessary to do a dma setup on
+ reselection, but it doesn't seem to be needed now -- sam */
+
static void NCR5380_reselect(struct Scsi_Host *instance)
{
SETUP_HOSTDATA(instance);
unsigned char target_mask;
- unsigned char lun, phase;
- int len;
+ unsigned char lun;
#ifdef SUPPORT_TAGS
unsigned char tag;
#endif
unsigned char msg[3];
- unsigned char *data;
- Scsi_Cmnd *tmp = NULL, *prev;
-/* unsigned long flags; */
+ int __maybe_unused len;
+ unsigned char __maybe_unused *data, __maybe_unused phase;
+ struct scsi_cmnd *tmp = NULL, *prev;
/*
* Disable arbitration, etc. since the host adapter obviously
@@ -2511,10 +2516,18 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
while (!(NCR5380_read(STATUS_REG) & SR_REQ))
;
+#if defined(CONFIG_SUN3) && defined(REAL_DMA)
+ /* acknowledge toggle to MSGIN */
+ NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(PHASE_MSGIN));
+
+ /* peek at the byte without really hitting the bus */
+ msg[0] = NCR5380_read(CURRENT_SCSI_DATA_REG);
+#else
len = 1;
data = msg;
phase = PHASE_MSGIN;
NCR5380_transfer_pio(instance, &phase, &len, &data);
+#endif
if (!(msg[0] & 0x80)) {
printk(KERN_DEBUG "scsi%d: expecting IDENTIFY message, got ", HOSTNO);
@@ -2524,13 +2537,13 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
}
lun = (msg[0] & 0x07);
-#ifdef SUPPORT_TAGS
+#if defined(SUPPORT_TAGS) && !defined(CONFIG_SUN3)
/* If the phase is still MSGIN, the target wants to send some more
* messages. In case it supports tagged queuing, this is probably a
* SIMPLE_QUEUE_TAG for the I_T_L_Q nexus.
*/
tag = TAG_NONE;
- if (phase == PHASE_MSGIN && setup_use_tagged_queuing) {
+ if (phase == PHASE_MSGIN && (hostdata->flags & FLAG_TAGGED_QUEUING)) {
/* Accept previous IDENTIFY message by clearing ACK */
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
len = 2;
@@ -2548,15 +2561,13 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
* just reestablished, and remove it from the disconnected queue.
*/
- for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL;
+ for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue, prev = NULL;
tmp; prev = tmp, tmp = NEXT(tmp)) {
if ((target_mask == (1 << tmp->device->id)) && (lun == tmp->device->lun)
#ifdef SUPPORT_TAGS
&& (tag == tmp->tag)
#endif
) {
- /* ++guenther: prevent race with falcon_release_lock */
- falcon_dont_release++;
if (prev) {
REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
SET_NEXT(prev, NEXT(tmp));
@@ -2588,22 +2599,63 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
return;
}
+#if defined(CONFIG_SUN3) && defined(REAL_DMA)
+ /* engage dma setup for the command we just saw */
+ {
+ void *d;
+ unsigned long count;
+
+ if (!tmp->SCp.this_residual && tmp->SCp.buffers_residual) {
+ count = tmp->SCp.buffer->length;
+ d = sg_virt(tmp->SCp.buffer);
+ } else {
+ count = tmp->SCp.this_residual;
+ d = tmp->SCp.ptr;
+ }
+ /* setup this command for dma if not already */
+ if ((count >= DMA_MIN_SIZE) && (sun3_dma_setup_done != tmp)) {
+ sun3scsi_dma_setup(d, count, rq_data_dir(tmp->request));
+ sun3_dma_setup_done = tmp;
+ }
+ }
+
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
+#endif
+
/* Accept message by clearing ACK */
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+#if defined(SUPPORT_TAGS) && defined(CONFIG_SUN3)
+ /* If the phase is still MSGIN, the target wants to send some more
+ * messages. In case it supports tagged queuing, this is probably a
+ * SIMPLE_QUEUE_TAG for the I_T_L_Q nexus.
+ */
+ tag = TAG_NONE;
+ if (phase == PHASE_MSGIN && setup_use_tagged_queuing) {
+ /* Accept previous IDENTIFY message by clearing ACK */
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+ len = 2;
+ data = msg + 1;
+ if (!NCR5380_transfer_pio(instance, &phase, &len, &data) &&
+ msg[1] == SIMPLE_QUEUE_TAG)
+ tag = msg[2];
+ dprintk(NDEBUG_TAGS, "scsi%d: target mask %02x, lun %d sent tag %d at reselection\n"
+ HOSTNO, target_mask, lun, tag);
+ }
+#endif
+
hostdata->connected = tmp;
dprintk(NDEBUG_RESELECTION, "scsi%d: nexus established, target = %d, lun = %llu, tag = %d\n",
HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag);
- falcon_dont_release--;
}
/*
- * Function : int NCR5380_abort (Scsi_Cmnd *cmd)
+ * Function : int NCR5380_abort (struct scsi_cmnd *cmd)
*
* Purpose : abort a command
*
- * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the
+ * Inputs : cmd - the scsi_cmnd to abort, code - code to set the
* host byte of the result field to, if zero DID_ABORTED is
* used.
*
@@ -2616,11 +2668,11 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
*/
static
-int NCR5380_abort(Scsi_Cmnd *cmd)
+int NCR5380_abort(struct scsi_cmnd *cmd)
{
struct Scsi_Host *instance = cmd->device->host;
SETUP_HOSTDATA(instance);
- Scsi_Cmnd *tmp, **prev;
+ struct scsi_cmnd *tmp, **prev;
unsigned long flags;
scmd_printk(KERN_NOTICE, cmd, "aborting command\n");
@@ -2629,10 +2681,6 @@ int NCR5380_abort(Scsi_Cmnd *cmd)
local_irq_save(flags);
- if (!IS_A_TT() && !falcon_got_lock)
- printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_abort\n",
- HOSTNO);
-
dprintk(NDEBUG_ABORT, "scsi%d: abort called basr 0x%02x, sr 0x%02x\n", HOSTNO,
NCR5380_read(BUS_AND_STATUS_REG),
NCR5380_read(STATUS_REG));
@@ -2673,12 +2721,12 @@ int NCR5380_abort(Scsi_Cmnd *cmd)
#else
hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
#endif
+ maybe_release_dma_irq(instance);
local_irq_restore(flags);
cmd->scsi_done(cmd);
- falcon_release_lock_if_possible(hostdata);
return SUCCESS;
} else {
-/* local_irq_restore(flags); */
+ local_irq_restore(flags);
printk("scsi%d: abort of connected command failed!\n", HOSTNO);
return FAILED;
}
@@ -2689,21 +2737,21 @@ int NCR5380_abort(Scsi_Cmnd *cmd)
* Case 2 : If the command hasn't been issued yet, we simply remove it
* from the issue queue.
*/
- for (prev = (Scsi_Cmnd **)&(hostdata->issue_queue),
- tmp = (Scsi_Cmnd *)hostdata->issue_queue;
+ for (prev = (struct scsi_cmnd **)&(hostdata->issue_queue),
+ tmp = (struct scsi_cmnd *)hostdata->issue_queue;
tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp)) {
if (cmd == tmp) {
REMOVE(5, *prev, tmp, NEXT(tmp));
(*prev) = NEXT(tmp);
SET_NEXT(tmp, NULL);
tmp->result = DID_ABORT << 16;
+ maybe_release_dma_irq(instance);
local_irq_restore(flags);
dprintk(NDEBUG_ABORT, "scsi%d: abort removed command from issue queue.\n",
HOSTNO);
/* Tagged queuing note: no tag to free here, hasn't been assigned
* yet... */
tmp->scsi_done(tmp);
- falcon_release_lock_if_possible(hostdata);
return SUCCESS;
}
}
@@ -2750,13 +2798,13 @@ int NCR5380_abort(Scsi_Cmnd *cmd)
* it from the disconnected queue.
*/
- for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp;
+ for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue; tmp;
tmp = NEXT(tmp)) {
if (cmd == tmp) {
local_irq_restore(flags);
dprintk(NDEBUG_ABORT, "scsi%d: aborting disconnected command.\n", HOSTNO);
- if (NCR5380_select(instance, cmd, (int)cmd->tag))
+ if (NCR5380_select(instance, cmd))
return FAILED;
dprintk(NDEBUG_ABORT, "scsi%d: nexus reestablished.\n", HOSTNO);
@@ -2764,8 +2812,8 @@ int NCR5380_abort(Scsi_Cmnd *cmd)
do_abort(instance);
local_irq_save(flags);
- for (prev = (Scsi_Cmnd **)&(hostdata->disconnected_queue),
- tmp = (Scsi_Cmnd *)hostdata->disconnected_queue;
+ for (prev = (struct scsi_cmnd **)&(hostdata->disconnected_queue),
+ tmp = (struct scsi_cmnd *)hostdata->disconnected_queue;
tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp)) {
if (cmd == tmp) {
REMOVE(5, *prev, tmp, NEXT(tmp));
@@ -2781,15 +2829,22 @@ int NCR5380_abort(Scsi_Cmnd *cmd)
#else
hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
#endif
+ maybe_release_dma_irq(instance);
local_irq_restore(flags);
tmp->scsi_done(tmp);
- falcon_release_lock_if_possible(hostdata);
return SUCCESS;
}
}
}
}
+ /* Maybe it is sufficient just to release the ST-DMA lock... (if
+ * possible at all) At least, we should check if the lock could be
+ * released after the abort, in case it is kept due to some bug.
+ */
+ maybe_release_dma_irq(instance);
+ local_irq_restore(flags);
+
/*
* Case 5 : If we reached this point, the command was not found in any of
* the queues.
@@ -2800,21 +2855,14 @@ int NCR5380_abort(Scsi_Cmnd *cmd)
* broke.
*/
- local_irq_restore(flags);
printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully before abortion\n", HOSTNO);
- /* Maybe it is sufficient just to release the ST-DMA lock... (if
- * possible at all) At least, we should check if the lock could be
- * released after the abort, in case it is kept due to some bug.
- */
- falcon_release_lock_if_possible(hostdata);
-
return FAILED;
}
/*
- * Function : int NCR5380_reset (Scsi_Cmnd *cmd)
+ * Function : int NCR5380_reset (struct scsi_cmnd *cmd)
*
* Purpose : reset the SCSI bus.
*
@@ -2822,20 +2870,14 @@ int NCR5380_abort(Scsi_Cmnd *cmd)
*
*/
-static int NCR5380_bus_reset(Scsi_Cmnd *cmd)
+static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
{
- SETUP_HOSTDATA(cmd->device->host);
+ struct Scsi_Host *instance = cmd->device->host;
+ struct NCR5380_hostdata *hostdata = shost_priv(instance);
int i;
unsigned long flags;
-#if defined(RESET_RUN_DONE)
- Scsi_Cmnd *connected, *disconnected_queue;
-#endif
-
- if (!IS_A_TT() && !falcon_got_lock)
- printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_reset\n",
- H_NO(cmd));
- NCR5380_print_status(cmd->device->host);
+ NCR5380_print_status(instance);
/* get in phase */
NCR5380_write(TARGET_COMMAND_REG,
@@ -2852,89 +2894,6 @@ static int NCR5380_bus_reset(Scsi_Cmnd *cmd)
* through anymore ... */
(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
- /* MSch 20140115 - looking at the generic NCR5380 driver, all of this
- * should go.
- * Catch-22: if we don't clear all queues, the SCSI driver lock will
- * not be reset by atari_scsi_reset()!
- */
-
-#if defined(RESET_RUN_DONE)
- /* XXX Should now be done by midlevel code, but it's broken XXX */
- /* XXX see below XXX */
-
- /* MSch: old-style reset: actually abort all command processing here */
-
- /* After the reset, there are no more connected or disconnected commands
- * and no busy units; to avoid problems with re-inserting the commands
- * into the issue_queue (via scsi_done()), the aborted commands are
- * remembered in local variables first.
- */
- local_irq_save(flags);
- connected = (Scsi_Cmnd *)hostdata->connected;
- hostdata->connected = NULL;
- disconnected_queue = (Scsi_Cmnd *)hostdata->disconnected_queue;
- hostdata->disconnected_queue = NULL;
-#ifdef SUPPORT_TAGS
- free_all_tags();
-#endif
- for (i = 0; i < 8; ++i)
- hostdata->busy[i] = 0;
-#ifdef REAL_DMA
- hostdata->dma_len = 0;
-#endif
- local_irq_restore(flags);
-
- /* In order to tell the mid-level code which commands were aborted,
- * set the command status to DID_RESET and call scsi_done() !!!
- * This ultimately aborts processing of these commands in the mid-level.
- */
-
- if ((cmd = connected)) {
- dprintk(NDEBUG_ABORT, "scsi%d: reset aborted a connected command\n", H_NO(cmd));
- cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
- cmd->scsi_done(cmd);
- }
-
- for (i = 0; (cmd = disconnected_queue); ++i) {
- disconnected_queue = NEXT(cmd);
- SET_NEXT(cmd, NULL);
- cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
- cmd->scsi_done(cmd);
- }
- if (i > 0)
- dprintk(NDEBUG_ABORT, "scsi: reset aborted %d disconnected command(s)\n", i);
-
- /* The Falcon lock should be released after a reset...
- */
- /* ++guenther: moved to atari_scsi_reset(), to prevent a race between
- * unlocking and enabling dma interrupt.
- */
-/* falcon_release_lock_if_possible( hostdata );*/
-
- /* since all commands have been explicitly terminated, we need to tell
- * the midlevel code that the reset was SUCCESSFUL, and there is no
- * need to 'wake up' the commands by a request_sense
- */
- return SUCCESS;
-#else /* 1 */
-
- /* MSch: new-style reset handling: let the mid-level do what it can */
-
- /* ++guenther: MID-LEVEL IS STILL BROKEN.
- * Mid-level is supposed to requeue all commands that were active on the
- * various low-level queues. In fact it does this, but that's not enough
- * because all these commands are subject to timeout. And if a timeout
- * happens for any removed command, *_abort() is called but all queues
- * are now empty. Abort then gives up the falcon lock, which is fatal,
- * since the mid-level will queue more commands and must have the lock
- * (it's all happening inside timer interrupt handler!!).
- * Even worse, abort will return NOT_RUNNING for all those commands not
- * on any queue, so they won't be retried ...
- *
- * Conclusion: either scsi.c disables timeout for all resetted commands
- * immediately, or we lose! As of linux-2.0.20 it doesn't.
- */
-
/* After the reset, there are no more connected or disconnected commands
* and no busy units; so clear the low-level status here to avoid
* conflicts when the mid-level code tries to wake up the affected
@@ -2953,16 +2912,16 @@ static int NCR5380_bus_reset(Scsi_Cmnd *cmd)
hostdata->connected = NULL;
hostdata->disconnected_queue = NULL;
#ifdef SUPPORT_TAGS
- free_all_tags();
+ free_all_tags(hostdata);
#endif
for (i = 0; i < 8; ++i)
hostdata->busy[i] = 0;
#ifdef REAL_DMA
hostdata->dma_len = 0;
#endif
+
+ maybe_release_dma_irq(instance);
local_irq_restore(flags);
- /* we did no complete reset of all commands, so a wakeup is required */
return SUCCESS;
-#endif /* 1 */
}
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c
index b522134528d6..d1c37a386947 100644
--- a/drivers/scsi/atari_scsi.c
+++ b/drivers/scsi/atari_scsi.c
@@ -64,45 +64,57 @@
/**************************************************************************/
-
#include <linux/module.h>
-
-#define AUTOSENSE
-/* For the Atari version, use only polled IO or REAL_DMA */
-#define REAL_DMA
-/* Support tagged queuing? (on devices that are able to... :-) */
-#define SUPPORT_TAGS
-#define MAX_TAGS 32
-
#include <linux/types.h>
-#include <linux/stddef.h>
-#include <linux/ctype.h>
#include <linux/delay.h>
-#include <linux/mm.h>
#include <linux/blkdev.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/nvram.h>
#include <linux/bitops.h>
#include <linux/wait.h>
+#include <linux/platform_device.h>
#include <asm/setup.h>
#include <asm/atarihw.h>
#include <asm/atariints.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/traps.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "atari_scsi.h"
-#include "NCR5380.h"
#include <asm/atari_stdma.h>
#include <asm/atari_stram.h>
#include <asm/io.h>
-#include <linux/stat.h>
+#include <scsi/scsi_host.h>
+
+/* Definitions for the core NCR5380 driver. */
+
+#define REAL_DMA
+#define SUPPORT_TAGS
+#define MAX_TAGS 32
+#define DMA_MIN_SIZE 32
+
+#define NCR5380_implementation_fields /* none */
+
+#define NCR5380_read(reg) atari_scsi_reg_read(reg)
+#define NCR5380_write(reg, value) atari_scsi_reg_write(reg, value)
+
+#define NCR5380_queue_command atari_scsi_queue_command
+#define NCR5380_abort atari_scsi_abort
+#define NCR5380_show_info atari_scsi_show_info
+#define NCR5380_info atari_scsi_info
+
+#define NCR5380_dma_read_setup(instance, data, count) \
+ atari_scsi_dma_setup(instance, data, count, 0)
+#define NCR5380_dma_write_setup(instance, data, count) \
+ atari_scsi_dma_setup(instance, data, count, 1)
+#define NCR5380_dma_residual(instance) \
+ atari_scsi_dma_residual(instance)
+#define NCR5380_dma_xfer_len(instance, cmd, phase) \
+ atari_dma_xfer_len(cmd->SCp.this_residual, cmd, !((phase) & SR_IO))
+
+#define NCR5380_acquire_dma_irq(instance) falcon_get_lock(instance)
+#define NCR5380_release_dma_irq(instance) falcon_release_lock()
+
+#include "NCR5380.h"
+
#define IS_A_TT() ATARIHW_PRESENT(TT_SCSI)
@@ -149,23 +161,6 @@ static inline unsigned long SCSI_DMA_GETADR(void)
return adr;
}
-static inline void ENABLE_IRQ(void)
-{
- if (IS_A_TT())
- atari_enable_irq(IRQ_TT_MFP_SCSI);
- else
- atari_enable_irq(IRQ_MFP_FSCSI);
-}
-
-static inline void DISABLE_IRQ(void)
-{
- if (IS_A_TT())
- atari_disable_irq(IRQ_TT_MFP_SCSI);
- else
- atari_disable_irq(IRQ_MFP_FSCSI);
-}
-
-
#define HOSTDATA_DMALEN (((struct NCR5380_hostdata *) \
(atari_scsi_host->hostdata))->dma_len)
@@ -178,30 +173,9 @@ static inline void DISABLE_IRQ(void)
#define AFTER_RESET_DELAY (5*HZ/2)
#endif
-/***************************** Prototypes *****************************/
-
#ifdef REAL_DMA
-static int scsi_dma_is_ignored_buserr(unsigned char dma_stat);
static void atari_scsi_fetch_restbytes(void);
-static long atari_scsi_dma_residual(struct Scsi_Host *instance);
-static int falcon_classify_cmd(Scsi_Cmnd *cmd);
-static unsigned long atari_dma_xfer_len(unsigned long wanted_len,
- Scsi_Cmnd *cmd, int write_flag);
-#endif
-static irqreturn_t scsi_tt_intr(int irq, void *dummy);
-static irqreturn_t scsi_falcon_intr(int irq, void *dummy);
-static void falcon_release_lock_if_possible(struct NCR5380_hostdata *hostdata);
-static void falcon_get_lock(void);
-#ifdef CONFIG_ATARI_SCSI_RESET_BOOT
-static void atari_scsi_reset_boot(void);
#endif
-static unsigned char atari_scsi_tt_reg_read(unsigned char reg);
-static void atari_scsi_tt_reg_write(unsigned char reg, unsigned char value);
-static unsigned char atari_scsi_falcon_reg_read(unsigned char reg);
-static void atari_scsi_falcon_reg_write(unsigned char reg, unsigned char value);
-
-/************************* End of Prototypes **************************/
-
static struct Scsi_Host *atari_scsi_host;
static unsigned char (*atari_scsi_reg_read)(unsigned char reg);
@@ -226,8 +200,6 @@ static char *atari_dma_orig_addr;
/* mask for address bits that can't be used with the ST-DMA */
static unsigned long atari_dma_stram_mask;
#define STRAM_ADDR(a) (((a) & atari_dma_stram_mask) == 0)
-/* number of bytes to cut from a transfer to handle NCR overruns */
-static int atari_read_overruns;
#endif
static int setup_can_queue = -1;
@@ -386,10 +358,6 @@ static irqreturn_t scsi_tt_intr(int irq, void *dummy)
NCR5380_intr(irq, dummy);
-#if 0
- /* To be sure the int is not masked */
- atari_enable_irq(IRQ_TT_MFP_SCSI);
-#endif
return IRQ_HANDLED;
}
@@ -480,257 +448,35 @@ static void atari_scsi_fetch_restbytes(void)
#endif /* REAL_DMA */
-static int falcon_got_lock = 0;
-static DECLARE_WAIT_QUEUE_HEAD(falcon_fairness_wait);
-static int falcon_trying_lock = 0;
-static DECLARE_WAIT_QUEUE_HEAD(falcon_try_wait);
-static int falcon_dont_release = 0;
-
/* This function releases the lock on the DMA chip if there is no
- * connected command and the disconnected queue is empty. On
- * releasing, instances of falcon_get_lock are awoken, that put
- * themselves to sleep for fairness. They can now try to get the lock
- * again (but others waiting longer more probably will win).
+ * connected command and the disconnected queue is empty.
*/
-static void falcon_release_lock_if_possible(struct NCR5380_hostdata *hostdata)
+static void falcon_release_lock(void)
{
- unsigned long flags;
-
if (IS_A_TT())
return;
- local_irq_save(flags);
-
- if (falcon_got_lock && !hostdata->disconnected_queue &&
- !hostdata->issue_queue && !hostdata->connected) {
-
- if (falcon_dont_release) {
-#if 0
- printk("WARNING: Lock release not allowed. Ignored\n");
-#endif
- local_irq_restore(flags);
- return;
- }
- falcon_got_lock = 0;
+ if (stdma_is_locked_by(scsi_falcon_intr))
stdma_release();
- wake_up(&falcon_fairness_wait);
- }
-
- local_irq_restore(flags);
}
/* This function manages the locking of the ST-DMA.
* If the DMA isn't locked already for SCSI, it tries to lock it by
* calling stdma_lock(). But if the DMA is locked by the SCSI code and
* there are other drivers waiting for the chip, we do not issue the
- * command immediately but wait on 'falcon_fairness_queue'. We will be
- * waked up when the DMA is unlocked by some SCSI interrupt. After that
- * we try to get the lock again.
- * But we must be prepared that more than one instance of
- * falcon_get_lock() is waiting on the fairness queue. They should not
- * try all at once to call stdma_lock(), one is enough! For that, the
- * first one sets 'falcon_trying_lock', others that see that variable
- * set wait on the queue 'falcon_try_wait'.
- * Complicated, complicated.... Sigh...
+ * command immediately but tell the SCSI mid-layer to defer.
*/
-static void falcon_get_lock(void)
+static int falcon_get_lock(struct Scsi_Host *instance)
{
- unsigned long flags;
-
if (IS_A_TT())
- return;
-
- local_irq_save(flags);
-
- wait_event_cmd(falcon_fairness_wait,
- in_interrupt() || !falcon_got_lock || !stdma_others_waiting(),
- local_irq_restore(flags),
- local_irq_save(flags));
-
- while (!falcon_got_lock) {
- if (in_irq())
- panic("Falcon SCSI hasn't ST-DMA lock in interrupt");
- if (!falcon_trying_lock) {
- falcon_trying_lock = 1;
- stdma_lock(scsi_falcon_intr, NULL);
- falcon_got_lock = 1;
- falcon_trying_lock = 0;
- wake_up(&falcon_try_wait);
- } else {
- wait_event_cmd(falcon_try_wait,
- falcon_got_lock && !falcon_trying_lock,
- local_irq_restore(flags),
- local_irq_save(flags));
- }
- }
-
- local_irq_restore(flags);
- if (!falcon_got_lock)
- panic("Falcon SCSI: someone stole the lock :-(\n");
-}
-
-
-static int __init atari_scsi_detect(struct scsi_host_template *host)
-{
- static int called = 0;
- struct Scsi_Host *instance;
-
- if (!MACH_IS_ATARI ||
- (!ATARIHW_PRESENT(ST_SCSI) && !ATARIHW_PRESENT(TT_SCSI)) ||
- called)
- return 0;
-
- host->proc_name = "Atari";
-
- atari_scsi_reg_read = IS_A_TT() ? atari_scsi_tt_reg_read :
- atari_scsi_falcon_reg_read;
- atari_scsi_reg_write = IS_A_TT() ? atari_scsi_tt_reg_write :
- atari_scsi_falcon_reg_write;
-
- /* setup variables */
- host->can_queue =
- (setup_can_queue > 0) ? setup_can_queue :
- IS_A_TT() ? ATARI_TT_CAN_QUEUE : ATARI_FALCON_CAN_QUEUE;
- host->cmd_per_lun =
- (setup_cmd_per_lun > 0) ? setup_cmd_per_lun :
- IS_A_TT() ? ATARI_TT_CMD_PER_LUN : ATARI_FALCON_CMD_PER_LUN;
- /* Force sg_tablesize to 0 on a Falcon! */
- host->sg_tablesize =
- !IS_A_TT() ? ATARI_FALCON_SG_TABLESIZE :
- (setup_sg_tablesize >= 0) ? setup_sg_tablesize : ATARI_TT_SG_TABLESIZE;
-
- if (setup_hostid >= 0)
- host->this_id = setup_hostid;
- else {
- /* use 7 as default */
- host->this_id = 7;
- /* Test if a host id is set in the NVRam */
- if (ATARIHW_PRESENT(TT_CLK) && nvram_check_checksum()) {
- unsigned char b = nvram_read_byte( 14 );
- /* Arbitration enabled? (for TOS) If yes, use configured host ID */
- if (b & 0x80)
- host->this_id = b & 7;
- }
- }
+ return 1;
-#ifdef SUPPORT_TAGS
- if (setup_use_tagged_queuing < 0)
- setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING;
-#endif
-#ifdef REAL_DMA
- /* If running on a Falcon and if there's TT-Ram (i.e., more than one
- * memory block, since there's always ST-Ram in a Falcon), then allocate a
- * STRAM_BUFFER_SIZE byte dribble buffer for transfers from/to alternative
- * Ram.
- */
- if (MACH_IS_ATARI && ATARIHW_PRESENT(ST_SCSI) &&
- !ATARIHW_PRESENT(EXTD_DMA) && m68k_num_memory > 1) {
- atari_dma_buffer = atari_stram_alloc(STRAM_BUFFER_SIZE, "SCSI");
- if (!atari_dma_buffer) {
- printk(KERN_ERR "atari_scsi_detect: can't allocate ST-RAM "
- "double buffer\n");
- return 0;
- }
- atari_dma_phys_buffer = atari_stram_to_phys(atari_dma_buffer);
- atari_dma_orig_addr = 0;
- }
-#endif
- instance = scsi_register(host, sizeof(struct NCR5380_hostdata));
- if (instance == NULL) {
- atari_stram_free(atari_dma_buffer);
- atari_dma_buffer = 0;
- return 0;
- }
- atari_scsi_host = instance;
- /*
- * Set irq to 0, to avoid that the mid-level code disables our interrupt
- * during queue_command calls. This is completely unnecessary, and even
- * worse causes bad problems on the Falcon, where the int is shared with
- * IDE and floppy!
- */
- instance->irq = 0;
-
-#ifdef CONFIG_ATARI_SCSI_RESET_BOOT
- atari_scsi_reset_boot();
-#endif
- NCR5380_init(instance, 0);
-
- if (IS_A_TT()) {
-
- /* This int is actually "pseudo-slow", i.e. it acts like a slow
- * interrupt after having cleared the pending flag for the DMA
- * interrupt. */
- if (request_irq(IRQ_TT_MFP_SCSI, scsi_tt_intr, IRQ_TYPE_SLOW,
- "SCSI NCR5380", instance)) {
- printk(KERN_ERR "atari_scsi_detect: cannot allocate irq %d, aborting",IRQ_TT_MFP_SCSI);
- scsi_unregister(atari_scsi_host);
- atari_stram_free(atari_dma_buffer);
- atari_dma_buffer = 0;
- return 0;
- }
- tt_mfp.active_edge |= 0x80; /* SCSI int on L->H */
-#ifdef REAL_DMA
- tt_scsi_dma.dma_ctrl = 0;
- atari_dma_residual = 0;
-
- if (MACH_IS_MEDUSA) {
- /* While the read overruns (described by Drew Eckhardt in
- * NCR5380.c) never happened on TTs, they do in fact on the Medusa
- * (This was the cause why SCSI didn't work right for so long
- * there.) Since handling the overruns slows down a bit, I turned
- * the #ifdef's into a runtime condition.
- *
- * In principle it should be sufficient to do max. 1 byte with
- * PIO, but there is another problem on the Medusa with the DMA
- * rest data register. So 'atari_read_overruns' is currently set
- * to 4 to avoid having transfers that aren't a multiple of 4. If
- * the rest data bug is fixed, this can be lowered to 1.
- */
- atari_read_overruns = 4;
- }
-#endif /*REAL_DMA*/
- } else { /* ! IS_A_TT */
-
- /* Nothing to do for the interrupt: the ST-DMA is initialized
- * already by atari_init_INTS()
- */
-
-#ifdef REAL_DMA
- atari_dma_residual = 0;
- atari_dma_active = 0;
- atari_dma_stram_mask = (ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000
- : 0xff000000);
-#endif
- }
+ if (in_interrupt())
+ return stdma_try_lock(scsi_falcon_intr, instance);
- printk(KERN_INFO "scsi%d: options CAN_QUEUE=%d CMD_PER_LUN=%d SCAT-GAT=%d "
-#ifdef SUPPORT_TAGS
- "TAGGED-QUEUING=%s "
-#endif
- "HOSTID=%d",
- instance->host_no, instance->hostt->can_queue,
- instance->hostt->cmd_per_lun,
- instance->hostt->sg_tablesize,
-#ifdef SUPPORT_TAGS
- setup_use_tagged_queuing ? "yes" : "no",
-#endif
- instance->hostt->this_id );
- NCR5380_print_options(instance);
- printk("\n");
-
- called = 1;
- return 1;
-}
-
-static int atari_scsi_release(struct Scsi_Host *sh)
-{
- if (IS_A_TT())
- free_irq(IRQ_TT_MFP_SCSI, sh);
- if (atari_dma_buffer)
- atari_stram_free(atari_dma_buffer);
- NCR5380_exit(sh);
+ stdma_lock(scsi_falcon_intr, instance);
return 1;
}
@@ -739,7 +485,7 @@ static int __init atari_scsi_setup(char *str)
{
/* Format of atascsi parameter is:
* atascsi=<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>
- * Defaults depend on TT or Falcon, hostid determined at run time.
+ * Defaults depend on TT or Falcon, determined at run time.
* Negative values mean don't change.
*/
int ints[6];
@@ -750,36 +496,17 @@ static int __init atari_scsi_setup(char *str)
printk("atari_scsi_setup: no arguments!\n");
return 0;
}
-
- if (ints[0] >= 1) {
- if (ints[1] > 0)
- /* no limits on this, just > 0 */
- setup_can_queue = ints[1];
- }
- if (ints[0] >= 2) {
- if (ints[2] > 0)
- setup_cmd_per_lun = ints[2];
- }
- if (ints[0] >= 3) {
- if (ints[3] >= 0) {
- setup_sg_tablesize = ints[3];
- /* Must be <= SG_ALL (255) */
- if (setup_sg_tablesize > SG_ALL)
- setup_sg_tablesize = SG_ALL;
- }
- }
- if (ints[0] >= 4) {
- /* Must be between 0 and 7 */
- if (ints[4] >= 0 && ints[4] <= 7)
- setup_hostid = ints[4];
- else if (ints[4] > 7)
- printk("atari_scsi_setup: invalid host ID %d !\n", ints[4]);
- }
+ if (ints[0] >= 1)
+ setup_can_queue = ints[1];
+ if (ints[0] >= 2)
+ setup_cmd_per_lun = ints[2];
+ if (ints[0] >= 3)
+ setup_sg_tablesize = ints[3];
+ if (ints[0] >= 4)
+ setup_hostid = ints[4];
#ifdef SUPPORT_TAGS
- if (ints[0] >= 5) {
- if (ints[5] >= 0)
- setup_use_tagged_queuing = !!ints[5];
- }
+ if (ints[0] >= 5)
+ setup_use_tagged_queuing = ints[5];
#endif
return 1;
@@ -788,45 +515,6 @@ static int __init atari_scsi_setup(char *str)
__setup("atascsi=", atari_scsi_setup);
#endif /* !MODULE */
-static int atari_scsi_bus_reset(Scsi_Cmnd *cmd)
-{
- int rv;
- struct NCR5380_hostdata *hostdata =
- (struct NCR5380_hostdata *)cmd->device->host->hostdata;
-
- /* For doing the reset, SCSI interrupts must be disabled first,
- * since the 5380 raises its IRQ line while _RST is active and we
- * can't disable interrupts completely, since we need the timer.
- */
- /* And abort a maybe active DMA transfer */
- if (IS_A_TT()) {
- atari_turnoff_irq(IRQ_TT_MFP_SCSI);
-#ifdef REAL_DMA
- tt_scsi_dma.dma_ctrl = 0;
-#endif /* REAL_DMA */
- } else {
- atari_turnoff_irq(IRQ_MFP_FSCSI);
-#ifdef REAL_DMA
- st_dma.dma_mode_status = 0x90;
- atari_dma_active = 0;
- atari_dma_orig_addr = NULL;
-#endif /* REAL_DMA */
- }
-
- rv = NCR5380_bus_reset(cmd);
-
- /* Re-enable ints */
- if (IS_A_TT()) {
- atari_turnon_irq(IRQ_TT_MFP_SCSI);
- } else {
- atari_turnon_irq(IRQ_MFP_FSCSI);
- }
- if (rv == SUCCESS)
- falcon_release_lock_if_possible(hostdata);
-
- return rv;
-}
-
#ifdef CONFIG_ATARI_SCSI_RESET_BOOT
static void __init atari_scsi_reset_boot(void)
@@ -860,15 +548,6 @@ static void __init atari_scsi_reset_boot(void)
}
#endif
-
-static const char *atari_scsi_info(struct Scsi_Host *host)
-{
- /* atari_scsi_detect() is verbose enough... */
- static const char string[] = "Atari native SCSI";
- return string;
-}
-
-
#if defined(REAL_DMA)
static unsigned long atari_scsi_dma_setup(struct Scsi_Host *instance,
@@ -949,7 +628,7 @@ static long atari_scsi_dma_residual(struct Scsi_Host *instance)
#define CMD_SURELY_BYTE_MODE 1
#define CMD_MODE_UNKNOWN 2
-static int falcon_classify_cmd(Scsi_Cmnd *cmd)
+static int falcon_classify_cmd(struct scsi_cmnd *cmd)
{
unsigned char opcode = cmd->cmnd[0];
@@ -981,7 +660,7 @@ static int falcon_classify_cmd(Scsi_Cmnd *cmd)
*/
static unsigned long atari_dma_xfer_len(unsigned long wanted_len,
- Scsi_Cmnd *cmd, int write_flag)
+ struct scsi_cmnd *cmd, int write_flag)
{
unsigned long possible_len, limit;
@@ -1099,23 +778,247 @@ static void atari_scsi_falcon_reg_write(unsigned char reg, unsigned char value)
#include "atari_NCR5380.c"
-static struct scsi_host_template driver_template = {
+static int atari_scsi_bus_reset(struct scsi_cmnd *cmd)
+{
+ int rv;
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+#ifdef REAL_DMA
+ /* Abort a maybe active DMA transfer */
+ if (IS_A_TT()) {
+ tt_scsi_dma.dma_ctrl = 0;
+ } else {
+ st_dma.dma_mode_status = 0x90;
+ atari_dma_active = 0;
+ atari_dma_orig_addr = NULL;
+ }
+#endif
+
+ rv = NCR5380_bus_reset(cmd);
+
+ /* The 5380 raises its IRQ line while _RST is active but the ST DMA
+ * "lock" has been released so this interrupt may end up handled by
+ * floppy or IDE driver (if one of them holds the lock). The NCR5380
+ * interrupt flag has been cleared already.
+ */
+
+ local_irq_restore(flags);
+
+ return rv;
+}
+
+#define DRV_MODULE_NAME "atari_scsi"
+#define PFX DRV_MODULE_NAME ": "
+
+static struct scsi_host_template atari_scsi_template = {
+ .module = THIS_MODULE,
+ .proc_name = DRV_MODULE_NAME,
.show_info = atari_scsi_show_info,
.name = "Atari native SCSI",
- .detect = atari_scsi_detect,
- .release = atari_scsi_release,
.info = atari_scsi_info,
.queuecommand = atari_scsi_queue_command,
.eh_abort_handler = atari_scsi_abort,
.eh_bus_reset_handler = atari_scsi_bus_reset,
- .can_queue = 0, /* initialized at run-time */
- .this_id = 0, /* initialized at run-time */
- .sg_tablesize = 0, /* initialized at run-time */
- .cmd_per_lun = 0, /* initialized at run-time */
+ .this_id = 7,
.use_clustering = DISABLE_CLUSTERING
};
+static int __init atari_scsi_probe(struct platform_device *pdev)
+{
+ struct Scsi_Host *instance;
+ int error;
+ struct resource *irq;
+ int host_flags = 0;
+
+ irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!irq)
+ return -ENODEV;
+
+ if (ATARIHW_PRESENT(TT_SCSI)) {
+ atari_scsi_reg_read = atari_scsi_tt_reg_read;
+ atari_scsi_reg_write = atari_scsi_tt_reg_write;
+ } else {
+ atari_scsi_reg_read = atari_scsi_falcon_reg_read;
+ atari_scsi_reg_write = atari_scsi_falcon_reg_write;
+ }
+
+ /* The values for CMD_PER_LUN and CAN_QUEUE are somehow arbitrary.
+ * Higher values should work, too; try it!
+ * (But cmd_per_lun costs memory!)
+ *
+ * But there seems to be a bug somewhere that requires CAN_QUEUE to be
+ * 2*CMD_PER_LUN. At least on a TT, no spurious timeouts seen since
+ * changed CMD_PER_LUN...
+ *
+ * Note: The Falcon currently uses 8/1 setting due to unsolved problems
+ * with cmd_per_lun != 1
+ */
+ if (ATARIHW_PRESENT(TT_SCSI)) {
+ atari_scsi_template.can_queue = 16;
+ atari_scsi_template.cmd_per_lun = 8;
+ atari_scsi_template.sg_tablesize = SG_ALL;
+ } else {
+ atari_scsi_template.can_queue = 8;
+ atari_scsi_template.cmd_per_lun = 1;
+ atari_scsi_template.sg_tablesize = SG_NONE;
+ }
+
+ if (setup_can_queue > 0)
+ atari_scsi_template.can_queue = setup_can_queue;
+
+ if (setup_cmd_per_lun > 0)
+ atari_scsi_template.cmd_per_lun = setup_cmd_per_lun;
+
+ /* Leave sg_tablesize at 0 on a Falcon! */
+ if (ATARIHW_PRESENT(TT_SCSI) && setup_sg_tablesize >= 0)
+ atari_scsi_template.sg_tablesize = setup_sg_tablesize;
+
+ if (setup_hostid >= 0) {
+ atari_scsi_template.this_id = setup_hostid & 7;
+ } else {
+ /* Test if a host id is set in the NVRam */
+ if (ATARIHW_PRESENT(TT_CLK) && nvram_check_checksum()) {
+ unsigned char b = nvram_read_byte(14);
+
+ /* Arbitration enabled? (for TOS)
+ * If yes, use configured host ID
+ */
+ if (b & 0x80)
+ atari_scsi_template.this_id = b & 7;
+ }
+ }
+
+
+#ifdef REAL_DMA
+ /* If running on a Falcon and if there's TT-Ram (i.e., more than one
+ * memory block, since there's always ST-Ram in a Falcon), then
+ * allocate a STRAM_BUFFER_SIZE byte dribble buffer for transfers
+ * from/to alternative Ram.
+ */
+ if (ATARIHW_PRESENT(ST_SCSI) && !ATARIHW_PRESENT(EXTD_DMA) &&
+ m68k_num_memory > 1) {
+ atari_dma_buffer = atari_stram_alloc(STRAM_BUFFER_SIZE, "SCSI");
+ if (!atari_dma_buffer) {
+ pr_err(PFX "can't allocate ST-RAM double buffer\n");
+ return -ENOMEM;
+ }
+ atari_dma_phys_buffer = atari_stram_to_phys(atari_dma_buffer);
+ atari_dma_orig_addr = 0;
+ }
+#endif
+
+ instance = scsi_host_alloc(&atari_scsi_template,
+ sizeof(struct NCR5380_hostdata));
+ if (!instance) {
+ error = -ENOMEM;
+ goto fail_alloc;
+ }
+ atari_scsi_host = instance;
+
+#ifdef CONFIG_ATARI_SCSI_RESET_BOOT
+ atari_scsi_reset_boot();
+#endif
+
+ instance->irq = irq->start;
+
+ host_flags |= IS_A_TT() ? 0 : FLAG_LATE_DMA_SETUP;
+
+#ifdef SUPPORT_TAGS
+ host_flags |= setup_use_tagged_queuing > 0 ? FLAG_TAGGED_QUEUING : 0;
+#endif
+
+ NCR5380_init(instance, host_flags);
+
+ if (IS_A_TT()) {
+ error = request_irq(instance->irq, scsi_tt_intr, 0,
+ "NCR5380", instance);
+ if (error) {
+ pr_err(PFX "request irq %d failed, aborting\n",
+ instance->irq);
+ goto fail_irq;
+ }
+ tt_mfp.active_edge |= 0x80; /* SCSI int on L->H */
+#ifdef REAL_DMA
+ tt_scsi_dma.dma_ctrl = 0;
+ atari_dma_residual = 0;
+
+ /* While the read overruns (described by Drew Eckhardt in
+ * NCR5380.c) never happened on TTs, they do in fact on the
+ * Medusa (This was the cause why SCSI didn't work right for
+ * so long there.) Since handling the overruns slows down
+ * a bit, I turned the #ifdef's into a runtime condition.
+ *
+ * In principle it should be sufficient to do max. 1 byte with
+ * PIO, but there is another problem on the Medusa with the DMA
+ * rest data register. So read_overruns is currently set
+ * to 4 to avoid having transfers that aren't a multiple of 4.
+ * If the rest data bug is fixed, this can be lowered to 1.
+ */
+ if (MACH_IS_MEDUSA) {
+ struct NCR5380_hostdata *hostdata =
+ shost_priv(instance);
+
+ hostdata->read_overruns = 4;
+ }
+#endif
+ } else {
+ /* Nothing to do for the interrupt: the ST-DMA is initialized
+ * already.
+ */
+#ifdef REAL_DMA
+ atari_dma_residual = 0;
+ atari_dma_active = 0;
+ atari_dma_stram_mask = (ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000
+ : 0xff000000);
+#endif
+ }
+
+ error = scsi_add_host(instance, NULL);
+ if (error)
+ goto fail_host;
+
+ platform_set_drvdata(pdev, instance);
+
+ scsi_scan_host(instance);
+ return 0;
+
+fail_host:
+ if (IS_A_TT())
+ free_irq(instance->irq, instance);
+fail_irq:
+ NCR5380_exit(instance);
+ scsi_host_put(instance);
+fail_alloc:
+ if (atari_dma_buffer)
+ atari_stram_free(atari_dma_buffer);
+ return error;
+}
+
+static int __exit atari_scsi_remove(struct platform_device *pdev)
+{
+ struct Scsi_Host *instance = platform_get_drvdata(pdev);
+
+ scsi_remove_host(instance);
+ if (IS_A_TT())
+ free_irq(instance->irq, instance);
+ NCR5380_exit(instance);
+ scsi_host_put(instance);
+ if (atari_dma_buffer)
+ atari_stram_free(atari_dma_buffer);
+ return 0;
+}
+
+static struct platform_driver atari_scsi_driver = {
+ .remove = __exit_p(atari_scsi_remove),
+ .driver = {
+ .name = DRV_MODULE_NAME,
+ .owner = THIS_MODULE,
+ },
+};
-#include "scsi_module.c"
+module_platform_driver_probe(atari_scsi_driver, atari_scsi_probe);
+MODULE_ALIAS("platform:" DRV_MODULE_NAME);
MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/atari_scsi.h b/drivers/scsi/atari_scsi.h
deleted file mode 100644
index 3299d91d7336..000000000000
--- a/drivers/scsi/atari_scsi.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * atari_scsi.h -- Header file for the Atari native SCSI driver
- *
- * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
- *
- * (Loosely based on the work of Robert De Vries' team)
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- *
- */
-
-
-#ifndef ATARI_SCSI_H
-#define ATARI_SCSI_H
-
-/* (I_HAVE_OVERRUNS stuff removed) */
-
-#ifndef ASM
-/* The values for CMD_PER_LUN and CAN_QUEUE are somehow arbitrary. Higher
- * values should work, too; try it! (but cmd_per_lun costs memory!) */
-
-/* But there seems to be a bug somewhere that requires CAN_QUEUE to be
- * 2*CMD_PER_LUN. At least on a TT, no spurious timeouts seen since
- * changed CMD_PER_LUN... */
-
-/* Note: The Falcon currently uses 8/1 setting due to unsolved problems with
- * cmd_per_lun != 1 */
-
-#define ATARI_TT_CAN_QUEUE 16
-#define ATARI_TT_CMD_PER_LUN 8
-#define ATARI_TT_SG_TABLESIZE SG_ALL
-
-#define ATARI_FALCON_CAN_QUEUE 8
-#define ATARI_FALCON_CMD_PER_LUN 1
-#define ATARI_FALCON_SG_TABLESIZE SG_NONE
-
-#define DEFAULT_USE_TAGGED_QUEUING 0
-
-
-#define NCR5380_implementation_fields /* none */
-
-#define NCR5380_read(reg) atari_scsi_reg_read( reg )
-#define NCR5380_write(reg, value) atari_scsi_reg_write( reg, value )
-
-#define NCR5380_intr atari_scsi_intr
-#define NCR5380_queue_command atari_scsi_queue_command
-#define NCR5380_abort atari_scsi_abort
-#define NCR5380_show_info atari_scsi_show_info
-#define NCR5380_dma_read_setup(inst,d,c) atari_scsi_dma_setup (inst, d, c, 0)
-#define NCR5380_dma_write_setup(inst,d,c) atari_scsi_dma_setup (inst, d, c, 1)
-#define NCR5380_dma_residual(inst) atari_scsi_dma_residual( inst )
-#define NCR5380_dma_xfer_len(i,cmd,phase) \
- atari_dma_xfer_len(cmd->SCp.this_residual,cmd,((phase) & SR_IO) ? 0 : 1)
-
-#endif /* ndef ASM */
-#endif /* ATARI_SCSI_H */
-
-
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 30d74a06b993..f3193406776c 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -556,7 +556,7 @@ static struct scsi_host_template beiscsi_sht = {
.name = "Emulex 10Gbe open-iscsi Initiator Driver",
.proc_name = DRV_NAME,
.queuecommand = iscsi_queuecommand,
- .change_queue_depth = iscsi_change_queue_depth,
+ .change_queue_depth = scsi_change_queue_depth,
.slave_configure = beiscsi_slave_configure,
.target_alloc = iscsi_target_alloc,
.eh_abort_handler = beiscsi_eh_abort,
@@ -570,7 +570,7 @@ static struct scsi_host_template beiscsi_sht = {
.cmd_per_lun = BEISCSI_CMD_PER_LUN,
.use_clustering = ENABLE_CLUSTERING,
.vendor_id = SCSI_NL_VID_TYPE_PCI | BE_VENDOR_ID,
-
+ .track_queue_depth = 1,
};
static struct scsi_transport_template *beiscsi_scsi_transport;
diff --git a/drivers/scsi/bfa/bfad_debugfs.c b/drivers/scsi/bfa/bfad_debugfs.c
index 8e83d0474fe7..74a307c0a240 100644
--- a/drivers/scsi/bfa/bfad_debugfs.c
+++ b/drivers/scsi/bfa/bfad_debugfs.c
@@ -260,18 +260,9 @@ bfad_debugfs_write_regrd(struct file *file, const char __user *buf,
unsigned long flags;
void *kern_buf;
- kern_buf = kzalloc(nbytes, GFP_KERNEL);
-
- if (!kern_buf) {
- printk(KERN_INFO "bfad[%d]: Failed to allocate buffer\n",
- bfad->inst_no);
- return -ENOMEM;
- }
-
- if (copy_from_user(kern_buf, (void __user *)buf, nbytes)) {
- kfree(kern_buf);
- return -ENOMEM;
- }
+ kern_buf = memdup_user(buf, nbytes);
+ if (IS_ERR(kern_buf))
+ return PTR_ERR(kern_buf);
rc = sscanf(kern_buf, "%x:%x", &addr, &len);
if (rc < 2) {
@@ -336,18 +327,9 @@ bfad_debugfs_write_regwr(struct file *file, const char __user *buf,
unsigned long flags;
void *kern_buf;
- kern_buf = kzalloc(nbytes, GFP_KERNEL);
-
- if (!kern_buf) {
- printk(KERN_INFO "bfad[%d]: Failed to allocate buffer\n",
- bfad->inst_no);
- return -ENOMEM;
- }
-
- if (copy_from_user(kern_buf, (void __user *)buf, nbytes)) {
- kfree(kern_buf);
- return -ENOMEM;
- }
+ kern_buf = memdup_user(buf, nbytes);
+ if (IS_ERR(kern_buf))
+ return PTR_ERR(kern_buf);
rc = sscanf(kern_buf, "%x:%x", &addr, &val);
if (rc < 2) {
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c
index 87b09cd232cc..7223b0006740 100644
--- a/drivers/scsi/bfa/bfad_im.c
+++ b/drivers/scsi/bfa/bfad_im.c
@@ -776,7 +776,7 @@ bfad_thread_workq(struct bfad_s *bfad)
static int
bfad_im_slave_configure(struct scsi_device *sdev)
{
- scsi_adjust_queue_depth(sdev, bfa_lun_queue_depth);
+ scsi_change_queue_depth(sdev, bfa_lun_queue_depth);
return 0;
}
@@ -866,7 +866,7 @@ bfad_ramp_up_qdepth(struct bfad_itnim_s *itnim, struct scsi_device *sdev)
if (bfa_lun_queue_depth > tmp_sdev->queue_depth) {
if (tmp_sdev->id != sdev->id)
continue;
- scsi_adjust_queue_depth(tmp_sdev,
+ scsi_change_queue_depth(tmp_sdev,
tmp_sdev->queue_depth + 1);
itnim->last_ramp_up_time = jiffies;
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
index 3c7db3e8aa76..e861f286b42e 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -1088,7 +1088,7 @@ static int bnx2fc_vport_create(struct fc_vport *vport, bool disabled)
mutex_unlock(&bnx2fc_dev_lock);
rtnl_unlock();
- if (IS_ERR(vn_port)) {
+ if (!vn_port) {
printk(KERN_ERR PFX "bnx2fc_vport_create (%s) failed\n",
netdev->name);
return -EIO;
@@ -2202,6 +2202,7 @@ static int _bnx2fc_create(struct net_device *netdev,
interface = bnx2fc_interface_create(hba, netdev, fip_mode);
if (!interface) {
printk(KERN_ERR PFX "bnx2fc_interface_create failed\n");
+ rc = -ENOMEM;
goto ifput_err;
}
@@ -2790,7 +2791,7 @@ static struct scsi_host_template bnx2fc_shost_template = {
.eh_target_reset_handler = bnx2fc_eh_target_reset, /* tgt reset */
.eh_host_reset_handler = fc_eh_host_reset,
.slave_alloc = fc_slave_alloc,
- .change_queue_depth = fc_change_queue_depth,
+ .change_queue_depth = scsi_change_queue_depth,
.change_queue_type = scsi_change_queue_type,
.this_id = -1,
.cmd_per_lun = 3,
@@ -2798,6 +2799,7 @@ static struct scsi_host_template bnx2fc_shost_template = {
.sg_tablesize = BNX2FC_MAX_BDS_PER_CMD,
.max_sectors = 1024,
.use_blk_tags = 1,
+ .track_queue_depth = 1,
};
static struct libfc_function_template bnx2fc_libfc_fcn_templ = {
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index 7a36388822aa..e53078d03309 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -2259,7 +2259,7 @@ static struct scsi_host_template bnx2i_host_template = {
.eh_abort_handler = iscsi_eh_abort,
.eh_device_reset_handler = iscsi_eh_device_reset,
.eh_target_reset_handler = iscsi_eh_recover_target,
- .change_queue_depth = iscsi_change_queue_depth,
+ .change_queue_depth = scsi_change_queue_depth,
.target_alloc = iscsi_target_alloc,
.can_queue = 2048,
.max_sectors = 127,
@@ -2268,6 +2268,7 @@ static struct scsi_host_template bnx2i_host_template = {
.use_clustering = ENABLE_CLUSTERING,
.sg_tablesize = ISCSI_MAX_BDS_PER_CMD,
.shost_attrs = bnx2i_dev_attributes,
+ .track_queue_depth = 1,
};
struct iscsi_transport bnx2i_iscsi_transport = {
diff --git a/drivers/scsi/csiostor/csio_scsi.c b/drivers/scsi/csiostor/csio_scsi.c
index 44a8cc51428f..4d0b6ce55f20 100644
--- a/drivers/scsi/csiostor/csio_scsi.c
+++ b/drivers/scsi/csiostor/csio_scsi.c
@@ -2241,7 +2241,7 @@ csio_slave_alloc(struct scsi_device *sdev)
static int
csio_slave_configure(struct scsi_device *sdev)
{
- scsi_adjust_queue_depth(sdev, csio_lun_qdepth);
+ scsi_change_queue_depth(sdev, csio_lun_qdepth);
return 0;
}
diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
index 49692a1ac44a..3db4c63978c5 100644
--- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
@@ -86,7 +86,7 @@ static struct scsi_host_template cxgb3i_host_template = {
.proc_name = DRV_MODULE_NAME,
.can_queue = CXGB3I_SCSI_HOST_QDEPTH,
.queuecommand = iscsi_queuecommand,
- .change_queue_depth = iscsi_change_queue_depth,
+ .change_queue_depth = scsi_change_queue_depth,
.sg_tablesize = SG_ALL,
.max_sectors = 0xFFFF,
.cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
@@ -96,6 +96,7 @@ static struct scsi_host_template cxgb3i_host_template = {
.target_alloc = iscsi_target_alloc,
.use_clustering = DISABLE_CLUSTERING,
.this_id = -1,
+ .track_queue_depth = 1,
};
static struct iscsi_transport cxgb3i_iscsi_transport = {
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
index 15081257cfc8..e6c3f55d9d36 100644
--- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
@@ -89,7 +89,7 @@ static struct scsi_host_template cxgb4i_host_template = {
.proc_name = DRV_MODULE_NAME,
.can_queue = CXGB4I_SCSI_HOST_QDEPTH,
.queuecommand = iscsi_queuecommand,
- .change_queue_depth = iscsi_change_queue_depth,
+ .change_queue_depth = scsi_change_queue_depth,
.sg_tablesize = SG_ALL,
.max_sectors = 0xFFFF,
.cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
@@ -99,6 +99,7 @@ static struct scsi_host_template cxgb4i_host_template = {
.target_alloc = iscsi_target_alloc,
.use_clustering = DISABLE_CLUSTERING,
.this_id = -1,
+ .track_queue_depth = 1,
};
static struct iscsi_transport cxgb4i_iscsi_transport = {
diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c
index 4b0dd8c56707..3e088125a8be 100644
--- a/drivers/scsi/dmx3191d.c
+++ b/drivers/scsi/dmx3191d.c
@@ -33,20 +33,20 @@
/*
* Definitions for the generic 5380 driver.
*/
-#define AUTOSENSE
+
+#define DONT_USE_INTR
#define NCR5380_read(reg) inb(port + reg)
#define NCR5380_write(reg, value) outb(value, port + reg)
-#define NCR5380_implementation_fields unsigned int port
-#define NCR5380_local_declare() NCR5380_implementation_fields
+#define NCR5380_implementation_fields /* none */
+#define NCR5380_local_declare() unsigned int port
#define NCR5380_setup(instance) port = instance->io_port
/*
* Includes needed for NCR5380.[ch] (XXX: Move them to NCR5380.h)
*/
#include <linux/delay.h>
-#include "scsi.h"
#include "NCR5380.h"
#include "NCR5380.c"
@@ -58,6 +58,7 @@
static struct scsi_host_template dmx3191d_driver_template = {
.proc_name = DMX3191D_DRIVER_NAME,
.name = "Domex DMX3191D",
+ .info = NCR5380_info,
.queuecommand = NCR5380_queue_command,
.eh_abort_handler = NCR5380_abort,
.eh_bus_reset_handler = NCR5380_bus_reset,
@@ -90,31 +91,23 @@ static int dmx3191d_probe_one(struct pci_dev *pdev,
if (!shost)
goto out_release_region;
shost->io_port = io;
- shost->irq = pdev->irq;
- NCR5380_init(shost, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E);
+ /* This card does not seem to raise an interrupt on pdev->irq.
+ * Steam-powered SCSI controllers run without an IRQ anyway.
+ */
+ shost->irq = NO_IRQ;
- if (request_irq(pdev->irq, NCR5380_intr, IRQF_SHARED,
- DMX3191D_DRIVER_NAME, shost)) {
- /*
- * Steam powered scsi controllers run without an IRQ anyway
- */
- printk(KERN_WARNING "dmx3191: IRQ %d not available - "
- "switching to polled mode.\n", pdev->irq);
- shost->irq = SCSI_IRQ_NONE;
- }
+ NCR5380_init(shost, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E);
pci_set_drvdata(pdev, shost);
error = scsi_add_host(shost, &pdev->dev);
if (error)
- goto out_free_irq;
+ goto out_release_region;
scsi_scan_host(shost);
return 0;
- out_free_irq:
- free_irq(shost->irq, shost);
out_release_region:
release_region(io, DMX3191D_REGION_LEN);
out_disable_device:
@@ -131,8 +124,6 @@ static void dmx3191d_remove_one(struct pci_dev *pdev)
NCR5380_exit(shost);
- if (shost->irq != SCSI_IRQ_NONE)
- free_irq(shost->irq, shost);
release_region(shost->io_port, DMX3191D_REGION_LEN);
pci_disable_device(pdev);
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 1af8d54bcded..0bf976936a10 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -415,7 +415,7 @@ static int adpt_slave_configure(struct scsi_device * device)
pHba = (adpt_hba *) host->hostdata[0];
if (host->can_queue && device->tagged_supported) {
- scsi_adjust_queue_depth(device,
+ scsi_change_queue_depth(device,
host->can_queue - 1);
}
return 0;
diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c
index 0a667fe05006..4c74c7ba2dff 100644
--- a/drivers/scsi/dtc.c
+++ b/drivers/scsi/dtc.c
@@ -1,5 +1,4 @@
-#define AUTOSENSE
#define PSEUDO_DMA
#define DONT_USE_INTR
#define UNSAFE /* Leave interrupts enabled during pseudo-dma I/O */
@@ -18,29 +17,9 @@
* (Unix and Linux consulting and custom programming)
* drew@colorado.edu
* +1 (303) 440-4894
- *
- * DISTRIBUTION RELEASE 1.
- *
- * For more information, please consult
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
-*/
+ */
/*
- * Options :
- * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
- * for commands that return with a CHECK CONDITION status.
- *
- * PSEUDO_DMA - enables PSEUDO-DMA hardware, should give a 3-4X performance
- * increase compared to polled I/O.
- *
- * PARITY - enable parity checking. Not supported.
- *
- * UNSAFE - leave interrupts enabled during pseudo-DMA transfers.
- * You probably want this.
- *
* The card is detected and initialized in one of several ways :
* 1. Autoprobe (default) - since the board is memory mapped,
* a BIOS signature is scanned for to locate the registers.
@@ -79,15 +58,11 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
-#include "scsi.h"
#include <scsi/scsi_host.h>
#include "dtc.h"
#define AUTOPROBE_IRQ
#include "NCR5380.h"
-
-#define DTC_PUBLIC_RELEASE 2
-
/*
* The DTC3180 & 3280 boards are memory mapped.
*
@@ -173,10 +148,13 @@ static const struct signature {
*
*/
-static void __init dtc_setup(char *str, int *ints)
+static int __init dtc_setup(char *str)
{
static int commandline_current = 0;
int i;
+ int ints[10];
+
+ get_options(str, ARRAY_SIZE(ints), ints);
if (ints[0] != 2)
printk("dtc_setup: usage dtc=address,irq\n");
else if (commandline_current < NO_OVERRIDES) {
@@ -189,7 +167,10 @@ static void __init dtc_setup(char *str, int *ints)
}
++commandline_current;
}
+ return 1;
}
+
+__setup("dtc=", dtc_setup);
#endif
/*
@@ -213,10 +194,6 @@ static int __init dtc_detect(struct scsi_host_template * tpnt)
void __iomem *base;
int sig, count;
- tpnt->proc_name = "dtc3x80";
- tpnt->show_info = dtc_show_info;
- tpnt->write_info = dtc_write_info;
-
for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
addr = 0;
base = NULL;
@@ -271,38 +248,33 @@ found:
else
instance->irq = NCR5380_probe_irq(instance, DTC_IRQS);
+ /* Compatibility with documented NCR5380 kernel parameters */
+ if (instance->irq == 255)
+ instance->irq = NO_IRQ;
+
#ifndef DONT_USE_INTR
/* With interrupts enabled, it will sometimes hang when doing heavy
* reads. So better not enable them until I finger it out. */
- if (instance->irq != SCSI_IRQ_NONE)
+ if (instance->irq != NO_IRQ)
if (request_irq(instance->irq, dtc_intr, 0,
"dtc", instance)) {
printk(KERN_ERR "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
- instance->irq = SCSI_IRQ_NONE;
+ instance->irq = NO_IRQ;
}
- if (instance->irq == SCSI_IRQ_NONE) {
+ if (instance->irq == NO_IRQ) {
printk(KERN_WARNING "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
printk(KERN_WARNING "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
}
#else
- if (instance->irq != SCSI_IRQ_NONE)
+ if (instance->irq != NO_IRQ)
printk(KERN_WARNING "scsi%d : interrupts not used. Might as well not jumper it.\n", instance->host_no);
- instance->irq = SCSI_IRQ_NONE;
+ instance->irq = NO_IRQ;
#endif
#if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT)
printk("scsi%d : irq = %d\n", instance->host_no, instance->irq);
#endif
- printk(KERN_INFO "scsi%d : at 0x%05X", instance->host_no, (int) instance->base);
- if (instance->irq == SCSI_IRQ_NONE)
- printk(" interrupts disabled");
- else
- printk(" irq %d", instance->irq);
- printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", CAN_QUEUE, CMD_PER_LUN, DTC_PUBLIC_RELEASE);
- NCR5380_print_options(instance);
- printk("\n");
-
++current_override;
++count;
}
@@ -354,20 +326,18 @@ static int dtc_biosparam(struct scsi_device *sdev, struct block_device *dev,
* timeout.
*/
-static int dtc_maxi = 0;
-static int dtc_wmaxi = 0;
-
static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len)
{
unsigned char *d = dst;
int i; /* For counting time spent in the poll-loop */
+ struct NCR5380_hostdata *hostdata = shost_priv(instance);
NCR5380_local_declare();
NCR5380_setup(instance);
i = 0;
NCR5380_read(RESET_PARITY_INTERRUPT_REG);
NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
- if (instance->irq == SCSI_IRQ_NONE)
+ if (instance->irq == NO_IRQ)
NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ);
else
NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ | CSR_INT_BASE);
@@ -391,8 +361,8 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
NCR5380_write(MODE_REG, 0); /* Clear the operating mode */
rtrc(0);
NCR5380_read(RESET_PARITY_INTERRUPT_REG);
- if (i > dtc_maxi)
- dtc_maxi = i;
+ if (i > hostdata->spin_max_r)
+ hostdata->spin_max_r = i;
return (0);
}
@@ -412,13 +382,14 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len)
{
int i;
+ struct NCR5380_hostdata *hostdata = shost_priv(instance);
NCR5380_local_declare();
NCR5380_setup(instance);
NCR5380_read(RESET_PARITY_INTERRUPT_REG);
NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
/* set direction (write) */
- if (instance->irq == SCSI_IRQ_NONE)
+ if (instance->irq == NO_IRQ)
NCR5380_write(DTC_CONTROL_REG, 0);
else
NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR);
@@ -444,8 +415,8 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
/* Check for parity error here. fixme. */
NCR5380_write(MODE_REG, 0); /* Clear the operating mode */
rtrc(0);
- if (i > dtc_wmaxi)
- dtc_wmaxi = i;
+ if (i > hostdata->spin_max_w)
+ hostdata->spin_max_w = i;
return (0);
}
@@ -457,7 +428,7 @@ static int dtc_release(struct Scsi_Host *shost)
{
NCR5380_local_declare();
NCR5380_setup(shost);
- if (shost->irq)
+ if (shost->irq != NO_IRQ)
free_irq(shost->irq, shost);
NCR5380_exit(shost);
if (shost->io_port && shost->n_io_port)
@@ -471,6 +442,10 @@ static struct scsi_host_template driver_template = {
.name = "DTC 3180/3280 ",
.detect = dtc_detect,
.release = dtc_release,
+ .proc_name = "dtc3x80",
+ .show_info = dtc_show_info,
+ .write_info = dtc_write_info,
+ .info = dtc_info,
.queuecommand = dtc_queue_command,
.eh_abort_handler = dtc_abort,
.eh_bus_reset_handler = dtc_bus_reset,
diff --git a/drivers/scsi/dtc.h b/drivers/scsi/dtc.h
index 92d7cfc3f4fc..78a2332e9064 100644
--- a/drivers/scsi/dtc.h
+++ b/drivers/scsi/dtc.h
@@ -5,24 +5,6 @@
* (Unix and Linux consulting and custom programming)
* drew@colorado.edu
* +1 (303) 440-4894
- *
- * DISTRIBUTION RELEASE 2.
- *
- * For more information, please consult
- *
- *
- *
- * and
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
*/
#ifndef DTC3280_H
@@ -32,13 +14,6 @@
#define DTCDEBUG_INIT 0x1
#define DTCDEBUG_TRANSFER 0x2
-static int dtc_abort(Scsi_Cmnd *);
-static int dtc_biosparam(struct scsi_device *, struct block_device *,
- sector_t, int*);
-static int dtc_detect(struct scsi_host_template *);
-static int dtc_queue_command(struct Scsi_Host *, struct scsi_cmnd *);
-static int dtc_bus_reset(Scsi_Cmnd *);
-
#ifndef CMD_PER_LUN
#define CMD_PER_LUN 2
#endif
@@ -88,6 +63,7 @@ static int dtc_bus_reset(Scsi_Cmnd *);
#define NCR5380_queue_command dtc_queue_command
#define NCR5380_abort dtc_abort
#define NCR5380_bus_reset dtc_bus_reset
+#define NCR5380_info dtc_info
#define NCR5380_show_info dtc_show_info
#define NCR5380_write_info dtc_write_info
diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c
index bc0f918f1729..227dd2c2ec2f 100644
--- a/drivers/scsi/eata.c
+++ b/drivers/scsi/eata.c
@@ -952,12 +952,12 @@ static int eata2x_slave_configure(struct scsi_device *dev)
} else {
tag_suffix = ", no tags";
}
- scsi_adjust_queue_depth(dev, tqd);
+ scsi_change_queue_depth(dev, tqd);
} else if (TLDEV(dev->type) && linked_comm) {
- scsi_adjust_queue_depth(dev, tqd);
+ scsi_change_queue_depth(dev, tqd);
tag_suffix = ", untagged";
} else {
- scsi_adjust_queue_depth(dev, utqd);
+ scsi_change_queue_depth(dev, utqd);
tag_suffix = "";
}
diff --git a/drivers/scsi/esas2r/esas2r.h b/drivers/scsi/esas2r/esas2r.h
index 1941d837f6f2..b6030e3edd01 100644
--- a/drivers/scsi/esas2r/esas2r.h
+++ b/drivers/scsi/esas2r/esas2r.h
@@ -972,7 +972,6 @@ u8 handle_hba_ioctl(struct esas2r_adapter *a,
struct atto_ioctl *ioctl_hba);
int esas2r_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd);
int esas2r_show_info(struct seq_file *m, struct Scsi_Host *sh);
-int esas2r_change_queue_depth(struct scsi_device *dev, int depth, int reason);
long esas2r_proc_ioctl(struct file *fp, unsigned int cmd, unsigned long arg);
/* SCSI error handler (eh) functions */
diff --git a/drivers/scsi/esas2r/esas2r_ioctl.c b/drivers/scsi/esas2r/esas2r_ioctl.c
index d89a0277a8e1..baf913047b48 100644
--- a/drivers/scsi/esas2r/esas2r_ioctl.c
+++ b/drivers/scsi/esas2r/esas2r_ioctl.c
@@ -117,9 +117,8 @@ static void do_fm_api(struct esas2r_adapter *a, struct esas2r_flash_img *fi)
rq = esas2r_alloc_request(a);
if (rq == NULL) {
- up(&a->fm_api_semaphore);
fi->status = FI_STAT_BUSY;
- return;
+ goto free_sem;
}
if (fi == &a->firmware.header) {
@@ -135,7 +134,7 @@ static void do_fm_api(struct esas2r_adapter *a, struct esas2r_flash_img *fi)
if (a->firmware.header_buff == NULL) {
esas2r_debug("failed to allocate header buffer!");
fi->status = FI_STAT_BUSY;
- return;
+ goto free_req;
}
memcpy(a->firmware.header_buff, fi,
@@ -171,9 +170,10 @@ all_done:
a->firmware.header_buff,
(dma_addr_t)a->firmware.header_buff_phys);
}
-
- up(&a->fm_api_semaphore);
+free_req:
esas2r_free_request(a, (struct esas2r_request *)rq);
+free_sem:
+ up(&a->fm_api_semaphore);
return;
}
@@ -1420,9 +1420,10 @@ int esas2r_ioctl_handler(void *hostdata, int cmd, void __user *arg)
rq = esas2r_alloc_request(a);
if (rq == NULL) {
- up(&a->nvram_semaphore);
- ioctl->data.prw.code = 0;
- break;
+ kfree(ioctl);
+ esas2r_log(ESAS2R_LOG_WARN,
+ "could not allocate an internal request");
+ return -ENOMEM;
}
code = esas2r_write_params(a, rq,
@@ -1523,9 +1524,12 @@ ioctl_done:
case -EINVAL:
ioctl->header.return_code = IOCTL_INVALID_PARAM;
break;
+
+ default:
+ ioctl->header.return_code = IOCTL_GENERAL_ERROR;
+ break;
}
- ioctl->header.return_code = IOCTL_GENERAL_ERROR;
}
/* Always copy the buffer back, if only to pick up the status */
diff --git a/drivers/scsi/esas2r/esas2r_main.c b/drivers/scsi/esas2r/esas2r_main.c
index 30fce64faf75..593ff8a63c70 100644
--- a/drivers/scsi/esas2r/esas2r_main.c
+++ b/drivers/scsi/esas2r/esas2r_main.c
@@ -254,7 +254,7 @@ static struct scsi_host_template driver_template = {
.use_clustering = ENABLE_CLUSTERING,
.emulated = 0,
.proc_name = ESAS2R_DRVR_NAME,
- .change_queue_depth = esas2r_change_queue_depth,
+ .change_queue_depth = scsi_change_queue_depth,
.change_queue_type = scsi_change_queue_type,
.max_sectors = 0xFFFF,
.use_blk_tags = 1,
@@ -1257,15 +1257,6 @@ int esas2r_target_reset(struct scsi_cmnd *cmd)
return esas2r_dev_targ_reset(cmd, true);
}
-int esas2r_change_queue_depth(struct scsi_device *dev, int depth, int reason)
-{
- esas2r_log(ESAS2R_LOG_INFO, "change_queue_depth %p, %d", dev, depth);
-
- scsi_adjust_queue_depth(dev, depth);
-
- return dev->queue_depth;
-}
-
void esas2r_log_request_failure(struct esas2r_adapter *a,
struct esas2r_request *rq)
{
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index 38c23e0b73af..ce5bd52fe692 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -49,55 +49,67 @@ static u32 esp_debug;
#define ESP_DEBUG_DATADONE 0x00000100
#define ESP_DEBUG_RECONNECT 0x00000200
#define ESP_DEBUG_AUTOSENSE 0x00000400
+#define ESP_DEBUG_EVENT 0x00000800
+#define ESP_DEBUG_COMMAND 0x00001000
#define esp_log_intr(f, a...) \
do { if (esp_debug & ESP_DEBUG_INTR) \
- printk(f, ## a); \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
} while (0)
#define esp_log_reset(f, a...) \
do { if (esp_debug & ESP_DEBUG_RESET) \
- printk(f, ## a); \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
} while (0)
#define esp_log_msgin(f, a...) \
do { if (esp_debug & ESP_DEBUG_MSGIN) \
- printk(f, ## a); \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
} while (0)
#define esp_log_msgout(f, a...) \
do { if (esp_debug & ESP_DEBUG_MSGOUT) \
- printk(f, ## a); \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
} while (0)
#define esp_log_cmddone(f, a...) \
do { if (esp_debug & ESP_DEBUG_CMDDONE) \
- printk(f, ## a); \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
} while (0)
#define esp_log_disconnect(f, a...) \
do { if (esp_debug & ESP_DEBUG_DISCONNECT) \
- printk(f, ## a); \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
} while (0)
#define esp_log_datastart(f, a...) \
do { if (esp_debug & ESP_DEBUG_DATASTART) \
- printk(f, ## a); \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
} while (0)
#define esp_log_datadone(f, a...) \
do { if (esp_debug & ESP_DEBUG_DATADONE) \
- printk(f, ## a); \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
} while (0)
#define esp_log_reconnect(f, a...) \
do { if (esp_debug & ESP_DEBUG_RECONNECT) \
- printk(f, ## a); \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
} while (0)
#define esp_log_autosense(f, a...) \
do { if (esp_debug & ESP_DEBUG_AUTOSENSE) \
- printk(f, ## a); \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
+} while (0)
+
+#define esp_log_event(f, a...) \
+do { if (esp_debug & ESP_DEBUG_EVENT) \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
+} while (0)
+
+#define esp_log_command(f, a...) \
+do { if (esp_debug & ESP_DEBUG_COMMAND) \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
} while (0)
#define esp_read8(REG) esp->ops->esp_read8(esp, REG)
@@ -126,10 +138,29 @@ void scsi_esp_cmd(struct esp *esp, u8 val)
esp->esp_event_cur = (idx + 1) & (ESP_EVENT_LOG_SZ - 1);
+ esp_log_command("cmd[%02x]\n", val);
esp_write8(val, ESP_CMD);
}
EXPORT_SYMBOL(scsi_esp_cmd);
+static void esp_send_dma_cmd(struct esp *esp, int len, int max_len, int cmd)
+{
+ if (esp->flags & ESP_FLAG_USE_FIFO) {
+ int i;
+
+ scsi_esp_cmd(esp, ESP_CMD_FLUSH);
+ for (i = 0; i < len; i++)
+ esp_write8(esp->command_block[i], ESP_FDATA);
+ scsi_esp_cmd(esp, cmd);
+ } else {
+ if (esp->rev == FASHME)
+ scsi_esp_cmd(esp, ESP_CMD_FLUSH);
+ cmd |= ESP_CMD_DMA;
+ esp->ops->send_dma_cmd(esp, esp->command_block_dma,
+ len, max_len, 0, cmd);
+ }
+}
+
static void esp_event(struct esp *esp, u8 val)
{
struct esp_event_ent *p;
@@ -150,19 +181,17 @@ static void esp_dump_cmd_log(struct esp *esp)
int idx = esp->esp_event_cur;
int stop = idx;
- printk(KERN_INFO PFX "esp%d: Dumping command log\n",
- esp->host->unique_id);
+ shost_printk(KERN_INFO, esp->host, "Dumping command log\n");
do {
struct esp_event_ent *p = &esp->esp_event_log[idx];
- printk(KERN_INFO PFX "esp%d: ent[%d] %s ",
- esp->host->unique_id, idx,
- p->type == ESP_EVENT_TYPE_CMD ? "CMD" : "EVENT");
-
- printk("val[%02x] sreg[%02x] seqreg[%02x] "
- "sreg2[%02x] ireg[%02x] ss[%02x] event[%02x]\n",
- p->val, p->sreg, p->seqreg,
- p->sreg2, p->ireg, p->select_state, p->event);
+ shost_printk(KERN_INFO, esp->host,
+ "ent[%d] %s val[%02x] sreg[%02x] seqreg[%02x] "
+ "sreg2[%02x] ireg[%02x] ss[%02x] event[%02x]\n",
+ idx,
+ p->type == ESP_EVENT_TYPE_CMD ? "CMD" : "EVENT",
+ p->val, p->sreg, p->seqreg,
+ p->sreg2, p->ireg, p->select_state, p->event);
idx = (idx + 1) & (ESP_EVENT_LOG_SZ - 1);
} while (idx != stop);
@@ -176,9 +205,8 @@ static void esp_flush_fifo(struct esp *esp)
while (esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES) {
if (--lim == 0) {
- printk(KERN_ALERT PFX "esp%d: ESP_FF_BYTES "
- "will not clear!\n",
- esp->host->unique_id);
+ shost_printk(KERN_ALERT, esp->host,
+ "ESP_FF_BYTES will not clear!\n");
break;
}
udelay(1);
@@ -240,6 +268,19 @@ static void esp_reset_esp(struct esp *esp)
} else {
esp->min_period = ((5 * esp->ccycle) / 1000);
}
+ if (esp->rev == FAS236) {
+ /*
+ * The AM53c974 chip returns the same ID as FAS236;
+ * try to configure glitch eater.
+ */
+ u8 config4 = ESP_CONFIG4_GE1;
+ esp_write8(config4, ESP_CFG4);
+ config4 = esp_read8(ESP_CFG4);
+ if (config4 & ESP_CONFIG4_GE1) {
+ esp->rev = PCSCSI;
+ esp_write8(esp->config4, ESP_CFG4);
+ }
+ }
esp->max_period = (esp->max_period + 3)>>2;
esp->min_period = (esp->min_period + 3)>>2;
@@ -265,7 +306,8 @@ static void esp_reset_esp(struct esp *esp)
/* fallthrough... */
case FAS236:
- /* Fast 236 or HME */
+ case PCSCSI:
+ /* Fast 236, AM53c974 or HME */
esp_write8(esp->config2, ESP_CFG2);
if (esp->rev == FASHME) {
u8 cfg3 = esp->target[0].esp_config3;
@@ -383,12 +425,11 @@ static void esp_advance_dma(struct esp *esp, struct esp_cmd_entry *ent,
p->cur_residue -= len;
p->tot_residue -= len;
if (p->cur_residue < 0 || p->tot_residue < 0) {
- printk(KERN_ERR PFX "esp%d: Data transfer overflow.\n",
- esp->host->unique_id);
- printk(KERN_ERR PFX "esp%d: cur_residue[%d] tot_residue[%d] "
- "len[%u]\n",
- esp->host->unique_id,
- p->cur_residue, p->tot_residue, len);
+ shost_printk(KERN_ERR, esp->host,
+ "Data transfer overflow.\n");
+ shost_printk(KERN_ERR, esp->host,
+ "cur_residue[%d] tot_residue[%d] len[%u]\n",
+ p->cur_residue, p->tot_residue, len);
p->cur_residue = 0;
p->tot_residue = 0;
}
@@ -604,9 +645,8 @@ static void esp_autosense(struct esp *esp, struct esp_cmd_entry *ent)
if (!ent->sense_ptr) {
- esp_log_autosense("esp%d: Doing auto-sense for "
- "tgt[%d] lun[%d]\n",
- esp->host->unique_id, tgt, lun);
+ esp_log_autosense("Doing auto-sense for tgt[%d] lun[%d]\n",
+ tgt, lun);
ent->sense_ptr = cmd->sense_buffer;
ent->sense_dma = esp->ops->map_single(esp,
@@ -642,10 +682,7 @@ static void esp_autosense(struct esp *esp, struct esp_cmd_entry *ent)
val = (p - esp->command_block);
- if (esp->rev == FASHME)
- scsi_esp_cmd(esp, ESP_CMD_FLUSH);
- esp->ops->send_dma_cmd(esp, esp->command_block_dma,
- val, 16, 0, ESP_CMD_DMA | ESP_CMD_SELA);
+ esp_send_dma_cmd(esp, val, 16, ESP_CMD_SELA);
}
static struct esp_cmd_entry *find_and_prep_issuable_command(struct esp *esp)
@@ -781,12 +818,12 @@ build_identify:
}
if (!(esp->flags & ESP_FLAG_DOING_SLOWCMD)) {
- start_cmd = ESP_CMD_DMA | ESP_CMD_SELA;
+ start_cmd = ESP_CMD_SELA;
if (ent->tag[0]) {
*p++ = ent->tag[0];
*p++ = ent->tag[1];
- start_cmd = ESP_CMD_DMA | ESP_CMD_SA3;
+ start_cmd = ESP_CMD_SA3;
}
for (i = 0; i < cmd->cmd_len; i++)
@@ -806,7 +843,7 @@ build_identify:
esp->msg_out_len += 2;
}
- start_cmd = ESP_CMD_DMA | ESP_CMD_SELAS;
+ start_cmd = ESP_CMD_SELAS;
esp->select_state = ESP_SELECT_MSGOUT;
}
val = tgt;
@@ -826,10 +863,7 @@ build_identify:
printk("]\n");
}
- if (esp->rev == FASHME)
- scsi_esp_cmd(esp, ESP_CMD_FLUSH);
- esp->ops->send_dma_cmd(esp, esp->command_block_dma,
- val, 16, 0, start_cmd);
+ esp_send_dma_cmd(esp, val, 16, start_cmd);
}
static struct esp_cmd_entry *esp_get_ent(struct esp *esp)
@@ -953,8 +987,8 @@ static int esp_check_gross_error(struct esp *esp)
* - DMA programmed with wrong direction
* - improper phase change
*/
- printk(KERN_ERR PFX "esp%d: Gross error sreg[%02x]\n",
- esp->host->unique_id, esp->sreg);
+ shost_printk(KERN_ERR, esp->host,
+ "Gross error sreg[%02x]\n", esp->sreg);
/* XXX Reset the chip. XXX */
return 1;
}
@@ -974,7 +1008,6 @@ static int esp_check_spur_intr(struct esp *esp)
default:
if (!(esp->sreg & ESP_STAT_INTR)) {
- esp->ireg = esp_read8(ESP_INTRPT);
if (esp->ireg & ESP_INTR_SR)
return 1;
@@ -982,14 +1015,13 @@ static int esp_check_spur_intr(struct esp *esp)
* ESP is not, the only possibility is a DMA error.
*/
if (!esp->ops->dma_error(esp)) {
- printk(KERN_ERR PFX "esp%d: Spurious irq, "
- "sreg=%02x.\n",
- esp->host->unique_id, esp->sreg);
+ shost_printk(KERN_ERR, esp->host,
+ "Spurious irq, sreg=%02x.\n",
+ esp->sreg);
return -1;
}
- printk(KERN_ERR PFX "esp%d: DMA error\n",
- esp->host->unique_id);
+ shost_printk(KERN_ERR, esp->host, "DMA error\n");
/* XXX Reset the chip. XXX */
return -1;
@@ -1002,7 +1034,7 @@ static int esp_check_spur_intr(struct esp *esp)
static void esp_schedule_reset(struct esp *esp)
{
- esp_log_reset("ESP: esp_schedule_reset() from %pf\n",
+ esp_log_reset("esp_schedule_reset() from %pf\n",
__builtin_return_address(0));
esp->flags |= ESP_FLAG_RESETTING;
esp_event(esp, ESP_EVENT_RESET);
@@ -1019,20 +1051,20 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp,
int i;
if (!lp->num_tagged) {
- printk(KERN_ERR PFX "esp%d: Reconnect w/num_tagged==0\n",
- esp->host->unique_id);
+ shost_printk(KERN_ERR, esp->host,
+ "Reconnect w/num_tagged==0\n");
return NULL;
}
- esp_log_reconnect("ESP: reconnect tag, ");
+ esp_log_reconnect("reconnect tag, ");
for (i = 0; i < ESP_QUICKIRQ_LIMIT; i++) {
if (esp->ops->irq_pending(esp))
break;
}
if (i == ESP_QUICKIRQ_LIMIT) {
- printk(KERN_ERR PFX "esp%d: Reconnect IRQ1 timeout\n",
- esp->host->unique_id);
+ shost_printk(KERN_ERR, esp->host,
+ "Reconnect IRQ1 timeout\n");
return NULL;
}
@@ -1043,14 +1075,14 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp,
i, esp->ireg, esp->sreg);
if (esp->ireg & ESP_INTR_DC) {
- printk(KERN_ERR PFX "esp%d: Reconnect, got disconnect.\n",
- esp->host->unique_id);
+ shost_printk(KERN_ERR, esp->host,
+ "Reconnect, got disconnect.\n");
return NULL;
}
if ((esp->sreg & ESP_STAT_PMASK) != ESP_MIP) {
- printk(KERN_ERR PFX "esp%d: Reconnect, not MIP sreg[%02x].\n",
- esp->host->unique_id, esp->sreg);
+ shost_printk(KERN_ERR, esp->host,
+ "Reconnect, not MIP sreg[%02x].\n", esp->sreg);
return NULL;
}
@@ -1073,8 +1105,7 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp,
udelay(1);
}
if (i == ESP_RESELECT_TAG_LIMIT) {
- printk(KERN_ERR PFX "esp%d: Reconnect IRQ2 timeout\n",
- esp->host->unique_id);
+ shost_printk(KERN_ERR, esp->host, "Reconnect IRQ2 timeout\n");
return NULL;
}
esp->ops->dma_drain(esp);
@@ -1087,17 +1118,17 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp,
if (esp->command_block[0] < SIMPLE_QUEUE_TAG ||
esp->command_block[0] > ORDERED_QUEUE_TAG) {
- printk(KERN_ERR PFX "esp%d: Reconnect, bad tag "
- "type %02x.\n",
- esp->host->unique_id, esp->command_block[0]);
+ shost_printk(KERN_ERR, esp->host,
+ "Reconnect, bad tag type %02x.\n",
+ esp->command_block[0]);
return NULL;
}
ent = lp->tagged_cmds[esp->command_block[1]];
if (!ent) {
- printk(KERN_ERR PFX "esp%d: Reconnect, no entry for "
- "tag %02x.\n",
- esp->host->unique_id, esp->command_block[1]);
+ shost_printk(KERN_ERR, esp->host,
+ "Reconnect, no entry for tag %02x.\n",
+ esp->command_block[1]);
return NULL;
}
@@ -1163,9 +1194,9 @@ static int esp_reconnect(struct esp *esp)
tp = &esp->target[target];
dev = __scsi_device_lookup_by_target(tp->starget, lun);
if (!dev) {
- printk(KERN_ERR PFX "esp%d: Reconnect, no lp "
- "tgt[%u] lun[%u]\n",
- esp->host->unique_id, target, lun);
+ shost_printk(KERN_ERR, esp->host,
+ "Reconnect, no lp tgt[%u] lun[%u]\n",
+ target, lun);
goto do_reset;
}
lp = dev->hostdata;
@@ -1291,8 +1322,8 @@ static int esp_finish_select(struct esp *esp)
return 0;
}
- printk("ESP: Unexpected selection completion ireg[%x].\n",
- esp->ireg);
+ shost_printk(KERN_INFO, esp->host,
+ "Unexpected selection completion ireg[%x]\n", esp->ireg);
esp_schedule_reset(esp);
return 0;
}
@@ -1312,11 +1343,42 @@ static int esp_data_bytes_sent(struct esp *esp, struct esp_cmd_entry *ent,
(((unsigned int)esp_read8(ESP_TCMED)) << 8));
if (esp->rev == FASHME)
ecount |= ((unsigned int)esp_read8(FAS_RLO)) << 16;
+ if (esp->rev == PCSCSI && (esp->config2 & ESP_CONFIG2_FENAB))
+ ecount |= ((unsigned int)esp_read8(ESP_TCHI)) << 16;
}
bytes_sent = esp->data_dma_len;
bytes_sent -= ecount;
+ /*
+ * The am53c974 has a DMA 'pecularity'. The doc states:
+ * In some odd byte conditions, one residual byte will
+ * be left in the SCSI FIFO, and the FIFO Flags will
+ * never count to '0 '. When this happens, the residual
+ * byte should be retrieved via PIO following completion
+ * of the BLAST operation.
+ */
+ if (fifo_cnt == 1 && ent->flags & ESP_CMD_FLAG_RESIDUAL) {
+ size_t count = 1;
+ size_t offset = bytes_sent;
+ u8 bval = esp_read8(ESP_FDATA);
+
+ if (ent->flags & ESP_CMD_FLAG_AUTOSENSE)
+ ent->sense_ptr[bytes_sent] = bval;
+ else {
+ struct esp_cmd_priv *p = ESP_CMD_PRIV(cmd);
+ u8 *ptr;
+
+ ptr = scsi_kmap_atomic_sg(p->cur_sg, p->u.num_sg,
+ &offset, &count);
+ if (likely(ptr)) {
+ *(ptr + offset) = bval;
+ scsi_kunmap_atomic_sg(ptr);
+ }
+ }
+ bytes_sent += fifo_cnt;
+ ent->flags &= ~ESP_CMD_FLAG_RESIDUAL;
+ }
if (!(ent->flags & ESP_CMD_FLAG_WRITE))
bytes_sent -= fifo_cnt;
@@ -1556,8 +1618,8 @@ static void esp_msgin_extended(struct esp *esp)
return;
}
- printk("ESP: Unexpected extended msg type %x\n",
- esp->msg_in[2]);
+ shost_printk(KERN_INFO, esp->host,
+ "Unexpected extended msg type %x\n", esp->msg_in[2]);
esp->msg_out[0] = ABORT_TASK_SET;
esp->msg_out_len = 1;
@@ -1574,7 +1636,8 @@ static int esp_msgin_process(struct esp *esp)
if (msg0 & 0x80) {
/* Identify */
- printk("ESP: Unexpected msgin identify\n");
+ shost_printk(KERN_INFO, esp->host,
+ "Unexpected msgin identify\n");
return 0;
}
@@ -1640,10 +1703,12 @@ static int esp_msgin_process(struct esp *esp)
static int esp_process_event(struct esp *esp)
{
- int write;
+ int write, i;
again:
write = 0;
+ esp_log_event("process event %d phase %x\n",
+ esp->event, esp->sreg & ESP_STAT_PMASK);
switch (esp->event) {
case ESP_EVENT_CHECK_PHASE:
switch (esp->sreg & ESP_STAT_PMASK) {
@@ -1673,8 +1738,9 @@ again:
break;
default:
- printk("ESP: Unexpected phase, sreg=%02x\n",
- esp->sreg);
+ shost_printk(KERN_INFO, esp->host,
+ "Unexpected phase, sreg=%02x\n",
+ esp->sreg);
esp_schedule_reset(esp);
return 0;
}
@@ -1708,18 +1774,17 @@ again:
esp->data_dma_len = dma_len;
if (!dma_len) {
- printk(KERN_ERR PFX "esp%d: DMA length is zero!\n",
- esp->host->unique_id);
- printk(KERN_ERR PFX "esp%d: cur adr[%08llx] len[%08x]\n",
- esp->host->unique_id,
- (unsigned long long)esp_cur_dma_addr(ent, cmd),
- esp_cur_dma_len(ent, cmd));
+ shost_printk(KERN_ERR, esp->host,
+ "DMA length is zero!\n");
+ shost_printk(KERN_ERR, esp->host,
+ "cur adr[%08llx] len[%08x]\n",
+ (unsigned long long)esp_cur_dma_addr(ent, cmd),
+ esp_cur_dma_len(ent, cmd));
esp_schedule_reset(esp);
return 0;
}
- esp_log_datastart("ESP: start data addr[%08llx] len[%u] "
- "write(%d)\n",
+ esp_log_datastart("start data addr[%08llx] len[%u] write(%d)\n",
(unsigned long long)dma_addr, dma_len, write);
esp->ops->send_dma_cmd(esp, dma_addr, dma_len, dma_len,
@@ -1733,7 +1798,8 @@ again:
int bytes_sent;
if (esp->ops->dma_error(esp)) {
- printk("ESP: data done, DMA error, resetting\n");
+ shost_printk(KERN_INFO, esp->host,
+ "data done, DMA error, resetting\n");
esp_schedule_reset(esp);
return 0;
}
@@ -1749,14 +1815,15 @@ again:
/* We should always see exactly a bus-service
* interrupt at the end of a successful transfer.
*/
- printk("ESP: data done, not BSERV, resetting\n");
+ shost_printk(KERN_INFO, esp->host,
+ "data done, not BSERV, resetting\n");
esp_schedule_reset(esp);
return 0;
}
bytes_sent = esp_data_bytes_sent(esp, ent, cmd);
- esp_log_datadone("ESP: data done flgs[%x] sent[%d]\n",
+ esp_log_datadone("data done flgs[%x] sent[%d]\n",
ent->flags, bytes_sent);
if (bytes_sent < 0) {
@@ -1785,8 +1852,9 @@ again:
}
if (ent->message != COMMAND_COMPLETE) {
- printk("ESP: Unexpected message %x in status\n",
- ent->message);
+ shost_printk(KERN_INFO, esp->host,
+ "Unexpected message %x in status\n",
+ ent->message);
esp_schedule_reset(esp);
return 0;
}
@@ -1804,8 +1872,7 @@ again:
scsi_esp_cmd(esp, ESP_CMD_ESEL);
if (ent->message == COMMAND_COMPLETE) {
- esp_log_cmddone("ESP: Command done status[%x] "
- "message[%x]\n",
+ esp_log_cmddone("Command done status[%x] message[%x]\n",
ent->status, ent->message);
if (ent->status == SAM_STAT_TASK_SET_FULL)
esp_event_queue_full(esp, ent);
@@ -1821,16 +1888,16 @@ again:
DID_OK));
}
} else if (ent->message == DISCONNECT) {
- esp_log_disconnect("ESP: Disconnecting tgt[%d] "
- "tag[%x:%x]\n",
+ esp_log_disconnect("Disconnecting tgt[%d] tag[%x:%x]\n",
cmd->device->id,
ent->tag[0], ent->tag[1]);
esp->active_cmd = NULL;
esp_maybe_execute_command(esp);
} else {
- printk("ESP: Unexpected message %x in freebus\n",
- ent->message);
+ shost_printk(KERN_INFO, esp->host,
+ "Unexpected message %x in freebus\n",
+ ent->message);
esp_schedule_reset(esp);
return 0;
}
@@ -1862,6 +1929,10 @@ again:
if (esp->msg_out_len == 1) {
esp_write8(esp->msg_out[0], ESP_FDATA);
scsi_esp_cmd(esp, ESP_CMD_TI);
+ } else if (esp->flags & ESP_FLAG_USE_FIFO) {
+ for (i = 0; i < esp->msg_out_len; i++)
+ esp_write8(esp->msg_out[i], ESP_FDATA);
+ scsi_esp_cmd(esp, ESP_CMD_TI);
} else {
/* Use DMA. */
memcpy(esp->command_block,
@@ -1917,7 +1988,7 @@ again:
val = esp_read8(ESP_FDATA);
esp->msg_in[esp->msg_in_len++] = val;
- esp_log_msgin("ESP: Got msgin byte %x\n", val);
+ esp_log_msgin("Got msgin byte %x\n", val);
if (!esp_msgin_process(esp))
esp->msg_in_len = 0;
@@ -1930,7 +2001,8 @@ again:
if (esp->event != ESP_EVENT_FREE_BUS)
esp_event(esp, ESP_EVENT_CHECK_PHASE);
} else {
- printk("ESP: MSGIN neither BSERV not FDON, resetting");
+ shost_printk(KERN_INFO, esp->host,
+ "MSGIN neither BSERV not FDON, resetting");
esp_schedule_reset(esp);
return 0;
}
@@ -1938,11 +2010,7 @@ again:
case ESP_EVENT_CMD_START:
memcpy(esp->command_block, esp->cmd_bytes_ptr,
esp->cmd_bytes_left);
- if (esp->rev == FASHME)
- scsi_esp_cmd(esp, ESP_CMD_FLUSH);
- esp->ops->send_dma_cmd(esp, esp->command_block_dma,
- esp->cmd_bytes_left, 16, 0,
- ESP_CMD_DMA | ESP_CMD_TI);
+ esp_send_dma_cmd(esp, esp->cmd_bytes_left, 16, ESP_CMD_TI);
esp_event(esp, ESP_EVENT_CMD_DONE);
esp->flags |= ESP_FLAG_QUICKIRQ_CHECK;
break;
@@ -1961,8 +2029,8 @@ again:
break;
default:
- printk("ESP: Unexpected event %x, resetting\n",
- esp->event);
+ shost_printk(KERN_INFO, esp->host,
+ "Unexpected event %x, resetting\n", esp->event);
esp_schedule_reset(esp);
return 0;
break;
@@ -2044,7 +2112,12 @@ static void __esp_interrupt(struct esp *esp)
int finish_reset, intr_done;
u8 phase;
+ /*
+ * Once INTRPT is read STATUS and SSTEP are cleared.
+ */
esp->sreg = esp_read8(ESP_STATUS);
+ esp->seqreg = esp_read8(ESP_SSTEP);
+ esp->ireg = esp_read8(ESP_INTRPT);
if (esp->flags & ESP_FLAG_RESETTING) {
finish_reset = 1;
@@ -2057,8 +2130,6 @@ static void __esp_interrupt(struct esp *esp)
return;
}
- esp->ireg = esp_read8(ESP_INTRPT);
-
if (esp->ireg & ESP_INTR_SR)
finish_reset = 1;
@@ -2085,14 +2156,15 @@ static void __esp_interrupt(struct esp *esp)
}
}
- esp_log_intr("ESP: intr sreg[%02x] seqreg[%02x] "
+ esp_log_intr("intr sreg[%02x] seqreg[%02x] "
"sreg2[%02x] ireg[%02x]\n",
esp->sreg, esp->seqreg, esp->sreg2, esp->ireg);
intr_done = 0;
if (esp->ireg & (ESP_INTR_S | ESP_INTR_SATN | ESP_INTR_IC)) {
- printk("ESP: unexpected IREG %02x\n", esp->ireg);
+ shost_printk(KERN_INFO, esp->host,
+ "unexpected IREG %02x\n", esp->ireg);
if (esp->ireg & ESP_INTR_IC)
esp_dump_cmd_log(esp);
@@ -2149,46 +2221,50 @@ static void esp_get_revision(struct esp *esp)
u8 val;
esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7));
- esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);
+ if (esp->config2 == 0) {
+ esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);
+ esp_write8(esp->config2, ESP_CFG2);
+
+ val = esp_read8(ESP_CFG2);
+ val &= ~ESP_CONFIG2_MAGIC;
+
+ esp->config2 = 0;
+ if (val != (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {
+ /*
+ * If what we write to cfg2 does not come back,
+ * cfg2 is not implemented.
+ * Therefore this must be a plain esp100.
+ */
+ esp->rev = ESP100;
+ return;
+ }
+ }
+
+ esp_set_all_config3(esp, 5);
+ esp->prev_cfg3 = 5;
esp_write8(esp->config2, ESP_CFG2);
+ esp_write8(0, ESP_CFG3);
+ esp_write8(esp->prev_cfg3, ESP_CFG3);
- val = esp_read8(ESP_CFG2);
- val &= ~ESP_CONFIG2_MAGIC;
- if (val != (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {
- /* If what we write to cfg2 does not come back, cfg2 is not
- * implemented, therefore this must be a plain esp100.
+ val = esp_read8(ESP_CFG3);
+ if (val != 5) {
+ /* The cfg2 register is implemented, however
+ * cfg3 is not, must be esp100a.
*/
- esp->rev = ESP100;
+ esp->rev = ESP100A;
} else {
- esp->config2 = 0;
- esp_set_all_config3(esp, 5);
- esp->prev_cfg3 = 5;
- esp_write8(esp->config2, ESP_CFG2);
- esp_write8(0, ESP_CFG3);
+ esp_set_all_config3(esp, 0);
+ esp->prev_cfg3 = 0;
esp_write8(esp->prev_cfg3, ESP_CFG3);
- val = esp_read8(ESP_CFG3);
- if (val != 5) {
- /* The cfg2 register is implemented, however
- * cfg3 is not, must be esp100a.
- */
- esp->rev = ESP100A;
+ /* All of cfg{1,2,3} implemented, must be one of
+ * the fas variants, figure out which one.
+ */
+ if (esp->cfact == 0 || esp->cfact > ESP_CCF_F5) {
+ esp->rev = FAST;
+ esp->sync_defp = SYNC_DEFP_FAST;
} else {
- esp_set_all_config3(esp, 0);
- esp->prev_cfg3 = 0;
- esp_write8(esp->prev_cfg3, ESP_CFG3);
-
- /* All of cfg{1,2,3} implemented, must be one of
- * the fas variants, figure out which one.
- */
- if (esp->cfact == 0 || esp->cfact > ESP_CCF_F5) {
- esp->rev = FAST;
- esp->sync_defp = SYNC_DEFP_FAST;
- } else {
- esp->rev = ESP236;
- }
- esp->config2 = 0;
- esp_write8(esp->config2, ESP_CFG2);
+ esp->rev = ESP236;
}
}
}
@@ -2308,6 +2384,7 @@ static const char *esp_chip_names[] = {
"FAS100A",
"FAST",
"FASHME",
+ "AM53C974",
};
static struct scsi_transport_template *esp_transport_template;
@@ -2317,6 +2394,10 @@ int scsi_esp_register(struct esp *esp, struct device *dev)
static int instance;
int err;
+ if (!esp->num_tags)
+ esp->num_tags = ESP_DEFAULT_TAGS;
+ else if (esp->num_tags >= ESP_MAX_TAG)
+ esp->num_tags = ESP_MAX_TAG - 1;
esp->host->transportt = esp_transport_template;
esp->host->max_lun = ESP_MAX_LUN;
esp->host->cmd_per_lun = 2;
@@ -2330,12 +2411,13 @@ int scsi_esp_register(struct esp *esp, struct device *dev)
esp_bootup_reset(esp);
- printk(KERN_INFO PFX "esp%u, regs[%1p:%1p] irq[%u]\n",
- esp->host->unique_id, esp->regs, esp->dma_regs,
- esp->host->irq);
- printk(KERN_INFO PFX "esp%u is a %s, %u MHz (ccf=%u), SCSI ID %u\n",
- esp->host->unique_id, esp_chip_names[esp->rev],
- esp->cfreq / 1000000, esp->cfact, esp->scsi_id);
+ dev_printk(KERN_INFO, dev, "esp%u: regs[%1p:%1p] irq[%u]\n",
+ esp->host->unique_id, esp->regs, esp->dma_regs,
+ esp->host->irq);
+ dev_printk(KERN_INFO, dev,
+ "esp%u: is a %s, %u MHz (ccf=%u), SCSI ID %u\n",
+ esp->host->unique_id, esp_chip_names[esp->rev],
+ esp->cfreq / 1000000, esp->cfact, esp->scsi_id);
/* Let the SCSI bus reset settle. */
ssleep(esp_bus_reset_settle);
@@ -2403,12 +2485,8 @@ static int esp_slave_configure(struct scsi_device *dev)
struct esp *esp = shost_priv(dev->host);
struct esp_target_data *tp = &esp->target[dev->id];
- if (dev->tagged_supported) {
- /* XXX make this configurable somehow XXX */
- int goal_tags = min(ESP_DEFAULT_TAGS, ESP_MAX_TAG);
-
- scsi_adjust_queue_depth(dev, goal_tags);
- }
+ if (dev->tagged_supported)
+ scsi_change_queue_depth(dev, esp->num_tags);
tp->flags |= ESP_TGT_DISCONNECT;
@@ -2437,19 +2515,20 @@ static int esp_eh_abort_handler(struct scsi_cmnd *cmd)
* XXX much for the final driver.
*/
spin_lock_irqsave(esp->host->host_lock, flags);
- printk(KERN_ERR PFX "esp%d: Aborting command [%p:%02x]\n",
- esp->host->unique_id, cmd, cmd->cmnd[0]);
+ shost_printk(KERN_ERR, esp->host, "Aborting command [%p:%02x]\n",
+ cmd, cmd->cmnd[0]);
ent = esp->active_cmd;
if (ent)
- printk(KERN_ERR PFX "esp%d: Current command [%p:%02x]\n",
- esp->host->unique_id, ent->cmd, ent->cmd->cmnd[0]);
+ shost_printk(KERN_ERR, esp->host,
+ "Current command [%p:%02x]\n",
+ ent->cmd, ent->cmd->cmnd[0]);
list_for_each_entry(ent, &esp->queued_cmds, list) {
- printk(KERN_ERR PFX "esp%d: Queued command [%p:%02x]\n",
- esp->host->unique_id, ent->cmd, ent->cmd->cmnd[0]);
+ shost_printk(KERN_ERR, esp->host, "Queued command [%p:%02x]\n",
+ ent->cmd, ent->cmd->cmnd[0]);
}
list_for_each_entry(ent, &esp->active_cmds, list) {
- printk(KERN_ERR PFX "esp%d: Active command [%p:%02x]\n",
- esp->host->unique_id, ent->cmd, ent->cmd->cmnd[0]);
+ shost_printk(KERN_ERR, esp->host, " Active command [%p:%02x]\n",
+ ent->cmd, ent->cmd->cmnd[0]);
}
esp_dump_cmd_log(esp);
spin_unlock_irqrestore(esp->host->host_lock, flags);
diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h
index cd68805e8d78..84dcbe4a6268 100644
--- a/drivers/scsi/esp_scsi.h
+++ b/drivers/scsi/esp_scsi.h
@@ -1,4 +1,4 @@
-/* esp_scsi.h: Defines and structures for the ESP drier.
+/* esp_scsi.h: Defines and structures for the ESP driver.
*
* Copyright (C) 2007 David S. Miller (davem@davemloft.net)
*/
@@ -25,6 +25,7 @@
#define ESP_CTEST 0x0aUL /* wo Chip test register 0x28 */
#define ESP_CFG2 0x0bUL /* rw Second cfg register 0x2c */
#define ESP_CFG3 0x0cUL /* rw Third cfg register 0x30 */
+#define ESP_CFG4 0x0dUL /* rw Fourth cfg register 0x34 */
#define ESP_TCHI 0x0eUL /* rw High bits transf count 0x38 */
#define ESP_UID ESP_TCHI /* ro Unique ID code 0x38 */
#define FAS_RLO ESP_TCHI /* rw HME extended counter 0x38 */
@@ -76,6 +77,18 @@
#define ESP_CONFIG3_IMS 0x80 /* ID msg chk'ng (esp/fas236) */
#define ESP_CONFIG3_OBPUSH 0x80 /* Push odd-byte to dma (hme) */
+/* ESP config register 4 read-write, found only on am53c974 chips */
+#define ESP_CONFIG4_RADE 0x04 /* Active negation */
+#define ESP_CONFIG4_RAE 0x08 /* Active negation on REQ and ACK */
+#define ESP_CONFIG4_PWD 0x20 /* Reduced power feature */
+#define ESP_CONFIG4_GE0 0x40 /* Glitch eater bit 0 */
+#define ESP_CONFIG4_GE1 0x80 /* Glitch eater bit 1 */
+
+#define ESP_CONFIG_GE_12NS (0)
+#define ESP_CONFIG_GE_25NS (ESP_CONFIG_GE1)
+#define ESP_CONFIG_GE_35NS (ESP_CONFIG_GE0)
+#define ESP_CONFIG_GE_0NS (ESP_CONFIG_GE0 | ESP_CONFIG_GE1)
+
/* ESP command register read-write */
/* Group 1 commands: These may be sent at any point in time to the ESP
* chip. None of them can generate interrupts 'cept
@@ -254,6 +267,7 @@ enum esp_rev {
FAS100A = 0x04,
FAST = 0x05,
FASHME = 0x06,
+ PCSCSI = 0x07, /* AM53c974 */
};
struct esp_cmd_entry {
@@ -269,6 +283,7 @@ struct esp_cmd_entry {
#define ESP_CMD_FLAG_WRITE 0x01 /* DMA is a write */
#define ESP_CMD_FLAG_ABORT 0x02 /* being aborted */
#define ESP_CMD_FLAG_AUTOSENSE 0x04 /* Doing automatic REQUEST_SENSE */
+#define ESP_CMD_FLAG_RESIDUAL 0x08 /* AM53c974 BLAST residual */
u8 tag[2];
u8 orig_tag[2];
@@ -283,7 +298,6 @@ struct esp_cmd_entry {
struct completion *eh_done;
};
-/* XXX make this configurable somehow XXX */
#define ESP_DEFAULT_TAGS 16
#define ESP_MAX_TARGET 16
@@ -445,7 +459,7 @@ struct esp {
u8 prev_soff;
u8 prev_stp;
u8 prev_cfg3;
- u8 __pad;
+ u8 num_tags;
struct list_head esp_cmd_pool;
@@ -466,6 +480,7 @@ struct esp {
u8 bursts;
u8 config1;
u8 config2;
+ u8 config4;
u8 scsi_id;
u32 scsi_id_mask;
@@ -479,6 +494,7 @@ struct esp {
#define ESP_FLAG_WIDE_CAPABLE 0x00000008
#define ESP_FLAG_QUICKIRQ_CHECK 0x00000010
#define ESP_FLAG_DISABLE_SYNC 0x00000020
+#define ESP_FLAG_USE_FIFO 0x00000040
u8 select_state;
#define ESP_SELECT_NONE 0x00 /* Not selecting */
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index a3eeb6842499..308a016fdaea 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -280,7 +280,7 @@ static struct scsi_host_template fcoe_shost_template = {
.eh_device_reset_handler = fc_eh_device_reset,
.eh_host_reset_handler = fc_eh_host_reset,
.slave_alloc = fc_slave_alloc,
- .change_queue_depth = fc_change_queue_depth,
+ .change_queue_depth = scsi_change_queue_depth,
.change_queue_type = scsi_change_queue_type,
.this_id = -1,
.cmd_per_lun = 3,
@@ -289,6 +289,7 @@ static struct scsi_host_template fcoe_shost_template = {
.sg_tablesize = SG_ALL,
.max_sectors = 0xffff,
.use_blk_tags = 1,
+ .track_queue_depth = 1,
};
/**
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
index bf8d34c26f13..3b73b96619e2 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -39,7 +39,7 @@
#define DRV_NAME "fnic"
#define DRV_DESCRIPTION "Cisco FCoE HBA Driver"
-#define DRV_VERSION "1.6.0.11"
+#define DRV_VERSION "1.6.0.16"
#define PFX DRV_NAME ": "
#define DFX DRV_NAME "%d: "
diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c
index f3984b48f8e9..bf0bbd42efb5 100644
--- a/drivers/scsi/fnic/fnic_fcs.c
+++ b/drivers/scsi/fnic/fnic_fcs.c
@@ -135,6 +135,11 @@ void fnic_handle_link(struct work_struct *work)
fnic->lport->host->host_no, FNIC_FC_LE,
"Link Status: UP_DOWN",
strlen("Link Status: UP_DOWN"));
+ if (fnic->config.flags & VFCF_FIP_CAPABLE) {
+ FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
+ "deleting fip-timer during link-down\n");
+ del_timer_sync(&fnic->fip_timer);
+ }
fcoe_ctlr_link_down(&fnic->ctlr);
}
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index cf1560c30b7f..0c1f8177b5b7 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -98,7 +98,7 @@ static int fnic_slave_alloc(struct scsi_device *sdev)
if (!rport || fc_remote_port_chkready(rport))
return -ENXIO;
- scsi_adjust_queue_depth(sdev, fnic_max_qdepth);
+ scsi_change_queue_depth(sdev, fnic_max_qdepth);
return 0;
}
@@ -110,7 +110,7 @@ static struct scsi_host_template fnic_host_template = {
.eh_device_reset_handler = fnic_device_reset,
.eh_host_reset_handler = fnic_host_reset,
.slave_alloc = fnic_slave_alloc,
- .change_queue_depth = fc_change_queue_depth,
+ .change_queue_depth = scsi_change_queue_depth,
.change_queue_type = scsi_change_queue_type,
.this_id = -1,
.cmd_per_lun = 3,
@@ -120,6 +120,7 @@ static struct scsi_host_template fnic_host_template = {
.max_sectors = 0xffff,
.shost_attrs = fnic_attrs,
.use_blk_tags = 1,
+ .track_queue_depth = 1,
};
static void
@@ -437,21 +438,30 @@ static int fnic_dev_wait(struct vnic_dev *vdev,
unsigned long time;
int done;
int err;
+ int count;
+
+ count = 0;
err = start(vdev, arg);
if (err)
return err;
- /* Wait for func to complete...2 seconds max */
+ /* Wait for func to complete.
+ * Sometime schedule_timeout_uninterruptible take long time
+ * to wake up so we do not retry as we are only waiting for
+ * 2 seconds in while loop. By adding count, we make sure
+ * we try atleast three times before returning -ETIMEDOUT
+ */
time = jiffies + (HZ * 2);
do {
err = finished(vdev, &done);
+ count++;
if (err)
return err;
if (done)
return 0;
schedule_timeout_uninterruptible(HZ / 10);
- } while (time_after(time, jiffies));
+ } while (time_after(time, jiffies) || (count < 3));
return -ETIMEDOUT;
}
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
index 10d5c6bbc9e7..2097de42a147 100644
--- a/drivers/scsi/fnic/fnic_scsi.c
+++ b/drivers/scsi/fnic/fnic_scsi.c
@@ -421,8 +421,10 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
int ret;
u64 cmd_trace;
int sg_count = 0;
- unsigned long flags;
+ unsigned long flags = 0;
unsigned long ptr;
+ struct fc_rport_priv *rdata;
+ spinlock_t *io_lock = NULL;
if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_IO_BLOCKED)))
return SCSI_MLQUEUE_HOST_BUSY;
@@ -436,6 +438,16 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
return 0;
}
+ rdata = lp->tt.rport_lookup(lp, rport->port_id);
+ if (!rdata || (rdata->rp_state == RPORT_ST_DELETE)) {
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ "returning IO as rport is removed\n");
+ atomic64_inc(&fnic_stats->misc_stats.rport_not_ready);
+ sc->result = DID_NO_CONNECT;
+ done(sc);
+ return 0;
+ }
+
if (lp->state != LPORT_ST_READY || !(lp->link_up))
return SCSI_MLQUEUE_HOST_BUSY;
@@ -498,6 +510,13 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
}
}
+ /*
+ * Will acquire lock defore setting to IO initialized.
+ */
+
+ io_lock = fnic_io_lock_hash(fnic, sc);
+ spin_lock_irqsave(io_lock, flags);
+
/* initialize rest of io_req */
io_req->port_id = rport->port_id;
io_req->start_time = jiffies;
@@ -514,11 +533,9 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
* In case another thread cancelled the request,
* refetch the pointer under the lock.
*/
- spinlock_t *io_lock = fnic_io_lock_hash(fnic, sc);
FNIC_TRACE(fnic_queuecommand, sc->device->host->host_no,
sc->request->tag, sc, 0, 0, 0,
(((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
- spin_lock_irqsave(io_lock, flags);
io_req = (struct fnic_io_req *)CMD_SP(sc);
CMD_SP(sc) = NULL;
CMD_STATE(sc) = FNIC_IOREQ_CMD_COMPLETE;
@@ -527,6 +544,10 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
fnic_release_ioreq_buf(fnic, io_req, sc);
mempool_free(io_req, fnic->io_req_pool);
}
+ atomic_dec(&fnic->in_flight);
+ /* acquire host lock before returning to SCSI */
+ spin_lock(lp->host->host_lock);
+ return ret;
} else {
atomic64_inc(&fnic_stats->io_stats.active_ios);
atomic64_inc(&fnic_stats->io_stats.num_ios);
@@ -548,6 +569,11 @@ out:
sc->request->tag, sc, io_req,
sg_count, cmd_trace,
(((u64)CMD_FLAGS(sc) >> 32) | CMD_STATE(sc)));
+
+ /* if only we issued IO, will we have the io lock */
+ if (CMD_FLAGS(sc) & FNIC_IO_INITIALIZED)
+ spin_unlock_irqrestore(io_lock, flags);
+
atomic_dec(&fnic->in_flight);
/* acquire host lock before returning to SCSI */
spin_lock(lp->host->host_lock);
diff --git a/drivers/scsi/fnic/fnic_trace.c b/drivers/scsi/fnic/fnic_trace.c
index acf1f95cb5c5..65a9bde26974 100644
--- a/drivers/scsi/fnic/fnic_trace.c
+++ b/drivers/scsi/fnic/fnic_trace.c
@@ -624,12 +624,12 @@ int fnic_fc_trace_set_data(u32 host_no, u8 frame_type,
if (frame_type == FNIC_FC_RECV) {
eth_fcoe_hdr_len = sizeof(struct ethhdr) +
sizeof(struct fcoe_hdr);
- fc_trc_frame_len = fc_trc_frame_len + eth_fcoe_hdr_len;
memset((char *)fc_trace, 0xff, eth_fcoe_hdr_len);
/* Copy the rest of data frame */
memcpy((char *)(fc_trace + eth_fcoe_hdr_len), (void *)frame,
min_t(u8, fc_trc_frame_len,
- (u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE)));
+ (u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE
+ - eth_fcoe_hdr_len)));
} else {
memcpy((char *)fc_trace, (void *)frame,
min_t(u8, fc_trc_frame_len,
diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index b331272e93bc..f35792f7051c 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -18,20 +18,6 @@
*
* Added ISAPNP support for DTC436 adapters,
* Thomas Sailer, sailer@ife.ee.ethz.ch
- *
- * ALPHA RELEASE 1.
- *
- * For more information, please consult
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
*/
/*
@@ -40,14 +26,6 @@
*/
/*
- * Options :
- *
- * PARITY - enable parity checking. Not supported.
- *
- * SCSI2 - enable support for SCSI-II tagged queueing. Untested.
- *
- * USLEEP - enable support for devices that don't disconnect. Untested.
- *
* The card is detected and initialized in one of several ways :
* 1. With command line overrides - NCR5380=port,irq may be
* used on the LILO command line to override the defaults.
@@ -79,27 +57,21 @@
*/
/* settings for DTC3181E card with only Mustek scanner attached */
-#define USLEEP
#define USLEEP_POLL 1
#define USLEEP_SLEEP 20
#define USLEEP_WAITLONG 500
#define AUTOPROBE_IRQ
-#define AUTOSENSE
-
#ifdef CONFIG_SCSI_GENERIC_NCR53C400
#define NCR53C400_PSEUDO_DMA 1
#define PSEUDO_DMA
#define NCR53C400
-#define NCR5380_STATS
-#undef NCR5380_STAT_LIMIT
#endif
#include <asm/io.h>
#include <linux/signal.h>
#include <linux/blkdev.h>
-#include "scsi.h"
#include <scsi/scsi_host.h>
#include "g_NCR5380.h"
#include "NCR5380.h"
@@ -277,7 +249,7 @@ static int __init do_DTC3181E_setup(char *str)
* Locks: none
*/
-int __init generic_NCR5380_detect(struct scsi_host_template * tpnt)
+static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
{
static int current_override = 0;
int count;
@@ -335,7 +307,7 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt)
if (pnp_irq_valid(dev, 0))
overrides[count].irq = pnp_irq(dev, 0);
else
- overrides[count].irq = SCSI_IRQ_NONE;
+ overrides[count].irq = NO_IRQ;
if (pnp_dma_valid(dev, 0))
overrides[count].dma = pnp_dma(dev, 0);
else
@@ -455,27 +427,22 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt)
else
instance->irq = NCR5380_probe_irq(instance, 0xffff);
- if (instance->irq != SCSI_IRQ_NONE)
+ /* Compatibility with documented NCR5380 kernel parameters */
+ if (instance->irq == 255)
+ instance->irq = NO_IRQ;
+
+ if (instance->irq != NO_IRQ)
if (request_irq(instance->irq, generic_NCR5380_intr,
0, "NCR5380", instance)) {
printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
- instance->irq = SCSI_IRQ_NONE;
+ instance->irq = NO_IRQ;
}
- if (instance->irq == SCSI_IRQ_NONE) {
+ if (instance->irq == NO_IRQ) {
printk(KERN_INFO "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
printk(KERN_INFO "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
}
- printk(KERN_INFO "scsi%d : at " STRVAL(NCR5380_map_name) " 0x%x", instance->host_no, (unsigned int) instance->NCR5380_instance_name);
- if (instance->irq == SCSI_IRQ_NONE)
- printk(" interrupts disabled");
- else
- printk(" irq %d", instance->irq);
- printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", CAN_QUEUE, CMD_PER_LUN, GENERIC_NCR5380_PUBLIC_RELEASE);
- NCR5380_print_options(instance);
- printk("\n");
-
++current_override;
++count;
}
@@ -483,19 +450,6 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt)
}
/**
- * generic_NCR5380_info - reporting string
- * @host: NCR5380 to report on
- *
- * Report driver information for the NCR5380
- */
-
-const char *generic_NCR5380_info(struct Scsi_Host *host)
-{
- static const char string[] = "Generic NCR5380/53C400 Driver";
- return string;
-}
-
-/**
* generic_NCR5380_release_resources - free resources
* @instance: host adapter to clean up
*
@@ -504,12 +458,12 @@ const char *generic_NCR5380_info(struct Scsi_Host *host)
* Locks: none
*/
-int generic_NCR5380_release_resources(struct Scsi_Host *instance)
+static int generic_NCR5380_release_resources(struct Scsi_Host *instance)
{
NCR5380_local_declare();
NCR5380_setup(instance);
- if (instance->irq != SCSI_IRQ_NONE)
+ if (instance->irq != NO_IRQ)
free_irq(instance->irq, instance);
NCR5380_exit(instance);
@@ -741,163 +695,9 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
#include "NCR5380.c"
-#define PRINTP(x) seq_printf(m, x)
-#define ANDP ,
-
-static void sprint_opcode(struct seq_file *m, int opcode)
-{
- PRINTP("0x%02x " ANDP opcode);
-}
-
-static void sprint_command(struct seq_file *m, unsigned char *command)
-{
- int i, s;
- sprint_opcode(m, command[0]);
- for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
- PRINTP("%02x " ANDP command[i]);
- PRINTP("\n");
-}
-
-/**
- * sprintf_Scsi_Cmnd - print a scsi command
- * @m: seq_fil to print into
- * @cmd: SCSI command block
- *
- * Print out the target and command data in hex
- */
-
-static void sprint_Scsi_Cmnd(struct seq_file *m, Scsi_Cmnd * cmd)
-{
- PRINTP("host number %d destination target %d, lun %llu\n" ANDP cmd->device->host->host_no ANDP cmd->device->id ANDP cmd->device->lun);
- PRINTP(" command = ");
- sprint_command(m, cmd->cmnd);
-}
-
-/**
- * generic_NCR5380_proc_info - /proc for NCR5380 driver
- * @buffer: buffer to print into
- * @start: start position
- * @offset: offset into buffer
- * @len: length
- * @hostno: instance to affect
- * @inout: read/write
- *
- * Provide the procfs information for the 5380 controller. We fill
- * this with useful debugging information including the commands
- * being executed, disconnected command queue and the statistical
- * data
- *
- * Locks: global cli/lock for queue walk
- */
-
-static int generic_NCR5380_show_info(struct seq_file *m, struct Scsi_Host *scsi_ptr)
-{
- NCR5380_local_declare();
- unsigned long flags;
- unsigned char status;
- int i;
- Scsi_Cmnd *ptr;
- struct NCR5380_hostdata *hostdata;
-#ifdef NCR5380_STATS
- struct scsi_device *dev;
-#endif
-
- NCR5380_setup(scsi_ptr);
- hostdata = (struct NCR5380_hostdata *) scsi_ptr->hostdata;
-
- spin_lock_irqsave(scsi_ptr->host_lock, flags);
- PRINTP("SCSI host number %d : %s\n" ANDP scsi_ptr->host_no ANDP scsi_ptr->hostt->name);
- PRINTP("Generic NCR5380 driver version %d\n" ANDP GENERIC_NCR5380_PUBLIC_RELEASE);
- PRINTP("NCR5380 core version %d\n" ANDP NCR5380_PUBLIC_RELEASE);
-#ifdef NCR53C400
- PRINTP("NCR53C400 extension version %d\n" ANDP NCR53C400_PUBLIC_RELEASE);
- PRINTP("NCR53C400 card%s detected\n" ANDP(((struct NCR5380_hostdata *) scsi_ptr->hostdata)->flags & FLAG_NCR53C400) ? "" : " not");
-# if NCR53C400_PSEUDO_DMA
- PRINTP("NCR53C400 pseudo DMA used\n");
-# endif
-#else
- PRINTP("NO NCR53C400 driver extensions\n");
-#endif
- PRINTP("Using %s mapping at %s 0x%lx, " ANDP STRVAL(NCR5380_map_config) ANDP STRVAL(NCR5380_map_name) ANDP scsi_ptr->NCR5380_instance_name);
- if (scsi_ptr->irq == SCSI_IRQ_NONE)
- PRINTP("no interrupt\n");
- else
- PRINTP("on interrupt %d\n" ANDP scsi_ptr->irq);
-
-#ifdef NCR5380_STATS
- if (hostdata->connected || hostdata->issue_queue || hostdata->disconnected_queue)
- PRINTP("There are commands pending, transfer rates may be crud\n");
- if (hostdata->pendingr)
- PRINTP(" %d pending reads" ANDP hostdata->pendingr);
- if (hostdata->pendingw)
- PRINTP(" %d pending writes" ANDP hostdata->pendingw);
- if (hostdata->pendingr || hostdata->pendingw)
- PRINTP("\n");
- shost_for_each_device(dev, scsi_ptr) {
- unsigned long br = hostdata->bytes_read[dev->id];
- unsigned long bw = hostdata->bytes_write[dev->id];
- long tr = hostdata->time_read[dev->id] / HZ;
- long tw = hostdata->time_write[dev->id] / HZ;
-
- PRINTP(" T:%d %s " ANDP dev->id ANDP scsi_device_type(dev->type));
- for (i = 0; i < 8; i++)
- if (dev->vendor[i] >= 0x20)
- seq_putc(m, dev->vendor[i]);
- seq_putc(m, ' ');
- for (i = 0; i < 16; i++)
- if (dev->model[i] >= 0x20)
- seq_putc(m, dev->model[i]);
- seq_putc(m, ' ');
- for (i = 0; i < 4; i++)
- if (dev->rev[i] >= 0x20)
- seq_putc(m, dev->rev[i]);
- seq_putc(m, ' ');
-
- PRINTP("\n%10ld kb read in %5ld secs" ANDP br / 1024 ANDP tr);
- if (tr)
- PRINTP(" @ %5ld bps" ANDP br / tr);
-
- PRINTP("\n%10ld kb written in %5ld secs" ANDP bw / 1024 ANDP tw);
- if (tw)
- PRINTP(" @ %5ld bps" ANDP bw / tw);
- PRINTP("\n");
- }
-#endif
-
- status = NCR5380_read(STATUS_REG);
- if (!(status & SR_REQ))
- PRINTP("REQ not asserted, phase unknown.\n");
- else {
- for (i = 0; (phases[i].value != PHASE_UNKNOWN) && (phases[i].value != (status & PHASE_MASK)); ++i);
- PRINTP("Phase %s\n" ANDP phases[i].name);
- }
-
- if (!hostdata->connected) {
- PRINTP("No currently connected command\n");
- } else {
- sprint_Scsi_Cmnd(m, (Scsi_Cmnd *) hostdata->connected);
- }
-
- PRINTP("issue_queue\n");
-
- for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
- sprint_Scsi_Cmnd(m, ptr);
-
- PRINTP("disconnected_queue\n");
-
- for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
- sprint_Scsi_Cmnd(m, ptr);
-
- spin_unlock_irqrestore(scsi_ptr->host_lock, flags);
- return 0;
-}
-
-#undef PRINTP
-#undef ANDP
-
static struct scsi_host_template driver_template = {
.show_info = generic_NCR5380_show_info,
- .name = "Generic NCR5380/NCR53C400 Scsi Driver",
+ .name = "Generic NCR5380/NCR53C400 SCSI",
.detect = generic_NCR5380_detect,
.release = generic_NCR5380_release_resources,
.info = generic_NCR5380_info,
diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h
index 703adf78e0b2..bea1a3b9b862 100644
--- a/drivers/scsi/g_NCR5380.h
+++ b/drivers/scsi/g_NCR5380.h
@@ -9,28 +9,11 @@
*
* NCR53C400 extensions (c) 1994,1995,1996, Kevin Lentin
* K.Lentin@cs.monash.edu.au
- *
- * ALPHA RELEASE 1.
- *
- * For more information, please consult
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
*/
#ifndef GENERIC_NCR5380_H
#define GENERIC_NCR5380_H
-
-#define GENERIC_NCR5380_PUBLIC_RELEASE 1
-
#ifdef NCR53C400
#define BIOSPARAM
#define NCR5380_BIOSPARAM generic_NCR5380_biosparam
@@ -39,12 +22,6 @@
#endif
#ifndef ASM
-static int generic_NCR5380_abort(Scsi_Cmnd *);
-static int generic_NCR5380_detect(struct scsi_host_template *);
-static int generic_NCR5380_release_resources(struct Scsi_Host *);
-static int generic_NCR5380_queue_command(struct Scsi_Host *, struct scsi_cmnd *);
-static int generic_NCR5380_bus_reset(Scsi_Cmnd *);
-static const char* generic_NCR5380_info(struct Scsi_Host *);
#ifndef CMD_PER_LUN
#define CMD_PER_LUN 2
@@ -118,7 +95,8 @@ static const char* generic_NCR5380_info(struct Scsi_Host *);
#define NCR5380_bus_reset generic_NCR5380_bus_reset
#define NCR5380_pread generic_NCR5380_pread
#define NCR5380_pwrite generic_NCR5380_pwrite
-#define NCR5380_proc_info notyet_generic_proc_info
+#define NCR5380_info generic_NCR5380_info
+#define NCR5380_show_info generic_NCR5380_show_info
#define BOARD_NCR5380 0
#define BOARD_NCR53C400 1
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 18ea2e16e34f..6bb4611b238a 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -48,6 +48,7 @@
#include <linux/bitmap.h>
#include <linux/atomic.h>
#include <linux/jiffies.h>
+#include <linux/percpu-defs.h>
#include <linux/percpu.h>
#include <asm/div64.h>
#include "hpsa_cmd.h"
@@ -103,7 +104,6 @@ static const struct pci_device_id hpsa_pci_device_id[] = {
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1922},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1923},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1924},
- {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1925},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1926},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1928},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1929},
@@ -149,6 +149,7 @@ static struct board_type products[] = {
{0x3249103C, "Smart Array P812", &SA5_access},
{0x324A103C, "Smart Array P712m", &SA5_access},
{0x324B103C, "Smart Array P711m", &SA5_access},
+ {0x3233103C, "HP StorageWorks 1210m", &SA5_access}, /* alias of 333f */
{0x3350103C, "Smart Array P222", &SA5_access},
{0x3351103C, "Smart Array P420", &SA5_access},
{0x3352103C, "Smart Array P421", &SA5_access},
@@ -193,12 +194,13 @@ static int number_of_controllers;
static irqreturn_t do_hpsa_intr_intx(int irq, void *dev_id);
static irqreturn_t do_hpsa_intr_msi(int irq, void *dev_id);
-static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg);
+static int hpsa_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
static void lock_and_start_io(struct ctlr_info *h);
static void start_io(struct ctlr_info *h, unsigned long *flags);
#ifdef CONFIG_COMPAT
-static int hpsa_compat_ioctl(struct scsi_device *dev, int cmd, void *arg);
+static int hpsa_compat_ioctl(struct scsi_device *dev, int cmd,
+ void __user *arg);
#endif
static void cmd_free(struct ctlr_info *h, struct CommandList *c);
@@ -214,8 +216,6 @@ static int 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);
-static int hpsa_change_queue_depth(struct scsi_device *sdev,
- int qdepth, int reason);
static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd);
static int hpsa_eh_abort_handler(struct scsi_cmnd *scsicmd);
@@ -274,12 +274,12 @@ static int check_for_unit_attention(struct ctlr_info *h,
"detected, command retried\n", h->ctlr);
break;
case LUN_FAILED:
- dev_warn(&h->pdev->dev, HPSA "%d: LUN failure "
- "detected, action required\n", h->ctlr);
+ dev_warn(&h->pdev->dev,
+ HPSA "%d: LUN failure detected\n", h->ctlr);
break;
case REPORT_LUNS_CHANGED:
- dev_warn(&h->pdev->dev, HPSA "%d: report LUN data "
- "changed, action required\n", h->ctlr);
+ dev_warn(&h->pdev->dev,
+ HPSA "%d: report LUN data changed\n", h->ctlr);
/*
* Note: this REPORT_LUNS_CHANGED condition only occurs on the external
* target (array) devices.
@@ -392,7 +392,8 @@ static ssize_t host_show_commands_outstanding(struct device *dev,
struct Scsi_Host *shost = class_to_shost(dev);
struct ctlr_info *h = shost_to_hba(shost);
- return snprintf(buf, 20, "%d\n", h->commands_outstanding);
+ return snprintf(buf, 20, "%d\n",
+ atomic_read(&h->commands_outstanding));
}
static ssize_t host_show_transport_mode(struct device *dev,
@@ -670,7 +671,7 @@ static struct scsi_host_template hpsa_driver_template = {
.queuecommand = hpsa_scsi_queue_command,
.scan_start = hpsa_scan_start,
.scan_finished = hpsa_scan_finished,
- .change_queue_depth = hpsa_change_queue_depth,
+ .change_queue_depth = scsi_change_queue_depth,
.this_id = -1,
.use_clustering = ENABLE_CLUSTERING,
.eh_abort_handler = hpsa_eh_abort_handler,
@@ -698,7 +699,6 @@ static inline u32 next_command(struct ctlr_info *h, u8 q)
{
u32 a;
struct reply_queue_buffer *rq = &h->reply_queue[q];
- unsigned long flags;
if (h->transMethod & CFGTBL_Trans_io_accel1)
return h->access.command_completed(h, q);
@@ -709,9 +709,7 @@ static inline u32 next_command(struct ctlr_info *h, u8 q)
if ((rq->head[rq->current_entry] & 1) == rq->wraparound) {
a = rq->head[rq->current_entry];
rq->current_entry++;
- spin_lock_irqsave(&h->lock, flags);
- h->commands_outstanding--;
- spin_unlock_irqrestore(&h->lock, flags);
+ atomic_dec(&h->commands_outstanding);
} else {
a = FIFO_EMPTY;
}
@@ -1500,22 +1498,22 @@ static int hpsa_map_sg_chain_block(struct ctlr_info *h,
{
struct SGDescriptor *chain_sg, *chain_block;
u64 temp64;
+ u32 chain_len;
chain_sg = &c->SG[h->max_cmd_sg_entries - 1];
chain_block = h->cmd_sg_list[c->cmdindex];
- chain_sg->Ext = HPSA_SG_CHAIN;
- chain_sg->Len = sizeof(*chain_sg) *
+ chain_sg->Ext = cpu_to_le32(HPSA_SG_CHAIN);
+ chain_len = sizeof(*chain_sg) *
(c->Header.SGTotal - h->max_cmd_sg_entries);
- temp64 = pci_map_single(h->pdev, chain_block, chain_sg->Len,
+ chain_sg->Len = cpu_to_le32(chain_len);
+ temp64 = pci_map_single(h->pdev, chain_block, chain_len,
PCI_DMA_TODEVICE);
if (dma_mapping_error(&h->pdev->dev, temp64)) {
/* prevent subsequent unmapping */
- chain_sg->Addr.lower = 0;
- chain_sg->Addr.upper = 0;
+ chain_sg->Addr = cpu_to_le64(0);
return -1;
}
- chain_sg->Addr.lower = (u32) (temp64 & 0x0FFFFFFFFULL);
- chain_sg->Addr.upper = (u32) ((temp64 >> 32) & 0x0FFFFFFFFULL);
+ chain_sg->Addr = cpu_to_le64(temp64);
return 0;
}
@@ -1523,15 +1521,13 @@ static void hpsa_unmap_sg_chain_block(struct ctlr_info *h,
struct CommandList *c)
{
struct SGDescriptor *chain_sg;
- union u64bit temp64;
- if (c->Header.SGTotal <= h->max_cmd_sg_entries)
+ if (le16_to_cpu(c->Header.SGTotal) <= h->max_cmd_sg_entries)
return;
chain_sg = &c->SG[h->max_cmd_sg_entries - 1];
- temp64.val32.lower = chain_sg->Addr.lower;
- temp64.val32.upper = chain_sg->Addr.upper;
- pci_unmap_single(h->pdev, temp64.val, chain_sg->Len, PCI_DMA_TODEVICE);
+ pci_unmap_single(h->pdev, le64_to_cpu(chain_sg->Addr),
+ le32_to_cpu(chain_sg->Len), PCI_DMA_TODEVICE);
}
@@ -1732,8 +1728,7 @@ static void complete_scsi_command(struct CommandList *cp)
struct io_accel1_cmd *c = &h->ioaccel_cmd_pool[cp->cmdindex];
cp->Header.SGList = cp->Header.SGTotal = scsi_sg_count(cmd);
cp->Request.CDBLen = c->io_flags & IOACCEL1_IOFLAGS_CDBLEN_MASK;
- cp->Header.Tag.lower = c->Tag.lower;
- cp->Header.Tag.upper = c->Tag.upper;
+ cp->Header.tag = c->tag;
memcpy(cp->Header.LUN.LunAddrBytes, c->CISS_LUN, 8);
memcpy(cp->Request.CDB, c->CDB, cp->Request.CDBLen);
@@ -1763,72 +1758,13 @@ static void complete_scsi_command(struct CommandList *cp)
/* Get addition sense code qualifier */
ascq = ei->SenseInfo[13];
}
-
if (ei->ScsiStatus == SAM_STAT_CHECK_CONDITION) {
- if (check_for_unit_attention(h, cp))
- break;
- if (sense_key == ILLEGAL_REQUEST) {
- /*
- * SCSI REPORT_LUNS is commonly unsupported on
- * Smart Array. Suppress noisy complaint.
- */
- if (cp->Request.CDB[0] == REPORT_LUNS)
- break;
-
- /* If ASC/ASCQ indicate Logical Unit
- * Not Supported condition,
- */
- if ((asc == 0x25) && (ascq == 0x0)) {
- dev_warn(&h->pdev->dev, "cp %p "
- "has check condition\n", cp);
- break;
- }
- }
-
- if (sense_key == NOT_READY) {
- /* If Sense is Not Ready, Logical Unit
- * Not ready, Manual Intervention
- * required
- */
- if ((asc == 0x04) && (ascq == 0x03)) {
- dev_warn(&h->pdev->dev, "cp %p "
- "has check condition: unit "
- "not ready, manual "
- "intervention required\n", cp);
- break;
- }
- }
if (sense_key == ABORTED_COMMAND) {
- /* Aborted command is retryable */
- dev_warn(&h->pdev->dev, "cp %p "
- "has check condition: aborted command: "
- "ASC: 0x%x, ASCQ: 0x%x\n",
- cp, asc, ascq);
cmd->result |= DID_SOFT_ERROR << 16;
break;
}
- /* Must be some other type of check condition */
- dev_dbg(&h->pdev->dev, "cp %p has check condition: "
- "unknown type: "
- "Sense: 0x%x, ASC: 0x%x, ASCQ: 0x%x, "
- "Returning result: 0x%x, "
- "cmd=[%02x %02x %02x %02x %02x "
- "%02x %02x %02x %02x %02x %02x "
- "%02x %02x %02x %02x %02x]\n",
- cp, sense_key, asc, ascq,
- cmd->result,
- cmd->cmnd[0], cmd->cmnd[1],
- cmd->cmnd[2], cmd->cmnd[3],
- cmd->cmnd[4], cmd->cmnd[5],
- cmd->cmnd[6], cmd->cmnd[7],
- cmd->cmnd[8], cmd->cmnd[9],
- cmd->cmnd[10], cmd->cmnd[11],
- cmd->cmnd[12], cmd->cmnd[13],
- cmd->cmnd[14], cmd->cmnd[15]);
break;
}
-
-
/* Problem was not a check condition
* Pass it up to the upper layers...
*/
@@ -1934,14 +1870,11 @@ static void hpsa_pci_unmap(struct pci_dev *pdev,
struct CommandList *c, int sg_used, int data_direction)
{
int i;
- union u64bit addr64;
- for (i = 0; i < sg_used; i++) {
- addr64.val32.lower = c->SG[i].Addr.lower;
- addr64.val32.upper = c->SG[i].Addr.upper;
- pci_unmap_single(pdev, (dma_addr_t) addr64.val, c->SG[i].Len,
- data_direction);
- }
+ for (i = 0; i < sg_used; i++)
+ pci_unmap_single(pdev, (dma_addr_t) le64_to_cpu(c->SG[i].Addr),
+ le32_to_cpu(c->SG[i].Len),
+ data_direction);
}
static int hpsa_map_one(struct pci_dev *pdev,
@@ -1954,25 +1887,22 @@ static int hpsa_map_one(struct pci_dev *pdev,
if (buflen == 0 || data_direction == PCI_DMA_NONE) {
cp->Header.SGList = 0;
- cp->Header.SGTotal = 0;
+ cp->Header.SGTotal = cpu_to_le16(0);
return 0;
}
- addr64 = (u64) pci_map_single(pdev, buf, buflen, data_direction);
+ addr64 = pci_map_single(pdev, buf, buflen, data_direction);
if (dma_mapping_error(&pdev->dev, addr64)) {
/* Prevent subsequent unmap of something never mapped */
cp->Header.SGList = 0;
- cp->Header.SGTotal = 0;
+ cp->Header.SGTotal = cpu_to_le16(0);
return -1;
}
- cp->SG[0].Addr.lower =
- (u32) (addr64 & (u64) 0x00000000FFFFFFFF);
- cp->SG[0].Addr.upper =
- (u32) ((addr64 >> 32) & (u64) 0x00000000FFFFFFFF);
- cp->SG[0].Len = buflen;
- cp->SG[0].Ext = HPSA_SG_LAST; /* we are not chaining */
- cp->Header.SGList = (u8) 1; /* no. SGs contig in this cmd */
- cp->Header.SGTotal = (u16) 1; /* total sgs in this cmd list */
+ cp->SG[0].Addr = cpu_to_le64(addr64);
+ cp->SG[0].Len = cpu_to_le32(buflen);
+ cp->SG[0].Ext = cpu_to_le32(HPSA_SG_LAST); /* we are not chaining */
+ cp->Header.SGList = 1; /* no. SGs contig in this cmd */
+ cp->Header.SGTotal = cpu_to_le16(1); /* total sgs in cmd list */
return 0;
}
@@ -2830,8 +2760,8 @@ static int hpsa_get_pdisk_of_ioaccel2(struct ctlr_info *h,
if (d == NULL)
return 0; /* no match */
- it_nexus = cpu_to_le32((u32) d->ioaccel_handle);
- scsi_nexus = cpu_to_le32((u32) c2a->scsi_nexus);
+ it_nexus = cpu_to_le32(d->ioaccel_handle);
+ scsi_nexus = cpu_to_le32(c2a->scsi_nexus);
find = c2a->scsi_nexus;
if (h->raid_offload_debug > 0)
@@ -2891,7 +2821,7 @@ static int hpsa_get_pdisk_of_ioaccel2(struct ctlr_info *h,
* Returns 0 on success, -1 otherwise.
*/
static int hpsa_gather_lun_info(struct ctlr_info *h,
- int reportlunsize,
+ int reportphyslunsize, int reportloglunsize,
struct ReportLUNdata *physdev, u32 *nphysicals, int *physical_mode,
struct ReportLUNdata *logdev, u32 *nlogicals)
{
@@ -2905,7 +2835,7 @@ static int hpsa_gather_lun_info(struct ctlr_info *h,
*physical_mode = HPSA_REPORT_PHYS_EXTENDED;
physical_entry_size = 24;
}
- if (hpsa_scsi_do_report_phys_luns(h, physdev, reportlunsize,
+ if (hpsa_scsi_do_report_phys_luns(h, physdev, reportphyslunsize,
*physical_mode)) {
dev_err(&h->pdev->dev, "report physical LUNs failed.\n");
return -1;
@@ -2918,7 +2848,7 @@ static int hpsa_gather_lun_info(struct ctlr_info *h,
*nphysicals - HPSA_MAX_PHYS_LUN);
*nphysicals = HPSA_MAX_PHYS_LUN;
}
- if (hpsa_scsi_do_report_log_luns(h, logdev, reportlunsize)) {
+ if (hpsa_scsi_do_report_log_luns(h, logdev, reportloglunsize)) {
dev_err(&h->pdev->dev, "report logical LUNs failed.\n");
return -1;
}
@@ -2941,8 +2871,8 @@ static int hpsa_gather_lun_info(struct ctlr_info *h,
return 0;
}
-u8 *figure_lunaddrbytes(struct ctlr_info *h, int raid_ctlr_position, int i,
- int nphysicals, int nlogicals,
+static u8 *figure_lunaddrbytes(struct ctlr_info *h, int raid_ctlr_position,
+ int i, int nphysicals, int nlogicals,
struct ReportExtendedLUNdata *physdev_list,
struct ReportLUNdata *logdev_list)
{
@@ -3011,15 +2941,14 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
u32 ndev_allocated = 0;
struct hpsa_scsi_dev_t **currentsd, *this_device, *tmpdevice;
int ncurrent = 0;
- int reportlunsize = sizeof(*physdev_list) + HPSA_MAX_PHYS_LUN * 24;
int i, n_ext_target_devs, ndevs_to_allocate;
int raid_ctlr_position;
int rescan_hba_mode;
DECLARE_BITMAP(lunzerobits, MAX_EXT_TARGETS);
currentsd = kzalloc(sizeof(*currentsd) * HPSA_MAX_DEVICES, GFP_KERNEL);
- physdev_list = kzalloc(reportlunsize, GFP_KERNEL);
- logdev_list = kzalloc(reportlunsize, GFP_KERNEL);
+ physdev_list = kzalloc(sizeof(*physdev_list), GFP_KERNEL);
+ logdev_list = kzalloc(sizeof(*logdev_list), GFP_KERNEL);
tmpdevice = kzalloc(sizeof(*tmpdevice), GFP_KERNEL);
if (!currentsd || !physdev_list || !logdev_list || !tmpdevice) {
@@ -3039,7 +2968,8 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
h->hba_mode_enabled = rescan_hba_mode;
- if (hpsa_gather_lun_info(h, reportlunsize,
+ if (hpsa_gather_lun_info(h,
+ sizeof(*physdev_list), sizeof(*logdev_list),
(struct ReportLUNdata *) physdev_list, &nphysicals,
&physical_mode, logdev_list, &nlogicals))
goto out;
@@ -3210,19 +3140,19 @@ static int hpsa_scatter_gather(struct ctlr_info *h,
}
addr64 = (u64) sg_dma_address(sg);
len = sg_dma_len(sg);
- curr_sg->Addr.lower = (u32) (addr64 & 0x0FFFFFFFFULL);
- curr_sg->Addr.upper = (u32) ((addr64 >> 32) & 0x0FFFFFFFFULL);
- curr_sg->Len = len;
- curr_sg->Ext = (i < scsi_sg_count(cmd) - 1) ? 0 : HPSA_SG_LAST;
+ curr_sg->Addr = cpu_to_le64(addr64);
+ curr_sg->Len = cpu_to_le32(len);
+ curr_sg->Ext = cpu_to_le32(0);
curr_sg++;
}
+ (--curr_sg)->Ext = cpu_to_le32(HPSA_SG_LAST);
if (use_sg + chained > h->maxSG)
h->maxSG = use_sg + chained;
if (chained) {
cp->Header.SGList = h->max_cmd_sg_entries;
- cp->Header.SGTotal = (u16) (use_sg + 1);
+ cp->Header.SGTotal = cpu_to_le16(use_sg + 1);
if (hpsa_map_sg_chain_block(h, cp)) {
scsi_dma_unmap(cmd);
return -1;
@@ -3233,7 +3163,7 @@ static int hpsa_scatter_gather(struct ctlr_info *h,
sglist_finished:
cp->Header.SGList = (u8) use_sg; /* no. SGs contig in this cmd */
- cp->Header.SGTotal = (u16) use_sg; /* total sgs in this cmd list */
+ cp->Header.SGTotal = cpu_to_le16(use_sg); /* total sgs in this cmd list */
return 0;
}
@@ -3325,17 +3255,12 @@ static int hpsa_scsi_ioaccel1_queue_command(struct ctlr_info *h,
addr64 = (u64) sg_dma_address(sg);
len = sg_dma_len(sg);
total_len += len;
- curr_sg->Addr.lower = (u32) (addr64 & 0x0FFFFFFFFULL);
- curr_sg->Addr.upper =
- (u32) ((addr64 >> 32) & 0x0FFFFFFFFULL);
- curr_sg->Len = len;
-
- if (i == (scsi_sg_count(cmd) - 1))
- curr_sg->Ext = HPSA_SG_LAST;
- else
- curr_sg->Ext = 0; /* we are not chaining */
+ curr_sg->Addr = cpu_to_le64(addr64);
+ curr_sg->Len = cpu_to_le32(len);
+ curr_sg->Ext = cpu_to_le32(0);
curr_sg++;
}
+ (--curr_sg)->Ext = cpu_to_le32(HPSA_SG_LAST);
switch (cmd->sc_data_direction) {
case DMA_TO_DEVICE:
@@ -3592,7 +3517,7 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h,
cp->data_len = cpu_to_le32(total_len);
cp->err_ptr = cpu_to_le64(c->busaddr +
offsetof(struct io_accel2_cmd, error_data));
- cp->err_len = cpu_to_le32((u32) sizeof(cp->error_data));
+ cp->err_len = cpu_to_le32(sizeof(cp->error_data));
enqueue_cmd_and_start_io(h, c);
return 0;
@@ -3809,11 +3734,6 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
offload_to_mirror =
(offload_to_mirror >= map->layout_map_count - 1)
? 0 : offload_to_mirror + 1;
- /* FIXME: remove after debug/dev */
- BUG_ON(offload_to_mirror >= map->layout_map_count);
- dev_warn(&h->pdev->dev,
- "DEBUG: Using physical disk map index %d from mirror group %d\n",
- map_index, offload_to_mirror);
dev->offload_to_mirror = offload_to_mirror;
/* Avoid direct use of dev->offload_to_mirror within this
* function since multiple threads might simultaneously
@@ -3959,8 +3879,11 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
dev->scsi3addr);
}
-static int hpsa_scsi_queue_command_lck(struct scsi_cmnd *cmd,
- void (*done)(struct scsi_cmnd *))
+/*
+ * Running in struct Scsi_Host->host_lock less mode using LLD internal
+ * struct ctlr_info *h->lock w/ spin_lock_irqsave() protection.
+ */
+static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
{
struct ctlr_info *h;
struct hpsa_scsi_dev_t *dev;
@@ -3973,14 +3896,14 @@ static int hpsa_scsi_queue_command_lck(struct scsi_cmnd *cmd,
dev = cmd->device->hostdata;
if (!dev) {
cmd->result = DID_NO_CONNECT << 16;
- done(cmd);
+ cmd->scsi_done(cmd);
return 0;
}
memcpy(scsi3addr, dev->scsi3addr, sizeof(scsi3addr));
if (unlikely(lockup_detected(h))) {
cmd->result = DID_ERROR << 16;
- done(cmd);
+ cmd->scsi_done(cmd);
return 0;
}
c = cmd_alloc(h);
@@ -3990,9 +3913,6 @@ static int hpsa_scsi_queue_command_lck(struct scsi_cmnd *cmd,
}
/* Fill in the command list header */
-
- cmd->scsi_done = done; /* save this for use by completion code */
-
/* save c in case we have to abort it */
cmd->host_scribble = (unsigned char *) c;
@@ -4026,8 +3946,8 @@ static int hpsa_scsi_queue_command_lck(struct scsi_cmnd *cmd,
c->Header.ReplyQueue = 0; /* unused in simple mode */
memcpy(&c->Header.LUN.LunAddrBytes[0], &scsi3addr[0], 8);
- c->Header.Tag.lower = (c->cmdindex << DIRECT_LOOKUP_SHIFT);
- c->Header.Tag.lower |= DIRECT_LOOKUP_BIT;
+ c->Header.tag = cpu_to_le64((c->cmdindex << DIRECT_LOOKUP_SHIFT) |
+ DIRECT_LOOKUP_BIT);
/* Fill in the request block... */
@@ -4036,17 +3956,18 @@ static int hpsa_scsi_queue_command_lck(struct scsi_cmnd *cmd,
BUG_ON(cmd->cmd_len > sizeof(c->Request.CDB));
c->Request.CDBLen = cmd->cmd_len;
memcpy(c->Request.CDB, cmd->cmnd, cmd->cmd_len);
- c->Request.Type.Type = TYPE_CMD;
- c->Request.Type.Attribute = ATTR_SIMPLE;
switch (cmd->sc_data_direction) {
case DMA_TO_DEVICE:
- c->Request.Type.Direction = XFER_WRITE;
+ c->Request.type_attr_dir =
+ TYPE_ATTR_DIR(TYPE_CMD, ATTR_SIMPLE, XFER_WRITE);
break;
case DMA_FROM_DEVICE:
- c->Request.Type.Direction = XFER_READ;
+ c->Request.type_attr_dir =
+ TYPE_ATTR_DIR(TYPE_CMD, ATTR_SIMPLE, XFER_READ);
break;
case DMA_NONE:
- c->Request.Type.Direction = XFER_NONE;
+ c->Request.type_attr_dir =
+ TYPE_ATTR_DIR(TYPE_CMD, ATTR_SIMPLE, XFER_NONE);
break;
case DMA_BIDIRECTIONAL:
/* This can happen if a buggy application does a scsi passthru
@@ -4054,7 +3975,8 @@ static int hpsa_scsi_queue_command_lck(struct scsi_cmnd *cmd,
* ../scsi/scsi_ioctl.c:scsi_ioctl_send_command() )
*/
- c->Request.Type.Direction = XFER_RSVD;
+ c->Request.type_attr_dir =
+ TYPE_ATTR_DIR(TYPE_CMD, ATTR_SIMPLE, XFER_RSVD);
/* This is technically wrong, and hpsa controllers should
* reject it with CMD_INVALID, which is the most correct
* response, but non-fibre backends appear to let it
@@ -4081,8 +4003,6 @@ static int hpsa_scsi_queue_command_lck(struct scsi_cmnd *cmd,
return 0;
}
-static DEF_SCSI_QCMD(hpsa_scsi_queue_command)
-
static int do_not_scan_if_controller_locked_up(struct ctlr_info *h)
{
unsigned long flags;
@@ -4152,23 +4072,6 @@ static int hpsa_scan_finished(struct Scsi_Host *sh,
return finished;
}
-static int hpsa_change_queue_depth(struct scsi_device *sdev,
- int qdepth, int reason)
-{
- struct ctlr_info *h = sdev_to_hba(sdev);
-
- if (reason != SCSI_QDEPTH_DEFAULT)
- return -ENOTSUPP;
-
- if (qdepth < 1)
- qdepth = 1;
- else
- if (qdepth > h->nr_cmds)
- qdepth = h->nr_cmds;
- scsi_adjust_queue_depth(sdev, qdepth);
- return sdev->queue_depth;
-}
-
static void hpsa_unregister_scsi(struct ctlr_info *h)
{
/* we are being forcibly unloaded, and may not refuse. */
@@ -4329,8 +4232,8 @@ static void hpsa_get_tag(struct ctlr_info *h,
if (c->cmd_type == CMD_IOACCEL1) {
struct io_accel1_cmd *cm1 = (struct io_accel1_cmd *)
&h->ioaccel_cmd_pool[c->cmdindex];
- *tagupper = cm1->Tag.upper;
- *taglower = cm1->Tag.lower;
+ *tagupper = (u32) (cm1->tag >> 32);
+ *taglower = (u32) (cm1->tag & 0x0ffffffffULL);
return;
}
if (c->cmd_type == CMD_IOACCEL2) {
@@ -4341,11 +4244,10 @@ static void hpsa_get_tag(struct ctlr_info *h,
*taglower = cm2->Tag;
return;
}
- *tagupper = c->Header.Tag.upper;
- *taglower = c->Header.Tag.lower;
+ *tagupper = (u32) (c->Header.tag >> 32);
+ *taglower = (u32) (c->Header.tag & 0x0ffffffffULL);
}
-
static int hpsa_send_abort(struct ctlr_info *h, unsigned char *scsi3addr,
struct CommandList *abort, int swizzle)
{
@@ -4410,7 +4312,7 @@ static struct CommandList *hpsa_find_cmd_in_queue(struct ctlr_info *h,
struct CommandList *c = NULL; /* ptr into cmpQ */
if (!find)
- return 0;
+ return NULL;
spin_lock_irqsave(&h->lock, flags);
list_for_each_entry(c, queue_head, list) {
if (c->scsi_cmd == NULL) /* e.g.: passthru ioctl */
@@ -4432,7 +4334,7 @@ static struct CommandList *hpsa_find_cmd_in_queue_by_tag(struct ctlr_info *h,
spin_lock_irqsave(&h->lock, flags);
list_for_each_entry(c, queue_head, list) {
- if (memcmp(&c->Header.Tag, tag, 8) != 0)
+ if (memcmp(&c->Header.tag, tag, 8) != 0)
continue;
spin_unlock_irqrestore(&h->lock, flags);
return c;
@@ -4686,19 +4588,32 @@ static struct CommandList *cmd_alloc(struct ctlr_info *h)
int i;
union u64bit temp64;
dma_addr_t cmd_dma_handle, err_dma_handle;
- unsigned long flags;
+ int loopcount;
+
+ /* There is some *extremely* small but non-zero chance that that
+ * multiple threads could get in here, and one thread could
+ * be scanning through the list of bits looking for a free
+ * one, but the free ones are always behind him, and other
+ * threads sneak in behind him and eat them before he can
+ * get to them, so that while there is always a free one, a
+ * very unlucky thread might be starved anyway, never able to
+ * beat the other threads. In reality, this happens so
+ * infrequently as to be indistinguishable from never.
+ */
- spin_lock_irqsave(&h->lock, flags);
+ loopcount = 0;
do {
i = find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds);
- if (i == h->nr_cmds) {
- spin_unlock_irqrestore(&h->lock, flags);
- return NULL;
- }
- } while (test_and_set_bit
- (i & (BITS_PER_LONG - 1),
- h->cmd_pool_bits + (i / BITS_PER_LONG)) != 0);
- spin_unlock_irqrestore(&h->lock, flags);
+ if (i == h->nr_cmds)
+ i = 0;
+ loopcount++;
+ } while (test_and_set_bit(i & (BITS_PER_LONG - 1),
+ h->cmd_pool_bits + (i / BITS_PER_LONG)) != 0 &&
+ loopcount < 10);
+
+ /* Thread got starved? We do not expect this to ever happen. */
+ if (loopcount >= 10)
+ return NULL;
c = h->cmd_pool + i;
memset(c, 0, sizeof(*c));
@@ -4714,9 +4629,8 @@ static struct CommandList *cmd_alloc(struct ctlr_info *h)
INIT_LIST_HEAD(&c->list);
c->busaddr = (u32) cmd_dma_handle;
temp64.val = (u64) err_dma_handle;
- c->ErrDesc.Addr.lower = temp64.val32.lower;
- c->ErrDesc.Addr.upper = temp64.val32.upper;
- c->ErrDesc.Len = sizeof(*c->err_info);
+ c->ErrDesc.Addr = cpu_to_le64(err_dma_handle);
+ c->ErrDesc.Len = cpu_to_le32(sizeof(*c->err_info));
c->h = h;
return c;
@@ -4729,7 +4643,6 @@ static struct CommandList *cmd_alloc(struct ctlr_info *h)
static struct CommandList *cmd_special_alloc(struct ctlr_info *h)
{
struct CommandList *c;
- union u64bit temp64;
dma_addr_t cmd_dma_handle, err_dma_handle;
c = pci_zalloc_consistent(h->pdev, sizeof(*c), &cmd_dma_handle);
@@ -4750,10 +4663,8 @@ static struct CommandList *cmd_special_alloc(struct ctlr_info *h)
INIT_LIST_HEAD(&c->list);
c->busaddr = (u32) cmd_dma_handle;
- temp64.val = (u64) err_dma_handle;
- c->ErrDesc.Addr.lower = temp64.val32.lower;
- c->ErrDesc.Addr.upper = temp64.val32.upper;
- c->ErrDesc.Len = sizeof(*c->err_info);
+ c->ErrDesc.Addr = cpu_to_le64(err_dma_handle);
+ c->ErrDesc.Len = cpu_to_le32(sizeof(*c->err_info));
c->h = h;
return c;
@@ -4762,30 +4673,25 @@ static struct CommandList *cmd_special_alloc(struct ctlr_info *h)
static void cmd_free(struct ctlr_info *h, struct CommandList *c)
{
int i;
- unsigned long flags;
i = c - h->cmd_pool;
- spin_lock_irqsave(&h->lock, flags);
clear_bit(i & (BITS_PER_LONG - 1),
h->cmd_pool_bits + (i / BITS_PER_LONG));
- spin_unlock_irqrestore(&h->lock, flags);
}
static void cmd_special_free(struct ctlr_info *h, struct CommandList *c)
{
- union u64bit temp64;
-
- temp64.val32.lower = c->ErrDesc.Addr.lower;
- temp64.val32.upper = c->ErrDesc.Addr.upper;
pci_free_consistent(h->pdev, sizeof(*c->err_info),
- c->err_info, (dma_addr_t) temp64.val);
+ c->err_info,
+ (dma_addr_t) le64_to_cpu(c->ErrDesc.Addr));
pci_free_consistent(h->pdev, sizeof(*c),
c, (dma_addr_t) (c->busaddr & DIRECT_LOOKUP_MASK));
}
#ifdef CONFIG_COMPAT
-static int hpsa_ioctl32_passthru(struct scsi_device *dev, int cmd, void *arg)
+static int hpsa_ioctl32_passthru(struct scsi_device *dev, int cmd,
+ void __user *arg)
{
IOCTL32_Command_struct __user *arg32 =
(IOCTL32_Command_struct __user *) arg;
@@ -4810,7 +4716,7 @@ static int hpsa_ioctl32_passthru(struct scsi_device *dev, int cmd, void *arg)
if (err)
return -EFAULT;
- err = hpsa_ioctl(dev, CCISS_PASSTHRU, (void *)p);
+ err = hpsa_ioctl(dev, CCISS_PASSTHRU, p);
if (err)
return err;
err |= copy_in_user(&arg32->error_info, &p->error_info,
@@ -4821,7 +4727,7 @@ static int hpsa_ioctl32_passthru(struct scsi_device *dev, int cmd, void *arg)
}
static int hpsa_ioctl32_big_passthru(struct scsi_device *dev,
- int cmd, void *arg)
+ int cmd, void __user *arg)
{
BIG_IOCTL32_Command_struct __user *arg32 =
(BIG_IOCTL32_Command_struct __user *) arg;
@@ -4848,7 +4754,7 @@ static int hpsa_ioctl32_big_passthru(struct scsi_device *dev,
if (err)
return -EFAULT;
- err = hpsa_ioctl(dev, CCISS_BIG_PASSTHRU, (void *)p);
+ err = hpsa_ioctl(dev, CCISS_BIG_PASSTHRU, p);
if (err)
return err;
err |= copy_in_user(&arg32->error_info, &p->error_info,
@@ -4858,7 +4764,7 @@ static int hpsa_ioctl32_big_passthru(struct scsi_device *dev,
return err;
}
-static int hpsa_compat_ioctl(struct scsi_device *dev, int cmd, void *arg)
+static int hpsa_compat_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
{
switch (cmd) {
case CCISS_GETPCIINFO:
@@ -4932,7 +4838,7 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
IOCTL_Command_struct iocommand;
struct CommandList *c;
char *buff = NULL;
- union u64bit temp64;
+ u64 temp64;
int rc = 0;
if (!argp)
@@ -4971,14 +4877,14 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
c->Header.ReplyQueue = 0; /* unused in simple mode */
if (iocommand.buf_size > 0) { /* buffer to fill */
c->Header.SGList = 1;
- c->Header.SGTotal = 1;
+ c->Header.SGTotal = cpu_to_le16(1);
} else { /* no buffers to fill */
c->Header.SGList = 0;
- c->Header.SGTotal = 0;
+ c->Header.SGTotal = cpu_to_le16(0);
}
memcpy(&c->Header.LUN, &iocommand.LUN_info, sizeof(c->Header.LUN));
/* use the kernel address the cmd block for tag */
- c->Header.Tag.lower = c->busaddr;
+ c->Header.tag = c->busaddr;
/* Fill in Request block */
memcpy(&c->Request, &iocommand.Request,
@@ -4986,19 +4892,17 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
/* Fill in the scatter gather information */
if (iocommand.buf_size > 0) {
- temp64.val = pci_map_single(h->pdev, buff,
+ temp64 = pci_map_single(h->pdev, buff,
iocommand.buf_size, PCI_DMA_BIDIRECTIONAL);
- if (dma_mapping_error(&h->pdev->dev, temp64.val)) {
- c->SG[0].Addr.lower = 0;
- c->SG[0].Addr.upper = 0;
- c->SG[0].Len = 0;
+ if (dma_mapping_error(&h->pdev->dev, (dma_addr_t) temp64)) {
+ c->SG[0].Addr = cpu_to_le64(0);
+ c->SG[0].Len = cpu_to_le32(0);
rc = -ENOMEM;
goto out;
}
- c->SG[0].Addr.lower = temp64.val32.lower;
- c->SG[0].Addr.upper = temp64.val32.upper;
- c->SG[0].Len = iocommand.buf_size;
- c->SG[0].Ext = HPSA_SG_LAST; /* we are not chaining*/
+ c->SG[0].Addr = cpu_to_le64(temp64);
+ c->SG[0].Len = cpu_to_le32(iocommand.buf_size);
+ c->SG[0].Ext = cpu_to_le32(HPSA_SG_LAST); /* not chaining */
}
hpsa_scsi_do_simple_cmd_core_if_no_lockup(h, c);
if (iocommand.buf_size > 0)
@@ -5033,7 +4937,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
struct CommandList *c;
unsigned char **buff = NULL;
int *buff_size = NULL;
- union u64bit temp64;
+ u64 temp64;
BYTE sg_used = 0;
int status = 0;
int i;
@@ -5107,29 +5011,30 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
}
c->cmd_type = CMD_IOCTL_PEND;
c->Header.ReplyQueue = 0;
- c->Header.SGList = c->Header.SGTotal = sg_used;
+ c->Header.SGList = (u8) sg_used;
+ c->Header.SGTotal = cpu_to_le16(sg_used);
memcpy(&c->Header.LUN, &ioc->LUN_info, sizeof(c->Header.LUN));
- c->Header.Tag.lower = c->busaddr;
+ c->Header.tag = c->busaddr;
memcpy(&c->Request, &ioc->Request, sizeof(c->Request));
if (ioc->buf_size > 0) {
int i;
for (i = 0; i < sg_used; i++) {
- temp64.val = pci_map_single(h->pdev, buff[i],
+ temp64 = pci_map_single(h->pdev, buff[i],
buff_size[i], PCI_DMA_BIDIRECTIONAL);
- if (dma_mapping_error(&h->pdev->dev, temp64.val)) {
- c->SG[i].Addr.lower = 0;
- c->SG[i].Addr.upper = 0;
- c->SG[i].Len = 0;
+ if (dma_mapping_error(&h->pdev->dev,
+ (dma_addr_t) temp64)) {
+ c->SG[i].Addr = cpu_to_le64(0);
+ c->SG[i].Len = cpu_to_le32(0);
hpsa_pci_unmap(h->pdev, c, i,
PCI_DMA_BIDIRECTIONAL);
status = -ENOMEM;
goto cleanup0;
}
- c->SG[i].Addr.lower = temp64.val32.lower;
- c->SG[i].Addr.upper = temp64.val32.upper;
- c->SG[i].Len = buff_size[i];
- c->SG[i].Ext = i < sg_used - 1 ? 0 : HPSA_SG_LAST;
+ c->SG[i].Addr = cpu_to_le64(temp64);
+ c->SG[i].Len = cpu_to_le32(buff_size[i]);
+ c->SG[i].Ext = cpu_to_le32(0);
}
+ c->SG[--i].Ext = cpu_to_le32(HPSA_SG_LAST);
}
hpsa_scsi_do_simple_cmd_core_if_no_lockup(h, c);
if (sg_used)
@@ -5206,7 +5111,7 @@ static void decrement_passthru_count(struct ctlr_info *h)
/*
* ioctl
*/
-static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg)
+static int hpsa_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
{
struct ctlr_info *h;
void __user *argp = (void __user *)arg;
@@ -5268,20 +5173,20 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
{
int pci_dir = XFER_NONE;
struct CommandList *a; /* for commands to be aborted */
+ u32 tupper, tlower;
c->cmd_type = CMD_IOCTL_PEND;
c->Header.ReplyQueue = 0;
if (buff != NULL && size > 0) {
c->Header.SGList = 1;
- c->Header.SGTotal = 1;
+ c->Header.SGTotal = cpu_to_le16(1);
} else {
c->Header.SGList = 0;
- c->Header.SGTotal = 0;
+ c->Header.SGTotal = cpu_to_le16(0);
}
- c->Header.Tag.lower = c->busaddr;
+ c->Header.tag = c->busaddr;
memcpy(c->Header.LUN.LunAddrBytes, scsi3addr, 8);
- c->Request.Type.Type = cmd_type;
if (cmd_type == TYPE_CMD) {
switch (cmd) {
case HPSA_INQUIRY:
@@ -5291,8 +5196,8 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
c->Request.CDB[2] = (page_code & 0xff);
}
c->Request.CDBLen = 6;
- c->Request.Type.Attribute = ATTR_SIMPLE;
- c->Request.Type.Direction = XFER_READ;
+ c->Request.type_attr_dir =
+ TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ);
c->Request.Timeout = 0;
c->Request.CDB[0] = HPSA_INQUIRY;
c->Request.CDB[4] = size & 0xFF;
@@ -5303,8 +5208,8 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
mode = 00 target = 0. Nothing to write.
*/
c->Request.CDBLen = 12;
- c->Request.Type.Attribute = ATTR_SIMPLE;
- c->Request.Type.Direction = XFER_READ;
+ c->Request.type_attr_dir =
+ TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ);
c->Request.Timeout = 0;
c->Request.CDB[0] = cmd;
c->Request.CDB[6] = (size >> 24) & 0xFF; /* MSB */
@@ -5314,8 +5219,9 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
break;
case HPSA_CACHE_FLUSH:
c->Request.CDBLen = 12;
- c->Request.Type.Attribute = ATTR_SIMPLE;
- c->Request.Type.Direction = XFER_WRITE;
+ c->Request.type_attr_dir =
+ TYPE_ATTR_DIR(cmd_type,
+ ATTR_SIMPLE, XFER_WRITE);
c->Request.Timeout = 0;
c->Request.CDB[0] = BMIC_WRITE;
c->Request.CDB[6] = BMIC_CACHE_FLUSH;
@@ -5324,14 +5230,14 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
break;
case TEST_UNIT_READY:
c->Request.CDBLen = 6;
- c->Request.Type.Attribute = ATTR_SIMPLE;
- c->Request.Type.Direction = XFER_NONE;
+ c->Request.type_attr_dir =
+ TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_NONE);
c->Request.Timeout = 0;
break;
case HPSA_GET_RAID_MAP:
c->Request.CDBLen = 12;
- c->Request.Type.Attribute = ATTR_SIMPLE;
- c->Request.Type.Direction = XFER_READ;
+ c->Request.type_attr_dir =
+ TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ);
c->Request.Timeout = 0;
c->Request.CDB[0] = HPSA_CISS_READ;
c->Request.CDB[1] = cmd;
@@ -5342,8 +5248,8 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
break;
case BMIC_SENSE_CONTROLLER_PARAMETERS:
c->Request.CDBLen = 10;
- c->Request.Type.Attribute = ATTR_SIMPLE;
- c->Request.Type.Direction = XFER_READ;
+ c->Request.type_attr_dir =
+ TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ);
c->Request.Timeout = 0;
c->Request.CDB[0] = BMIC_READ;
c->Request.CDB[6] = BMIC_SENSE_CONTROLLER_PARAMETERS;
@@ -5360,9 +5266,8 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
case HPSA_DEVICE_RESET_MSG:
c->Request.CDBLen = 16;
- c->Request.Type.Type = 1; /* It is a MSG not a CMD */
- c->Request.Type.Attribute = ATTR_SIMPLE;
- c->Request.Type.Direction = XFER_NONE;
+ c->Request.type_attr_dir =
+ TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_NONE);
c->Request.Timeout = 0; /* Don't time out */
memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB));
c->Request.CDB[0] = cmd;
@@ -5376,27 +5281,28 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
break;
case HPSA_ABORT_MSG:
a = buff; /* point to command to be aborted */
- dev_dbg(&h->pdev->dev, "Abort Tag:0x%08x:%08x using request Tag:0x%08x:%08x\n",
- a->Header.Tag.upper, a->Header.Tag.lower,
- c->Header.Tag.upper, c->Header.Tag.lower);
+ dev_dbg(&h->pdev->dev, "Abort Tag:0x%016llx using request Tag:0x%016llx",
+ a->Header.tag, c->Header.tag);
+ tlower = (u32) (a->Header.tag >> 32);
+ tupper = (u32) (a->Header.tag & 0x0ffffffffULL);
c->Request.CDBLen = 16;
- c->Request.Type.Type = TYPE_MSG;
- c->Request.Type.Attribute = ATTR_SIMPLE;
- c->Request.Type.Direction = XFER_WRITE;
+ c->Request.type_attr_dir =
+ TYPE_ATTR_DIR(cmd_type,
+ ATTR_SIMPLE, XFER_WRITE);
c->Request.Timeout = 0; /* Don't time out */
c->Request.CDB[0] = HPSA_TASK_MANAGEMENT;
c->Request.CDB[1] = HPSA_TMF_ABORT_TASK;
c->Request.CDB[2] = 0x00; /* reserved */
c->Request.CDB[3] = 0x00; /* reserved */
/* Tag to abort goes in CDB[4]-CDB[11] */
- c->Request.CDB[4] = a->Header.Tag.lower & 0xFF;
- c->Request.CDB[5] = (a->Header.Tag.lower >> 8) & 0xFF;
- c->Request.CDB[6] = (a->Header.Tag.lower >> 16) & 0xFF;
- c->Request.CDB[7] = (a->Header.Tag.lower >> 24) & 0xFF;
- c->Request.CDB[8] = a->Header.Tag.upper & 0xFF;
- c->Request.CDB[9] = (a->Header.Tag.upper >> 8) & 0xFF;
- c->Request.CDB[10] = (a->Header.Tag.upper >> 16) & 0xFF;
- c->Request.CDB[11] = (a->Header.Tag.upper >> 24) & 0xFF;
+ c->Request.CDB[4] = tlower & 0xFF;
+ c->Request.CDB[5] = (tlower >> 8) & 0xFF;
+ c->Request.CDB[6] = (tlower >> 16) & 0xFF;
+ c->Request.CDB[7] = (tlower >> 24) & 0xFF;
+ c->Request.CDB[8] = tupper & 0xFF;
+ c->Request.CDB[9] = (tupper >> 8) & 0xFF;
+ c->Request.CDB[10] = (tupper >> 16) & 0xFF;
+ c->Request.CDB[11] = (tupper >> 24) & 0xFF;
c->Request.CDB[12] = 0x00; /* reserved */
c->Request.CDB[13] = 0x00; /* reserved */
c->Request.CDB[14] = 0x00; /* reserved */
@@ -5412,7 +5318,7 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
BUG();
}
- switch (c->Request.Type.Direction) {
+ switch (GET_DIR(c->Request.type_attr_dir)) {
case XFER_READ:
pci_dir = PCI_DMA_FROMDEVICE;
break;
@@ -5467,15 +5373,9 @@ static void start_io(struct ctlr_info *h, unsigned long *flags)
/* Put job onto the completed Q */
addQ(&h->cmpQ, c);
-
- /* Must increment commands_outstanding before unlocking
- * and submitting to avoid race checking for fifo full
- * condition.
- */
- h->commands_outstanding++;
-
- /* Tell the controller execute command */
+ atomic_inc(&h->commands_outstanding);
spin_unlock_irqrestore(&h->lock, *flags);
+ /* Tell the controller execute command */
h->access.submit_command(h, c);
spin_lock_irqsave(&h->lock, *flags);
}
@@ -5521,6 +5421,7 @@ static inline void finish_cmd(struct CommandList *c)
unsigned long flags;
int io_may_be_stalled = 0;
struct ctlr_info *h = c->h;
+ int count;
spin_lock_irqsave(&h->lock, flags);
removeQ(c);
@@ -5541,11 +5442,10 @@ static inline void finish_cmd(struct CommandList *c)
* want to get in a cycle where we call start_io every time
* through here.
*/
- if (unlikely(h->fifo_recently_full) &&
- h->commands_outstanding < 5)
- io_may_be_stalled = 1;
-
+ count = atomic_read(&h->commands_outstanding);
spin_unlock_irqrestore(&h->lock, flags);
+ if (unlikely(h->fifo_recently_full) && count < 5)
+ io_may_be_stalled = 1;
dial_up_lockup_detection_on_fw_flash_complete(c->h, c);
if (likely(c->cmd_type == CMD_IOACCEL1 || c->cmd_type == CMD_SCSI
@@ -5765,22 +5665,20 @@ static int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
cmd->CommandHeader.ReplyQueue = 0;
cmd->CommandHeader.SGList = 0;
- cmd->CommandHeader.SGTotal = 0;
- cmd->CommandHeader.Tag.lower = paddr32;
- cmd->CommandHeader.Tag.upper = 0;
+ cmd->CommandHeader.SGTotal = cpu_to_le16(0);
+ cmd->CommandHeader.tag = paddr32;
memset(&cmd->CommandHeader.LUN.LunAddrBytes, 0, 8);
cmd->Request.CDBLen = 16;
- cmd->Request.Type.Type = TYPE_MSG;
- cmd->Request.Type.Attribute = ATTR_HEADOFQUEUE;
- cmd->Request.Type.Direction = XFER_NONE;
+ cmd->Request.type_attr_dir =
+ TYPE_ATTR_DIR(TYPE_MSG, ATTR_HEADOFQUEUE, XFER_NONE);
cmd->Request.Timeout = 0; /* Don't time out */
cmd->Request.CDB[0] = opcode;
cmd->Request.CDB[1] = type;
memset(&cmd->Request.CDB[2], 0, 14); /* rest of the CDB is reserved */
- cmd->ErrorDescriptor.Addr.lower = paddr32 + sizeof(*cmd);
- cmd->ErrorDescriptor.Addr.upper = 0;
- cmd->ErrorDescriptor.Len = sizeof(struct ErrorInfo);
+ cmd->ErrorDescriptor.Addr =
+ cpu_to_le64((paddr32 + sizeof(*cmd)));
+ cmd->ErrorDescriptor.Len = cpu_to_le32(sizeof(struct ErrorInfo));
writel(paddr32, vaddr + SA5_REQUEST_PORT_OFFSET);
@@ -5818,7 +5716,7 @@ static int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
#define hpsa_noop(p) hpsa_message(p, 3, 0)
static int hpsa_controller_hard_reset(struct pci_dev *pdev,
- void * __iomem vaddr, u32 use_doorbell)
+ void __iomem *vaddr, u32 use_doorbell)
{
u16 pmcsr;
int pos;
@@ -6056,7 +5954,7 @@ unmap_vaddr:
* the io functions.
* This is for debug only.
*/
-static void print_cfg_table(struct device *dev, struct CfgTable *tb)
+static void print_cfg_table(struct device *dev, struct CfgTable __iomem *tb)
{
#ifdef HPSA_DEBUG
int i;
@@ -6323,11 +6221,11 @@ static void hpsa_find_board_params(struct ctlr_info *h)
h->max_cmd_sg_entries = 31;
if (h->maxsgentries > 512) {
h->max_cmd_sg_entries = 32;
- h->chainsize = h->maxsgentries - h->max_cmd_sg_entries + 1;
+ h->chainsize = h->maxsgentries - h->max_cmd_sg_entries;
h->maxsgentries--; /* save one for chain pointer */
} else {
- h->maxsgentries = 31; /* default to traditional values */
h->chainsize = 0;
+ h->maxsgentries = 31; /* default to traditional values */
}
/* Find out what task management functions are supported and cache */
@@ -6456,15 +6354,15 @@ static int hpsa_pci_init(struct ctlr_info *h)
return err;
}
- /* Enable bus mastering (pci_disable_device may disable this) */
- pci_set_master(h->pdev);
-
err = pci_request_regions(h->pdev, HPSA);
if (err) {
dev_err(&h->pdev->dev,
"cannot obtain PCI resources, aborting\n");
return err;
}
+
+ pci_set_master(h->pdev);
+
hpsa_interrupt_mode(h);
err = hpsa_pci_find_memory_BAR(h->pdev, &h->paddr);
if (err)
@@ -6544,7 +6442,9 @@ static int hpsa_init_reset_devices(struct pci_dev *pdev)
dev_warn(&pdev->dev, "failed to enable device.\n");
return -ENODEV;
}
+
pci_set_master(pdev);
+
/* Reset the controller with a PCI power-cycle or via doorbell */
rc = hpsa_kdump_hard_reset_controller(pdev);
@@ -7431,13 +7331,12 @@ static void hpsa_enter_performant_mode(struct ctlr_info *h, u32 trans_support)
cp->host_context_flags = IOACCEL1_HCFLAGS_CISS_FORMAT;
cp->timeout_sec = 0;
cp->ReplyQueue = 0;
- cp->Tag.lower = (i << DIRECT_LOOKUP_SHIFT) |
- DIRECT_LOOKUP_BIT;
- cp->Tag.upper = 0;
- cp->host_addr.lower =
- (u32) (h->ioaccel_cmd_pool_dhandle +
+ cp->tag =
+ cpu_to_le64((i << DIRECT_LOOKUP_SHIFT) |
+ DIRECT_LOOKUP_BIT);
+ cp->host_addr =
+ cpu_to_le64(h->ioaccel_cmd_pool_dhandle +
(i * sizeof(struct io_accel1_cmd)));
- cp->host_addr.upper = 0;
}
} else if (trans_support & CFGTBL_Trans_io_accel2) {
u64 cfg_offset, cfg_base_addr_index;
@@ -7711,7 +7610,7 @@ static void __attribute__((unused)) verify_offsets(void)
VERIFY_OFFSET(timeout_sec, 0x62);
VERIFY_OFFSET(ReplyQueue, 0x64);
VERIFY_OFFSET(reserved9, 0x65);
- VERIFY_OFFSET(Tag, 0x68);
+ VERIFY_OFFSET(tag, 0x68);
VERIFY_OFFSET(host_addr, 0x70);
VERIFY_OFFSET(CISS_LUN, 0x78);
VERIFY_OFFSET(SG, 0x78 + 8);
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 24472cec7de3..8e06d9e280ec 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -118,7 +118,7 @@ struct ctlr_info {
struct CfgTable __iomem *cfgtable;
int interrupts_enabled;
int max_commands;
- int commands_outstanding;
+ atomic_t commands_outstanding;
# define PERF_MODE_INT 0
# define DOORBELL_INT 1
# define SIMPLE_MODE_INT 2
@@ -164,7 +164,7 @@ struct ctlr_info {
*/
u32 trans_support;
u32 trans_offset;
- struct TransTable_struct *transtable;
+ struct TransTable_struct __iomem *transtable;
unsigned long transMethod;
/* cap concurrent passthrus at some reasonable maximum */
@@ -181,7 +181,7 @@ struct ctlr_info {
u32 *blockFetchTable;
u32 *ioaccel1_blockFetchTable;
u32 *ioaccel2_blockFetchTable;
- u32 *ioaccel2_bft2_regs;
+ u32 __iomem *ioaccel2_bft2_regs;
unsigned char *hba_inquiry_data;
u32 driver_support;
u32 fw_support;
@@ -192,7 +192,7 @@ struct ctlr_info {
u64 last_heartbeat_timestamp;
u32 heartbeat_sample_interval;
atomic_t firmware_flash_in_progress;
- u32 *lockup_detected;
+ u32 __percpu *lockup_detected;
struct delayed_work monitor_ctlr_work;
int remove_in_progress;
u32 fifo_recently_full;
@@ -395,7 +395,7 @@ static void SA5_performant_intr_mask(struct ctlr_info *h, unsigned long val)
static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q)
{
struct reply_queue_buffer *rq = &h->reply_queue[q];
- unsigned long flags, register_value = FIFO_EMPTY;
+ unsigned long register_value = FIFO_EMPTY;
/* msi auto clears the interrupt pending bit. */
if (!(h->msi_vector || h->msix_vector)) {
@@ -413,9 +413,7 @@ static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q)
if ((rq->head[rq->current_entry] & 1) == rq->wraparound) {
register_value = rq->head[rq->current_entry];
rq->current_entry++;
- spin_lock_irqsave(&h->lock, flags);
- h->commands_outstanding--;
- spin_unlock_irqrestore(&h->lock, flags);
+ atomic_dec(&h->commands_outstanding);
} else {
register_value = FIFO_EMPTY;
}
@@ -433,11 +431,7 @@ static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q)
*/
static unsigned long SA5_fifo_full(struct ctlr_info *h)
{
- if (h->commands_outstanding >= h->max_commands)
- return 1;
- else
- return 0;
-
+ return atomic_read(&h->commands_outstanding) >= h->max_commands;
}
/*
* returns value read from hardware.
@@ -448,13 +442,9 @@ static unsigned long SA5_completed(struct ctlr_info *h,
{
unsigned long register_value
= readl(h->vaddr + SA5_REPLY_PORT_OFFSET);
- unsigned long flags;
- if (register_value != FIFO_EMPTY) {
- spin_lock_irqsave(&h->lock, flags);
- h->commands_outstanding--;
- spin_unlock_irqrestore(&h->lock, flags);
- }
+ if (register_value != FIFO_EMPTY)
+ atomic_dec(&h->commands_outstanding);
#ifdef HPSA_DEBUG
if (register_value != FIFO_EMPTY)
@@ -510,7 +500,6 @@ static unsigned long SA5_ioaccel_mode1_completed(struct ctlr_info *h, u8 q)
{
u64 register_value;
struct reply_queue_buffer *rq = &h->reply_queue[q];
- unsigned long flags;
BUG_ON(q >= h->nreply_queues);
@@ -528,9 +517,7 @@ static unsigned long SA5_ioaccel_mode1_completed(struct ctlr_info *h, u8 q)
wmb();
writel((q << 24) | rq->current_entry, h->vaddr +
IOACCEL_MODE1_CONSUMER_INDEX);
- spin_lock_irqsave(&h->lock, flags);
- h->commands_outstanding--;
- spin_unlock_irqrestore(&h->lock, flags);
+ atomic_dec(&h->commands_outstanding);
}
return (unsigned long) register_value;
}
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h
index b5125dc31439..cb988c41cad9 100644
--- a/drivers/scsi/hpsa_cmd.h
+++ b/drivers/scsi/hpsa_cmd.h
@@ -252,7 +252,7 @@ struct ReportExtendedLUNdata {
u8 LUNListLength[4];
u8 extended_response_flag;
u8 reserved[3];
- struct ext_report_lun_entry LUN[HPSA_MAX_LUN];
+ struct ext_report_lun_entry LUN[HPSA_MAX_PHYS_LUN];
};
struct SenseSubsystem_info {
@@ -314,28 +314,36 @@ struct CommandListHeader {
u8 ReplyQueue;
u8 SGList;
u16 SGTotal;
- struct vals32 Tag;
+ u64 tag;
union LUNAddr LUN;
};
struct RequestBlock {
u8 CDBLen;
- struct {
- u8 Type:3;
- u8 Attribute:3;
- u8 Direction:2;
- } Type;
+ /*
+ * type_attr_dir:
+ * type: low 3 bits
+ * attr: middle 3 bits
+ * dir: high 2 bits
+ */
+ u8 type_attr_dir;
+#define TYPE_ATTR_DIR(t, a, d) ((((d) & 0x03) << 6) |\
+ (((a) & 0x07) << 3) |\
+ ((t) & 0x07))
+#define GET_TYPE(tad) ((tad) & 0x07)
+#define GET_ATTR(tad) (((tad) >> 3) & 0x07)
+#define GET_DIR(tad) (((tad) >> 6) & 0x03)
u16 Timeout;
u8 CDB[16];
};
struct ErrDescriptor {
- struct vals32 Addr;
+ u64 Addr;
u32 Len;
};
struct SGDescriptor {
- struct vals32 Addr;
+ u64 Addr;
u32 Len;
u32 Ext;
};
@@ -434,8 +442,8 @@ struct io_accel1_cmd {
u16 timeout_sec; /* 0x62 - 0x63 */
u8 ReplyQueue; /* 0x64 */
u8 reserved9[3]; /* 0x65 - 0x67 */
- struct vals32 Tag; /* 0x68 - 0x6F */
- struct vals32 host_addr; /* 0x70 - 0x77 */
+ u64 tag; /* 0x68 - 0x6F */
+ u64 host_addr; /* 0x70 - 0x77 */
u8 CISS_LUN[8]; /* 0x78 - 0x7F */
struct SGDescriptor SG[IOACCEL1_MAXSGENTRIES];
} __aligned(IOACCEL1_COMMANDLIST_ALIGNMENT);
@@ -555,8 +563,8 @@ struct hpsa_tmf_struct {
u8 reserved1; /* byte 3 Reserved */
u32 it_nexus; /* SCSI I-T Nexus */
u8 lun_id[8]; /* LUN ID for TMF request */
- struct vals32 Tag; /* cciss tag associated w/ request */
- struct vals32 abort_tag;/* cciss tag of SCSI cmd or task to abort */
+ u64 tag; /* cciss tag associated w/ request */
+ u64 abort_tag; /* cciss tag of SCSI cmd or task to abort */
u64 error_ptr; /* Error Pointer */
u32 error_len; /* Error Length */
};
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
index 151893148abd..e995218476ed 100644
--- a/drivers/scsi/hptiop.c
+++ b/drivers/scsi/hptiop.c
@@ -1118,17 +1118,13 @@ static int hptiop_reset(struct scsi_cmnd *scp)
}
static int hptiop_adjust_disk_queue_depth(struct scsi_device *sdev,
- int queue_depth, int reason)
+ int queue_depth)
{
struct hptiop_hba *hba = (struct hptiop_hba *)sdev->host->hostdata;
- if (reason != SCSI_QDEPTH_DEFAULT)
- return -EOPNOTSUPP;
-
if (queue_depth > hba->max_requests)
queue_depth = hba->max_requests;
- scsi_adjust_queue_depth(sdev, queue_depth);
- return queue_depth;
+ return scsi_change_queue_depth(sdev, queue_depth);
}
static ssize_t hptiop_show_version(struct device *dev,
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 147b80e07b00..f58c6d8e0264 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -2900,17 +2900,12 @@ static int ibmvfc_slave_configure(struct scsi_device *sdev)
* Return value:
* actual depth set
**/
-static int ibmvfc_change_queue_depth(struct scsi_device *sdev, int qdepth,
- int reason)
+static int ibmvfc_change_queue_depth(struct scsi_device *sdev, int qdepth)
{
- if (reason != SCSI_QDEPTH_DEFAULT)
- return -EOPNOTSUPP;
-
if (qdepth > IBMVFC_MAX_CMDS_PER_LUN)
qdepth = IBMVFC_MAX_CMDS_PER_LUN;
- scsi_adjust_queue_depth(sdev, qdepth);
- return sdev->queue_depth;
+ return scsi_change_queue_depth(sdev, qdepth);
}
static ssize_t ibmvfc_show_host_partition_name(struct device *dev,
@@ -3103,6 +3098,7 @@ static struct scsi_host_template driver_template = {
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = ibmvfc_attrs,
.use_blk_tags = 1,
+ .track_queue_depth = 1,
};
/**
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index e8c3cdf0d03b..acea5d6eebd0 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -1941,17 +1941,11 @@ static int ibmvscsi_slave_configure(struct scsi_device *sdev)
* Return value:
* actual depth set
**/
-static int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth,
- int reason)
+static int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth)
{
- if (reason != SCSI_QDEPTH_DEFAULT)
- return -EOPNOTSUPP;
-
if (qdepth > IBMVSCSI_MAX_CMDS_PER_LUN)
qdepth = IBMVSCSI_MAX_CMDS_PER_LUN;
-
- scsi_adjust_queue_depth(sdev, qdepth);
- return sdev->queue_depth;
+ return scsi_change_queue_depth(sdev, qdepth);
}
/* ------------------------------------------------------------
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 256ef98f5c29..540294389355 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -3942,8 +3942,9 @@ static int ipr_update_ioa_ucode(struct ipr_ioa_cfg *ioa_cfg,
return -EIO;
}
- sglist->num_dma_sg = pci_map_sg(ioa_cfg->pdev, sglist->scatterlist,
- sglist->num_sg, DMA_TO_DEVICE);
+ sglist->num_dma_sg = dma_map_sg(&ioa_cfg->pdev->dev,
+ sglist->scatterlist, sglist->num_sg,
+ DMA_TO_DEVICE);
if (!sglist->num_dma_sg) {
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
@@ -4327,16 +4328,12 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg) { return 0; };
* Return value:
* actual depth set
**/
-static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth,
- int reason)
+static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth)
{
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata;
struct ipr_resource_entry *res;
unsigned long lock_flags = 0;
- if (reason != SCSI_QDEPTH_DEFAULT)
- return -EOPNOTSUPP;
-
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
res = (struct ipr_resource_entry *)sdev->hostdata;
@@ -4344,7 +4341,7 @@ static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth,
qdepth = IPR_MAX_CMD_PER_ATA_LUN;
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
- scsi_adjust_queue_depth(sdev, qdepth);
+ scsi_change_queue_depth(sdev, qdepth);
return sdev->queue_depth;
}
@@ -4751,7 +4748,7 @@ static int ipr_slave_configure(struct scsi_device *sdev)
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
if (ap) {
- scsi_adjust_queue_depth(sdev, IPR_MAX_CMD_PER_ATA_LUN);
+ scsi_change_queue_depth(sdev, IPR_MAX_CMD_PER_ATA_LUN);
ata_sas_slave_configure(sdev, ap);
}
@@ -5571,7 +5568,7 @@ static int ipr_build_ioadl64(struct ipr_ioa_cfg *ioa_cfg,
nseg = scsi_dma_map(scsi_cmd);
if (nseg < 0) {
if (printk_ratelimit())
- dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n");
+ dev_err(&ioa_cfg->pdev->dev, "scsi_dma_map failed!\n");
return -1;
}
@@ -5622,7 +5619,7 @@ static int ipr_build_ioadl(struct ipr_ioa_cfg *ioa_cfg,
nseg = scsi_dma_map(scsi_cmd);
if (nseg < 0) {
- dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n");
+ dev_err(&ioa_cfg->pdev->dev, "scsi_dma_map failed!\n");
return -1;
}
@@ -8392,7 +8389,7 @@ static int ipr_reset_ucode_download_done(struct ipr_cmnd *ipr_cmd)
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
struct ipr_sglist *sglist = ioa_cfg->ucode_sglist;
- pci_unmap_sg(ioa_cfg->pdev, sglist->scatterlist,
+ dma_unmap_sg(&ioa_cfg->pdev->dev, sglist->scatterlist,
sglist->num_sg, DMA_TO_DEVICE);
ipr_cmd->job_step = ipr_reset_alert;
@@ -8832,7 +8829,7 @@ static void ipr_free_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
for (i = 0; i < IPR_NUM_CMD_BLKS; i++) {
if (ioa_cfg->ipr_cmnd_list[i])
- pci_pool_free(ioa_cfg->ipr_cmd_pool,
+ dma_pool_free(ioa_cfg->ipr_cmd_pool,
ioa_cfg->ipr_cmnd_list[i],
ioa_cfg->ipr_cmnd_list_dma[i]);
@@ -8840,7 +8837,7 @@ static void ipr_free_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
}
if (ioa_cfg->ipr_cmd_pool)
- pci_pool_destroy(ioa_cfg->ipr_cmd_pool);
+ dma_pool_destroy(ioa_cfg->ipr_cmd_pool);
kfree(ioa_cfg->ipr_cmnd_list);
kfree(ioa_cfg->ipr_cmnd_list_dma);
@@ -8861,25 +8858,24 @@ static void ipr_free_mem(struct ipr_ioa_cfg *ioa_cfg)
int i;
kfree(ioa_cfg->res_entries);
- pci_free_consistent(ioa_cfg->pdev, sizeof(struct ipr_misc_cbs),
- ioa_cfg->vpd_cbs, ioa_cfg->vpd_cbs_dma);
+ dma_free_coherent(&ioa_cfg->pdev->dev, sizeof(struct ipr_misc_cbs),
+ ioa_cfg->vpd_cbs, ioa_cfg->vpd_cbs_dma);
ipr_free_cmd_blks(ioa_cfg);
for (i = 0; i < ioa_cfg->hrrq_num; i++)
- pci_free_consistent(ioa_cfg->pdev,
- sizeof(u32) * ioa_cfg->hrrq[i].size,
- ioa_cfg->hrrq[i].host_rrq,
- ioa_cfg->hrrq[i].host_rrq_dma);
+ dma_free_coherent(&ioa_cfg->pdev->dev,
+ sizeof(u32) * ioa_cfg->hrrq[i].size,
+ ioa_cfg->hrrq[i].host_rrq,
+ ioa_cfg->hrrq[i].host_rrq_dma);
- pci_free_consistent(ioa_cfg->pdev, ioa_cfg->cfg_table_size,
- ioa_cfg->u.cfg_table,
- ioa_cfg->cfg_table_dma);
+ dma_free_coherent(&ioa_cfg->pdev->dev, ioa_cfg->cfg_table_size,
+ ioa_cfg->u.cfg_table, ioa_cfg->cfg_table_dma);
for (i = 0; i < IPR_NUM_HCAMS; i++) {
- pci_free_consistent(ioa_cfg->pdev,
- sizeof(struct ipr_hostrcb),
- ioa_cfg->hostrcb[i],
- ioa_cfg->hostrcb_dma[i]);
+ dma_free_coherent(&ioa_cfg->pdev->dev,
+ sizeof(struct ipr_hostrcb),
+ ioa_cfg->hostrcb[i],
+ ioa_cfg->hostrcb_dma[i]);
}
ipr_free_dump(ioa_cfg);
@@ -8940,7 +8936,7 @@ static int ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
dma_addr_t dma_addr;
int i, entries_each_hrrq, hrrq_id = 0;
- ioa_cfg->ipr_cmd_pool = pci_pool_create(IPR_NAME, ioa_cfg->pdev,
+ ioa_cfg->ipr_cmd_pool = dma_pool_create(IPR_NAME, &ioa_cfg->pdev->dev,
sizeof(struct ipr_cmnd), 512, 0);
if (!ioa_cfg->ipr_cmd_pool)
@@ -8990,7 +8986,7 @@ static int ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
}
for (i = 0; i < IPR_NUM_CMD_BLKS; i++) {
- ipr_cmd = pci_pool_alloc(ioa_cfg->ipr_cmd_pool, GFP_KERNEL, &dma_addr);
+ ipr_cmd = dma_pool_alloc(ioa_cfg->ipr_cmd_pool, GFP_KERNEL, &dma_addr);
if (!ipr_cmd) {
ipr_free_cmd_blks(ioa_cfg);
@@ -9061,9 +9057,10 @@ static int ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
ioa_cfg->res_entries[i].ioa_cfg = ioa_cfg;
}
- ioa_cfg->vpd_cbs = pci_alloc_consistent(ioa_cfg->pdev,
- sizeof(struct ipr_misc_cbs),
- &ioa_cfg->vpd_cbs_dma);
+ ioa_cfg->vpd_cbs = dma_alloc_coherent(&pdev->dev,
+ sizeof(struct ipr_misc_cbs),
+ &ioa_cfg->vpd_cbs_dma,
+ GFP_KERNEL);
if (!ioa_cfg->vpd_cbs)
goto out_free_res_entries;
@@ -9072,13 +9069,14 @@ static int ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
goto out_free_vpd_cbs;
for (i = 0; i < ioa_cfg->hrrq_num; i++) {
- ioa_cfg->hrrq[i].host_rrq = pci_alloc_consistent(ioa_cfg->pdev,
+ ioa_cfg->hrrq[i].host_rrq = dma_alloc_coherent(&pdev->dev,
sizeof(u32) * ioa_cfg->hrrq[i].size,
- &ioa_cfg->hrrq[i].host_rrq_dma);
+ &ioa_cfg->hrrq[i].host_rrq_dma,
+ GFP_KERNEL);
if (!ioa_cfg->hrrq[i].host_rrq) {
while (--i > 0)
- pci_free_consistent(pdev,
+ dma_free_coherent(&pdev->dev,
sizeof(u32) * ioa_cfg->hrrq[i].size,
ioa_cfg->hrrq[i].host_rrq,
ioa_cfg->hrrq[i].host_rrq_dma);
@@ -9087,17 +9085,19 @@ static int ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
ioa_cfg->hrrq[i].ioa_cfg = ioa_cfg;
}
- ioa_cfg->u.cfg_table = pci_alloc_consistent(ioa_cfg->pdev,
- ioa_cfg->cfg_table_size,
- &ioa_cfg->cfg_table_dma);
+ ioa_cfg->u.cfg_table = dma_alloc_coherent(&pdev->dev,
+ ioa_cfg->cfg_table_size,
+ &ioa_cfg->cfg_table_dma,
+ GFP_KERNEL);
if (!ioa_cfg->u.cfg_table)
goto out_free_host_rrq;
for (i = 0; i < IPR_NUM_HCAMS; i++) {
- ioa_cfg->hostrcb[i] = pci_alloc_consistent(ioa_cfg->pdev,
- sizeof(struct ipr_hostrcb),
- &ioa_cfg->hostrcb_dma[i]);
+ ioa_cfg->hostrcb[i] = dma_alloc_coherent(&pdev->dev,
+ sizeof(struct ipr_hostrcb),
+ &ioa_cfg->hostrcb_dma[i],
+ GFP_KERNEL);
if (!ioa_cfg->hostrcb[i])
goto out_free_hostrcb_dma;
@@ -9121,25 +9121,24 @@ out:
out_free_hostrcb_dma:
while (i-- > 0) {
- pci_free_consistent(pdev, sizeof(struct ipr_hostrcb),
- ioa_cfg->hostrcb[i],
- ioa_cfg->hostrcb_dma[i]);
+ dma_free_coherent(&pdev->dev, sizeof(struct ipr_hostrcb),
+ ioa_cfg->hostrcb[i],
+ ioa_cfg->hostrcb_dma[i]);
}
- pci_free_consistent(pdev, ioa_cfg->cfg_table_size,
- ioa_cfg->u.cfg_table,
- ioa_cfg->cfg_table_dma);
+ dma_free_coherent(&pdev->dev, ioa_cfg->cfg_table_size,
+ ioa_cfg->u.cfg_table, ioa_cfg->cfg_table_dma);
out_free_host_rrq:
for (i = 0; i < ioa_cfg->hrrq_num; i++) {
- pci_free_consistent(pdev,
- sizeof(u32) * ioa_cfg->hrrq[i].size,
- ioa_cfg->hrrq[i].host_rrq,
- ioa_cfg->hrrq[i].host_rrq_dma);
+ dma_free_coherent(&pdev->dev,
+ sizeof(u32) * ioa_cfg->hrrq[i].size,
+ ioa_cfg->hrrq[i].host_rrq,
+ ioa_cfg->hrrq[i].host_rrq_dma);
}
out_ipr_free_cmd_blocks:
ipr_free_cmd_blks(ioa_cfg);
out_free_vpd_cbs:
- pci_free_consistent(pdev, sizeof(struct ipr_misc_cbs),
- ioa_cfg->vpd_cbs, ioa_cfg->vpd_cbs_dma);
+ dma_free_coherent(&pdev->dev, sizeof(struct ipr_misc_cbs),
+ ioa_cfg->vpd_cbs, ioa_cfg->vpd_cbs_dma);
out_free_res_entries:
kfree(ioa_cfg->res_entries);
goto out;
@@ -9579,16 +9578,17 @@ static int ipr_probe_ioa(struct pci_dev *pdev,
ipr_init_regs(ioa_cfg);
if (ioa_cfg->sis64) {
- rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+ rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
if (rc < 0) {
- dev_dbg(&pdev->dev, "Failed to set 64 bit PCI DMA mask\n");
- rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ dev_dbg(&pdev->dev, "Failed to set 64 bit DMA mask\n");
+ rc = dma_set_mask_and_coherent(&pdev->dev,
+ DMA_BIT_MASK(32));
}
} else
- rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (rc < 0) {
- dev_err(&pdev->dev, "Failed to set PCI DMA mask\n");
+ dev_err(&pdev->dev, "Failed to set DMA mask\n");
goto cleanup_nomem;
}
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index d0201ceb4aac..9ebdebd944e7 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -1549,7 +1549,7 @@ struct ipr_ioa_cfg {
struct ipr_misc_cbs *vpd_cbs;
dma_addr_t vpd_cbs_dma;
- struct pci_pool *ipr_cmd_pool;
+ struct dma_pool *ipr_cmd_pool;
struct ipr_cmnd *reset_cmd;
int (*reset) (struct ipr_cmnd *);
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index 454741a8da45..e5c28435d768 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -1210,7 +1210,7 @@ ips_slave_configure(struct scsi_device * SDptr)
min = ha->max_cmds / 2;
if (ha->enq->ucLogDriveCount <= 2)
min = ha->max_cmds - 1;
- scsi_adjust_queue_depth(SDptr, min);
+ scsi_change_queue_depth(SDptr, min);
}
SDptr->skip_ms_page_8 = 1;
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index 897562056018..724c6265b667 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -173,6 +173,7 @@ static struct scsi_host_template isci_sht = {
.ioctl = sas_ioctl,
.shost_attrs = isci_host_attrs,
.use_blk_tags = 1,
+ .track_queue_depth = 1,
};
static struct sas_domain_function_template isci_transport_ops = {
@@ -259,8 +260,6 @@ static int isci_register_sas_ha(struct isci_host *isci_host)
sas_ha->sas_port = sas_ports;
sas_ha->num_phys = SCI_MAX_PHYS;
- sas_ha->lldd_queue_size = ISCI_CAN_QUEUE_VAL;
- sas_ha->lldd_max_execute_num = 1;
sas_ha->strict_wide_ports = 1;
sas_register_ha(sas_ha);
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
index 5d6fda72d659..3f63c6318b0d 100644
--- a/drivers/scsi/isci/task.c
+++ b/drivers/scsi/isci/task.c
@@ -117,104 +117,97 @@ static inline int isci_device_io_ready(struct isci_remote_device *idev,
* functions. This function is called by libsas to send a task down to
* hardware.
* @task: This parameter specifies the SAS task to send.
- * @num: This parameter specifies the number of tasks to queue.
* @gfp_flags: This parameter specifies the context of this call.
*
* status, zero indicates success.
*/
-int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags)
+int isci_task_execute_task(struct sas_task *task, gfp_t gfp_flags)
{
struct isci_host *ihost = dev_to_ihost(task->dev);
struct isci_remote_device *idev;
unsigned long flags;
+ enum sci_status status = SCI_FAILURE;
bool io_ready;
u16 tag;
- dev_dbg(&ihost->pdev->dev, "%s: num=%d\n", __func__, num);
+ spin_lock_irqsave(&ihost->scic_lock, flags);
+ idev = isci_lookup_device(task->dev);
+ io_ready = isci_device_io_ready(idev, task);
+ tag = isci_alloc_tag(ihost);
+ spin_unlock_irqrestore(&ihost->scic_lock, flags);
- for_each_sas_task(num, task) {
- enum sci_status status = SCI_FAILURE;
+ dev_dbg(&ihost->pdev->dev,
+ "task: %p, dev: %p idev: %p:%#lx cmd = %p\n",
+ task, task->dev, idev, idev ? idev->flags : 0,
+ task->uldd_task);
- spin_lock_irqsave(&ihost->scic_lock, flags);
- idev = isci_lookup_device(task->dev);
- io_ready = isci_device_io_ready(idev, task);
- tag = isci_alloc_tag(ihost);
- spin_unlock_irqrestore(&ihost->scic_lock, flags);
+ if (!idev) {
+ isci_task_refuse(ihost, task, SAS_TASK_UNDELIVERED,
+ SAS_DEVICE_UNKNOWN);
+ } else if (!io_ready || tag == SCI_CONTROLLER_INVALID_IO_TAG) {
+ /* Indicate QUEUE_FULL so that the scsi midlayer
+ * retries.
+ */
+ isci_task_refuse(ihost, task, SAS_TASK_COMPLETE,
+ SAS_QUEUE_FULL);
+ } else {
+ /* There is a device and it's ready for I/O. */
+ spin_lock_irqsave(&task->task_state_lock, flags);
- dev_dbg(&ihost->pdev->dev,
- "task: %p, num: %d dev: %p idev: %p:%#lx cmd = %p\n",
- task, num, task->dev, idev, idev ? idev->flags : 0,
- task->uldd_task);
-
- if (!idev) {
- isci_task_refuse(ihost, task, SAS_TASK_UNDELIVERED,
- SAS_DEVICE_UNKNOWN);
- } else if (!io_ready || tag == SCI_CONTROLLER_INVALID_IO_TAG) {
- /* Indicate QUEUE_FULL so that the scsi midlayer
- * retries.
- */
- isci_task_refuse(ihost, task, SAS_TASK_COMPLETE,
- SAS_QUEUE_FULL);
+ if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
+ /* The I/O was aborted. */
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
+
+ isci_task_refuse(ihost, task,
+ SAS_TASK_UNDELIVERED,
+ SAM_STAT_TASK_ABORTED);
} else {
- /* There is a device and it's ready for I/O. */
- spin_lock_irqsave(&task->task_state_lock, flags);
-
- if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
- /* The I/O was aborted. */
- spin_unlock_irqrestore(&task->task_state_lock,
- flags);
-
- isci_task_refuse(ihost, task,
- SAS_TASK_UNDELIVERED,
- SAM_STAT_TASK_ABORTED);
- } else {
- task->task_state_flags |= SAS_TASK_AT_INITIATOR;
+ task->task_state_flags |= SAS_TASK_AT_INITIATOR;
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
+
+ /* build and send the request. */
+ status = isci_request_execute(ihost, idev, task, tag);
+
+ if (status != SCI_SUCCESS) {
+ spin_lock_irqsave(&task->task_state_lock, flags);
+ /* Did not really start this command. */
+ task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
spin_unlock_irqrestore(&task->task_state_lock, flags);
- /* build and send the request. */
- status = isci_request_execute(ihost, idev, task, tag);
-
- if (status != SCI_SUCCESS) {
-
- spin_lock_irqsave(&task->task_state_lock, flags);
- /* Did not really start this command. */
- task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
- spin_unlock_irqrestore(&task->task_state_lock, flags);
-
- if (test_bit(IDEV_GONE, &idev->flags)) {
-
- /* Indicate that the device
- * is gone.
- */
- isci_task_refuse(ihost, task,
- SAS_TASK_UNDELIVERED,
- SAS_DEVICE_UNKNOWN);
- } else {
- /* Indicate QUEUE_FULL so that
- * the scsi midlayer retries.
- * If the request failed for
- * remote device reasons, it
- * gets returned as
- * SAS_TASK_UNDELIVERED next
- * time through.
- */
- isci_task_refuse(ihost, task,
- SAS_TASK_COMPLETE,
- SAS_QUEUE_FULL);
- }
+ if (test_bit(IDEV_GONE, &idev->flags)) {
+ /* Indicate that the device
+ * is gone.
+ */
+ isci_task_refuse(ihost, task,
+ SAS_TASK_UNDELIVERED,
+ SAS_DEVICE_UNKNOWN);
+ } else {
+ /* Indicate QUEUE_FULL so that
+ * the scsi midlayer retries.
+ * If the request failed for
+ * remote device reasons, it
+ * gets returned as
+ * SAS_TASK_UNDELIVERED next
+ * time through.
+ */
+ isci_task_refuse(ihost, task,
+ SAS_TASK_COMPLETE,
+ SAS_QUEUE_FULL);
}
}
}
- if (status != SCI_SUCCESS && tag != SCI_CONTROLLER_INVALID_IO_TAG) {
- spin_lock_irqsave(&ihost->scic_lock, flags);
- /* command never hit the device, so just free
- * the tci and skip the sequence increment
- */
- isci_tci_free(ihost, ISCI_TAG_TCI(tag));
- spin_unlock_irqrestore(&ihost->scic_lock, flags);
- }
- isci_put_device(idev);
}
+
+ if (status != SCI_SUCCESS && tag != SCI_CONTROLLER_INVALID_IO_TAG) {
+ spin_lock_irqsave(&ihost->scic_lock, flags);
+ /* command never hit the device, so just free
+ * the tci and skip the sequence increment
+ */
+ isci_tci_free(ihost, ISCI_TAG_TCI(tag));
+ spin_unlock_irqrestore(&ihost->scic_lock, flags);
+ }
+
+ isci_put_device(idev);
return 0;
}
diff --git a/drivers/scsi/isci/task.h b/drivers/scsi/isci/task.h
index 9c06cbad1d26..8f4531f22ac2 100644
--- a/drivers/scsi/isci/task.h
+++ b/drivers/scsi/isci/task.h
@@ -131,7 +131,6 @@ static inline void isci_print_tmf(struct isci_host *ihost, struct isci_tmf *tmf)
int isci_task_execute_task(
struct sas_task *task,
- int num,
gfp_t gfp_flags);
int isci_task_abort_task(
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 427af0f24b0f..0b8af186e707 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -952,7 +952,7 @@ static struct scsi_host_template iscsi_sw_tcp_sht = {
.module = THIS_MODULE,
.name = "iSCSI Initiator over TCP/IP",
.queuecommand = iscsi_queuecommand,
- .change_queue_depth = iscsi_change_queue_depth,
+ .change_queue_depth = scsi_change_queue_depth,
.can_queue = ISCSI_DEF_XMIT_CMDS_MAX - 1,
.sg_tablesize = 4096,
.max_sectors = 0xFFFF,
@@ -966,6 +966,7 @@ static struct scsi_host_template iscsi_sw_tcp_sht = {
.target_alloc = iscsi_target_alloc,
.proc_name = "iscsi_tcp",
.this_id = -1,
+ .track_queue_depth = 1,
};
static struct iscsi_transport iscsi_sw_tcp_transport = {
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index bf954ee050f8..c6795941b45d 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -2160,37 +2160,12 @@ int fc_slave_alloc(struct scsi_device *sdev)
if (!rport || fc_remote_port_chkready(rport))
return -ENXIO;
- scsi_adjust_queue_depth(sdev, FC_FCP_DFLT_QUEUE_DEPTH);
+ scsi_change_queue_depth(sdev, FC_FCP_DFLT_QUEUE_DEPTH);
return 0;
}
EXPORT_SYMBOL(fc_slave_alloc);
/**
- * fc_change_queue_depth() - Change a device's queue depth
- * @sdev: The SCSI device whose queue depth is to change
- * @qdepth: The new queue depth
- * @reason: The resason for the change
- */
-int fc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
-{
- switch (reason) {
- case SCSI_QDEPTH_DEFAULT:
- scsi_adjust_queue_depth(sdev, qdepth);
- break;
- case SCSI_QDEPTH_QFULL:
- scsi_track_queue_full(sdev, qdepth);
- break;
- case SCSI_QDEPTH_RAMP_UP:
- scsi_adjust_queue_depth(sdev, qdepth);
- break;
- default:
- return -EOPNOTSUPP;
- }
- return sdev->queue_depth;
-}
-EXPORT_SYMBOL(fc_change_queue_depth);
-
-/**
* fc_fcp_destory() - Tear down the FCP layer for a given local port
* @lport: The local port that no longer needs the FCP layer
*/
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index d521624dedfb..8053f24f0349 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1771,25 +1771,6 @@ fault:
}
EXPORT_SYMBOL_GPL(iscsi_queuecommand);
-int iscsi_change_queue_depth(struct scsi_device *sdev, int depth, int reason)
-{
- switch (reason) {
- case SCSI_QDEPTH_DEFAULT:
- scsi_adjust_queue_depth(sdev, depth);
- break;
- case SCSI_QDEPTH_QFULL:
- scsi_track_queue_full(sdev, depth);
- break;
- case SCSI_QDEPTH_RAMP_UP:
- scsi_adjust_queue_depth(sdev, depth);
- break;
- default:
- return -EOPNOTSUPP;
- }
- return sdev->queue_depth;
-}
-EXPORT_SYMBOL_GPL(iscsi_change_queue_depth);
-
int iscsi_target_alloc(struct scsi_target *starget)
{
struct iscsi_cls_session *cls_session = starget_to_session(starget);
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 766098af4eb7..577770fdee86 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -171,7 +171,6 @@ static void sas_ata_task_done(struct sas_task *task)
spin_unlock_irqrestore(ap->lock, flags);
qc_already_gone:
- list_del_init(&task->list);
sas_free_task(task);
}
@@ -244,12 +243,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
if (qc->scsicmd)
ASSIGN_SAS_TASK(qc->scsicmd, task);
- if (sas_ha->lldd_max_execute_num < 2)
- ret = i->dft->lldd_execute_task(task, 1, GFP_ATOMIC);
- else
- ret = sas_queue_up(task);
-
- /* Examine */
+ ret = i->dft->lldd_execute_task(task, GFP_ATOMIC);
if (ret) {
SAS_DPRINTK("lldd_execute_task returned: %d\n", ret);
@@ -485,7 +479,6 @@ static void sas_ata_internal_abort(struct sas_task *task)
return;
out:
- list_del_init(&task->list);
sas_free_task(task);
}
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 0cac7d8fd0f7..022bb6e10d98 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -96,7 +96,7 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
task->slow_task->timer.expires = jiffies + SMP_TIMEOUT*HZ;
add_timer(&task->slow_task->timer);
- res = i->dft->lldd_execute_task(task, 1, GFP_KERNEL);
+ res = i->dft->lldd_execute_task(task, GFP_KERNEL);
if (res) {
del_timer(&task->slow_task->timer);
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index dbc8a793fd86..362da44f2948 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -45,7 +45,6 @@ struct sas_task *sas_alloc_task(gfp_t flags)
struct sas_task *task = kmem_cache_zalloc(sas_task_cache, flags);
if (task) {
- INIT_LIST_HEAD(&task->list);
spin_lock_init(&task->task_state_lock);
task->task_state_flags = SAS_TASK_STATE_PENDING;
}
@@ -77,7 +76,6 @@ EXPORT_SYMBOL_GPL(sas_alloc_slow_task);
void sas_free_task(struct sas_task *task)
{
if (task) {
- BUG_ON(!list_empty(&task->list));
kfree(task->slow_task);
kmem_cache_free(sas_task_cache, task);
}
@@ -127,11 +125,6 @@ int sas_register_ha(struct sas_ha_struct *sas_ha)
spin_lock_init(&sas_ha->phy_port_lock);
sas_hash_addr(sas_ha->hashed_sas_addr, sas_ha->sas_addr);
- if (sas_ha->lldd_queue_size == 0)
- sas_ha->lldd_queue_size = 1;
- else if (sas_ha->lldd_queue_size == -1)
- sas_ha->lldd_queue_size = 128; /* Sanity */
-
set_bit(SAS_HA_REGISTERED, &sas_ha->state);
spin_lock_init(&sas_ha->lock);
mutex_init(&sas_ha->drain_mutex);
@@ -157,15 +150,6 @@ int sas_register_ha(struct sas_ha_struct *sas_ha)
goto Undo_ports;
}
- if (sas_ha->lldd_max_execute_num > 1) {
- error = sas_init_queue(sas_ha);
- if (error) {
- printk(KERN_NOTICE "couldn't start queue thread:%d, "
- "running in direct mode\n", error);
- sas_ha->lldd_max_execute_num = 1;
- }
- }
-
INIT_LIST_HEAD(&sas_ha->eh_done_q);
INIT_LIST_HEAD(&sas_ha->eh_ata_q);
@@ -201,11 +185,6 @@ int sas_unregister_ha(struct sas_ha_struct *sas_ha)
__sas_drain_work(sas_ha);
mutex_unlock(&sas_ha->drain_mutex);
- if (sas_ha->lldd_max_execute_num > 1) {
- sas_shutdown_queue(sas_ha);
- sas_ha->lldd_max_execute_num = 1;
- }
-
return 0;
}
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index 7e7ba83f0a21..9cf0bc260b0e 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -66,9 +66,7 @@ void sas_unregister_ports(struct sas_ha_struct *sas_ha);
enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *);
-int sas_init_queue(struct sas_ha_struct *sas_ha);
int sas_init_events(struct sas_ha_struct *sas_ha);
-void sas_shutdown_queue(struct sas_ha_struct *sas_ha);
void sas_disable_revalidation(struct sas_ha_struct *ha);
void sas_enable_revalidation(struct sas_ha_struct *ha);
void __sas_drain_work(struct sas_ha_struct *ha);
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 89e8b687a679..72918d227ead 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -112,7 +112,6 @@ static void sas_end_task(struct scsi_cmnd *sc, struct sas_task *task)
sc->result = (hs << 16) | stat;
ASSIGN_SAS_TASK(sc, NULL);
- list_del_init(&task->list);
sas_free_task(task);
}
@@ -138,7 +137,6 @@ static void sas_scsi_task_done(struct sas_task *task)
if (unlikely(!sc)) {
SAS_DPRINTK("task_done called with non existing SCSI cmnd!\n");
- list_del_init(&task->list);
sas_free_task(task);
return;
}
@@ -179,31 +177,10 @@ static struct sas_task *sas_create_task(struct scsi_cmnd *cmd,
return task;
}
-int sas_queue_up(struct sas_task *task)
-{
- struct sas_ha_struct *sas_ha = task->dev->port->ha;
- struct scsi_core *core = &sas_ha->core;
- unsigned long flags;
- LIST_HEAD(list);
-
- spin_lock_irqsave(&core->task_queue_lock, flags);
- if (sas_ha->lldd_queue_size < core->task_queue_size + 1) {
- spin_unlock_irqrestore(&core->task_queue_lock, flags);
- return -SAS_QUEUE_FULL;
- }
- list_add_tail(&task->list, &core->task_queue);
- core->task_queue_size += 1;
- spin_unlock_irqrestore(&core->task_queue_lock, flags);
- wake_up_process(core->queue_thread);
-
- return 0;
-}
-
int 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);
- struct sas_ha_struct *sas_ha = dev->port->ha;
struct sas_task *task;
int res = 0;
@@ -224,12 +201,7 @@ int sas_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
if (!task)
return SCSI_MLQUEUE_HOST_BUSY;
- /* Queue up, Direct Mode or Task Collector Mode. */
- if (sas_ha->lldd_max_execute_num < 2)
- res = i->dft->lldd_execute_task(task, 1, GFP_ATOMIC);
- else
- res = sas_queue_up(task);
-
+ res = i->dft->lldd_execute_task(task, GFP_ATOMIC);
if (res)
goto out_free_task;
return 0;
@@ -323,37 +295,17 @@ enum task_disposition {
TASK_IS_DONE,
TASK_IS_ABORTED,
TASK_IS_AT_LU,
- TASK_IS_NOT_AT_HA,
TASK_IS_NOT_AT_LU,
TASK_ABORT_FAILED,
};
static enum task_disposition sas_scsi_find_task(struct sas_task *task)
{
- struct sas_ha_struct *ha = task->dev->port->ha;
unsigned long flags;
int i, res;
struct sas_internal *si =
to_sas_internal(task->dev->port->ha->core.shost->transportt);
- if (ha->lldd_max_execute_num > 1) {
- struct scsi_core *core = &ha->core;
- struct sas_task *t, *n;
-
- mutex_lock(&core->task_queue_flush);
- spin_lock_irqsave(&core->task_queue_lock, flags);
- list_for_each_entry_safe(t, n, &core->task_queue, list)
- if (task == t) {
- list_del_init(&t->list);
- break;
- }
- spin_unlock_irqrestore(&core->task_queue_lock, flags);
- mutex_unlock(&core->task_queue_flush);
-
- if (task == t)
- return TASK_IS_NOT_AT_HA;
- }
-
for (i = 0; i < 5; i++) {
SAS_DPRINTK("%s: aborting task 0x%p\n", __func__, task);
res = si->dft->lldd_abort_task(task);
@@ -667,14 +619,6 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head *
cmd->eh_eflags = 0;
switch (res) {
- case TASK_IS_NOT_AT_HA:
- SAS_DPRINTK("%s: task 0x%p is not at ha: %s\n",
- __func__, task,
- cmd->retries ? "retry" : "aborted");
- if (cmd->retries)
- cmd->retries--;
- sas_eh_finish_cmd(cmd);
- continue;
case TASK_IS_DONE:
SAS_DPRINTK("%s: task 0x%p is done\n", __func__,
task);
@@ -836,9 +780,6 @@ retry:
scsi_eh_ready_devs(shost, &eh_work_q, &ha->eh_done_q);
out:
- if (ha->lldd_max_execute_num > 1)
- wake_up_process(ha->core.queue_thread);
-
sas_eh_handle_resets(shost);
/* now link into libata eh --- if we have any ata devices */
@@ -940,12 +881,12 @@ int sas_slave_configure(struct scsi_device *scsi_dev)
sas_read_port_mode_page(scsi_dev);
if (scsi_dev->tagged_supported) {
- scsi_adjust_queue_depth(scsi_dev, SAS_DEF_QD);
+ scsi_change_queue_depth(scsi_dev, SAS_DEF_QD);
} else {
SAS_DPRINTK("device %llx, LUN %llx doesn't support "
"TCQ\n", SAS_ADDR(dev->sas_addr),
scsi_dev->lun);
- scsi_adjust_queue_depth(scsi_dev, 1);
+ scsi_change_queue_depth(scsi_dev, 1);
}
scsi_dev->allow_restart = 1;
@@ -953,29 +894,16 @@ int sas_slave_configure(struct scsi_device *scsi_dev)
return 0;
}
-int sas_change_queue_depth(struct scsi_device *sdev, int depth, int reason)
+int sas_change_queue_depth(struct scsi_device *sdev, int depth)
{
struct domain_device *dev = sdev_to_domain_dev(sdev);
if (dev_is_sata(dev))
- return __ata_change_queue_depth(dev->sata_dev.ap, sdev, depth,
- reason);
-
- switch (reason) {
- case SCSI_QDEPTH_DEFAULT:
- case SCSI_QDEPTH_RAMP_UP:
- if (!sdev->tagged_supported)
- depth = 1;
- scsi_adjust_queue_depth(sdev, depth);
- break;
- case SCSI_QDEPTH_QFULL:
- scsi_track_queue_full(sdev, depth);
- break;
- default:
- return -EOPNOTSUPP;
- }
+ return __ata_change_queue_depth(dev->sata_dev.ap, sdev, depth);
- return depth;
+ if (!sdev->tagged_supported)
+ depth = 1;
+ return scsi_change_queue_depth(sdev, depth);
}
int sas_change_queue_type(struct scsi_device *scsi_dev, int type)
@@ -997,121 +925,6 @@ int sas_bios_param(struct scsi_device *scsi_dev,
return 0;
}
-/* ---------- Task Collector Thread implementation ---------- */
-
-static void sas_queue(struct sas_ha_struct *sas_ha)
-{
- struct scsi_core *core = &sas_ha->core;
- unsigned long flags;
- LIST_HEAD(q);
- int can_queue;
- int res;
- struct sas_internal *i = to_sas_internal(core->shost->transportt);
-
- mutex_lock(&core->task_queue_flush);
- spin_lock_irqsave(&core->task_queue_lock, flags);
- while (!kthread_should_stop() &&
- !list_empty(&core->task_queue) &&
- !test_bit(SAS_HA_FROZEN, &sas_ha->state)) {
-
- can_queue = sas_ha->lldd_queue_size - core->task_queue_size;
- if (can_queue >= 0) {
- can_queue = core->task_queue_size;
- list_splice_init(&core->task_queue, &q);
- } else {
- struct list_head *a, *n;
-
- can_queue = sas_ha->lldd_queue_size;
- list_for_each_safe(a, n, &core->task_queue) {
- list_move_tail(a, &q);
- if (--can_queue == 0)
- break;
- }
- can_queue = sas_ha->lldd_queue_size;
- }
- core->task_queue_size -= can_queue;
- spin_unlock_irqrestore(&core->task_queue_lock, flags);
- {
- struct sas_task *task = list_entry(q.next,
- struct sas_task,
- list);
- list_del_init(&q);
- res = i->dft->lldd_execute_task(task, can_queue,
- GFP_KERNEL);
- if (unlikely(res))
- __list_add(&q, task->list.prev, &task->list);
- }
- spin_lock_irqsave(&core->task_queue_lock, flags);
- if (res) {
- list_splice_init(&q, &core->task_queue); /*at head*/
- core->task_queue_size += can_queue;
- }
- }
- spin_unlock_irqrestore(&core->task_queue_lock, flags);
- mutex_unlock(&core->task_queue_flush);
-}
-
-/**
- * sas_queue_thread -- The Task Collector thread
- * @_sas_ha: pointer to struct sas_ha
- */
-static int sas_queue_thread(void *_sas_ha)
-{
- struct sas_ha_struct *sas_ha = _sas_ha;
-
- while (1) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule();
- sas_queue(sas_ha);
- if (kthread_should_stop())
- break;
- }
-
- return 0;
-}
-
-int sas_init_queue(struct sas_ha_struct *sas_ha)
-{
- struct scsi_core *core = &sas_ha->core;
-
- spin_lock_init(&core->task_queue_lock);
- mutex_init(&core->task_queue_flush);
- core->task_queue_size = 0;
- INIT_LIST_HEAD(&core->task_queue);
-
- core->queue_thread = kthread_run(sas_queue_thread, sas_ha,
- "sas_queue_%d", core->shost->host_no);
- if (IS_ERR(core->queue_thread))
- return PTR_ERR(core->queue_thread);
- return 0;
-}
-
-void sas_shutdown_queue(struct sas_ha_struct *sas_ha)
-{
- unsigned long flags;
- struct scsi_core *core = &sas_ha->core;
- struct sas_task *task, *n;
-
- kthread_stop(core->queue_thread);
-
- if (!list_empty(&core->task_queue))
- SAS_DPRINTK("HA: %llx: scsi core task queue is NOT empty!?\n",
- SAS_ADDR(sas_ha->sas_addr));
-
- spin_lock_irqsave(&core->task_queue_lock, flags);
- list_for_each_entry_safe(task, n, &core->task_queue, list) {
- struct scsi_cmnd *cmd = task->uldd_task;
-
- list_del_init(&task->list);
-
- ASSIGN_SAS_TASK(cmd, NULL);
- sas_free_task(task);
- cmd->result = DID_ABORT << 16;
- cmd->scsi_done(cmd);
- }
- spin_unlock_irqrestore(&core->task_queue_lock, flags);
-}
-
/*
* Tell an upper layer that it needs to initiate an abort for a given task.
* This should only ever be called by an LLDD.
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 8533ee9b818d..fd85952b621d 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -243,108 +243,6 @@ lpfc_update_stats(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
}
/**
- * lpfc_send_sdev_queuedepth_change_event - Posts a queuedepth change event
- * @phba: Pointer to HBA context object.
- * @vport: Pointer to vport object.
- * @ndlp: Pointer to FC node associated with the target.
- * @lun: Lun number of the scsi device.
- * @old_val: Old value of the queue depth.
- * @new_val: New value of the queue depth.
- *
- * This function sends an event to the mgmt application indicating
- * there is a change in the scsi device queue depth.
- **/
-static void
-lpfc_send_sdev_queuedepth_change_event(struct lpfc_hba *phba,
- struct lpfc_vport *vport,
- struct lpfc_nodelist *ndlp,
- uint64_t lun,
- uint32_t old_val,
- uint32_t new_val)
-{
- struct lpfc_fast_path_event *fast_path_evt;
- unsigned long flags;
-
- fast_path_evt = lpfc_alloc_fast_evt(phba);
- if (!fast_path_evt)
- return;
-
- fast_path_evt->un.queue_depth_evt.scsi_event.event_type =
- FC_REG_SCSI_EVENT;
- fast_path_evt->un.queue_depth_evt.scsi_event.subcategory =
- LPFC_EVENT_VARQUEDEPTH;
-
- /* Report all luns with change in queue depth */
- fast_path_evt->un.queue_depth_evt.scsi_event.lun = lun;
- if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
- memcpy(&fast_path_evt->un.queue_depth_evt.scsi_event.wwpn,
- &ndlp->nlp_portname, sizeof(struct lpfc_name));
- memcpy(&fast_path_evt->un.queue_depth_evt.scsi_event.wwnn,
- &ndlp->nlp_nodename, sizeof(struct lpfc_name));
- }
-
- fast_path_evt->un.queue_depth_evt.oldval = old_val;
- fast_path_evt->un.queue_depth_evt.newval = new_val;
- fast_path_evt->vport = vport;
-
- fast_path_evt->work_evt.evt = LPFC_EVT_FASTPATH_MGMT_EVT;
- spin_lock_irqsave(&phba->hbalock, flags);
- list_add_tail(&fast_path_evt->work_evt.evt_listp, &phba->work_list);
- spin_unlock_irqrestore(&phba->hbalock, flags);
- lpfc_worker_wake_up(phba);
-
- return;
-}
-
-/**
- * lpfc_change_queue_depth - Alter scsi device queue depth
- * @sdev: Pointer the scsi device on which to change the queue depth.
- * @qdepth: New queue depth to set the sdev to.
- * @reason: The reason for the queue depth change.
- *
- * This function is called by the midlayer and the LLD to alter the queue
- * depth for a scsi device. This function sets the queue depth to the new
- * value and sends an event out to log the queue depth change.
- **/
-static int
-lpfc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
-{
- struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata;
- struct lpfc_hba *phba = vport->phba;
- struct lpfc_rport_data *rdata;
- unsigned long new_queue_depth, old_queue_depth;
-
- old_queue_depth = sdev->queue_depth;
-
- switch (reason) {
- case SCSI_QDEPTH_DEFAULT:
- /* change request from sysfs, fall through */
- case SCSI_QDEPTH_RAMP_UP:
- scsi_adjust_queue_depth(sdev, qdepth);
- break;
- case SCSI_QDEPTH_QFULL:
- if (scsi_track_queue_full(sdev, qdepth) == 0)
- return sdev->queue_depth;
-
- lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
- "0711 detected queue full - lun queue "
- "depth adjusted to %d.\n", sdev->queue_depth);
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- new_queue_depth = sdev->queue_depth;
- rdata = lpfc_rport_data_from_scsi_device(sdev);
- if (rdata)
- lpfc_send_sdev_queuedepth_change_event(phba, vport,
- rdata->pnode, sdev->lun,
- old_queue_depth,
- new_queue_depth);
- return sdev->queue_depth;
-}
-
-/**
* lpfc_rampdown_queue_depth - Post RAMP_DOWN_QUEUE event to worker thread
* @phba: The Hba for which this call is being executed.
*
@@ -429,8 +327,7 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
else
new_queue_depth = sdev->queue_depth -
new_queue_depth;
- lpfc_change_queue_depth(sdev, new_queue_depth,
- SCSI_QDEPTH_DEFAULT);
+ scsi_change_queue_depth(sdev, new_queue_depth);
}
}
lpfc_destroy_vport_work_array(phba, vports);
@@ -5598,7 +5495,7 @@ lpfc_slave_configure(struct scsi_device *sdev)
struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata;
struct lpfc_hba *phba = vport->phba;
- scsi_adjust_queue_depth(sdev, vport->cfg_lun_queue_depth);
+ scsi_change_queue_depth(sdev, vport->cfg_lun_queue_depth);
if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
lpfc_sli_handle_fast_ring_event(phba,
@@ -5981,9 +5878,10 @@ struct scsi_host_template lpfc_template = {
.shost_attrs = lpfc_hba_attrs,
.max_sectors = 0xFFFF,
.vendor_id = LPFC_NL_VENDOR_ID,
- .change_queue_depth = lpfc_change_queue_depth,
+ .change_queue_depth = scsi_change_queue_depth,
.change_queue_type = scsi_change_queue_type,
.use_blk_tags = 1,
+ .track_queue_depth = 1,
};
struct scsi_host_template lpfc_vport_template = {
@@ -6005,7 +5903,8 @@ struct scsi_host_template lpfc_vport_template = {
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = lpfc_vport_attrs,
.max_sectors = 0xFFFF,
- .change_queue_depth = lpfc_change_queue_depth,
+ .change_queue_depth = scsi_change_queue_depth,
.change_queue_type = scsi_change_queue_type,
.use_blk_tags = 1,
+ .track_queue_depth = 1,
};
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
index 6a039eb1cbce..953fd9b953c7 100644
--- a/drivers/scsi/mac_scsi.c
+++ b/drivers/scsi/mac_scsi.c
@@ -9,69 +9,62 @@
* Generic Generic NCR5380 driver
*
* Copyright 1995, Russell King
- *
- * ALPHA RELEASE 1.
- *
- * For more information, please consult
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
*/
#include <linux/types.h>
-#include <linux/stddef.h>
-#include <linux/ctype.h>
#include <linux/delay.h>
-
#include <linux/module.h>
-#include <linux/signal.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/blkdev.h>
#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <asm/hwtest.h>
#include <asm/io.h>
-#include <asm/irq.h>
-
-#include <asm/macintosh.h>
#include <asm/macints.h>
-#include <asm/mac_via.h>
+#include <asm/setup.h>
-#include "scsi.h"
#include <scsi/scsi_host.h>
-#include "mac_scsi.h"
-/* These control the behaviour of the generic 5380 core */
-#define AUTOSENSE
+/* Definitions for the core NCR5380 driver. */
+
#define PSEUDO_DMA
-#include "NCR5380.h"
+#define NCR5380_implementation_fields unsigned char *pdma_base
+#define NCR5380_local_declare() struct Scsi_Host *_instance
+#define NCR5380_setup(instance) _instance = instance
-#define RESET_BOOT
-#define DRIVER_SETUP
+#define NCR5380_read(reg) macscsi_read(_instance, reg)
+#define NCR5380_write(reg, value) macscsi_write(_instance, reg, value)
-extern void via_scsi_clear(void);
+#define NCR5380_pread macscsi_pread
+#define NCR5380_pwrite macscsi_pwrite
-#ifdef RESET_BOOT
-static void mac_scsi_reset_boot(struct Scsi_Host *instance);
-#endif
+#define NCR5380_intr macscsi_intr
+#define NCR5380_queue_command macscsi_queue_command
+#define NCR5380_abort macscsi_abort
+#define NCR5380_bus_reset macscsi_bus_reset
+#define NCR5380_info macscsi_info
+#define NCR5380_show_info macscsi_show_info
+#define NCR5380_write_info macscsi_write_info
+
+#include "NCR5380.h"
+
+#define RESET_BOOT
-static int setup_called = 0;
static int setup_can_queue = -1;
+module_param(setup_can_queue, int, 0);
static int setup_cmd_per_lun = -1;
+module_param(setup_cmd_per_lun, int, 0);
static int setup_sg_tablesize = -1;
+module_param(setup_sg_tablesize, int, 0);
static int setup_use_pdma = -1;
-#ifdef SUPPORT_TAGS
+module_param(setup_use_pdma, int, 0);
static int setup_use_tagged_queuing = -1;
-#endif
+module_param(setup_use_tagged_queuing, int, 0);
static int setup_hostid = -1;
+module_param(setup_hostid, int, 0);
/* Time (in jiffies) to wait after a reset; the SCSI standard calls for 250ms,
* we usually do 0.5s to be on the safe side. But Toshiba CD-ROMs once more
@@ -84,232 +77,48 @@ static int setup_hostid = -1;
#define AFTER_RESET_DELAY (HZ/2)
#endif
-static volatile unsigned char *mac_scsi_regp = NULL;
-static volatile unsigned char *mac_scsi_drq = NULL;
-static volatile unsigned char *mac_scsi_nodrq = NULL;
-
-
/*
* NCR 5380 register access functions
*/
-#if 0
-/* Debug versions */
-#define CTRL(p,v) (*ctrl = (v))
-
-static char macscsi_read(struct Scsi_Host *instance, int reg)
+static inline char macscsi_read(struct Scsi_Host *instance, int reg)
{
- int iobase = instance->io_port;
- int i;
- int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
-
- CTRL(iobase, 0);
- i = in_8(iobase + (reg<<4));
- CTRL(iobase, 0x40);
-
- return i;
+ return in_8(instance->base + (reg << 4));
}
-static void macscsi_write(struct Scsi_Host *instance, int reg, int value)
-{
- int iobase = instance->io_port;
- int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
-
- CTRL(iobase, 0);
- out_8(iobase + (reg<<4), value);
- CTRL(iobase, 0x40);
-}
-#else
-
-/* Fast versions */
-static __inline__ char macscsi_read(struct Scsi_Host *instance, int reg)
+static inline void macscsi_write(struct Scsi_Host *instance, int reg, int value)
{
- return in_8(instance->io_port + (reg<<4));
+ out_8(instance->base + (reg << 4), value);
}
-static __inline__ void macscsi_write(struct Scsi_Host *instance, int reg, int value)
+#ifndef MODULE
+static int __init mac_scsi_setup(char *str)
{
- out_8(instance->io_port + (reg<<4), value);
-}
-#endif
-
+ int ints[7];
-/*
- * Function : mac_scsi_setup(char *str)
- *
- * Purpose : booter command line initialization of the overrides array,
- *
- * Inputs : str - comma delimited list of options
- *
- */
+ (void)get_options(str, ARRAY_SIZE(ints), ints);
-static int __init mac_scsi_setup(char *str) {
-#ifdef DRIVER_SETUP
- int ints[7];
-
- (void)get_options( str, ARRAY_SIZE(ints), ints);
-
- if (setup_called++ || ints[0] < 1 || ints[0] > 6) {
- printk(KERN_WARNING "scsi: <mac5380>"
- " Usage: mac5380=<can_queue>[,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>,<use_pdma>]\n");
- printk(KERN_ALERT "scsi: <mac5380> Bad Penguin parameters?\n");
- return 0;
- }
-
- if (ints[0] >= 1) {
- if (ints[1] > 0)
- /* no limits on this, just > 0 */
- setup_can_queue = ints[1];
- }
- if (ints[0] >= 2) {
- if (ints[2] > 0)
- setup_cmd_per_lun = ints[2];
- }
- if (ints[0] >= 3) {
- if (ints[3] >= 0) {
- setup_sg_tablesize = ints[3];
- /* Must be <= SG_ALL (255) */
- if (setup_sg_tablesize > SG_ALL)
- setup_sg_tablesize = SG_ALL;
- }
- }
- if (ints[0] >= 4) {
- /* Must be between 0 and 7 */
- if (ints[4] >= 0 && ints[4] <= 7)
- setup_hostid = ints[4];
- else if (ints[4] > 7)
- printk(KERN_WARNING "mac_scsi_setup: invalid host ID %d !\n", ints[4] );
- }
-#ifdef SUPPORT_TAGS
- if (ints[0] >= 5) {
- if (ints[5] >= 0)
- setup_use_tagged_queuing = !!ints[5];
+ if (ints[0] < 1 || ints[0] > 6) {
+ pr_err("Usage: mac5380=<can_queue>[,<cmd_per_lun>[,<sg_tablesize>[,<hostid>[,<use_tags>[,<use_pdma>]]]]]\n");
+ return 0;
}
-
- if (ints[0] == 6) {
- if (ints[6] >= 0)
+ if (ints[0] >= 1)
+ setup_can_queue = ints[1];
+ if (ints[0] >= 2)
+ setup_cmd_per_lun = ints[2];
+ if (ints[0] >= 3)
+ setup_sg_tablesize = ints[3];
+ if (ints[0] >= 4)
+ setup_hostid = ints[4];
+ if (ints[0] >= 5)
+ setup_use_tagged_queuing = ints[5];
+ if (ints[0] >= 6)
setup_use_pdma = ints[6];
- }
-#else
- if (ints[0] == 5) {
- if (ints[5] >= 0)
- setup_use_pdma = ints[5];
- }
-#endif /* SUPPORT_TAGS */
-
-#endif /* DRIVER_SETUP */
return 1;
}
__setup("mac5380=", mac_scsi_setup);
-
-/*
- * Function : int macscsi_detect(struct scsi_host_template * tpnt)
- *
- * Purpose : initializes mac NCR5380 driver based on the
- * command line / compile time port and irq definitions.
- *
- * Inputs : tpnt - template for this SCSI adapter.
- *
- * Returns : 1 if a host adapter was found, 0 if not.
- *
- */
-
-int __init macscsi_detect(struct scsi_host_template * tpnt)
-{
- static int called = 0;
- int flags = 0;
- struct Scsi_Host *instance;
-
- if (!MACH_IS_MAC || called)
- return( 0 );
-
- if (macintosh_config->scsi_type != MAC_SCSI_OLD)
- return( 0 );
-
- /* setup variables */
- tpnt->can_queue =
- (setup_can_queue > 0) ? setup_can_queue : CAN_QUEUE;
- tpnt->cmd_per_lun =
- (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : CMD_PER_LUN;
- tpnt->sg_tablesize =
- (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_TABLESIZE;
-
- if (setup_hostid >= 0)
- tpnt->this_id = setup_hostid;
- else {
- /* use 7 as default */
- tpnt->this_id = 7;
- }
-
-#ifdef SUPPORT_TAGS
- if (setup_use_tagged_queuing < 0)
- setup_use_tagged_queuing = USE_TAGGED_QUEUING;
-#endif
-
- /* Once we support multiple 5380s (e.g. DuoDock) we'll do
- something different here */
- instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
- if (instance == NULL)
- return 0;
-
- if (macintosh_config->ident == MAC_MODEL_IIFX) {
- mac_scsi_regp = via1+0x8000;
- mac_scsi_drq = via1+0xE000;
- mac_scsi_nodrq = via1+0xC000;
- /* The IIFX should be able to do true DMA, but pseudo-dma doesn't work */
- flags = FLAG_NO_PSEUDO_DMA;
- } else {
- mac_scsi_regp = via1+0x10000;
- mac_scsi_drq = via1+0x6000;
- mac_scsi_nodrq = via1+0x12000;
- }
-
- if (! setup_use_pdma)
- flags = FLAG_NO_PSEUDO_DMA;
-
- instance->io_port = (unsigned long) mac_scsi_regp;
- instance->irq = IRQ_MAC_SCSI;
-
-#ifdef RESET_BOOT
- mac_scsi_reset_boot(instance);
-#endif
-
- NCR5380_init(instance, flags);
-
- instance->n_io_port = 255;
-
- ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
-
- if (instance->irq != SCSI_IRQ_NONE)
- if (request_irq(instance->irq, NCR5380_intr, 0, "ncr5380", instance)) {
- printk(KERN_WARNING "scsi%d: IRQ%d not free, interrupts disabled\n",
- instance->host_no, instance->irq);
- instance->irq = SCSI_IRQ_NONE;
- }
-
- printk(KERN_INFO "scsi%d: generic 5380 at port %lX irq", instance->host_no, instance->io_port);
- if (instance->irq == SCSI_IRQ_NONE)
- printk (KERN_INFO "s disabled");
- else
- printk (KERN_INFO " %d", instance->irq);
- printk(KERN_INFO " options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
- instance->can_queue, instance->cmd_per_lun, MACSCSI_PUBLIC_RELEASE);
- printk(KERN_INFO "\nscsi%d:", instance->host_no);
- NCR5380_print_options(instance);
- printk("\n");
- called = 1;
- return 1;
-}
-
-int macscsi_release (struct Scsi_Host *shpnt)
-{
- if (shpnt->irq != SCSI_IRQ_NONE)
- free_irq(shpnt->irq, shpnt);
- NCR5380_exit(shpnt);
-
- return 0;
-}
+#endif /* !MODULE */
#ifdef RESET_BOOT
/*
@@ -349,10 +158,7 @@ static void mac_scsi_reset_boot(struct Scsi_Host *instance)
}
#endif
-const char * macscsi_info (struct Scsi_Host *spnt) {
- return "";
-}
-
+#ifdef PSEUDO_DMA
/*
Pseudo-DMA: (Ove Edlund)
The code attempts to catch bus errors that occur if one for example
@@ -422,38 +228,39 @@ __asm__ __volatile__ \
: "0"(s), "1"(d), "2"(len) \
: "d0")
-
-static int macscsi_pread (struct Scsi_Host *instance,
- unsigned char *dst, int len)
+static int macscsi_pread(struct Scsi_Host *instance,
+ unsigned char *dst, int len)
{
- unsigned char *d;
- volatile unsigned char *s;
-
- NCR5380_local_declare();
- NCR5380_setup(instance);
-
- s = mac_scsi_drq+0x60;
- d = dst;
-
-/* These conditions are derived from MacOS */
-
- while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)
- && !(NCR5380_read(STATUS_REG) & SR_REQ))
- ;
- if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)
- && (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) {
- printk(KERN_ERR "Error in macscsi_pread\n");
- return -1;
- }
-
- CP_IO_TO_MEM(s, d, len);
-
- if (len != 0) {
- printk(KERN_NOTICE "Bus error in macscsi_pread\n");
- return -1;
- }
-
- return 0;
+ struct NCR5380_hostdata *hostdata = shost_priv(instance);
+ unsigned char *d;
+ unsigned char *s;
+
+ NCR5380_local_declare();
+ NCR5380_setup(instance);
+
+ s = hostdata->pdma_base + (INPUT_DATA_REG << 4);
+ d = dst;
+
+ /* These conditions are derived from MacOS */
+
+ while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) &&
+ !(NCR5380_read(STATUS_REG) & SR_REQ))
+ ;
+
+ if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) &&
+ (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) {
+ pr_err("Error in macscsi_pread\n");
+ return -1;
+ }
+
+ CP_IO_TO_MEM(s, d, len);
+
+ if (len != 0) {
+ pr_notice("Bus error in macscsi_pread\n");
+ return -1;
+ }
+
+ return 0;
}
@@ -515,59 +322,172 @@ __asm__ __volatile__ \
: "0"(s), "1"(d), "2"(len) \
: "d0")
-static int macscsi_pwrite (struct Scsi_Host *instance,
- unsigned char *src, int len)
+static int macscsi_pwrite(struct Scsi_Host *instance,
+ unsigned char *src, int len)
{
- unsigned char *s;
- volatile unsigned char *d;
-
- NCR5380_local_declare();
- NCR5380_setup(instance);
-
- s = src;
- d = mac_scsi_drq;
-
-/* These conditions are derived from MacOS */
-
- while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)
- && (!(NCR5380_read(STATUS_REG) & SR_REQ)
- || (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)))
- ;
- if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)) {
- printk(KERN_ERR "Error in macscsi_pwrite\n");
- return -1;
- }
-
- CP_MEM_TO_IO(s, d, len);
-
- if (len != 0) {
- printk(KERN_NOTICE "Bus error in macscsi_pwrite\n");
- return -1;
- }
-
- return 0;
-}
+ struct NCR5380_hostdata *hostdata = shost_priv(instance);
+ unsigned char *s;
+ unsigned char *d;
+
+ NCR5380_local_declare();
+ NCR5380_setup(instance);
+
+ s = src;
+ d = hostdata->pdma_base + (OUTPUT_DATA_REG << 4);
+
+ /* These conditions are derived from MacOS */
+
+ while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) &&
+ (!(NCR5380_read(STATUS_REG) & SR_REQ) ||
+ (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)))
+ ;
+
+ if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)) {
+ pr_err("Error in macscsi_pwrite\n");
+ return -1;
+ }
+
+ CP_MEM_TO_IO(s, d, len);
+
+ if (len != 0) {
+ pr_notice("Bus error in macscsi_pwrite\n");
+ return -1;
+ }
+ return 0;
+}
+#endif
#include "NCR5380.c"
-static struct scsi_host_template driver_template = {
- .proc_name = "Mac5380",
+#define DRV_MODULE_NAME "mac_scsi"
+#define PFX DRV_MODULE_NAME ": "
+
+static struct scsi_host_template mac_scsi_template = {
+ .module = THIS_MODULE,
+ .proc_name = DRV_MODULE_NAME,
.show_info = macscsi_show_info,
.write_info = macscsi_write_info,
.name = "Macintosh NCR5380 SCSI",
- .detect = macscsi_detect,
- .release = macscsi_release,
.info = macscsi_info,
.queuecommand = macscsi_queue_command,
.eh_abort_handler = macscsi_abort,
.eh_bus_reset_handler = macscsi_bus_reset,
- .can_queue = CAN_QUEUE,
+ .can_queue = 16,
.this_id = 7,
.sg_tablesize = SG_ALL,
- .cmd_per_lun = CMD_PER_LUN,
+ .cmd_per_lun = 2,
.use_clustering = DISABLE_CLUSTERING
};
+static int __init mac_scsi_probe(struct platform_device *pdev)
+{
+ struct Scsi_Host *instance;
+ int error;
+ int host_flags = 0;
+ struct resource *irq, *pio_mem, *pdma_mem = NULL;
+
+ pio_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!pio_mem)
+ return -ENODEV;
+
+#ifdef PSEUDO_DMA
+ pdma_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+#endif
+
+ irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+ if (!hwreg_present((unsigned char *)pio_mem->start +
+ (STATUS_REG << 4))) {
+ pr_info(PFX "no device detected at %pap\n", &pio_mem->start);
+ return -ENODEV;
+ }
+
+ if (setup_can_queue > 0)
+ mac_scsi_template.can_queue = setup_can_queue;
+ if (setup_cmd_per_lun > 0)
+ mac_scsi_template.cmd_per_lun = setup_cmd_per_lun;
+ if (setup_sg_tablesize >= 0)
+ mac_scsi_template.sg_tablesize = setup_sg_tablesize;
+ if (setup_hostid >= 0)
+ mac_scsi_template.this_id = setup_hostid & 7;
+ if (setup_use_pdma < 0)
+ setup_use_pdma = 0;
+
+ instance = scsi_host_alloc(&mac_scsi_template,
+ sizeof(struct NCR5380_hostdata));
+ if (!instance)
+ return -ENOMEM;
+
+ instance->base = pio_mem->start;
+ if (irq)
+ instance->irq = irq->start;
+ else
+ instance->irq = NO_IRQ;
+
+ if (pdma_mem && setup_use_pdma) {
+ struct NCR5380_hostdata *hostdata = shost_priv(instance);
+
+ hostdata->pdma_base = (unsigned char *)pdma_mem->start;
+ } else
+ host_flags |= FLAG_NO_PSEUDO_DMA;
+
+#ifdef RESET_BOOT
+ mac_scsi_reset_boot(instance);
+#endif
+
+#ifdef SUPPORT_TAGS
+ host_flags |= setup_use_tagged_queuing > 0 ? FLAG_TAGGED_QUEUING : 0;
+#endif
+
+ NCR5380_init(instance, host_flags);
+
+ if (instance->irq != NO_IRQ) {
+ error = request_irq(instance->irq, macscsi_intr, IRQF_SHARED,
+ "NCR5380", instance);
+ if (error)
+ goto fail_irq;
+ }
+
+ error = scsi_add_host(instance, NULL);
+ if (error)
+ goto fail_host;
+
+ platform_set_drvdata(pdev, instance);
+
+ scsi_scan_host(instance);
+ return 0;
+
+fail_host:
+ if (instance->irq != NO_IRQ)
+ free_irq(instance->irq, instance);
+fail_irq:
+ NCR5380_exit(instance);
+ scsi_host_put(instance);
+ return error;
+}
+
+static int __exit mac_scsi_remove(struct platform_device *pdev)
+{
+ struct Scsi_Host *instance = platform_get_drvdata(pdev);
+
+ scsi_remove_host(instance);
+ if (instance->irq != NO_IRQ)
+ free_irq(instance->irq, instance);
+ NCR5380_exit(instance);
+ scsi_host_put(instance);
+ return 0;
+}
+
+static struct platform_driver mac_scsi_driver = {
+ .remove = __exit_p(mac_scsi_remove),
+ .driver = {
+ .name = DRV_MODULE_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+module_platform_driver_probe(mac_scsi_driver, mac_scsi_probe);
-#include "scsi_module.c"
+MODULE_ALIAS("platform:" DRV_MODULE_NAME);
+MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/mac_scsi.h b/drivers/scsi/mac_scsi.h
deleted file mode 100644
index 06969b06e54b..000000000000
--- a/drivers/scsi/mac_scsi.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Cumana Generic NCR5380 driver defines
- *
- * Copyright 1993, Drew Eckhardt
- * Visionary Computing
- * (Unix and Linux consulting and custom programming)
- * drew@colorado.edu
- * +1 (303) 440-4894
- *
- * ALPHA RELEASE 1.
- *
- * For more information, please consult
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
- */
-
-#ifndef MAC_NCR5380_H
-#define MAC_NCR5380_H
-
-#define MACSCSI_PUBLIC_RELEASE 2
-
-#ifndef ASM
-
-#ifndef CMD_PER_LUN
-#define CMD_PER_LUN 2
-#endif
-
-#ifndef CAN_QUEUE
-#define CAN_QUEUE 16
-#endif
-
-#ifndef SG_TABLESIZE
-#define SG_TABLESIZE SG_NONE
-#endif
-
-#ifndef USE_TAGGED_QUEUING
-#define USE_TAGGED_QUEUING 0
-#endif
-
-#include <scsi/scsicam.h>
-
-#define NCR5380_implementation_fields \
- int port, ctrl
-
-#define NCR5380_local_declare() \
- struct Scsi_Host *_instance
-
-#define NCR5380_setup(instance) \
- _instance = instance
-
-#define NCR5380_read(reg) macscsi_read(_instance, reg)
-#define NCR5380_write(reg, value) macscsi_write(_instance, reg, value)
-
-#define NCR5380_pread macscsi_pread
-#define NCR5380_pwrite macscsi_pwrite
-
-#define NCR5380_intr macscsi_intr
-#define NCR5380_queue_command macscsi_queue_command
-#define NCR5380_abort macscsi_abort
-#define NCR5380_bus_reset macscsi_bus_reset
-#define NCR5380_show_info macscsi_show_info
-#define NCR5380_write_info macscsi_write_info
-
-#endif /* ndef ASM */
-#endif /* MAC_NCR5380_H */
-
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index 6b077d839f2b..f0987f22ea70 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -332,27 +332,6 @@ static struct device_attribute *megaraid_sdev_attrs[] = {
NULL,
};
-/**
- * megaraid_change_queue_depth - Change the device's queue depth
- * @sdev: scsi device struct
- * @qdepth: depth to set
- * @reason: calling context
- *
- * Return value:
- * actual depth set
- */
-static int megaraid_change_queue_depth(struct scsi_device *sdev, int qdepth,
- int reason)
-{
- if (reason != SCSI_QDEPTH_DEFAULT)
- return -EOPNOTSUPP;
-
- if (qdepth > MBOX_MAX_SCSI_CMDS)
- qdepth = MBOX_MAX_SCSI_CMDS;
- scsi_adjust_queue_depth(sdev, qdepth);
- return sdev->queue_depth;
-}
-
/*
* Scsi host template for megaraid unified driver
*/
@@ -365,7 +344,7 @@ static struct scsi_host_template megaraid_template_g = {
.eh_device_reset_handler = megaraid_reset_handler,
.eh_bus_reset_handler = megaraid_reset_handler,
.eh_host_reset_handler = megaraid_reset_handler,
- .change_queue_depth = megaraid_change_queue_depth,
+ .change_queue_depth = scsi_change_queue_depth,
.use_clustering = ENABLE_CLUSTERING,
.no_write_same = 1,
.sdev_attrs = megaraid_sdev_attrs,
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index a49914de4b95..0d44d91c2fce 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -1,7 +1,8 @@
/*
* Linux MegaRAID driver for SAS based RAID controllers
*
- * Copyright (c) 2003-2012 LSI Corporation.
+ * Copyright (c) 2003-2013 LSI Corporation
+ * Copyright (c) 2013-2014 Avago Technologies
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -14,17 +15,18 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* FILE: megaraid_sas.h
*
- * Authors: LSI Corporation
+ * Authors: Avago Technologies
+ * Kashyap Desai <kashyap.desai@avagotech.com>
+ * Sumit Saxena <sumit.saxena@avagotech.com>
*
- * Send feedback to: <megaraidlinux@lsi.com>
+ * Send feedback to: megaraidlinux.pdl@avagotech.com
*
- * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
- * ATTN: Linuxraid
+ * Mail to: Avago Technologies, 350 West Trimble Road, Building 90,
+ * San Jose, California 95131
*/
#ifndef LSI_MEGARAID_SAS_H
@@ -33,9 +35,7 @@
/*
* MegaRAID SAS Driver meta data
*/
-#define MEGASAS_VERSION "06.805.06.00-rc1"
-#define MEGASAS_RELDATE "Sep. 4, 2014"
-#define MEGASAS_EXT_VERSION "Thu. Sep. 4 17:00:00 PDT 2014"
+#define MEGASAS_VERSION "06.805.06.01-rc1"
/*
* Device IDs
@@ -1931,8 +1931,7 @@ u16 get_updated_dev_handle(struct megasas_instance *instance,
struct LD_LOAD_BALANCE_INFO *lbInfo, struct IO_REQUEST_INFO *in_info);
void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *map,
struct LD_LOAD_BALANCE_INFO *lbInfo);
-int megasas_get_ctrl_info(struct megasas_instance *instance,
- struct megasas_ctrl_info *ctrl_info);
+int megasas_get_ctrl_info(struct megasas_instance *instance);
int megasas_set_crash_dump_params(struct megasas_instance *instance,
u8 crash_buf_state);
void megasas_free_host_crash_buffer(struct megasas_instance *instance);
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index 107244cebd22..f05580e693d0 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -1,7 +1,8 @@
/*
* Linux MegaRAID driver for SAS based RAID controllers
*
- * Copyright (c) 2003-2012 LSI Corporation.
+ * Copyright (c) 2003-2013 LSI Corporation
+ * Copyright (c) 2013-2014 Avago Technologies
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -14,22 +15,20 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
- * FILE: megaraid_sas_base.c
- * Version : 06.805.06.00-rc1
- *
- * Authors: LSI Corporation
+ * Authors: Avago Technologies
* Sreenivas Bagalkote
* Sumant Patro
* Bo Yang
- * Adam Radford <linuxraid@lsi.com>
+ * Adam Radford
+ * Kashyap Desai <kashyap.desai@avagotech.com>
+ * Sumit Saxena <sumit.saxena@avagotech.com>
*
- * Send feedback to: <megaraidlinux@lsi.com>
+ * Send feedback to: megaraidlinux.pdl@avagotech.com
*
- * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
- * ATTN: Linuxraid
+ * Mail to: Avago Technologies, 350 West Trimble Road, Building 90,
+ * San Jose, California 95131
*/
#include <linux/kernel.h>
@@ -1008,7 +1007,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
cpu_to_le32(upper_32_bits(cmd_to_abort->frame_phys_addr));
cmd->sync_cmd = 1;
- cmd->cmd_status = 0xFF;
+ cmd->cmd_status = ENODATA;
instance->instancet->issue_dcmd(instance, cmd);
@@ -1572,6 +1571,12 @@ megasas_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
instance = (struct megasas_instance *)
scmd->device->host->hostdata;
+ if (instance->unload == 1) {
+ scmd->result = DID_NO_CONNECT << 16;
+ scmd->scsi_done(scmd);
+ return 0;
+ }
+
if (instance->issuepend_done == 0)
return SCSI_MLQUEUE_HOST_BUSY;
@@ -2586,19 +2591,6 @@ megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
}
}
-static int megasas_change_queue_depth(struct scsi_device *sdev,
- int queue_depth, int reason)
-{
- if (reason != SCSI_QDEPTH_DEFAULT)
- return -EOPNOTSUPP;
-
- if (queue_depth > sdev->host->can_queue)
- queue_depth = sdev->host->can_queue;
- scsi_adjust_queue_depth(sdev, queue_depth);
-
- return queue_depth;
-}
-
static ssize_t
megasas_fw_crash_buffer_store(struct device *cdev,
struct device_attribute *attr, const char *buf, size_t count)
@@ -2763,7 +2755,7 @@ static struct scsi_host_template megasas_template = {
.shost_attrs = megaraid_host_attrs,
.bios_param = megasas_bios_param,
.use_clustering = ENABLE_CLUSTERING,
- .change_queue_depth = megasas_change_queue_depth,
+ .change_queue_depth = scsi_change_queue_depth,
.no_write_same = 1,
};
@@ -4027,25 +4019,83 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type)
return ret;
}
+/*
+ * megasas_update_ext_vd_details : Update details w.r.t Extended VD
+ * instance : Controller's instance
+*/
+static void megasas_update_ext_vd_details(struct megasas_instance *instance)
+{
+ struct fusion_context *fusion;
+ u32 old_map_sz;
+ u32 new_map_sz;
+
+ fusion = instance->ctrl_context;
+ /* For MFI based controllers return dummy success */
+ if (!fusion)
+ return;
+
+ instance->supportmax256vd =
+ instance->ctrl_info->adapterOperations3.supportMaxExtLDs;
+ /* Below is additional check to address future FW enhancement */
+ if (instance->ctrl_info->max_lds > 64)
+ instance->supportmax256vd = 1;
+
+ instance->drv_supported_vd_count = MEGASAS_MAX_LD_CHANNELS
+ * MEGASAS_MAX_DEV_PER_CHANNEL;
+ instance->drv_supported_pd_count = MEGASAS_MAX_PD_CHANNELS
+ * MEGASAS_MAX_DEV_PER_CHANNEL;
+ if (instance->supportmax256vd) {
+ instance->fw_supported_vd_count = MAX_LOGICAL_DRIVES_EXT;
+ instance->fw_supported_pd_count = MAX_PHYSICAL_DEVICES;
+ } else {
+ instance->fw_supported_vd_count = MAX_LOGICAL_DRIVES;
+ instance->fw_supported_pd_count = MAX_PHYSICAL_DEVICES;
+ }
+ dev_info(&instance->pdev->dev, "Firmware supports %d VD %d PD\n",
+ instance->fw_supported_vd_count,
+ instance->fw_supported_pd_count);
+ dev_info(&instance->pdev->dev, "Driver supports %d VD %d PD\n",
+ instance->drv_supported_vd_count,
+ instance->drv_supported_pd_count);
+
+ old_map_sz = sizeof(struct MR_FW_RAID_MAP) +
+ (sizeof(struct MR_LD_SPAN_MAP) *
+ (instance->fw_supported_vd_count - 1));
+ new_map_sz = sizeof(struct MR_FW_RAID_MAP_EXT);
+ fusion->drv_map_sz = sizeof(struct MR_DRV_RAID_MAP) +
+ (sizeof(struct MR_LD_SPAN_MAP) *
+ (instance->drv_supported_vd_count - 1));
+
+ fusion->max_map_sz = max(old_map_sz, new_map_sz);
+
+
+ if (instance->supportmax256vd)
+ fusion->current_map_sz = new_map_sz;
+ else
+ fusion->current_map_sz = old_map_sz;
+
+}
+
/**
* megasas_get_controller_info - Returns FW's controller structure
* @instance: Adapter soft state
- * @ctrl_info: Controller information structure
*
* Issues an internal command (DCMD) to get the FW's controller structure.
* This information is mainly used to find out the maximum IO transfer per
* command supported by the FW.
*/
int
-megasas_get_ctrl_info(struct megasas_instance *instance,
- struct megasas_ctrl_info *ctrl_info)
+megasas_get_ctrl_info(struct megasas_instance *instance)
{
int ret = 0;
struct megasas_cmd *cmd;
struct megasas_dcmd_frame *dcmd;
struct megasas_ctrl_info *ci;
+ struct megasas_ctrl_info *ctrl_info;
dma_addr_t ci_h = 0;
+ ctrl_info = instance->ctrl_info;
+
cmd = megasas_get_cmd(instance);
if (!cmd) {
@@ -4085,8 +4135,13 @@ megasas_get_ctrl_info(struct megasas_instance *instance,
else
ret = megasas_issue_polled(instance, cmd);
- if (!ret)
+ if (!ret) {
memcpy(ctrl_info, ci, sizeof(struct megasas_ctrl_info));
+ le32_to_cpus((u32 *)&ctrl_info->properties.OnOffProperties);
+ le32_to_cpus((u32 *)&ctrl_info->adapterOperations2);
+ le32_to_cpus((u32 *)&ctrl_info->adapterOperations3);
+ megasas_update_ext_vd_details(instance);
+ }
pci_free_consistent(instance->pdev, sizeof(struct megasas_ctrl_info),
ci, ci_h);
@@ -4288,7 +4343,7 @@ megasas_init_adapter_mfi(struct megasas_instance *instance)
if (megasas_issue_init_mfi(instance))
goto fail_fw_init;
- if (megasas_get_ctrl_info(instance, instance->ctrl_info)) {
+ if (megasas_get_ctrl_info(instance)) {
dev_err(&instance->pdev->dev, "(%d): Could get controller info "
"Fail from %s %d\n", instance->unique_id,
__func__, __LINE__);
@@ -4526,12 +4581,8 @@ static int megasas_init_fw(struct megasas_instance *instance)
dev_info(&instance->pdev->dev,
"Controller type: iMR\n");
}
- /* OnOffProperties are converted into CPU arch*/
- le32_to_cpus((u32 *)&ctrl_info->properties.OnOffProperties);
instance->disableOnlineCtrlReset =
ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
- /* adapterOperations2 are converted into CPU arch*/
- le32_to_cpus((u32 *)&ctrl_info->adapterOperations2);
instance->mpio = ctrl_info->adapterOperations2.mpio;
instance->UnevenSpanSupport =
ctrl_info->adapterOperations2.supportUnevenSpans;
@@ -4561,7 +4612,6 @@ static int megasas_init_fw(struct megasas_instance *instance)
"requestorId %d\n", instance->requestorId);
}
- le32_to_cpus((u32 *)&ctrl_info->adapterOperations3);
instance->crash_dump_fw_support =
ctrl_info->adapterOperations3.supportCrashDump;
instance->crash_dump_drv_support =
@@ -4586,8 +4636,6 @@ static int megasas_init_fw(struct megasas_instance *instance)
if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors))
instance->max_sectors_per_req = tmp_sectors;
- kfree(ctrl_info);
-
/* Check for valid throttlequeuedepth module parameter */
if (instance->is_imr) {
if (throttlequeuedepth > (instance->max_fw_cmds -
@@ -4956,10 +5004,6 @@ static int megasas_io_attach(struct megasas_instance *instance)
return -ENODEV;
}
- /*
- * Trigger SCSI to scan our drives
- */
- scsi_scan_host(host);
return 0;
}
@@ -5082,6 +5126,8 @@ static int megasas_probe_one(struct pci_dev *pdev,
goto fail_alloc_dma_buf;
}
fusion = instance->ctrl_context;
+ memset(fusion, 0,
+ ((1 << PAGE_SHIFT) << instance->ctrl_context_pages));
INIT_LIST_HEAD(&fusion->cmd_pool);
spin_lock_init(&fusion->mpt_pool_lock);
memset(fusion->load_balance_info, 0,
@@ -5287,6 +5333,10 @@ retry_irq_register:
goto fail_io_attach;
instance->unload = 0;
+ /*
+ * Trigger SCSI to scan our drives
+ */
+ scsi_scan_host(host);
/*
* Initiate AEN (Asynchronous Event Notification)
@@ -6050,6 +6100,11 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
megasas_issue_blocked_cmd(instance, cmd, 0);
cmd->sync_cmd = 0;
+ if (instance->unload == 1) {
+ dev_info(&instance->pdev->dev, "Driver unload is in progress "
+ "don't submit data to application\n");
+ goto out;
+ }
/*
* copy out the kernel buffers to user buffers
*/
@@ -6399,16 +6454,6 @@ static ssize_t megasas_sysfs_show_version(struct device_driver *dd, char *buf)
static DRIVER_ATTR(version, S_IRUGO, megasas_sysfs_show_version, NULL);
static ssize_t
-megasas_sysfs_show_release_date(struct device_driver *dd, char *buf)
-{
- return snprintf(buf, strlen(MEGASAS_RELDATE) + 2, "%s\n",
- MEGASAS_RELDATE);
-}
-
-static DRIVER_ATTR(release_date, S_IRUGO, megasas_sysfs_show_release_date,
- NULL);
-
-static ssize_t
megasas_sysfs_show_support_poll_for_event(struct device_driver *dd, char *buf)
{
return sprintf(buf, "%u\n", support_poll_for_event);
@@ -6711,8 +6756,7 @@ static int __init megasas_init(void)
/*
* Announce driver version and other information
*/
- printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION,
- MEGASAS_EXT_VERSION);
+ pr_info("megasas: %s\n", MEGASAS_VERSION);
spin_lock_init(&poll_aen_lock);
@@ -6747,10 +6791,6 @@ static int __init megasas_init(void)
&driver_attr_version);
if (rval)
goto err_dcf_attr_ver;
- rval = driver_create_file(&megasas_pci_driver.driver,
- &driver_attr_release_date);
- if (rval)
- goto err_dcf_rel_date;
rval = driver_create_file(&megasas_pci_driver.driver,
&driver_attr_support_poll_for_event);
@@ -6774,12 +6814,7 @@ err_dcf_support_device_change:
err_dcf_dbg_lvl:
driver_remove_file(&megasas_pci_driver.driver,
&driver_attr_support_poll_for_event);
-
err_dcf_support_poll_for_event:
- driver_remove_file(&megasas_pci_driver.driver,
- &driver_attr_release_date);
-
-err_dcf_rel_date:
driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
err_dcf_attr_ver:
pci_unregister_driver(&megasas_pci_driver);
@@ -6799,8 +6834,6 @@ static void __exit megasas_exit(void)
&driver_attr_support_poll_for_event);
driver_remove_file(&megasas_pci_driver.driver,
&driver_attr_support_device_change);
- driver_remove_file(&megasas_pci_driver.driver,
- &driver_attr_release_date);
driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
pci_unregister_driver(&megasas_pci_driver);
diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
index 685e6f391fe4..460c6a3d4ade 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fp.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
@@ -1,7 +1,8 @@
/*
* Linux MegaRAID driver for SAS based RAID controllers
*
- * Copyright (c) 2009-2012 LSI Corporation.
+ * Copyright (c) 2009-2013 LSI Corporation
+ * Copyright (c) 2013-2014 Avago Technologies
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -14,20 +15,21 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* FILE: megaraid_sas_fp.c
*
- * Authors: LSI Corporation
+ * Authors: Avago Technologies
* Sumant Patro
* Varad Talamacki
* Manoj Jose
+ * Kashyap Desai <kashyap.desai@avagotech.com>
+ * Sumit Saxena <sumit.saxena@avagotech.com>
*
- * Send feedback to: <megaraidlinux@lsi.com>
+ * Send feedback to: megaraidlinux.pdl@avagotech.com
*
- * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
- * ATTN: Linuxraid
+ * Mail to: Avago Technologies, 350 West Trimble Road, Building 90,
+ * San Jose, California 95131
*/
#include <linux/kernel.h>
@@ -183,14 +185,15 @@ void MR_PopulateDrvRaidMap(struct megasas_instance *instance)
/* New Raid map will not set totalSize, so keep expected value
* for legacy code in ValidateMapInfo
*/
- pDrvRaidMap->totalSize = sizeof(struct MR_FW_RAID_MAP_EXT);
+ pDrvRaidMap->totalSize =
+ cpu_to_le32(sizeof(struct MR_FW_RAID_MAP_EXT));
} else {
fw_map_old = (struct MR_FW_RAID_MAP_ALL *)
fusion->ld_map[(instance->map_id & 1)];
pFwRaidMap = &fw_map_old->raidMap;
#if VD_EXT_DEBUG
- for (i = 0; i < pFwRaidMap->ldCount; i++) {
+ for (i = 0; i < le16_to_cpu(pFwRaidMap->ldCount); i++) {
dev_dbg(&instance->pdev->dev, "(%d) :Index 0x%x "
"Target Id 0x%x Seq Num 0x%x Size 0/%llx\n",
instance->unique_id, i,
@@ -202,12 +205,12 @@ void MR_PopulateDrvRaidMap(struct megasas_instance *instance)
memset(drv_map, 0, fusion->drv_map_sz);
pDrvRaidMap->totalSize = pFwRaidMap->totalSize;
- pDrvRaidMap->ldCount = pFwRaidMap->ldCount;
+ pDrvRaidMap->ldCount = (__le16)pFwRaidMap->ldCount;
pDrvRaidMap->fpPdIoTimeoutSec = pFwRaidMap->fpPdIoTimeoutSec;
for (i = 0; i < MAX_RAIDMAP_LOGICAL_DRIVES + MAX_RAIDMAP_VIEWS; i++)
pDrvRaidMap->ldTgtIdToLd[i] =
(u8)pFwRaidMap->ldTgtIdToLd[i];
- for (i = 0; i < pDrvRaidMap->ldCount; i++) {
+ for (i = 0; i < le16_to_cpu(pDrvRaidMap->ldCount); i++) {
pDrvRaidMap->ldSpanMap[i] = pFwRaidMap->ldSpanMap[i];
#if VD_EXT_DEBUG
dev_dbg(&instance->pdev->dev,
@@ -268,7 +271,7 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance)
else
expected_size =
(sizeof(struct MR_FW_RAID_MAP) - sizeof(struct MR_LD_SPAN_MAP) +
- (sizeof(struct MR_LD_SPAN_MAP) * le32_to_cpu(pDrvRaidMap->ldCount)));
+ (sizeof(struct MR_LD_SPAN_MAP) * le16_to_cpu(pDrvRaidMap->ldCount)));
if (le32_to_cpu(pDrvRaidMap->totalSize) != expected_size) {
dev_err(&instance->pdev->dev, "map info structure size 0x%x is not matching with ld count\n",
@@ -284,7 +287,7 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance)
mr_update_load_balance_params(drv_map, lbInfo);
- num_lds = le32_to_cpu(drv_map->raidMap.ldCount);
+ num_lds = le16_to_cpu(drv_map->raidMap.ldCount);
/*Convert Raid capability values to CPU arch */
for (ldCount = 0; ldCount < num_lds; ldCount++) {
@@ -457,7 +460,7 @@ u32 mr_spanset_get_span_block(struct megasas_instance *instance,
quad = &map->raidMap.ldSpanMap[ld].
spanBlock[span].
block_span_info.quad[info];
- if (le32_to_cpu(quad->diff == 0))
+ if (le32_to_cpu(quad->diff) == 0)
return SPAN_INVALID;
if (le64_to_cpu(quad->logStart) <= row &&
row <= le64_to_cpu(quad->logEnd) &&
@@ -520,7 +523,7 @@ static u64 get_row_from_strip(struct megasas_instance *instance,
span_set->span_row_data_width) * span_set->diff;
for (span = 0, span_offset = 0; span < raid->spanDepth; span++)
if (le32_to_cpu(map->raidMap.ldSpanMap[ld].spanBlock[span].
- block_span_info.noElements >= info+1)) {
+ block_span_info.noElements) >= info+1) {
if (strip_offset >=
span_set->strip_offset[span])
span_offset++;
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index f37eed682c75..71557f64bb5e 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -1,7 +1,8 @@
/*
* Linux MegaRAID driver for SAS based RAID controllers
*
- * Copyright (c) 2009-2012 LSI Corporation.
+ * Copyright (c) 2009-2013 LSI Corporation
+ * Copyright (c) 2013-2014 Avago Technologies
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -14,19 +15,20 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* FILE: megaraid_sas_fusion.c
*
- * Authors: LSI Corporation
+ * Authors: Avago Technologies
* Sumant Patro
- * Adam Radford <linuxraid@lsi.com>
+ * Adam Radford
+ * Kashyap Desai <kashyap.desai@avagotech.com>
+ * Sumit Saxena <sumit.saxena@avagotech.com>
*
- * Send feedback to: <megaraidlinux@lsi.com>
+ * Send feedback to: megaraidlinux.pdl@avagotech.com
*
- * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
- * ATTN: Linuxraid
+ * Mail to: Avago Technologies, 350 West Trimble Road, Building 90,
+ * San Jose, California 95131
*/
#include <linux/kernel.h>
@@ -880,7 +882,7 @@ megasas_sync_map_info(struct megasas_instance *instance)
map = fusion->ld_drv_map[instance->map_id & 1];
- num_lds = le32_to_cpu(map->raidMap.ldCount);
+ num_lds = le16_to_cpu(map->raidMap.ldCount);
dcmd = &cmd->frame->dcmd;
@@ -1065,48 +1067,16 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
goto fail_ioc_init;
megasas_display_intel_branding(instance);
- if (megasas_get_ctrl_info(instance, instance->ctrl_info)) {
+ if (megasas_get_ctrl_info(instance)) {
dev_err(&instance->pdev->dev,
"Could not get controller info. Fail from %s %d\n",
__func__, __LINE__);
goto fail_ioc_init;
}
- instance->supportmax256vd =
- instance->ctrl_info->adapterOperations3.supportMaxExtLDs;
- /* Below is additional check to address future FW enhancement */
- if (instance->ctrl_info->max_lds > 64)
- instance->supportmax256vd = 1;
- instance->drv_supported_vd_count = MEGASAS_MAX_LD_CHANNELS
- * MEGASAS_MAX_DEV_PER_CHANNEL;
- instance->drv_supported_pd_count = MEGASAS_MAX_PD_CHANNELS
- * MEGASAS_MAX_DEV_PER_CHANNEL;
- if (instance->supportmax256vd) {
- instance->fw_supported_vd_count = MAX_LOGICAL_DRIVES_EXT;
- instance->fw_supported_pd_count = MAX_PHYSICAL_DEVICES;
- } else {
- instance->fw_supported_vd_count = MAX_LOGICAL_DRIVES;
- instance->fw_supported_pd_count = MAX_PHYSICAL_DEVICES;
- }
- dev_info(&instance->pdev->dev, "Firmware supports %d VDs %d PDs\n"
- "Driver supports %d VDs %d PDs\n",
- instance->fw_supported_vd_count,
- instance->fw_supported_pd_count,
- instance->drv_supported_vd_count,
- instance->drv_supported_pd_count);
-
instance->flag_ieee = 1;
fusion->fast_path_io = 0;
- fusion->old_map_sz =
- sizeof(struct MR_FW_RAID_MAP) + (sizeof(struct MR_LD_SPAN_MAP) *
- (instance->fw_supported_vd_count - 1));
- fusion->new_map_sz =
- sizeof(struct MR_FW_RAID_MAP_EXT);
- fusion->drv_map_sz =
- sizeof(struct MR_DRV_RAID_MAP) + (sizeof(struct MR_LD_SPAN_MAP) *
- (instance->drv_supported_vd_count - 1));
-
fusion->drv_map_pages = get_order(fusion->drv_map_sz);
for (i = 0; i < 2; i++) {
fusion->ld_map[i] = NULL;
@@ -1121,16 +1091,10 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
fusion->drv_map_pages);
goto fail_ioc_init;
}
+ memset(fusion->ld_drv_map[i], 0,
+ ((1 << PAGE_SHIFT) << fusion->drv_map_pages));
}
- fusion->max_map_sz = max(fusion->old_map_sz, fusion->new_map_sz);
-
- if (instance->supportmax256vd)
- fusion->current_map_sz = fusion->new_map_sz;
- else
- fusion->current_map_sz = fusion->old_map_sz;
-
-
for (i = 0; i < 2; i++) {
fusion->ld_map[i] = dma_alloc_coherent(&instance->pdev->dev,
fusion->max_map_sz,
@@ -1173,9 +1137,10 @@ megasas_fire_cmd_fusion(struct megasas_instance *instance,
struct megasas_register_set __iomem *regs)
{
#if defined(writeq) && defined(CONFIG_64BIT)
- u64 req_data = (((u64)req_desc_hi << 32) | (u32)req_desc_lo);
+ u64 req_data = (((u64)le32_to_cpu(req_desc_hi) << 32) |
+ le32_to_cpu(req_desc_lo));
- writeq(le64_to_cpu(req_data), &(regs)->inbound_low_queue_port);
+ writeq(req_data, &(regs)->inbound_low_queue_port);
#else
unsigned long flags;
@@ -1373,7 +1338,7 @@ megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len,
/* Logical block reference tag */
io_request->CDB.EEDP32.PrimaryReferenceTag =
cpu_to_be32(ref_tag);
- io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0xffff;
+ io_request->CDB.EEDP32.PrimaryApplicationTagMask = cpu_to_be16(0xffff);
io_request->IoFlags = cpu_to_le16(32); /* Specify 32-byte cdb */
/* Transfer length */
@@ -1769,7 +1734,7 @@ megasas_build_dcdb_fusion(struct megasas_instance *instance,
/* set RAID context values */
pRAID_Context->regLockFlags = REGION_TYPE_SHARED_READ;
- pRAID_Context->timeoutValue = raid->fpIoTimeoutForLd;
+ pRAID_Context->timeoutValue = cpu_to_le16(raid->fpIoTimeoutForLd);
pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id);
pRAID_Context->regLockRowLBA = 0;
pRAID_Context->regLockLength = 0;
@@ -2254,7 +2219,7 @@ build_mpt_mfi_pass_thru(struct megasas_instance *instance,
* megasas_complete_cmd
*/
- if (frame_hdr->flags & MFI_FRAME_DONT_POST_IN_REPLY_QUEUE)
+ if (frame_hdr->flags & cpu_to_le16(MFI_FRAME_DONT_POST_IN_REPLY_QUEUE))
cmd->flags = MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
fusion = instance->ctrl_context;
@@ -2385,6 +2350,8 @@ megasas_alloc_host_crash_buffer(struct megasas_instance *instance)
"memory allocation failed at index %d\n", i);
break;
}
+ memset(instance->crash_buf[i], 0,
+ ((1 << PAGE_SHIFT) << instance->crash_buf_pages));
}
instance->drv_buf_alloc = i;
}
@@ -2837,11 +2804,15 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
}
}
- clear_bit(MEGASAS_FUSION_IN_RESET,
- &instance->reset_flags);
- instance->instancet->enable_intr(instance);
- instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
-
+ if (megasas_get_ctrl_info(instance)) {
+ dev_info(&instance->pdev->dev,
+ "Failed from %s %d\n",
+ __func__, __LINE__);
+ instance->adprecovery =
+ MEGASAS_HW_CRITICAL_ERROR;
+ megaraid_sas_kill_hba(instance);
+ retval = FAILED;
+ }
/* Reset load balance info */
memset(fusion->load_balance_info, 0,
sizeof(struct LD_LOAD_BALANCE_INFO)
@@ -2850,6 +2821,11 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
if (!megasas_get_map_info(instance))
megasas_sync_map_info(instance);
+ clear_bit(MEGASAS_FUSION_IN_RESET,
+ &instance->reset_flags);
+ instance->instancet->enable_intr(instance);
+ instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
+
/* Restart SR-IOV heartbeat */
if (instance->requestorId) {
if (!megasas_sriov_start_heartbeat(instance, 0))
@@ -2866,14 +2842,14 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
"successful for scsi%d.\n",
instance->host->host_no);
- if (instance->crash_dump_drv_support) {
- if (instance->crash_dump_app_support)
- megasas_set_crash_dump_params(instance,
- MR_CRASH_BUF_TURN_ON);
- else
- megasas_set_crash_dump_params(instance,
- MR_CRASH_BUF_TURN_OFF);
- }
+ if (instance->crash_dump_drv_support &&
+ instance->crash_dump_app_support)
+ megasas_set_crash_dump_params(instance,
+ MR_CRASH_BUF_TURN_ON);
+ else
+ megasas_set_crash_dump_params(instance,
+ MR_CRASH_BUF_TURN_OFF);
+
retval = SUCCESS;
goto out;
}
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h
index 0d183d521bdd..5ab7daee11be 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.h
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h
@@ -1,7 +1,8 @@
/*
* Linux MegaRAID driver for SAS based RAID controllers
*
- * Copyright (c) 2009-2012 LSI Corporation.
+ * Copyright (c) 2009-2013 LSI Corporation
+ * Copyright (c) 2013-2014 Avago Technologies
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -14,19 +15,20 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* FILE: megaraid_sas_fusion.h
*
- * Authors: LSI Corporation
+ * Authors: Avago Technologies
* Manoj Jose
* Sumant Patro
+ * Kashyap Desai <kashyap.desai@avagotech.com>
+ * Sumit Saxena <sumit.saxena@avagotech.com>
*
- * Send feedback to: <megaraidlinux@lsi.com>
+ * Send feedback to: megaraidlinux.pdl@avagotech.com
*
- * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
- * ATTN: Linuxraid
+ * Mail to: Avago Technologies, 350 West Trimble Road, Building 90,
+ * San Jose, California 95131
*/
#ifndef _MEGARAID_SAS_FUSION_H_
@@ -834,8 +836,6 @@ struct fusion_context {
u32 max_map_sz;
u32 current_map_sz;
- u32 old_map_sz;
- u32 new_map_sz;
u32 drv_map_sz;
u32 drv_map_pages;
u8 fast_path_io;
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index 42fef914d441..8431eb10bbb1 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -1179,15 +1179,14 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc,
}
/**
- * _scsih_adjust_queue_depth - setting device queue depth
+ * _scsih_change_queue_depth - setting device queue depth
* @sdev: scsi device struct
* @qdepth: requested queue depth
*
- *
- * Returns nothing
+ * Returns queue depth.
*/
-static void
-_scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth)
+static int
+_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
{
struct Scsi_Host *shost = sdev->host;
int max_depth;
@@ -1217,41 +1216,11 @@ _scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth)
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
not_sata:
-
if (!sdev->tagged_supported)
max_depth = 1;
if (qdepth > max_depth)
qdepth = max_depth;
- scsi_adjust_queue_depth(sdev, qdepth);
-}
-
-/**
- * _scsih_change_queue_depth - setting device queue depth
- * @sdev: scsi device struct
- * @qdepth: requested queue depth
- * @reason: SCSI_QDEPTH_DEFAULT/SCSI_QDEPTH_QFULL/SCSI_QDEPTH_RAMP_UP
- * (see include/scsi/scsi_host.h for definition)
- *
- * Returns queue depth.
- */
-static int
-_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
-{
- if (reason == SCSI_QDEPTH_DEFAULT || reason == SCSI_QDEPTH_RAMP_UP)
- _scsih_adjust_queue_depth(sdev, qdepth);
- else if (reason == SCSI_QDEPTH_QFULL)
- scsi_track_queue_full(sdev, qdepth);
- else
- return -EOPNOTSUPP;
-
- if (sdev->inquiry_len > 7)
- sdev_printk(KERN_INFO, sdev, "qdepth(%d), tagged(%d), "
- "simple(%d), scsi_level(%d), cmd_que(%d)\n",
- sdev->queue_depth, sdev->tagged_supported, sdev->simple_tags,
- sdev->scsi_level,
- (sdev->inquiry[7] & 2) >> 1);
-
- return sdev->queue_depth;
+ return scsi_change_queue_depth(sdev, qdepth);
}
/**
@@ -2082,7 +2051,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
r_level, raid_device->handle,
(unsigned long long)raid_device->wwid,
raid_device->num_pds, ds);
- _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
+ _scsih_change_queue_depth(sdev, qdepth);
/* raid transport support */
if (!ioc->is_warpdrive)
_scsih_set_level(sdev, raid_device->volume_type);
@@ -2147,7 +2116,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
_scsih_display_sata_capabilities(ioc, handle, sdev);
- _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
+ _scsih_change_queue_depth(sdev, qdepth);
if (ssp_target) {
sas_read_port_mode_page(sdev);
@@ -7637,6 +7606,7 @@ static struct scsi_host_template scsih_driver_template = {
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = mpt2sas_host_attrs,
.sdev_attrs = mpt2sas_dev_attrs,
+ .track_queue_depth = 1,
};
/**
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index b23c2e7588e5..a2b60991efd4 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -1053,9 +1053,15 @@ _scsih_scsi_lookup_find_by_lun(struct MPT3SAS_ADAPTER *ioc, int id,
return found;
}
-
-static void
-_scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth)
+/**
+ * _scsih_change_queue_depth - setting device queue depth
+ * @sdev: scsi device struct
+ * @qdepth: requested queue depth
+ *
+ * Returns queue depth.
+ */
+static int
+_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
{
struct Scsi_Host *shost = sdev->host;
int max_depth;
@@ -1090,36 +1096,7 @@ _scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth)
max_depth = 1;
if (qdepth > max_depth)
qdepth = max_depth;
- scsi_adjust_queue_depth(sdev, qdepth);
-}
-
-/**
- * _scsih_change_queue_depth - setting device queue depth
- * @sdev: scsi device struct
- * @qdepth: requested queue depth
- * @reason: SCSI_QDEPTH_DEFAULT/SCSI_QDEPTH_QFULL/SCSI_QDEPTH_RAMP_UP
- * (see include/scsi/scsi_host.h for definition)
- *
- * Returns queue depth.
- */
-static int
-_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
-{
- if (reason == SCSI_QDEPTH_DEFAULT || reason == SCSI_QDEPTH_RAMP_UP)
- _scsih_adjust_queue_depth(sdev, qdepth);
- else if (reason == SCSI_QDEPTH_QFULL)
- scsi_track_queue_full(sdev, qdepth);
- else
- return -EOPNOTSUPP;
-
- if (sdev->inquiry_len > 7)
- sdev_printk(KERN_INFO, sdev, "qdepth(%d), tagged(%d), " \
- "simple(%d), scsi_level(%d), cmd_que(%d)\n",
- sdev->queue_depth, sdev->tagged_supported, sdev->simple_tags,
- sdev->scsi_level,
- (sdev->inquiry[7] & 2) >> 1);
-
- return sdev->queue_depth;
+ return scsi_change_queue_depth(sdev, qdepth);
}
/**
@@ -1739,7 +1716,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
raid_device->num_pds, ds);
- _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
+ _scsih_change_queue_depth(sdev, qdepth);
/* raid transport support */
_scsih_set_level(sdev, raid_device->volume_type);
@@ -1805,7 +1782,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
_scsih_display_sata_capabilities(ioc, handle, sdev);
- _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
+ _scsih_change_queue_depth(sdev, qdepth);
if (ssp_target) {
sas_read_port_mode_page(sdev);
@@ -7266,6 +7243,7 @@ static struct scsi_host_template scsih_driver_template = {
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = mpt3sas_host_attrs,
.sdev_attrs = mpt3sas_dev_attrs,
+ .track_queue_depth = 1,
};
/**
diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c
index d3c1fa5e76fb..f15df3de6790 100644
--- a/drivers/scsi/mvsas/mv_init.c
+++ b/drivers/scsi/mvsas/mv_init.c
@@ -26,18 +26,9 @@
#include "mv_sas.h"
-static int lldd_max_execute_num = 1;
-module_param_named(collector, lldd_max_execute_num, int, S_IRUGO);
-MODULE_PARM_DESC(collector, "\n"
- "\tIf greater than one, tells the SAS Layer to run in Task Collector\n"
- "\tMode. If 1 or 0, tells the SAS Layer to run in Direct Mode.\n"
- "\tThe mvsas SAS LLDD supports both modes.\n"
- "\tDefault: 1 (Direct Mode).\n");
-
int interrupt_coalescing = 0x80;
static struct scsi_transport_template *mvs_stt;
-struct kmem_cache *mvs_task_list_cache;
static const struct mvs_chip_info mvs_chips[] = {
[chip_6320] = { 1, 2, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, },
[chip_6440] = { 1, 4, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, },
@@ -77,6 +68,7 @@ static struct scsi_host_template mvs_sht = {
.ioctl = sas_ioctl,
.shost_attrs = mvst_host_attrs,
.use_blk_tags = 1,
+ .track_queue_depth = 1,
};
static struct sas_domain_function_template mvs_transport_ops = {
@@ -512,14 +504,11 @@ static void mvs_post_sas_ha_init(struct Scsi_Host *shost,
sha->num_phys = nr_core * chip_info->n_phy;
- sha->lldd_max_execute_num = lldd_max_execute_num;
-
if (mvi->flags & MVF_FLAG_SOC)
can_queue = MVS_SOC_CAN_QUEUE;
else
can_queue = MVS_CHIP_SLOT_SZ;
- sha->lldd_queue_size = can_queue;
shost->sg_tablesize = min_t(u16, SG_ALL, MVS_MAX_SG);
shost->can_queue = can_queue;
mvi->shost->cmd_per_lun = MVS_QUEUE_SIZE;
@@ -832,16 +821,7 @@ static int __init mvs_init(void)
if (!mvs_stt)
return -ENOMEM;
- mvs_task_list_cache = kmem_cache_create("mvs_task_list", sizeof(struct mvs_task_list),
- 0, SLAB_HWCACHE_ALIGN, NULL);
- if (!mvs_task_list_cache) {
- rc = -ENOMEM;
- mv_printk("%s: mvs_task_list_cache alloc failed! \n", __func__);
- goto err_out;
- }
-
rc = pci_register_driver(&mvs_pci_driver);
-
if (rc)
goto err_out;
@@ -856,7 +836,6 @@ static void __exit mvs_exit(void)
{
pci_unregister_driver(&mvs_pci_driver);
sas_release_transport(mvs_stt);
- kmem_cache_destroy(mvs_task_list_cache);
}
struct device_attribute *mvst_host_attrs[] = {
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
index ac52f7c99513..85d86a5cdb60 100644
--- a/drivers/scsi/mvsas/mv_sas.c
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -852,43 +852,7 @@ prep_out:
return rc;
}
-static struct mvs_task_list *mvs_task_alloc_list(int *num, gfp_t gfp_flags)
-{
- struct mvs_task_list *first = NULL;
-
- for (; *num > 0; --*num) {
- struct mvs_task_list *mvs_list = kmem_cache_zalloc(mvs_task_list_cache, gfp_flags);
-
- if (!mvs_list)
- break;
-
- INIT_LIST_HEAD(&mvs_list->list);
- if (!first)
- first = mvs_list;
- else
- list_add_tail(&mvs_list->list, &first->list);
-
- }
-
- return first;
-}
-
-static inline void mvs_task_free_list(struct mvs_task_list *mvs_list)
-{
- LIST_HEAD(list);
- struct list_head *pos, *a;
- struct mvs_task_list *mlist = NULL;
-
- __list_add(&list, mvs_list->list.prev, &mvs_list->list);
-
- list_for_each_safe(pos, a, &list) {
- list_del_init(pos);
- mlist = list_entry(pos, struct mvs_task_list, list);
- kmem_cache_free(mvs_task_list_cache, mlist);
- }
-}
-
-static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
+static int mvs_task_exec(struct sas_task *task, gfp_t gfp_flags,
struct completion *completion, int is_tmf,
struct mvs_tmf_task *tmf)
{
@@ -912,74 +876,9 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
return rc;
}
-static int mvs_collector_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
- struct completion *completion, int is_tmf,
- struct mvs_tmf_task *tmf)
+int mvs_queue_command(struct sas_task *task, gfp_t gfp_flags)
{
- struct domain_device *dev = task->dev;
- struct mvs_prv_info *mpi = dev->port->ha->lldd_ha;
- struct mvs_info *mvi = NULL;
- struct sas_task *t = task;
- struct mvs_task_list *mvs_list = NULL, *a;
- LIST_HEAD(q);
- int pass[2] = {0};
- u32 rc = 0;
- u32 n = num;
- unsigned long flags = 0;
-
- mvs_list = mvs_task_alloc_list(&n, gfp_flags);
- if (n) {
- printk(KERN_ERR "%s: mvs alloc list failed.\n", __func__);
- rc = -ENOMEM;
- goto free_list;
- }
-
- __list_add(&q, mvs_list->list.prev, &mvs_list->list);
-
- list_for_each_entry(a, &q, list) {
- a->task = t;
- t = list_entry(t->list.next, struct sas_task, list);
- }
-
- list_for_each_entry(a, &q , list) {
-
- t = a->task;
- mvi = ((struct mvs_device *)t->dev->lldd_dev)->mvi_info;
-
- spin_lock_irqsave(&mvi->lock, flags);
- rc = mvs_task_prep(t, mvi, is_tmf, tmf, &pass[mvi->id]);
- if (rc)
- dev_printk(KERN_ERR, mvi->dev, "mvsas exec failed[%d]!\n", rc);
- spin_unlock_irqrestore(&mvi->lock, flags);
- }
-
- if (likely(pass[0]))
- MVS_CHIP_DISP->start_delivery(mpi->mvi[0],
- (mpi->mvi[0]->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1));
-
- if (likely(pass[1]))
- MVS_CHIP_DISP->start_delivery(mpi->mvi[1],
- (mpi->mvi[1]->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1));
-
- list_del_init(&q);
-
-free_list:
- if (mvs_list)
- mvs_task_free_list(mvs_list);
-
- return rc;
-}
-
-int mvs_queue_command(struct sas_task *task, const int num,
- gfp_t gfp_flags)
-{
- struct mvs_device *mvi_dev = task->dev->lldd_dev;
- struct sas_ha_struct *sas = mvi_dev->mvi_info->sas;
-
- if (sas->lldd_max_execute_num < 2)
- return mvs_task_exec(task, num, gfp_flags, NULL, 0, NULL);
- else
- return mvs_collector_task_exec(task, num, gfp_flags, NULL, 0, NULL);
+ return mvs_task_exec(task, gfp_flags, NULL, 0, NULL);
}
static void mvs_slot_free(struct mvs_info *mvi, u32 rx_desc)
@@ -1411,7 +1310,7 @@ static int mvs_exec_internal_tmf_task(struct domain_device *dev,
task->slow_task->timer.expires = jiffies + MVS_TASK_TIMEOUT*HZ;
add_timer(&task->slow_task->timer);
- res = mvs_task_exec(task, 1, GFP_KERNEL, NULL, 1, tmf);
+ res = mvs_task_exec(task, GFP_KERNEL, NULL, 1, tmf);
if (res) {
del_timer(&task->slow_task->timer);
diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h
index d6b19dc80bee..dc409c04747a 100644
--- a/drivers/scsi/mvsas/mv_sas.h
+++ b/drivers/scsi/mvsas/mv_sas.h
@@ -65,7 +65,6 @@ extern struct mvs_tgt_initiator mvs_tgt;
extern struct mvs_info *tgt_mvi;
extern const struct mvs_dispatch mvs_64xx_dispatch;
extern const struct mvs_dispatch mvs_94xx_dispatch;
-extern struct kmem_cache *mvs_task_list_cache;
#define DEV_IS_EXPANDER(type) \
((type == SAS_EDGE_EXPANDER_DEVICE) || (type == SAS_FANOUT_EXPANDER_DEVICE))
@@ -440,12 +439,6 @@ struct mvs_task_exec_info {
int n_elem;
};
-struct mvs_task_list {
- struct sas_task *task;
- struct list_head list;
-};
-
-
/******************** function prototype *********************/
void mvs_get_sas_addr(void *buf, u32 buflen);
void mvs_tag_clear(struct mvs_info *mvi, u32 tag);
@@ -462,8 +455,7 @@ void mvs_set_sas_addr(struct mvs_info *mvi, int port_id, u32 off_lo,
u32 off_hi, u64 sas_addr);
void mvs_scan_start(struct Scsi_Host *shost);
int mvs_scan_finished(struct Scsi_Host *shost, unsigned long time);
-int mvs_queue_command(struct sas_task *task, const int num,
- gfp_t gfp_flags);
+int mvs_queue_command(struct sas_task *task, gfp_t gfp_flags);
int mvs_abort_task(struct sas_task *task);
int mvs_abort_task_set(struct domain_device *dev, u8 *lun);
int mvs_clear_aca(struct domain_device *dev, u8 *lun);
diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
index 9c331b7bfdcd..5b93ed810f6e 100644
--- a/drivers/scsi/ncr53c8xx.c
+++ b/drivers/scsi/ncr53c8xx.c
@@ -7997,7 +7997,7 @@ static int ncr53c8xx_slave_configure(struct scsi_device *device)
if (depth_to_use > MAX_TAGS)
depth_to_use = MAX_TAGS;
- scsi_adjust_queue_depth(device, depth_to_use);
+ scsi_change_queue_depth(device, depth_to_use);
/*
** Since the queue depth is not tunable under Linux,
diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c
index 80bacb5dc1d4..e81eadd08afc 100644
--- a/drivers/scsi/pas16.c
+++ b/drivers/scsi/pas16.c
@@ -1,6 +1,4 @@
-#define AUTOSENSE
#define PSEUDO_DMA
-#define FOO
#define UNSAFE /* Not unsafe for PAS16 -- use it */
#define PDEBUG 0
@@ -24,47 +22,9 @@
* Media Vision
* (510) 770-8600
* (800) 348-7116
- *
- * and
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
*/
/*
- * Options :
- * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
- * for commands that return with a CHECK CONDITION status.
- *
- * LIMIT_TRANSFERSIZE - if defined, limit the pseudo-dma transfers to 512
- * bytes at a time. Since interrupts are disabled by default during
- * these transfers, we might need this to give reasonable interrupt
- * service time if the transfer size gets too large.
- *
- * PSEUDO_DMA - enables PSEUDO-DMA hardware, should give a 3-4X performance
- * increase compared to polled I/O.
- *
- * PARITY - enable parity checking. Not supported.
- *
- * SCSI2 - enable support for SCSI-II tagged queueing. Untested.
- *
- * UNSAFE - leave interrupts enabled during pseudo-DMA transfers. This
- * parameter comes from the NCR5380 code. It is NOT unsafe with
- * the PAS16 and you should use it. If you don't you will have
- * a problem with dropped characters during high speed
- * communications during SCSI transfers. If you really don't
- * want to use UNSAFE you can try defining LIMIT_TRANSFERSIZE or
- * twiddle with the transfer size in the high level code.
- *
- * USLEEP - enable support for devices that don't disconnect. Untested.
- *
* The card is detected and initialized in one of several ways :
* 1. Autoprobe (default) - There are many different models of
* the Pro Audio Spectrum/Studio 16, and I only have one of
@@ -102,13 +62,11 @@
* If you have problems with your card not being recognized, use
* the LILO command line override. Try to get it recognized without
* interrupts. Ie, for a board at the default 0x388 base port,
- * boot: linux pas16=0x388,255
+ * boot: linux pas16=0x388,0
*
- * SCSI_IRQ_NONE (255) should be specified for no interrupt,
+ * NO_IRQ (0) should be specified for no interrupt,
* IRQ_AUTO (254) to autoprobe for an IRQ line if overridden
* on the command line.
- *
- * (IRQ_AUTO == 254, SCSI_IRQ_NONE == 255 in NCR5380.h)
*/
#include <linux/module.h>
@@ -123,15 +81,12 @@
#include <linux/stat.h>
#include <linux/init.h>
-#include "scsi.h"
#include <scsi/scsi_host.h>
#include "pas16.h"
#define AUTOPROBE_IRQ
#include "NCR5380.h"
-static int pas_maxi = 0;
-static int pas_wmaxi = 0;
static unsigned short pas16_addr = 0;
static int pas16_irq = 0;
@@ -337,6 +292,7 @@ static int __init
}
+#ifndef MODULE
/*
* Function : pas16_setup(char *str, int *ints)
*
@@ -347,10 +303,13 @@ static int __init
*
*/
-void __init pas16_setup(char *str, int *ints)
+static int __init pas16_setup(char *str)
{
static int commandline_current = 0;
int i;
+ int ints[10];
+
+ get_options(str, ARRAY_SIZE(ints), ints);
if (ints[0] != 2)
printk("pas16_setup : usage pas16=io_port,irq\n");
else
@@ -364,8 +323,12 @@ void __init pas16_setup(char *str, int *ints)
}
++commandline_current;
}
+ return 1;
}
+__setup("pas16=", pas16_setup);
+#endif
+
/*
* Function : int pas16_detect(struct scsi_host_template * tpnt)
*
@@ -379,7 +342,7 @@ void __init pas16_setup(char *str, int *ints)
*
*/
-int __init pas16_detect(struct scsi_host_template * tpnt)
+static int __init pas16_detect(struct scsi_host_template *tpnt)
{
static int current_override = 0;
static unsigned short current_base = 0;
@@ -387,10 +350,6 @@ int __init pas16_detect(struct scsi_host_template * tpnt)
unsigned short io_port;
int count;
- tpnt->proc_name = "pas16";
- tpnt->show_info = pas16_show_info;
- tpnt->write_info = pas16_write_info;
-
if (pas16_addr != 0) {
overrides[0].io_port = pas16_addr;
/*
@@ -452,15 +411,19 @@ int __init pas16_detect(struct scsi_host_template * tpnt)
else
instance->irq = NCR5380_probe_irq(instance, PAS16_IRQS);
- if (instance->irq != SCSI_IRQ_NONE)
+ /* Compatibility with documented NCR5380 kernel parameters */
+ if (instance->irq == 255)
+ instance->irq = NO_IRQ;
+
+ if (instance->irq != NO_IRQ)
if (request_irq(instance->irq, pas16_intr, 0,
"pas16", instance)) {
printk("scsi%d : IRQ%d not free, interrupts disabled\n",
instance->host_no, instance->irq);
- instance->irq = SCSI_IRQ_NONE;
+ instance->irq = NO_IRQ;
}
- if (instance->irq == SCSI_IRQ_NONE) {
+ if (instance->irq == NO_IRQ) {
printk("scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
printk("scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
/* Disable 5380 interrupts, leave drive params the same */
@@ -472,17 +435,6 @@ int __init pas16_detect(struct scsi_host_template * tpnt)
printk("scsi%d : irq = %d\n", instance->host_no, instance->irq);
#endif
- printk("scsi%d : at 0x%04x", instance->host_no, (int)
- instance->io_port);
- if (instance->irq == SCSI_IRQ_NONE)
- printk (" interrupts disabled");
- else
- printk (" irq %d", instance->irq);
- printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
- CAN_QUEUE, CMD_PER_LUN, PAS16_PUBLIC_RELEASE);
- NCR5380_print_options(instance);
- printk("\n");
-
++current_override;
++count;
}
@@ -509,8 +461,8 @@ int __init pas16_detect(struct scsi_host_template * tpnt)
* and matching the H_C_S coordinates to what DOS uses.
*/
-int pas16_biosparam(struct scsi_device *sdev, struct block_device *dev,
- sector_t capacity, int * ip)
+static int pas16_biosparam(struct scsi_device *sdev, struct block_device *dev,
+ sector_t capacity, int *ip)
{
int size = capacity;
ip[0] = 64;
@@ -547,6 +499,7 @@ static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst,
P_DATA_REG_OFFSET);
register int i = len;
int ii = 0;
+ struct NCR5380_hostdata *hostdata = shost_priv(instance);
while ( !(inb(instance->io_port + P_STATUS_REG_OFFSET) & P_ST_RDY) )
++ii;
@@ -559,8 +512,8 @@ static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst,
instance->host_no);
return -1;
}
- if (ii > pas_maxi)
- pas_maxi = ii;
+ if (ii > hostdata->spin_max_r)
+ hostdata->spin_max_r = ii;
return 0;
}
@@ -583,6 +536,7 @@ static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src
register unsigned short reg = (instance->io_port + P_DATA_REG_OFFSET);
register int i = len;
int ii = 0;
+ struct NCR5380_hostdata *hostdata = shost_priv(instance);
while ( !((inb(instance->io_port + P_STATUS_REG_OFFSET)) & P_ST_RDY) )
++ii;
@@ -595,8 +549,8 @@ static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src
instance->host_no);
return -1;
}
- if (ii > pas_maxi)
- pas_wmaxi = ii;
+ if (ii > hostdata->spin_max_w)
+ hostdata->spin_max_w = ii;
return 0;
}
@@ -604,7 +558,7 @@ static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src
static int pas16_release(struct Scsi_Host *shost)
{
- if (shost->irq)
+ if (shost->irq != NO_IRQ)
free_irq(shost->irq, shost);
NCR5380_exit(shost);
if (shost->io_port && shost->n_io_port)
@@ -617,6 +571,10 @@ static struct scsi_host_template driver_template = {
.name = "Pro Audio Spectrum-16 SCSI",
.detect = pas16_detect,
.release = pas16_release,
+ .proc_name = "pas16",
+ .show_info = pas16_show_info,
+ .write_info = pas16_write_info,
+ .info = pas16_info,
.queuecommand = pas16_queue_command,
.eh_abort_handler = pas16_abort,
.eh_bus_reset_handler = pas16_bus_reset,
diff --git a/drivers/scsi/pas16.h b/drivers/scsi/pas16.h
index aa528f53c533..c6109c80050b 100644
--- a/drivers/scsi/pas16.h
+++ b/drivers/scsi/pas16.h
@@ -18,26 +18,12 @@
* Media Vision
* (510) 770-8600
* (800) 348-7116
- *
- * and
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
*/
#ifndef PAS16_H
#define PAS16_H
-#define PAS16_PUBLIC_RELEASE 3
-
#define PDEBUG_INIT 0x1
#define PDEBUG_TRANSFER 0x2
@@ -114,12 +100,6 @@
#ifndef ASM
-static int pas16_abort(Scsi_Cmnd *);
-static int pas16_biosparam(struct scsi_device *, struct block_device *,
- sector_t, int*);
-static int pas16_detect(struct scsi_host_template *);
-static int pas16_queue_command(struct Scsi_Host *, struct scsi_cmnd *);
-static int pas16_bus_reset(Scsi_Cmnd *);
#ifndef CMD_PER_LUN
#define CMD_PER_LUN 2
@@ -161,6 +141,7 @@ static int pas16_bus_reset(Scsi_Cmnd *);
#define NCR5380_queue_command pas16_queue_command
#define NCR5380_abort pas16_abort
#define NCR5380_bus_reset pas16_bus_reset
+#define NCR5380_info pas16_info
#define NCR5380_show_info pas16_show_info
#define NCR5380_write_info pas16_write_info
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 3ff759a3b74d..329aba0083ab 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -90,6 +90,7 @@ static struct scsi_host_template pm8001_sht = {
.ioctl = sas_ioctl,
.shost_attrs = pm8001_host_attrs,
.use_blk_tags = 1,
+ .track_queue_depth = 1,
};
/**
@@ -600,8 +601,6 @@ static void pm8001_post_sas_ha_init(struct Scsi_Host *shost,
sha->lldd_module = THIS_MODULE;
sha->sas_addr = &pm8001_ha->sas_addr[0];
sha->num_phys = chip_info->n_phy;
- sha->lldd_max_execute_num = 1;
- sha->lldd_queue_size = PM8001_CAN_QUEUE;
sha->core.shost = shost;
}
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 76570e6a547d..b93f289b42b3 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -350,7 +350,7 @@ static int sas_find_local_port_id(struct domain_device *dev)
*/
#define DEV_IS_GONE(pm8001_dev) \
((!pm8001_dev || (pm8001_dev->dev_type == SAS_PHY_UNUSED)))
-static int pm8001_task_exec(struct sas_task *task, const int num,
+static int pm8001_task_exec(struct sas_task *task,
gfp_t gfp_flags, int is_tmf, struct pm8001_tmf_task *tmf)
{
struct domain_device *dev = task->dev;
@@ -360,7 +360,6 @@ static int pm8001_task_exec(struct sas_task *task, const int num,
struct sas_task *t = task;
struct pm8001_ccb_info *ccb;
u32 tag = 0xdeadbeef, rc, n_elem = 0;
- u32 n = num;
unsigned long flags = 0;
if (!dev->port) {
@@ -387,18 +386,12 @@ static int pm8001_task_exec(struct sas_task *task, const int num,
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
t->task_done(t);
spin_lock_irqsave(&pm8001_ha->lock, flags);
- if (n > 1)
- t = list_entry(t->list.next,
- struct sas_task, list);
continue;
} else {
struct task_status_struct *ts = &t->task_status;
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_PHY_DOWN;
t->task_done(t);
- if (n > 1)
- t = list_entry(t->list.next,
- struct sas_task, list);
continue;
}
}
@@ -460,9 +453,7 @@ static int pm8001_task_exec(struct sas_task *task, const int num,
t->task_state_flags |= SAS_TASK_AT_INITIATOR;
spin_unlock(&t->task_state_lock);
pm8001_dev->running_req++;
- if (n > 1)
- t = list_entry(t->list.next, struct sas_task, list);
- } while (--n);
+ } while (0);
rc = 0;
goto out_done;
@@ -483,14 +474,11 @@ out_done:
* pm8001_queue_command - register for upper layer used, all IO commands sent
* to HBA are from this interface.
* @task: the task to be execute.
- * @num: if can_queue great than 1, the task can be queued up. for SMP task,
- * we always execute one one time
* @gfp_flags: gfp_flags
*/
-int pm8001_queue_command(struct sas_task *task, const int num,
- gfp_t gfp_flags)
+int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags)
{
- return pm8001_task_exec(task, num, gfp_flags, 0, NULL);
+ return pm8001_task_exec(task, gfp_flags, 0, NULL);
}
/**
@@ -708,7 +696,7 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev,
task->slow_task->timer.expires = jiffies + PM8001_TASK_TIMEOUT*HZ;
add_timer(&task->slow_task->timer);
- res = pm8001_task_exec(task, 1, GFP_KERNEL, 1, tmf);
+ res = pm8001_task_exec(task, GFP_KERNEL, 1, tmf);
if (res) {
del_timer(&task->slow_task->timer);
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index f6b2ac59dae4..8dd8b7840f04 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -623,8 +623,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
void *funcdata);
void pm8001_scan_start(struct Scsi_Host *shost);
int pm8001_scan_finished(struct Scsi_Host *shost, unsigned long time);
-int pm8001_queue_command(struct sas_task *task, const int num,
- gfp_t gfp_flags);
+int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags);
int pm8001_abort_task(struct sas_task *task);
int pm8001_abort_task_set(struct domain_device *dev, u8 *lun);
int pm8001_clear_aca(struct domain_device *dev, u8 *lun);
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
index d8b9ba251fbd..b1b1f66b1ab7 100644
--- a/drivers/scsi/pmcraid.c
+++ b/drivers/scsi/pmcraid.c
@@ -285,23 +285,15 @@ static void pmcraid_slave_destroy(struct scsi_device *scsi_dev)
* pmcraid_change_queue_depth - Change the device's queue depth
* @scsi_dev: scsi device struct
* @depth: depth to set
- * @reason: calling context
*
* Return value
* actual depth set
*/
-static int pmcraid_change_queue_depth(struct scsi_device *scsi_dev, int depth,
- int reason)
+static int pmcraid_change_queue_depth(struct scsi_device *scsi_dev, int depth)
{
- if (reason != SCSI_QDEPTH_DEFAULT)
- return -EOPNOTSUPP;
-
if (depth > PMCRAID_MAX_CMD_PER_LUN)
depth = PMCRAID_MAX_CMD_PER_LUN;
-
- scsi_adjust_queue_depth(scsi_dev, depth);
-
- return scsi_dev->queue_depth;
+ return scsi_change_queue_depth(scsi_dev, depth);
}
/**
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index adedb6ef8eec..c68a66e8cfc1 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -1224,9 +1224,9 @@ qla1280_slave_configure(struct scsi_device *device)
if (device->tagged_supported &&
(ha->bus_settings[bus].qtag_enables & (BIT_0 << target))) {
- scsi_adjust_queue_depth(device, ha->bus_settings[bus].hiwat);
+ scsi_change_queue_depth(device, ha->bus_settings[bus].hiwat);
} else {
- scsi_adjust_queue_depth(device, default_depth);
+ scsi_change_queue_depth(device, default_depth);
}
nv->bus[bus].target[target].parameter.enable_sync = device->sdtr;
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index b1865a72ce59..7686bfe9a4a9 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -752,8 +752,6 @@ extern void qla8044_set_idc_dontreset(struct scsi_qla_host *ha);
extern int qla8044_rd_direct(struct scsi_qla_host *vha, const uint32_t crb_reg);
extern void qla8044_wr_direct(struct scsi_qla_host *vha,
const uint32_t crb_reg, const uint32_t value);
-extern inline void qla8044_set_qsnt_ready(struct scsi_qla_host *vha);
-extern inline void qla8044_need_reset_handler(struct scsi_qla_host *vha);
extern int qla8044_device_state_handler(struct scsi_qla_host *vha);
extern void qla8044_clear_qsnt_ready(struct scsi_qla_host *vha);
extern void qla8044_clear_drv_active(struct qla_hw_data *);
diff --git a/drivers/scsi/qla2xxx/qla_nx2.c b/drivers/scsi/qla2xxx/qla_nx2.c
index 24a852828b5d..ed4d6b6b53e3 100644
--- a/drivers/scsi/qla2xxx/qla_nx2.c
+++ b/drivers/scsi/qla2xxx/qla_nx2.c
@@ -238,7 +238,7 @@ qla8044_rmw_crb_reg(struct scsi_qla_host *vha,
return;
}
-inline void
+static inline void
qla8044_set_qsnt_ready(struct scsi_qla_host *vha)
{
uint32_t qsnt_state;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 33166ebec7d8..6b4d9235368a 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -236,7 +236,6 @@ static int qla2xxx_eh_target_reset(struct scsi_cmnd *);
static int qla2xxx_eh_bus_reset(struct scsi_cmnd *);
static int qla2xxx_eh_host_reset(struct scsi_cmnd *);
-static int qla2x00_change_queue_depth(struct scsi_device *, int, int);
static void qla2x00_clear_drv_active(struct qla_hw_data *);
static void qla2x00_free_device(scsi_qla_host_t *);
static void qla83xx_disable_laser(scsi_qla_host_t *vha);
@@ -258,7 +257,7 @@ struct scsi_host_template qla2xxx_driver_template = {
.slave_destroy = qla2xxx_slave_destroy,
.scan_finished = qla2xxx_scan_finished,
.scan_start = qla2xxx_scan_start,
- .change_queue_depth = qla2x00_change_queue_depth,
+ .change_queue_depth = scsi_change_queue_depth,
.change_queue_type = scsi_change_queue_type,
.this_id = -1,
.cmd_per_lun = 3,
@@ -270,6 +269,7 @@ struct scsi_host_template qla2xxx_driver_template = {
.supported_mode = MODE_INITIATOR,
.use_blk_tags = 1,
+ .track_queue_depth = 1,
};
static struct scsi_transport_template *qla2xxx_transport_template = NULL;
@@ -1405,7 +1405,7 @@ qla2xxx_slave_configure(struct scsi_device *sdev)
if (IS_T10_PI_CAPABLE(vha->hw))
blk_queue_update_dma_alignment(sdev->request_queue, 0x7);
- scsi_adjust_queue_depth(sdev, req->max_q_depth);
+ scsi_change_queue_depth(sdev, req->max_q_depth);
return 0;
}
@@ -1415,58 +1415,6 @@ qla2xxx_slave_destroy(struct scsi_device *sdev)
sdev->hostdata = NULL;
}
-static void qla2x00_handle_queue_full(struct scsi_device *sdev, int qdepth)
-{
- fc_port_t *fcport = (struct fc_port *) sdev->hostdata;
-
- if (!scsi_track_queue_full(sdev, qdepth))
- return;
-
- ql_dbg(ql_dbg_io, fcport->vha, 0x3029,
- "Queue depth adjusted-down to %d for nexus=%ld:%d:%llu.\n",
- sdev->queue_depth, fcport->vha->host_no, sdev->id, sdev->lun);
-}
-
-static void qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, int qdepth)
-{
- fc_port_t *fcport = sdev->hostdata;
- struct scsi_qla_host *vha = fcport->vha;
- struct req_que *req = NULL;
-
- req = vha->req;
- if (!req)
- return;
-
- if (req->max_q_depth <= sdev->queue_depth || req->max_q_depth < qdepth)
- return;
-
- scsi_adjust_queue_depth(sdev, qdepth);
-
- ql_dbg(ql_dbg_io, vha, 0x302a,
- "Queue depth adjusted-up to %d for nexus=%ld:%d:%llu.\n",
- sdev->queue_depth, fcport->vha->host_no, sdev->id, sdev->lun);
-}
-
-static int
-qla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
-{
- switch (reason) {
- case SCSI_QDEPTH_DEFAULT:
- scsi_adjust_queue_depth(sdev, qdepth);
- break;
- case SCSI_QDEPTH_QFULL:
- qla2x00_handle_queue_full(sdev, qdepth);
- break;
- case SCSI_QDEPTH_RAMP_UP:
- qla2x00_adjust_sdev_qdepth_up(sdev, qdepth);
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- return sdev->queue_depth;
-}
-
/**
* qla2x00_config_dma_addressing() - Configure OS DMA addressing method.
* @ha: HA context
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index f8724f2e0158..6d25879d87c8 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -164,8 +164,6 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd);
static int qla4xxx_slave_alloc(struct scsi_device *device);
static umode_t qla4_attr_is_visible(int param_type, int param);
static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type);
-static int qla4xxx_change_queue_depth(struct scsi_device *sdev, int qdepth,
- int reason);
/*
* iSCSI Flash DDB sysfs entry points
@@ -203,7 +201,7 @@ static struct scsi_host_template qla4xxx_driver_template = {
.eh_timed_out = qla4xxx_eh_cmd_timed_out,
.slave_alloc = qla4xxx_slave_alloc,
- .change_queue_depth = qla4xxx_change_queue_depth,
+ .change_queue_depth = scsi_change_queue_depth,
.this_id = -1,
.cmd_per_lun = 3,
@@ -9061,19 +9059,10 @@ static int qla4xxx_slave_alloc(struct scsi_device *sdev)
if (ql4xmaxqdepth != 0 && ql4xmaxqdepth <= 0xffffU)
queue_depth = ql4xmaxqdepth;
- scsi_adjust_queue_depth(sdev, queue_depth);
+ scsi_change_queue_depth(sdev, queue_depth);
return 0;
}
-static int qla4xxx_change_queue_depth(struct scsi_device *sdev, int qdepth,
- int reason)
-{
- if (!ql4xqfulltracking)
- return -EOPNOTSUPP;
-
- return iscsi_change_queue_depth(sdev, qdepth, reason);
-}
-
/**
* qla4xxx_del_from_active_array - returns an active srb
* @ha: Pointer to host adapter structure.
@@ -9873,6 +9862,9 @@ static int __init qla4xxx_module_init(void)
{
int ret;
+ if (ql4xqfulltracking)
+ qla4xxx_driver_template.track_queue_depth = 1;
+
/* Allocate cache for SRBs. */
srb_cachep = kmem_cache_create("qla4xxx_srbs", sizeof(struct srb), 0,
SLAB_HWCACHE_ALIGN, NULL);
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 2d9730432233..1ad0c36375b8 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -661,30 +661,18 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
}
/**
- * scsi_adjust_queue_depth - Let low level drivers change a device's queue depth
+ * scsi_change_queue_depth - change a device's queue depth
* @sdev: SCSI Device in question
- * @tags: Number of tags allowed if tagged queueing enabled,
- * or number of commands the low level driver can
- * queue up in non-tagged mode (as per cmd_per_lun).
+ * @depth: number of commands allowed to be queued to the driver
*
- * Returns: Nothing
- *
- * Lock Status: None held on entry
- *
- * Notes: Low level drivers may call this at any time and we will do
- * the right thing depending on whether or not the device is
- * currently active and whether or not it even has the
- * command blocks built yet.
+ * Sets the device queue depth and returns the new value.
*/
-void scsi_adjust_queue_depth(struct scsi_device *sdev, int tags)
+int scsi_change_queue_depth(struct scsi_device *sdev, int depth)
{
unsigned long flags;
- /*
- * refuse to set tagged depth to an unworkable size
- */
- if (tags <= 0)
- return;
+ if (depth <= 0)
+ goto out;
spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
@@ -699,15 +687,17 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tags)
*/
if (!shost_use_blk_mq(sdev->host) && !sdev->host->bqt) {
if (blk_queue_tagged(sdev->request_queue) &&
- blk_queue_resize_tags(sdev->request_queue, tags) != 0)
- goto out;
+ blk_queue_resize_tags(sdev->request_queue, depth) != 0)
+ goto out_unlock;
}
- sdev->queue_depth = tags;
- out:
+ sdev->queue_depth = depth;
+out_unlock:
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
+out:
+ return sdev->queue_depth;
}
-EXPORT_SYMBOL(scsi_adjust_queue_depth);
+EXPORT_SYMBOL(scsi_change_queue_depth);
/**
* scsi_track_queue_full - track QUEUE_FULL events to adjust queue depth
@@ -752,12 +742,11 @@ int scsi_track_queue_full(struct scsi_device *sdev, int depth)
if (sdev->last_queue_full_depth < 8) {
/* Drop back to untagged */
scsi_set_tag_type(sdev, 0);
- scsi_adjust_queue_depth(sdev, sdev->host->cmd_per_lun);
+ scsi_change_queue_depth(sdev, sdev->host->cmd_per_lun);
return -1;
}
- scsi_adjust_queue_depth(sdev, depth);
- return depth;
+ return scsi_change_queue_depth(sdev, depth);
}
EXPORT_SYMBOL(scsi_track_queue_full);
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 378e0aae29ca..aa4b6b80aade 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -63,8 +63,8 @@
#include "sd.h"
#include "scsi_logging.h"
-#define SCSI_DEBUG_VERSION "1.84"
-static const char *scsi_debug_version_date = "20140706";
+#define SCSI_DEBUG_VERSION "1.85"
+static const char *scsi_debug_version_date = "20141022";
#define MY_NAME "scsi_debug"
@@ -75,19 +75,22 @@ static const char *scsi_debug_version_date = "20140706";
#define UNRECOVERED_READ_ERR 0x11
#define PARAMETER_LIST_LENGTH_ERR 0x1a
#define INVALID_OPCODE 0x20
-#define ADDR_OUT_OF_RANGE 0x21
-#define INVALID_COMMAND_OPCODE 0x20
+#define LBA_OUT_OF_RANGE 0x21
#define INVALID_FIELD_IN_CDB 0x24
#define INVALID_FIELD_IN_PARAM_LIST 0x26
#define UA_RESET_ASC 0x29
#define UA_CHANGED_ASC 0x2a
+#define INSUFF_RES_ASC 0x55
+#define INSUFF_RES_ASCQ 0x3
#define POWER_ON_RESET_ASCQ 0x0
#define BUS_RESET_ASCQ 0x2 /* scsi bus reset occurred */
#define MODE_CHANGED_ASCQ 0x1 /* mode parameters changed */
+#define CAPACITY_CHANGED_ASCQ 0x9
#define SAVING_PARAMS_UNSUP 0x39
#define TRANSPORT_PROBLEM 0x4b
#define THRESHOLD_EXCEEDED 0x5d
#define LOW_POWER_COND_ON 0x5e
+#define MISCOMPARE_VERIFY_ASC 0x1d
/* Additional Sense Code Qualifier (ASCQ) */
#define ACK_NAK_TO 0x3
@@ -133,6 +136,7 @@ static const char *scsi_debug_version_date = "20140706";
#define DEF_VIRTUAL_GB 0
#define DEF_VPD_USE_HOSTNO 1
#define DEF_WRITESAME_LENGTH 0xFFFF
+#define DEF_STRICT 0
#define DELAY_OVERRIDDEN -9999
/* bit mask values for scsi_debug_opts */
@@ -176,11 +180,12 @@ static const char *scsi_debug_version_date = "20140706";
#define SDEBUG_UA_POR 0 /* Power on, reset, or bus device reset */
#define SDEBUG_UA_BUS_RESET 1
#define SDEBUG_UA_MODE_CHANGED 2
-#define SDEBUG_NUM_UAS 3
+#define SDEBUG_UA_CAPACITY_CHANGED 3
+#define SDEBUG_NUM_UAS 4
/* for check_readiness() */
-#define UAS_ONLY 1
-#define UAS_TUR 0
+#define UAS_ONLY 1 /* check for UAs only */
+#define UAS_TUR 0 /* if no UAs then check if media access possible */
/* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this
* sector on read commands: */
@@ -206,6 +211,301 @@ static const char *scsi_debug_version_date = "20140706";
#warning "Expect DEF_CMD_PER_LUN <= SCSI_DEBUG_CANQUEUE"
#endif
+/* SCSI opcodes (first byte of cdb) mapped onto these indexes */
+enum sdeb_opcode_index {
+ SDEB_I_INVALID_OPCODE = 0,
+ SDEB_I_INQUIRY = 1,
+ SDEB_I_REPORT_LUNS = 2,
+ SDEB_I_REQUEST_SENSE = 3,
+ SDEB_I_TEST_UNIT_READY = 4,
+ SDEB_I_MODE_SENSE = 5, /* 6, 10 */
+ SDEB_I_MODE_SELECT = 6, /* 6, 10 */
+ SDEB_I_LOG_SENSE = 7,
+ SDEB_I_READ_CAPACITY = 8, /* 10; 16 is in SA_IN(16) */
+ SDEB_I_READ = 9, /* 6, 10, 12, 16 */
+ SDEB_I_WRITE = 10, /* 6, 10, 12, 16 */
+ SDEB_I_START_STOP = 11,
+ SDEB_I_SERV_ACT_IN = 12, /* 12, 16 */
+ SDEB_I_SERV_ACT_OUT = 13, /* 12, 16 */
+ SDEB_I_MAINT_IN = 14,
+ SDEB_I_MAINT_OUT = 15,
+ SDEB_I_VERIFY = 16, /* 10 only */
+ SDEB_I_VARIABLE_LEN = 17,
+ SDEB_I_RESERVE = 18, /* 6, 10 */
+ SDEB_I_RELEASE = 19, /* 6, 10 */
+ SDEB_I_ALLOW_REMOVAL = 20, /* PREVENT ALLOW MEDIUM REMOVAL */
+ SDEB_I_REZERO_UNIT = 21, /* REWIND in SSC */
+ SDEB_I_ATA_PT = 22, /* 12, 16 */
+ SDEB_I_SEND_DIAG = 23,
+ SDEB_I_UNMAP = 24,
+ SDEB_I_XDWRITEREAD = 25, /* 10 only */
+ SDEB_I_WRITE_BUFFER = 26,
+ SDEB_I_WRITE_SAME = 27, /* 10, 16 */
+ SDEB_I_SYNC_CACHE = 28, /* 10 only */
+ SDEB_I_COMP_WRITE = 29,
+ SDEB_I_LAST_ELEMENT = 30, /* keep this last */
+};
+
+static const unsigned char opcode_ind_arr[256] = {
+/* 0x0; 0x0->0x1f: 6 byte cdbs */
+ SDEB_I_TEST_UNIT_READY, SDEB_I_REZERO_UNIT, 0, SDEB_I_REQUEST_SENSE,
+ 0, 0, 0, 0,
+ SDEB_I_READ, 0, SDEB_I_WRITE, 0, 0, 0, 0, 0,
+ 0, 0, SDEB_I_INQUIRY, 0, 0, SDEB_I_MODE_SELECT, SDEB_I_RESERVE,
+ SDEB_I_RELEASE,
+ 0, 0, SDEB_I_MODE_SENSE, SDEB_I_START_STOP, 0, SDEB_I_SEND_DIAG,
+ SDEB_I_ALLOW_REMOVAL, 0,
+/* 0x20; 0x20->0x3f: 10 byte cdbs */
+ 0, 0, 0, 0, 0, SDEB_I_READ_CAPACITY, 0, 0,
+ SDEB_I_READ, 0, SDEB_I_WRITE, 0, 0, 0, 0, SDEB_I_VERIFY,
+ 0, 0, 0, 0, 0, SDEB_I_SYNC_CACHE, 0, 0,
+ 0, 0, 0, SDEB_I_WRITE_BUFFER, 0, 0, 0, 0,
+/* 0x40; 0x40->0x5f: 10 byte cdbs */
+ 0, SDEB_I_WRITE_SAME, SDEB_I_UNMAP, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, SDEB_I_LOG_SENSE, 0, 0,
+ 0, 0, 0, SDEB_I_XDWRITEREAD, 0, SDEB_I_MODE_SELECT, SDEB_I_RESERVE,
+ SDEB_I_RELEASE,
+ 0, 0, SDEB_I_MODE_SENSE, 0, 0, 0, 0, 0,
+/* 0x60; 0x60->0x7d are reserved */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, SDEB_I_VARIABLE_LEN,
+/* 0x80; 0x80->0x9f: 16 byte cdbs */
+ 0, 0, 0, 0, 0, SDEB_I_ATA_PT, 0, 0,
+ SDEB_I_READ, SDEB_I_COMP_WRITE, SDEB_I_WRITE, 0, 0, 0, 0, 0,
+ 0, 0, 0, SDEB_I_WRITE_SAME, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, SDEB_I_SERV_ACT_IN, SDEB_I_SERV_ACT_OUT,
+/* 0xa0; 0xa0->0xbf: 12 byte cdbs */
+ SDEB_I_REPORT_LUNS, SDEB_I_ATA_PT, 0, SDEB_I_MAINT_IN,
+ SDEB_I_MAINT_OUT, 0, 0, 0,
+ SDEB_I_READ, SDEB_I_SERV_ACT_OUT, SDEB_I_WRITE, SDEB_I_SERV_ACT_IN,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 0xc0; 0xc0->0xff: vendor specific */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+#define F_D_IN 1
+#define F_D_OUT 2
+#define F_D_OUT_MAYBE 4 /* WRITE SAME, NDOB bit */
+#define F_D_UNKN 8
+#define F_RL_WLUN_OK 0x10
+#define F_SKIP_UA 0x20
+#define F_DELAY_OVERR 0x40
+#define F_SA_LOW 0x80 /* cdb byte 1, bits 4 to 0 */
+#define F_SA_HIGH 0x100 /* as used by variable length cdbs */
+#define F_INV_OP 0x200
+#define F_FAKE_RW 0x400
+#define F_M_ACCESS 0x800 /* media access */
+
+#define FF_RESPOND (F_RL_WLUN_OK | F_SKIP_UA | F_DELAY_OVERR)
+#define FF_DIRECT_IO (F_M_ACCESS | F_FAKE_RW)
+#define FF_SA (F_SA_HIGH | F_SA_LOW)
+
+struct sdebug_dev_info;
+static int resp_inquiry(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_report_luns(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_requests(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_mode_sense(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_mode_select(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_log_sense(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_readcap(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_read_dt0(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_write_dt0(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_start_stop(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_readcap16(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_get_lba_status(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_report_tgtpgs(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_unmap(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_rsup_opcodes(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_rsup_tmfs(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_write_same_10(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_write_same_16(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_xdwriteread_10(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_comp_write(struct scsi_cmnd *, struct sdebug_dev_info *);
+
+struct opcode_info_t {
+ u8 num_attached; /* 0 if this is it (i.e. a leaf); use 0xff
+ * for terminating element */
+ u8 opcode; /* if num_attached > 0, preferred */
+ u16 sa; /* service action */
+ u32 flags; /* OR-ed set of SDEB_F_* */
+ int (*pfp)(struct scsi_cmnd *, struct sdebug_dev_info *);
+ const struct opcode_info_t *arrp; /* num_attached elements or NULL */
+ u8 len_mask[16]; /* len=len_mask[0], then mask for cdb[1]... */
+ /* ignore cdb bytes after position 15 */
+};
+
+static const struct opcode_info_t msense_iarr[1] = {
+ {0, 0x1a, 0, F_D_IN, NULL, NULL,
+ {6, 0xe8, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+};
+
+static const struct opcode_info_t mselect_iarr[1] = {
+ {0, 0x15, 0, F_D_OUT, NULL, NULL,
+ {6, 0xf1, 0, 0, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+};
+
+static const struct opcode_info_t read_iarr[3] = {
+ {0, 0x28, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, NULL,/* READ(10) */
+ {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, 0, 0,
+ 0, 0, 0, 0} },
+ {0, 0x8, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, NULL, /* READ(6) */
+ {6, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {0, 0xa8, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, NULL,/* READ(12) */
+ {12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f,
+ 0xc7, 0, 0, 0, 0} },
+};
+
+static const struct opcode_info_t write_iarr[3] = {
+ {0, 0x2a, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, NULL, /* 10 */
+ {10, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, 0, 0,
+ 0, 0, 0, 0} },
+ {0, 0xa, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, NULL, /* 6 */
+ {6, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {0, 0xaa, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, NULL, /* 12 */
+ {12, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f,
+ 0xc7, 0, 0, 0, 0} },
+};
+
+static const struct opcode_info_t sa_in_iarr[1] = {
+ {0, 0x9e, 0x12, F_SA_LOW | F_D_IN, resp_get_lba_status, NULL,
+ {16, 0x12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0, 0xc7} },
+};
+
+static const struct opcode_info_t vl_iarr[1] = { /* VARIABLE LENGTH */
+ {0, 0x7f, 0xb, F_SA_HIGH | F_D_OUT | FF_DIRECT_IO, resp_write_dt0,
+ NULL, {32, 0xc7, 0, 0, 0, 0, 0x1f, 0x18, 0x0, 0xb, 0xfa,
+ 0, 0xff, 0xff, 0xff, 0xff} }, /* WRITE(32) */
+};
+
+static const struct opcode_info_t maint_in_iarr[2] = {
+ {0, 0xa3, 0xc, F_SA_LOW | F_D_IN, resp_rsup_opcodes, NULL,
+ {12, 0xc, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0,
+ 0xc7, 0, 0, 0, 0} },
+ {0, 0xa3, 0xd, F_SA_LOW | F_D_IN, resp_rsup_tmfs, NULL,
+ {12, 0xd, 0x80, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0,
+ 0, 0} },
+};
+
+static const struct opcode_info_t write_same_iarr[1] = {
+ {0, 0x93, 0, F_D_OUT_MAYBE | FF_DIRECT_IO, resp_write_same_16, NULL,
+ {16, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x1f, 0xc7} },
+};
+
+static const struct opcode_info_t reserve_iarr[1] = {
+ {0, 0x16, 0, F_D_OUT, NULL, NULL, /* RESERVE(6) */
+ {6, 0x1f, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+};
+
+static const struct opcode_info_t release_iarr[1] = {
+ {0, 0x17, 0, F_D_OUT, NULL, NULL, /* RELEASE(6) */
+ {6, 0x1f, 0xff, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+};
+
+
+/* This array is accessed via SDEB_I_* values. Make sure all are mapped,
+ * plus the terminating elements for logic that scans this table such as
+ * REPORT SUPPORTED OPERATION CODES. */
+static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEMENT + 1] = {
+/* 0 */
+ {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL,
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {0, 0x12, 0, FF_RESPOND | F_D_IN, resp_inquiry, NULL,
+ {6, 0xe3, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {0, 0xa0, 0, FF_RESPOND | F_D_IN, resp_report_luns, NULL,
+ {12, 0xe3, 0xff, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0,
+ 0, 0} },
+ {0, 0x3, 0, FF_RESPOND | F_D_IN, resp_requests, NULL,
+ {6, 0xe1, 0, 0, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {0, 0x0, 0, F_M_ACCESS | F_RL_WLUN_OK, NULL, NULL,/* TEST UNIT READY */
+ {6, 0, 0, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {1, 0x5a, 0, F_D_IN, resp_mode_sense, msense_iarr,
+ {10, 0xf8, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0,
+ 0} },
+ {1, 0x55, 0, F_D_OUT, resp_mode_select, mselect_iarr,
+ {10, 0xf1, 0, 0, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0} },
+ {0, 0x4d, 0, F_D_IN, resp_log_sense, NULL,
+ {10, 0xe3, 0xff, 0xff, 0, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0,
+ 0, 0, 0} },
+ {0, 0x25, 0, F_D_IN, resp_readcap, NULL,
+ {10, 0xe1, 0xff, 0xff, 0xff, 0xff, 0, 0, 0x1, 0xc7, 0, 0, 0, 0,
+ 0, 0} },
+ {3, 0x88, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, read_iarr,
+ {16, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x9f, 0xc7} }, /* READ(16) */
+/* 10 */
+ {3, 0x8a, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, write_iarr,
+ {16, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x9f, 0xc7} }, /* WRITE(16) */
+ {0, 0x1b, 0, 0, resp_start_stop, NULL, /* START STOP UNIT */
+ {6, 0x1, 0, 0xf, 0xf7, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {1, 0x9e, 0x10, F_SA_LOW | F_D_IN, resp_readcap16, sa_in_iarr,
+ {16, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x1, 0xc7} }, /* READ CAPACITY(16) */
+ {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* SA OUT */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {2, 0xa3, 0xa, F_SA_LOW | F_D_IN, resp_report_tgtpgs, maint_in_iarr,
+ {12, 0xea, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0, 0,
+ 0} },
+ {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* MAINT OUT */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* VERIFY */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {1, 0x7f, 0x9, F_SA_HIGH | F_D_IN | FF_DIRECT_IO, resp_read_dt0,
+ vl_iarr, {32, 0xc7, 0, 0, 0, 0, 0x1f, 0x18, 0x0, 0x9, 0xfe, 0,
+ 0xff, 0xff, 0xff, 0xff} },/* VARIABLE LENGTH, READ(32) */
+ {1, 0x56, 0, F_D_OUT, NULL, reserve_iarr, /* RESERVE(10) */
+ {10, 0xff, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0,
+ 0} },
+ {1, 0x57, 0, F_D_OUT, NULL, release_iarr, /* RELEASE(10) */
+ {10, 0x13, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0,
+ 0} },
+/* 20 */
+ {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* ALLOW REMOVAL */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {0, 0x1, 0, 0, resp_start_stop, NULL, /* REWIND ?? */
+ {6, 0x1, 0, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* ATA_PT */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {0, 0x1d, F_D_OUT, 0, NULL, NULL, /* SEND DIAGNOSTIC */
+ {6, 0xf7, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {0, 0x42, 0, F_D_OUT | FF_DIRECT_IO, resp_unmap, NULL, /* UNMAP */
+ {10, 0x1, 0, 0, 0, 0, 0x1f, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0} },
+ {0, 0x53, 0, F_D_IN | F_D_OUT | FF_DIRECT_IO, resp_xdwriteread_10,
+ NULL, {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7,
+ 0, 0, 0, 0, 0, 0} },
+ {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* WRITE_BUFFER */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {1, 0x41, 0, F_D_OUT_MAYBE | FF_DIRECT_IO, resp_write_same_10,
+ write_same_iarr, {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff,
+ 0xff, 0xc7, 0, 0, 0, 0, 0, 0} },
+ {0, 0x35, 0, F_DELAY_OVERR | FF_DIRECT_IO, NULL, NULL, /* SYNC_CACHE */
+ {10, 0x7, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, 0, 0,
+ 0, 0, 0, 0} },
+ {0, 0x89, 0, F_D_OUT | FF_DIRECT_IO, resp_comp_write, NULL,
+ {16, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0,
+ 0, 0xff, 0x1f, 0xc7} }, /* COMPARE AND WRITE */
+
+/* 30 */
+ {0xff, 0, 0, 0, NULL, NULL, /* terminating element */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+};
+
+struct sdebug_scmd_extra_t {
+ bool inj_recovered;
+ bool inj_transport;
+ bool inj_dif;
+ bool inj_dix;
+ bool inj_short;
+};
+
static int scsi_debug_add_host = DEF_NUM_HOST;
static int scsi_debug_ato = DEF_ATO;
static int scsi_debug_delay = DEF_DELAY;
@@ -245,6 +545,8 @@ static unsigned int scsi_debug_write_same_length = DEF_WRITESAME_LENGTH;
static bool scsi_debug_removable = DEF_REMOVABLE;
static bool scsi_debug_clustering;
static bool scsi_debug_host_lock = DEF_HOST_LOCK;
+static bool scsi_debug_strict = DEF_STRICT;
+static bool sdebug_any_injecting_opt;
static atomic_t sdebug_cmnd_count;
static atomic_t sdebug_completions;
@@ -277,11 +579,10 @@ struct sdebug_dev_info {
unsigned int target;
u64 lun;
struct sdebug_host_info *sdbg_host;
- u64 wlun;
unsigned long uas_bm[1];
atomic_t num_in_q;
- char stopped;
- char used;
+ char stopped; /* TODO: should be atomic */
+ bool used;
};
struct sdebug_host_info {
@@ -394,6 +695,50 @@ static void sdebug_max_tgts_luns(void)
spin_unlock(&sdebug_host_list_lock);
}
+enum sdeb_cmd_data {SDEB_IN_DATA = 0, SDEB_IN_CDB = 1};
+
+/* Set in_bit to -1 to indicate no bit position of invalid field */
+static void
+mk_sense_invalid_fld(struct scsi_cmnd *scp, enum sdeb_cmd_data c_d,
+ int in_byte, int in_bit)
+{
+ unsigned char *sbuff;
+ u8 sks[4];
+ int sl, asc;
+
+ sbuff = scp->sense_buffer;
+ if (!sbuff) {
+ sdev_printk(KERN_ERR, scp->device,
+ "%s: sense_buffer is NULL\n", __func__);
+ return;
+ }
+ asc = c_d ? INVALID_FIELD_IN_CDB : INVALID_FIELD_IN_PARAM_LIST;
+ memset(sbuff, 0, SCSI_SENSE_BUFFERSIZE);
+ scsi_build_sense_buffer(scsi_debug_dsense, sbuff, ILLEGAL_REQUEST,
+ asc, 0);
+ memset(sks, 0, sizeof(sks));
+ sks[0] = 0x80;
+ if (c_d)
+ sks[0] |= 0x40;
+ if (in_bit >= 0) {
+ sks[0] |= 0x8;
+ sks[0] |= 0x7 & in_bit;
+ }
+ put_unaligned_be16(in_byte, sks + 1);
+ if (scsi_debug_dsense) {
+ sl = sbuff[7] + 8;
+ sbuff[7] = sl;
+ sbuff[sl] = 0x2;
+ sbuff[sl + 1] = 0x6;
+ memcpy(sbuff + sl + 4, sks, 3);
+ } else
+ memcpy(sbuff + 15, sks, 3);
+ if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+ sdev_printk(KERN_INFO, scp->device, "%s: [sense_key,asc,ascq"
+ "]: [0x5,0x%x,0x0] %c byte=%d, bit=%d\n",
+ my_name, asc, c_d ? 'C' : 'D', in_byte, in_bit);
+}
+
static void mk_sense_buffer(struct scsi_cmnd *scp, int key, int asc, int asq)
{
unsigned char *sbuff;
@@ -414,63 +759,10 @@ static void mk_sense_buffer(struct scsi_cmnd *scp, int key, int asc, int asq)
my_name, key, asc, asq);
}
-static void get_data_transfer_info(unsigned char *cmd,
- unsigned long long *lba, unsigned int *num,
- u32 *ei_lba)
+static void
+mk_sense_invalid_opcode(struct scsi_cmnd *scp)
{
- *ei_lba = 0;
-
- switch (*cmd) {
- case VARIABLE_LENGTH_CMD:
- *lba = (u64)cmd[19] | (u64)cmd[18] << 8 |
- (u64)cmd[17] << 16 | (u64)cmd[16] << 24 |
- (u64)cmd[15] << 32 | (u64)cmd[14] << 40 |
- (u64)cmd[13] << 48 | (u64)cmd[12] << 56;
-
- *ei_lba = (u32)cmd[23] | (u32)cmd[22] << 8 |
- (u32)cmd[21] << 16 | (u32)cmd[20] << 24;
-
- *num = (u32)cmd[31] | (u32)cmd[30] << 8 | (u32)cmd[29] << 16 |
- (u32)cmd[28] << 24;
- break;
-
- case WRITE_SAME_16:
- case WRITE_16:
- case READ_16:
- *lba = (u64)cmd[9] | (u64)cmd[8] << 8 |
- (u64)cmd[7] << 16 | (u64)cmd[6] << 24 |
- (u64)cmd[5] << 32 | (u64)cmd[4] << 40 |
- (u64)cmd[3] << 48 | (u64)cmd[2] << 56;
-
- *num = (u32)cmd[13] | (u32)cmd[12] << 8 | (u32)cmd[11] << 16 |
- (u32)cmd[10] << 24;
- break;
- case WRITE_12:
- case READ_12:
- *lba = (u32)cmd[5] | (u32)cmd[4] << 8 | (u32)cmd[3] << 16 |
- (u32)cmd[2] << 24;
-
- *num = (u32)cmd[9] | (u32)cmd[8] << 8 | (u32)cmd[7] << 16 |
- (u32)cmd[6] << 24;
- break;
- case WRITE_SAME:
- case WRITE_10:
- case READ_10:
- case XDWRITEREAD_10:
- *lba = (u32)cmd[5] | (u32)cmd[4] << 8 | (u32)cmd[3] << 16 |
- (u32)cmd[2] << 24;
-
- *num = (u32)cmd[8] | (u32)cmd[7] << 8;
- break;
- case WRITE_6:
- case READ_6:
- *lba = (u32)cmd[3] | (u32)cmd[2] << 8 |
- (u32)(cmd[1] & 0x1f) << 16;
- *num = (0 == cmd[4]) ? 256 : cmd[4];
- break;
- default:
- break;
- }
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_OPCODE, 0);
}
static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
@@ -520,6 +812,11 @@ static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only,
if (debug)
cp = "mode parameters changed";
break;
+ case SDEBUG_UA_CAPACITY_CHANGED:
+ mk_sense_buffer(SCpnt, UNIT_ATTENTION,
+ UA_CHANGED_ASC, CAPACITY_CHANGED_ASCQ);
+ if (debug)
+ cp = "capacity data changed";
default:
pr_warn("%s: unexpected unit attention code=%d\n",
__func__, k);
@@ -924,19 +1221,20 @@ static int inquiry_evpd_b2(unsigned char *arr)
#define SDEBUG_LONG_INQ_SZ 96
#define SDEBUG_MAX_INQ_ARR_SZ 584
-static int resp_inquiry(struct scsi_cmnd *scp, int target,
- struct sdebug_dev_info * devip)
+static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
{
unsigned char pq_pdt;
unsigned char * arr;
unsigned char *cmd = scp->cmnd;
int alloc_len, n, ret;
+ bool have_wlun;
alloc_len = (cmd[3] << 8) + cmd[4];
arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC);
if (! arr)
return DID_REQUEUE << 16;
- if (devip->wlun)
+ have_wlun = (scp->device->lun == SAM2_WLUN_REPORT_LUNS);
+ if (have_wlun)
pq_pdt = 0x1e; /* present, wlun */
else if (scsi_debug_no_lun_0 && (0 == devip->lun))
pq_pdt = 0x7f; /* not present, no device type */
@@ -944,8 +1242,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, int target,
pq_pdt = (scsi_debug_ptype & 0x1f);
arr[0] = pq_pdt;
if (0x2 & cmd[1]) { /* CMDDT bit set */
- mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
- 0);
+ mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 1);
kfree(arr);
return check_condition_result;
} else if (0x1 & cmd[1]) { /* EVPD bit set */
@@ -957,7 +1254,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, int target,
(devip->channel & 0x7f);
if (0 == scsi_debug_vpd_use_hostno)
host_no = 0;
- lu_id_num = devip->wlun ? -1 : (((host_no + 1) * 2000) +
+ lu_id_num = have_wlun ? -1 : (((host_no + 1) * 2000) +
(devip->target * 1000) + devip->lun);
target_dev_id = ((host_no + 1) * 2000) +
(devip->target * 1000) - 3;
@@ -1029,9 +1326,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, int target,
arr[1] = cmd[2]; /*sanity */
arr[3] = inquiry_evpd_b2(&arr[4]);
} else {
- /* Illegal request, invalid field in cdb */
- mk_sense_buffer(scp, ILLEGAL_REQUEST,
- INVALID_FIELD_IN_CDB, 0);
+ mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1);
kfree(arr);
return check_condition_result;
}
@@ -1077,18 +1372,20 @@ static int resp_requests(struct scsi_cmnd * scp,
unsigned char * sbuff;
unsigned char *cmd = scp->cmnd;
unsigned char arr[SCSI_SENSE_BUFFERSIZE];
- int want_dsense;
+ bool dsense, want_dsense;
int len = 18;
memset(arr, 0, sizeof(arr));
- want_dsense = !!(cmd[1] & 1) || scsi_debug_dsense;
+ dsense = !!(cmd[1] & 1);
+ want_dsense = dsense || scsi_debug_dsense;
sbuff = scp->sense_buffer;
if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) {
- if (want_dsense) {
+ if (dsense) {
arr[0] = 0x72;
arr[1] = 0x0; /* NO_SENSE in sense_key */
arr[2] = THRESHOLD_EXCEEDED;
arr[3] = 0xff; /* TEST set and MRIE==6 */
+ len = 8;
} else {
arr[0] = 0x70;
arr[2] = 0x0; /* NO_SENSE in sense_key */
@@ -1098,15 +1395,34 @@ static int resp_requests(struct scsi_cmnd * scp,
}
} else {
memcpy(arr, sbuff, SCSI_SENSE_BUFFERSIZE);
- if ((cmd[1] & 1) && (! scsi_debug_dsense)) {
- /* DESC bit set and sense_buff in fixed format */
- memset(arr, 0, sizeof(arr));
+ if (arr[0] >= 0x70 && dsense == scsi_debug_dsense)
+ ; /* have sense and formats match */
+ else if (arr[0] <= 0x70) {
+ if (dsense) {
+ memset(arr, 0, 8);
+ arr[0] = 0x72;
+ len = 8;
+ } else {
+ memset(arr, 0, 18);
+ arr[0] = 0x70;
+ arr[7] = 0xa;
+ }
+ } else if (dsense) {
+ memset(arr, 0, 8);
arr[0] = 0x72;
arr[1] = sbuff[2]; /* sense key */
arr[2] = sbuff[12]; /* asc */
arr[3] = sbuff[13]; /* ascq */
len = 8;
+ } else {
+ memset(arr, 0, 18);
+ arr[0] = 0x70;
+ arr[2] = sbuff[1];
+ arr[7] = 0xa;
+ arr[12] = sbuff[1];
+ arr[13] = sbuff[3];
}
+
}
mk_sense_buffer(scp, 0, NO_ADDITIONAL_SENSE, 0);
return fill_from_dev_buffer(scp, arr, len);
@@ -1116,15 +1432,11 @@ static int resp_start_stop(struct scsi_cmnd * scp,
struct sdebug_dev_info * devip)
{
unsigned char *cmd = scp->cmnd;
- int power_cond, errsts, start;
+ int power_cond, start;
- errsts = check_readiness(scp, UAS_ONLY, devip);
- if (errsts)
- return errsts;
power_cond = (cmd[4] & 0xf0) >> 4;
if (power_cond) {
- mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
- 0);
+ mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, 7);
return check_condition_result;
}
start = cmd[4] & 1;
@@ -1148,11 +1460,7 @@ static int resp_readcap(struct scsi_cmnd * scp,
{
unsigned char arr[SDEBUG_READCAP_ARR_SZ];
unsigned int capac;
- int errsts;
- errsts = check_readiness(scp, UAS_ONLY, devip);
- if (errsts)
- return errsts;
/* following just in case virtual_gb changed */
sdebug_capacity = get_sdebug_capacity();
memset(arr, 0, SDEBUG_READCAP_ARR_SZ);
@@ -1180,11 +1488,8 @@ static int resp_readcap16(struct scsi_cmnd * scp,
unsigned char *cmd = scp->cmnd;
unsigned char arr[SDEBUG_READCAP16_ARR_SZ];
unsigned long long capac;
- int errsts, k, alloc_len;
+ int k, alloc_len;
- errsts = check_readiness(scp, UAS_ONLY, devip);
- if (errsts)
- return errsts;
alloc_len = ((cmd[10] << 24) + (cmd[11] << 16) + (cmd[12] << 8)
+ cmd[13]);
/* following just in case virtual_gb changed */
@@ -1300,6 +1605,184 @@ static int resp_report_tgtpgs(struct scsi_cmnd * scp,
return ret;
}
+static int
+resp_rsup_opcodes(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+{
+ bool rctd;
+ u8 reporting_opts, req_opcode, sdeb_i, supp;
+ u16 req_sa, u;
+ u32 alloc_len, a_len;
+ int k, offset, len, errsts, count, bump, na;
+ const struct opcode_info_t *oip;
+ const struct opcode_info_t *r_oip;
+ u8 *arr;
+ u8 *cmd = scp->cmnd;
+
+ rctd = !!(cmd[2] & 0x80);
+ reporting_opts = cmd[2] & 0x7;
+ req_opcode = cmd[3];
+ req_sa = get_unaligned_be16(cmd + 4);
+ alloc_len = get_unaligned_be32(cmd + 6);
+ if (alloc_len < 4 && alloc_len > 0xffff) {
+ mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1);
+ return check_condition_result;
+ }
+ if (alloc_len > 8192)
+ a_len = 8192;
+ else
+ a_len = alloc_len;
+ arr = kzalloc((a_len < 256) ? 320 : a_len + 64, GFP_KERNEL);
+ if (NULL == arr) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
+ INSUFF_RES_ASCQ);
+ return check_condition_result;
+ }
+ switch (reporting_opts) {
+ case 0: /* all commands */
+ /* count number of commands */
+ for (count = 0, oip = opcode_info_arr;
+ oip->num_attached != 0xff; ++oip) {
+ if (F_INV_OP & oip->flags)
+ continue;
+ count += (oip->num_attached + 1);
+ }
+ bump = rctd ? 20 : 8;
+ put_unaligned_be32(count * bump, arr);
+ for (offset = 4, oip = opcode_info_arr;
+ oip->num_attached != 0xff && offset < a_len; ++oip) {
+ if (F_INV_OP & oip->flags)
+ continue;
+ na = oip->num_attached;
+ arr[offset] = oip->opcode;
+ put_unaligned_be16(oip->sa, arr + offset + 2);
+ if (rctd)
+ arr[offset + 5] |= 0x2;
+ if (FF_SA & oip->flags)
+ arr[offset + 5] |= 0x1;
+ put_unaligned_be16(oip->len_mask[0], arr + offset + 6);
+ if (rctd)
+ put_unaligned_be16(0xa, arr + offset + 8);
+ r_oip = oip;
+ for (k = 0, oip = oip->arrp; k < na; ++k, ++oip) {
+ if (F_INV_OP & oip->flags)
+ continue;
+ offset += bump;
+ arr[offset] = oip->opcode;
+ put_unaligned_be16(oip->sa, arr + offset + 2);
+ if (rctd)
+ arr[offset + 5] |= 0x2;
+ if (FF_SA & oip->flags)
+ arr[offset + 5] |= 0x1;
+ put_unaligned_be16(oip->len_mask[0],
+ arr + offset + 6);
+ if (rctd)
+ put_unaligned_be16(0xa,
+ arr + offset + 8);
+ }
+ oip = r_oip;
+ offset += bump;
+ }
+ break;
+ case 1: /* one command: opcode only */
+ case 2: /* one command: opcode plus service action */
+ case 3: /* one command: if sa==0 then opcode only else opcode+sa */
+ sdeb_i = opcode_ind_arr[req_opcode];
+ oip = &opcode_info_arr[sdeb_i];
+ if (F_INV_OP & oip->flags) {
+ supp = 1;
+ offset = 4;
+ } else {
+ if (1 == reporting_opts) {
+ if (FF_SA & oip->flags) {
+ mk_sense_invalid_fld(scp, SDEB_IN_CDB,
+ 2, 2);
+ kfree(arr);
+ return check_condition_result;
+ }
+ req_sa = 0;
+ } else if (2 == reporting_opts &&
+ 0 == (FF_SA & oip->flags)) {
+ mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, -1);
+ kfree(arr); /* point at requested sa */
+ return check_condition_result;
+ }
+ if (0 == (FF_SA & oip->flags) &&
+ req_opcode == oip->opcode)
+ supp = 3;
+ else if (0 == (FF_SA & oip->flags)) {
+ na = oip->num_attached;
+ for (k = 0, oip = oip->arrp; k < na;
+ ++k, ++oip) {
+ if (req_opcode == oip->opcode)
+ break;
+ }
+ supp = (k >= na) ? 1 : 3;
+ } else if (req_sa != oip->sa) {
+ na = oip->num_attached;
+ for (k = 0, oip = oip->arrp; k < na;
+ ++k, ++oip) {
+ if (req_sa == oip->sa)
+ break;
+ }
+ supp = (k >= na) ? 1 : 3;
+ } else