forked from Minki/linux
Merge remote-tracking branch 'scsi-queue/drivers-for-3.19' into for-linus
Conflicts: drivers/scsi/scsi_debug.c Agreed and tested resolution to a merge problem between a fix in scsi_debug and a driver update Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
commit
096cbc35ea
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
21
Documentation/scsi/wd719x.txt
Normal file
21
Documentation/scsi/wd719x.txt
Normal file
@ -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
|
17
MAINTAINERS
17
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.*
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
||||
/*
|
||||
|
@ -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 **************************/
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 = {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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 {
|
||||
|
@ -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));
|
||||
|
@ -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[];
|
||||
|
@ -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
|
||||
@ -234,6 +234,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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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 *);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
/*
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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++)
|
||||
|
@ -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
|
||||
|
@ -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/
|
||||
|
||||
|
@ -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
|
||||
#ifdef AUTOSENSE
|
||||
" AUTOSENSE"
|
||||
"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 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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
586
drivers/scsi/am53c974.c
Normal file
586
drivers/scsi/am53c974.c
Normal file
@ -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);
|
@ -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 = {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#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
|
||||
}
|
||||
|
||||
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)
|
||||
static int falcon_get_lock(struct Scsi_Host *instance)
|
||||
{
|
||||
if (IS_A_TT())
|
||||
free_irq(IRQ_TT_MFP_SCSI, sh);
|
||||
if (atari_dma_buffer)
|
||||
atari_stram_free(atari_dma_buffer);
|
||||
NCR5380_exit(sh);
|
||||
return 1;
|
||||
|
||||
if (in_interrupt())
|
||||
return stdma_try_lock(scsi_falcon_intr, instance);
|
||||
|
||||
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;
|
||||
|
||||
#include "scsi_module.c"
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver_probe(atari_scsi_driver, atari_scsi_probe);
|
||||
|
||||
MODULE_ALIAS("platform:" DRV_MODULE_NAME);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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;
|
||||
|
||||
/* 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;
|
||||
|
||||
NCR5380_init(shost, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 = "";
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
esp_write8(esp->config2, ESP_CFG2);
|
||||
|
||||
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.
|
||||
*/
|
||||
esp->rev = ESP100;
|
||||
} else {
|
||||
esp->config2 = 0;
|
||||
esp_set_all_config3(esp, 5);
|
||||
esp->prev_cfg3 = 5;
|
||||
if (esp->config2 == 0) {
|
||||
esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);
|
||||
esp_write8(esp->config2, ESP_CFG2);
|
||||
esp_write8(0, ESP_CFG3);
|
||||
|
||||
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_CFG3);
|
||||
if (val != 5) {
|
||||
/* The cfg2 register is implemented, however
|
||||
* cfg3 is not, must be esp100a.
|
||||
*/
|
||||
esp->rev = ESP100A;
|
||||
} else {
|
||||
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);
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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: "
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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,46 +427,28 @@ 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;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,
|
||||
|
@ -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
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
};
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 *);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
|
||||
/* The I/O was aborted. */
|
||||
spin_unlock_irqrestore(&task->task_state_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);
|
||||
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);
|
||||
task->task_state_flags |= SAS_TASK_AT_INITIATOR;
|
||||
spin_unlock_irqrestore(&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);
|
||||
/* build and send the request. */
|
||||
status = isci_request_execute(ihost, idev, task, tag);
|
||||
|
||||
isci_task_refuse(ihost, task,
|
||||
SAS_TASK_UNDELIVERED,
|
||||
SAM_STAT_TASK_ABORTED);
|
||||
} else {
|
||||
task->task_state_flags |= SAS_TASK_AT_INITIATOR;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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 = {
|
||||
|
@ -2160,36 +2160,11 @@ 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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
return __ata_change_queue_depth(dev->sata_dev.ap, sdev, depth);
|
||||
|
||||
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 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.
|
||||
|
@ -242,108 +242,6 @@ lpfc_update_stats(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,
|
||||
};
|
||||
|
@ -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
|
||||
|
||||
#define NCR5380_implementation_fields unsigned char *pdma_base
|
||||
#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_info macscsi_info
|
||||
#define NCR5380_show_info macscsi_show_info
|
||||
#define NCR5380_write_info macscsi_write_info
|
||||
|
||||
#include "NCR5380.h"
|
||||
|
||||
#define RESET_BOOT
|
||||
#define DRIVER_SETUP
|
||||
|
||||
extern void via_scsi_clear(void);
|
||||
|
||||
#ifdef RESET_BOOT
|
||||
static void mac_scsi_reset_boot(struct Scsi_Host *instance);
|
||||
#endif
|
||||
|
||||
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)
|
||||
static inline 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)
|
||||
{
|
||||
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
|
||||
|
||||
|
||||
/*
|
||||
* Function : mac_scsi_setup(char *str)
|
||||
*
|
||||
* Purpose : booter command line initialization of the overrides array,
|
||||
*
|
||||
* Inputs : str - comma delimited list of options
|
||||
*
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
(void)get_options(str, ARRAY_SIZE(ints), ints);
|
||||
|
||||
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] >= 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] == 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;
|
||||
struct NCR5380_hostdata *hostdata = shost_priv(instance);
|
||||
unsigned char *d;
|
||||
unsigned char *s;
|
||||
|
||||
NCR5380_local_declare();
|
||||
NCR5380_setup(instance);
|
||||
NCR5380_local_declare();
|
||||
NCR5380_setup(instance);
|
||||
|
||||
s = mac_scsi_drq+0x60;
|
||||
d = dst;
|
||||
s = hostdata->pdma_base + (INPUT_DATA_REG << 4);
|
||||
d = dst;
|
||||
|
||||
/* These conditions are derived from MacOS */
|
||||
/* 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;
|
||||
}
|
||||
while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) &&
|
||||
!(NCR5380_read(STATUS_REG) & SR_REQ))
|
||||
;
|
||||
|
||||
CP_IO_TO_MEM(s, d, len);
|
||||
|
||||
if (len != 0) {
|
||||
printk(KERN_NOTICE "Bus error in macscsi_pread\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
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;
|
||||
struct NCR5380_hostdata *hostdata = shost_priv(instance);
|
||||
unsigned char *s;
|
||||
unsigned char *d;
|
||||
|
||||
NCR5380_local_declare();
|
||||
NCR5380_setup(instance);
|
||||
NCR5380_local_declare();
|
||||
NCR5380_setup(instance);
|
||||
|
||||
s = src;
|
||||
d = mac_scsi_drq;
|
||||
|
||||
/* These conditions are derived from MacOS */
|
||||
s = src;
|
||||
d = hostdata->pdma_base + (OUTPUT_DATA_REG << 4);
|
||||
|
||||
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;
|
||||
}
|
||||
/* These conditions are derived from MacOS */
|
||||
|
||||
CP_MEM_TO_IO(s, d, len);
|
||||
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 (len != 0) {
|
||||
printk(KERN_NOTICE "Bus error in macscsi_pwrite\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
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;
|
||||
|
||||
#include "scsi_module.c"
|
||||
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);
|
||||
|
||||
MODULE_ALIAS("platform:" DRV_MODULE_NAME);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user