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:
James Bottomley 2014-12-08 07:42:02 -08:00
commit 096cbc35ea
154 changed files with 7002 additions and 11814 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View 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

View File

@ -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.*

View File

@ -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;
}

View File

@ -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);
/*

View File

@ -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 **************************/

View File

@ -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

View File

@ -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;
}
/*

View File

@ -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

View File

@ -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);
}
/**

View File

@ -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);
}

View File

@ -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

View File

@ -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 {

View File

@ -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));

View File

@ -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[];

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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 {

View File

@ -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;

View File

@ -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 *);

View File

@ -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;

View File

@ -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 */
/*

View File

@ -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,
};
/**

View File

@ -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
};

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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);
}

View File

@ -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++)

View File

@ -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

View File

@ -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/

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -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);
}
/*

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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)

View File

@ -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);
}

View File

@ -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
View 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);

View File

@ -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 = {

View File

@ -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;

View File

@ -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

View File

@ -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");

View File

@ -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 */

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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;
}

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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);

View File

@ -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;

View File

@ -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,

View File

@ -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

View File

@ -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 = "";
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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)
{

View File

@ -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);

View File

@ -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 */

View File

@ -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,
};
/**

View File

@ -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: "

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -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;
}

View File

@ -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 */
};

View File

@ -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,

View File

@ -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,
};
/**

View File

@ -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);
}
/* ------------------------------------------------------------

View File

@ -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;
}

View File

@ -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 *);

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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(

View File

@ -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 = {

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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.

View File

@ -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,
};

View File

@ -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