summaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/BusLogic.c73
-rw-r--r--drivers/scsi/Kconfig24
-rw-r--r--drivers/scsi/Makefile2
-rw-r--r--drivers/scsi/aacraid/aachba.c402
-rw-r--r--drivers/scsi/aacraid/aacraid.h76
-rw-r--r--drivers/scsi/aacraid/commctrl.c286
-rw-r--r--drivers/scsi/aacraid/comminit.c4
-rw-r--r--drivers/scsi/aacraid/commsup.c112
-rw-r--r--drivers/scsi/aacraid/dpcsup.c36
-rw-r--r--drivers/scsi/aacraid/linit.c65
-rw-r--r--drivers/scsi/aacraid/nark.c3
-rw-r--r--drivers/scsi/aacraid/rkt.c3
-rw-r--r--drivers/scsi/aacraid/rx.c115
-rw-r--r--drivers/scsi/aacraid/sa.c1
-rw-r--r--drivers/scsi/aha1542.c1
-rw-r--r--drivers/scsi/aic7xxx/Kconfig.aic79xx12
-rw-r--r--drivers/scsi/aic7xxx/Kconfig.aic7xxx10
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c6
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.h2
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.h5
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_core.c2
-rw-r--r--drivers/scsi/aic94xx/aic94xx_scb.c1
-rw-r--r--drivers/scsi/arcmsr/arcmsr_attr.c1
-rw-r--r--drivers/scsi/atari_NCR5380.c4398
-rw-r--r--drivers/scsi/atari_scsi.c377
-rw-r--r--drivers/scsi/atari_scsi.h174
-rw-r--r--drivers/scsi/constants.c274
-rw-r--r--drivers/scsi/dpt/dpti_i2o.h48
-rw-r--r--drivers/scsi/dpt/dpti_ioctl.h2
-rw-r--r--drivers/scsi/dpt/dptsig.h4
-rw-r--r--drivers/scsi/dpt_i2o.c2
-rw-r--r--drivers/scsi/eata_generic.h7
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c80
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.h2
-rw-r--r--drivers/scsi/ibmvscsi/ibmvstgt.c37
-rw-r--r--drivers/scsi/ipr.c290
-rw-r--r--drivers/scsi/ipr.h45
-rw-r--r--drivers/scsi/iscsi_tcp.c21
-rw-r--r--drivers/scsi/libiscsi.c29
-rw-r--r--drivers/scsi/libsas/sas_expander.c1
-rw-r--r--drivers/scsi/libsrp.c13
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c2
-rw-r--r--drivers/scsi/megaraid.c2
-rw-r--r--drivers/scsi/osst.c1
-rw-r--r--drivers/scsi/pci2000.h197
-rw-r--r--drivers/scsi/pcmcia/Kconfig9
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h13
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c177
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c16
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c7
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c11
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h2
-rw-r--r--drivers/scsi/scsi.c47
-rw-r--r--drivers/scsi/scsi_error.c19
-rw-r--r--drivers/scsi/scsi_lib.c8
-rw-r--r--drivers/scsi/scsi_scan.c2
-rw-r--r--drivers/scsi/scsi_sysfs.c54
-rw-r--r--drivers/scsi/scsi_tgt_if.c6
-rw-r--r--drivers/scsi/scsi_tgt_lib.c261
-rw-r--r--drivers/scsi/scsi_tgt_priv.h5
-rw-r--r--drivers/scsi/scsi_transport_fc.c2
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c6
-rw-r--r--drivers/scsi/sd.c405
-rw-r--r--drivers/scsi/sg.c13
-rw-r--r--drivers/scsi/sr.c2
-rw-r--r--drivers/scsi/st.c1
-rw-r--r--drivers/scsi/tmscsim.c2
67 files changed, 4251 insertions, 4065 deletions
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index e874b8944875..96f4cab07614 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -579,17 +579,17 @@ static void __init BusLogic_InitializeProbeInfoListISA(struct BusLogic_HostAdapt
/*
Append the list of standard BusLogic MultiMaster ISA I/O Addresses.
*/
- if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe330 : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0)
+ if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe330)
BusLogic_AppendProbeAddressISA(0x330);
- if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe334 : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0)
+ if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe334)
BusLogic_AppendProbeAddressISA(0x334);
- if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe230 : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0)
+ if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe230)
BusLogic_AppendProbeAddressISA(0x230);
- if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe234 : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0)
+ if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe234)
BusLogic_AppendProbeAddressISA(0x234);
- if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe130 : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0)
+ if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe130)
BusLogic_AppendProbeAddressISA(0x130);
- if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe134 : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0)
+ if (!BusLogic_ProbeOptions.LimitedProbeISA || BusLogic_ProbeOptions.Probe134)
BusLogic_AppendProbeAddressISA(0x134);
}
@@ -795,7 +795,9 @@ static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAd
host adapters are probed.
*/
if (!BusLogic_ProbeOptions.NoProbeISA)
- if (PrimaryProbeInfo->IO_Address == 0 && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe330 : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0)) {
+ if (PrimaryProbeInfo->IO_Address == 0 &&
+ (!BusLogic_ProbeOptions.LimitedProbeISA ||
+ BusLogic_ProbeOptions.Probe330)) {
PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster;
PrimaryProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus;
PrimaryProbeInfo->IO_Address = 0x330;
@@ -805,15 +807,25 @@ static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAd
omitting the Primary I/O Address which has already been handled.
*/
if (!BusLogic_ProbeOptions.NoProbeISA) {
- if (!StandardAddressSeen[1] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe334 : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0))
+ if (!StandardAddressSeen[1] &&
+ (!BusLogic_ProbeOptions.LimitedProbeISA ||
+ BusLogic_ProbeOptions.Probe334))
BusLogic_AppendProbeAddressISA(0x334);
- if (!StandardAddressSeen[2] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe230 : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0))
+ if (!StandardAddressSeen[2] &&
+ (!BusLogic_ProbeOptions.LimitedProbeISA ||
+ BusLogic_ProbeOptions.Probe230))
BusLogic_AppendProbeAddressISA(0x230);
- if (!StandardAddressSeen[3] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe234 : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0))
+ if (!StandardAddressSeen[3] &&
+ (!BusLogic_ProbeOptions.LimitedProbeISA ||
+ BusLogic_ProbeOptions.Probe234))
BusLogic_AppendProbeAddressISA(0x234);
- if (!StandardAddressSeen[4] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe130 : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0))
+ if (!StandardAddressSeen[4] &&
+ (!BusLogic_ProbeOptions.LimitedProbeISA ||
+ BusLogic_ProbeOptions.Probe130))
BusLogic_AppendProbeAddressISA(0x130);
- if (!StandardAddressSeen[5] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe134 : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0))
+ if (!StandardAddressSeen[5] &&
+ (!BusLogic_ProbeOptions.LimitedProbeISA ||
+ BusLogic_ProbeOptions.Probe134))
BusLogic_AppendProbeAddressISA(0x134);
}
/*
@@ -2220,22 +2232,35 @@ static int __init BusLogic_init(void)
HostAdapter->PCI_Device = ProbeInfo->PCI_Device;
HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel;
HostAdapter->AddressCount = BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType];
+
+ /*
+ Make sure region is free prior to probing.
+ */
+ if (!request_region(HostAdapter->IO_Address, HostAdapter->AddressCount,
+ "BusLogic"))
+ continue;
/*
Probe the Host Adapter. If unsuccessful, abort further initialization.
*/
- if (!BusLogic_ProbeHostAdapter(HostAdapter))
+ if (!BusLogic_ProbeHostAdapter(HostAdapter)) {
+ release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
continue;
+ }
/*
Hard Reset the Host Adapter. If unsuccessful, abort further
initialization.
*/
- if (!BusLogic_HardwareResetHostAdapter(HostAdapter, true))
+ if (!BusLogic_HardwareResetHostAdapter(HostAdapter, true)) {
+ release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
continue;
+ }
/*
Check the Host Adapter. If unsuccessful, abort further initialization.
*/
- if (!BusLogic_CheckHostAdapter(HostAdapter))
+ if (!BusLogic_CheckHostAdapter(HostAdapter)) {
+ release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
continue;
+ }
/*
Initialize the Driver Options field if provided.
*/
@@ -2247,16 +2272,6 @@ static int __init BusLogic_init(void)
*/
BusLogic_AnnounceDriver(HostAdapter);
/*
- Register usage of the I/O Address range. From this point onward, any
- failure will be assumed to be due to a problem with the Host Adapter,
- rather than due to having mistakenly identified this port as belonging
- to a BusLogic Host Adapter. The I/O Address range will not be
- released, thereby preventing it from being incorrectly identified as
- any other type of Host Adapter.
- */
- if (!request_region(HostAdapter->IO_Address, HostAdapter->AddressCount, "BusLogic"))
- continue;
- /*
Register the SCSI Host structure.
*/
@@ -2280,6 +2295,12 @@ static int __init BusLogic_init(void)
Acquire the System Resources necessary to use the Host Adapter, then
Create the Initial CCBs, Initialize the Host Adapter, and finally
perform Target Device Inquiry.
+
+ From this point onward, any failure will be assumed to be due to a
+ problem with the Host Adapter, rather than due to having mistakenly
+ identified this port as belonging to a BusLogic Host Adapter. The
+ I/O Address range will not be released, thereby preventing it from
+ being incorrectly identified as any other type of Host Adapter.
*/
if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) &&
BusLogic_ReportHostAdapterConfiguration(HostAdapter) &&
@@ -3598,6 +3619,7 @@ static void __exit BusLogic_exit(void)
__setup("BusLogic=", BusLogic_Setup);
+#ifdef MODULE
static struct pci_device_id BusLogic_pci_tbl[] __devinitdata = {
{ PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
@@ -3607,6 +3629,7 @@ static struct pci_device_id BusLogic_pci_tbl[] __devinitdata = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ }
};
+#endif
MODULE_DEVICE_TABLE(pci, BusLogic_pci_tbl);
module_init(BusLogic_init);
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index fcc4cb6c7f46..58c811d20eb2 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -241,6 +241,12 @@ config SCSI_SCAN_ASYNC
You can override this choice by specifying "scsi_mod.scan=sync"
or async on the kernel's command line.
+config SCSI_WAIT_SCAN
+ tristate
+ default m
+ depends on SCSI
+ depends on MODULES
+
menu "SCSI Transports"
depends on SCSI
@@ -1194,17 +1200,6 @@ config SCSI_NCR53C8XX_SYNC
There is no safe option other than using good cabling, right
terminations and SCSI conformant devices.
-config SCSI_NCR53C8XX_PROFILE
- bool "enable profiling"
- depends on SCSI_ZALON || SCSI_NCR_Q720
- help
- This option allows you to enable profiling information gathering.
- These statistics are not very accurate due to the low frequency
- of the kernel clock (100 Hz on i386) and have performance impact
- on systems that use very fast devices.
-
- The normal answer therefore is N.
-
config SCSI_NCR53C8XX_NO_DISCONNECT
bool "not allow targets to disconnect"
depends on (SCSI_ZALON || SCSI_NCR_Q720) && SCSI_NCR53C8XX_DEFAULT_TAGS=0
@@ -1334,11 +1329,6 @@ config SCSI_SIM710
It currently supports Compaq EISA cards and NCR MCA cards
-config 53C700_IO_MAPPED
- bool
- depends on SCSI_SIM710
- default y
-
config SCSI_SYM53C416
tristate "Symbios 53c416 SCSI support"
depends on ISA && SCSI
@@ -1649,7 +1639,7 @@ config OKTAGON_SCSI
config ATARI_SCSI
tristate "Atari native SCSI support"
- depends on ATARI && SCSI && BROKEN
+ depends on ATARI && SCSI
select SCSI_SPI_ATTRS
---help---
If you have an Atari with built-in NCR5380 SCSI controller (TT,
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 70cff4c599d7..51e884fa10b0 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -146,7 +146,7 @@ obj-$(CONFIG_CHR_DEV_SCH) += ch.o
# This goes last, so that "real" scsi devices probe earlier
obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o
-obj-$(CONFIG_SCSI) += scsi_wait_scan.o
+obj-$(CONFIG_SCSI_WAIT_SCAN) += scsi_wait_scan.o
scsi_mod-y += scsi.o hosts.o scsi_ioctl.o constants.o \
scsicam.o scsi_error.o scsi_lib.o \
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index d789e61bdc49..1e82c69b36b0 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -5,7 +5,7 @@
* based on the old aacraid driver that is..
* Adaptec aacraid device driver for Linux.
*
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -172,6 +172,30 @@ MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size.
int expose_physicals = -1;
module_param(expose_physicals, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. -1=protect 0=off, 1=on");
+
+
+static inline int aac_valid_context(struct scsi_cmnd *scsicmd,
+ struct fib *fibptr) {
+ struct scsi_device *device;
+
+ if (unlikely(!scsicmd || !scsicmd->scsi_done )) {
+ dprintk((KERN_WARNING "aac_valid_context: scsi command corrupt\n"))
+;
+ aac_fib_complete(fibptr);
+ aac_fib_free(fibptr);
+ return 0;
+ }
+ scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
+ device = scsicmd->device;
+ if (unlikely(!device || !scsi_device_online(device))) {
+ dprintk((KERN_WARNING "aac_valid_context: scsi device corrupt\n"));
+ aac_fib_complete(fibptr);
+ aac_fib_free(fibptr);
+ return 0;
+ }
+ return 1;
+}
+
/**
* aac_get_config_status - check the adapter configuration
* @common: adapter to query
@@ -258,13 +282,10 @@ int aac_get_containers(struct aac_dev *dev)
u32 index;
int status = 0;
struct fib * fibptr;
- unsigned instance;
struct aac_get_container_count *dinfo;
struct aac_get_container_count_resp *dresp;
int maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
- instance = dev->scsi_host_ptr->unique_id;
-
if (!(fibptr = aac_fib_alloc(dev)))
return -ENOMEM;
@@ -284,88 +305,35 @@ int aac_get_containers(struct aac_dev *dev)
maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries);
aac_fib_complete(fibptr);
}
+ aac_fib_free(fibptr);
if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS)
maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
- fsa_dev_ptr = kmalloc(
- sizeof(*fsa_dev_ptr) * maximum_num_containers, GFP_KERNEL);
- if (!fsa_dev_ptr) {
- aac_fib_free(fibptr);
+ fsa_dev_ptr = kmalloc(sizeof(*fsa_dev_ptr) * maximum_num_containers,
+ GFP_KERNEL);
+ if (!fsa_dev_ptr)
return -ENOMEM;
- }
memset(fsa_dev_ptr, 0, sizeof(*fsa_dev_ptr) * maximum_num_containers);
dev->fsa_dev = fsa_dev_ptr;
dev->maximum_num_containers = maximum_num_containers;
- for (index = 0; index < dev->maximum_num_containers; index++) {
- struct aac_query_mount *dinfo;
- struct aac_mount *dresp;
-
+ for (index = 0; index < dev->maximum_num_containers; ) {
fsa_dev_ptr[index].devname[0] = '\0';
- aac_fib_init(fibptr);
- dinfo = (struct aac_query_mount *) fib_data(fibptr);
-
- dinfo->command = cpu_to_le32(VM_NameServe);
- dinfo->count = cpu_to_le32(index);
- dinfo->type = cpu_to_le32(FT_FILESYS);
+ status = aac_probe_container(dev, index);
- status = aac_fib_send(ContainerCommand,
- fibptr,
- sizeof (struct aac_query_mount),
- FsaNormal,
- 1, 1,
- NULL, NULL);
- if (status < 0 ) {
+ if (status < 0) {
printk(KERN_WARNING "aac_get_containers: SendFIB failed.\n");
break;
}
- dresp = (struct aac_mount *)fib_data(fibptr);
- if ((le32_to_cpu(dresp->status) == ST_OK) &&
- (le32_to_cpu(dresp->mnt[0].vol) == CT_NONE)) {
- dinfo->command = cpu_to_le32(VM_NameServe64);
- dinfo->count = cpu_to_le32(index);
- dinfo->type = cpu_to_le32(FT_FILESYS);
-
- if (aac_fib_send(ContainerCommand,
- fibptr,
- sizeof(struct aac_query_mount),
- FsaNormal,
- 1, 1,
- NULL, NULL) < 0)
- continue;
- } else
- dresp->mnt[0].capacityhigh = 0;
-
- dprintk ((KERN_DEBUG
- "VM_NameServe cid=%d status=%d vol=%d state=%d cap=%llu\n",
- (int)index, (int)le32_to_cpu(dresp->status),
- (int)le32_to_cpu(dresp->mnt[0].vol),
- (int)le32_to_cpu(dresp->mnt[0].state),
- ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +
- (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32)));
- if ((le32_to_cpu(dresp->status) == ST_OK) &&
- (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) &&
- (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) {
- fsa_dev_ptr[index].valid = 1;
- fsa_dev_ptr[index].type = le32_to_cpu(dresp->mnt[0].vol);
- fsa_dev_ptr[index].size
- = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +
- (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32);
- if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY)
- fsa_dev_ptr[index].ro = 1;
- }
- aac_fib_complete(fibptr);
/*
* If there are no more containers, then stop asking.
*/
- if ((index + 1) >= le32_to_cpu(dresp->count)){
+ if (++index >= status)
break;
- }
}
- aac_fib_free(fibptr);
return status;
}
@@ -382,8 +350,9 @@ static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigne
buf = scsicmd->request_buffer;
transfer_len = min(scsicmd->request_bufflen, len + offset);
}
-
- memcpy(buf + offset, data, transfer_len - offset);
+ transfer_len -= offset;
+ if (buf && transfer_len)
+ memcpy(buf + offset, data, transfer_len);
if (scsicmd->use_sg)
kunmap_atomic(buf - sg->offset, KM_IRQ0);
@@ -396,7 +365,9 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
struct scsi_cmnd * scsicmd;
scsicmd = (struct scsi_cmnd *) context;
- scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
+
+ if (!aac_valid_context(scsicmd, fibptr))
+ return;
dprintk((KERN_DEBUG "get_container_name_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies));
BUG_ON(fibptr == NULL);
@@ -431,7 +402,7 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
/**
* aac_get_container_name - get container name, none blocking.
*/
-static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
+static int aac_get_container_name(struct scsi_cmnd * scsicmd)
{
int status;
struct aac_get_name *dinfo;
@@ -448,7 +419,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
dinfo->command = cpu_to_le32(VM_ContainerConfig);
dinfo->type = cpu_to_le32(CT_READ_NAME);
- dinfo->cid = cpu_to_le32(cid);
+ dinfo->cid = cpu_to_le32(scmd_id(scsicmd));
dinfo->count = cpu_to_le32(sizeof(((struct aac_get_name_resp *)NULL)->data));
status = aac_fib_send(ContainerCommand,
@@ -473,85 +444,192 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
return -1;
}
-/**
- * aac_probe_container - query a logical volume
- * @dev: device to query
- * @cid: container identifier
- *
- * Queries the controller about the given volume. The volume information
- * is updated in the struct fsa_dev_info structure rather than returned.
- */
-
-int aac_probe_container(struct aac_dev *dev, int cid)
+static int aac_probe_container_callback2(struct scsi_cmnd * scsicmd)
+{
+ struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
+
+ if (fsa_dev_ptr[scmd_id(scsicmd)].valid)
+ return aac_scsi_cmd(scsicmd);
+
+ scsicmd->result = DID_NO_CONNECT << 16;
+ scsicmd->scsi_done(scsicmd);
+ return 0;
+}
+
+static int _aac_probe_container2(void * context, struct fib * fibptr)
{
struct fsa_dev_info *fsa_dev_ptr;
- int status;
+ int (*callback)(struct scsi_cmnd *);
+ struct scsi_cmnd * scsicmd = (struct scsi_cmnd *)context;
+
+ if (!aac_valid_context(scsicmd, fibptr))
+ return 0;
+
+ fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
+
+ scsicmd->SCp.Status = 0;
+ if (fsa_dev_ptr) {
+ struct aac_mount * dresp = (struct aac_mount *) fib_data(fibptr);
+ fsa_dev_ptr += scmd_id(scsicmd);
+
+ if ((le32_to_cpu(dresp->status) == ST_OK) &&
+ (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) &&
+ (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) {
+ fsa_dev_ptr->valid = 1;
+ fsa_dev_ptr->type = le32_to_cpu(dresp->mnt[0].vol);
+ fsa_dev_ptr->size
+ = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +
+ (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32);
+ fsa_dev_ptr->ro = ((le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) != 0);
+ }
+ if ((fsa_dev_ptr->valid & 1) == 0)
+ fsa_dev_ptr->valid = 0;
+ scsicmd->SCp.Status = le32_to_cpu(dresp->count);
+ }
+ aac_fib_complete(fibptr);
+ aac_fib_free(fibptr);
+ callback = (int (*)(struct scsi_cmnd *))(scsicmd->SCp.ptr);
+ scsicmd->SCp.ptr = NULL;
+ return (*callback)(scsicmd);
+}
+
+static int _aac_probe_container1(void * context, struct fib * fibptr)
+{
+ struct scsi_cmnd * scsicmd;
+ struct aac_mount * dresp;
struct aac_query_mount *dinfo;
- struct aac_mount *dresp;
- struct fib * fibptr;
- unsigned instance;
+ int status;
- fsa_dev_ptr = dev->fsa_dev;
- if (!fsa_dev_ptr)
- return -ENOMEM;
- instance = dev->scsi_host_ptr->unique_id;
+ dresp = (struct aac_mount *) fib_data(fibptr);
+ dresp->mnt[0].capacityhigh = 0;
+ if ((le32_to_cpu(dresp->status) != ST_OK) ||
+ (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE))
+ return _aac_probe_container2(context, fibptr);
+ scsicmd = (struct scsi_cmnd *) context;
+ scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
- if (!(fibptr = aac_fib_alloc(dev)))
- return -ENOMEM;
+ if (!aac_valid_context(scsicmd, fibptr))
+ return 0;
aac_fib_init(fibptr);
dinfo = (struct aac_query_mount *)fib_data(fibptr);
- dinfo->command = cpu_to_le32(VM_NameServe);
- dinfo->count = cpu_to_le32(cid);
+ dinfo->command = cpu_to_le32(VM_NameServe64);
+ dinfo->count = cpu_to_le32(scmd_id(scsicmd));
dinfo->type = cpu_to_le32(FT_FILESYS);
status = aac_fib_send(ContainerCommand,
- fibptr,
- sizeof(struct aac_query_mount),
- FsaNormal,
- 1, 1,
- NULL, NULL);
+ fibptr,
+ sizeof(struct aac_query_mount),
+ FsaNormal,
+ 0, 1,
+ (fib_callback) _aac_probe_container2,
+ (void *) scsicmd);
+ /*
+ * Check that the command queued to the controller
+ */
+ if (status == -EINPROGRESS) {
+ scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
+ return 0;
+ }
if (status < 0) {
- printk(KERN_WARNING "aacraid: aac_probe_container query failed.\n");
- goto error;
+ /* Inherit results from VM_NameServe, if any */
+ dresp->status = cpu_to_le32(ST_OK);
+ return _aac_probe_container2(context, fibptr);
}
+ return 0;
+}
- dresp = (struct aac_mount *) fib_data(fibptr);
+static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(struct scsi_cmnd *))
+{
+ struct fib * fibptr;
+ int status = -ENOMEM;
- if ((le32_to_cpu(dresp->status) == ST_OK) &&
- (le32_to_cpu(dresp->mnt[0].vol) == CT_NONE)) {
- dinfo->command = cpu_to_le32(VM_NameServe64);
- dinfo->count = cpu_to_le32(cid);
- dinfo->type = cpu_to_le32(FT_FILESYS);
+ if ((fibptr = aac_fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata))) {
+ struct aac_query_mount *dinfo;
- if (aac_fib_send(ContainerCommand,
- fibptr,
- sizeof(struct aac_query_mount),
- FsaNormal,
- 1, 1,
- NULL, NULL) < 0)
- goto error;
- } else
- dresp->mnt[0].capacityhigh = 0;
+ aac_fib_init(fibptr);
+
+ dinfo = (struct aac_query_mount *)fib_data(fibptr);
+
+ dinfo->command = cpu_to_le32(VM_NameServe);
+ dinfo->count = cpu_to_le32(scmd_id(scsicmd));
+ dinfo->type = cpu_to_le32(FT_FILESYS);
+ scsicmd->SCp.ptr = (char *)callback;
- if ((le32_to_cpu(dresp->status) == ST_OK) &&
- (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) &&
- (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) {
- fsa_dev_ptr[cid].valid = 1;
- fsa_dev_ptr[cid].type = le32_to_cpu(dresp->mnt[0].vol);
- fsa_dev_ptr[cid].size
- = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +
- (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32);
- if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY)
- fsa_dev_ptr[cid].ro = 1;
+ status = aac_fib_send(ContainerCommand,
+ fibptr,
+ sizeof(struct aac_query_mount),
+ FsaNormal,
+ 0, 1,
+ (fib_callback) _aac_probe_container1,
+ (void *) scsicmd);
+ /*
+ * Check that the command queued to the controller
+ */
+ if (status == -EINPROGRESS) {
+ scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
+ return 0;
+ }
+ if (status < 0) {
+ scsicmd->SCp.ptr = NULL;
+ aac_fib_complete(fibptr);
+ aac_fib_free(fibptr);
+ }
}
+ if (status < 0) {
+ struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
+ if (fsa_dev_ptr) {
+ fsa_dev_ptr += scmd_id(scsicmd);
+ if ((fsa_dev_ptr->valid & 1) == 0) {
+ fsa_dev_ptr->valid = 0;
+ return (*callback)(scsicmd);
+ }
+ }
+ }
+ return status;
+}
-error:
- aac_fib_complete(fibptr);
- aac_fib_free(fibptr);
+/**
+ * aac_probe_container - query a logical volume
+ * @dev: device to query
+ * @cid: container identifier
+ *
+ * Queries the controller about the given volume. The volume information
+ * is updated in the struct fsa_dev_info structure rather than returned.
+ */
+static int aac_probe_container_callback1(struct scsi_cmnd * scsicmd)
+{
+ scsicmd->device = NULL;
+ return 0;
+}
+
+int aac_probe_container(struct aac_dev *dev, int cid)
+{
+ struct scsi_cmnd *scsicmd = kmalloc(sizeof(*scsicmd), GFP_KERNEL);
+ struct scsi_device *scsidev = kmalloc(sizeof(*scsidev), GFP_KERNEL);
+ int status;
+ if (!scsicmd || !scsidev) {
+ kfree(scsicmd);
+ kfree(scsidev);
+ return -ENOMEM;
+ }
+ scsicmd->list.next = NULL;
+ scsicmd->scsi_done = (void (*)(struct scsi_cmnd*))_aac_probe_container1;
+
+ scsicmd->device = scsidev;
+ scsidev->sdev_state = 0;
+ scsidev->id = cid;
+ scsidev->host = dev->scsi_host_ptr;
+
+ if (_aac_probe_container(scsicmd, aac_probe_container_callback1) == 0)
+ while (scsicmd->device == scsidev)
+ schedule();
+ kfree(scsidev);
+ status = scsicmd->SCp.Status;
+ kfree(scsicmd);
return status;
}
@@ -1115,6 +1193,12 @@ int aac_get_adapter_info(struct aac_dev* dev)
printk(KERN_INFO "%s%d: serial %x\n",
dev->name, dev->id,
le32_to_cpu(dev->adapter_info.serial[0]));
+ if (dev->supplement_adapter_info.VpdInfo.Tsid[0]) {
+ printk(KERN_INFO "%s%d: TSID %.*s\n",
+ dev->name, dev->id,
+ (int)sizeof(dev->supplement_adapter_info.VpdInfo.Tsid),
+ dev->supplement_adapter_info.VpdInfo.Tsid);
+ }
}
dev->nondasd_support = 0;
@@ -1241,7 +1325,9 @@ static void io_callback(void *context, struct fib * fibptr)
u32 cid;
scsicmd = (struct scsi_cmnd *) context;
- scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
+
+ if (!aac_valid_context(scsicmd, fibptr))
+ return;
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
cid = scmd_id(scsicmd);
@@ -1317,7 +1403,7 @@ static void io_callback(void *context, struct fib * fibptr)
scsicmd->scsi_done(scsicmd);
}
-static int aac_read(struct scsi_cmnd * scsicmd, int cid)
+static int aac_read(struct scsi_cmnd * scsicmd)
{
u64 lba;
u32 count;
@@ -1331,7 +1417,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
*/
switch (scsicmd->cmnd[0]) {
case READ_6:
- dprintk((KERN_DEBUG "aachba: received a read(6) command on id %d.\n", cid));
+ dprintk((KERN_DEBUG "aachba: received a read(6) command on id %d.\n", scmd_id(scsicmd)));
lba = ((scsicmd->cmnd[1] & 0x1F) << 16) |
(scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
@@ -1341,7 +1427,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
count = 256;
break;
case READ_16:
- dprintk((KERN_DEBUG "aachba: received a read(16) command on id %d.\n", cid));
+ dprintk((KERN_DEBUG "aachba: received a read(16) command on id %d.\n", scmd_id(scsicmd)));
lba = ((u64)scsicmd->cmnd[2] << 56) |
((u64)scsicmd->cmnd[3] << 48) |
@@ -1355,7 +1441,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
(scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13];
break;
case READ_12:
- dprintk((KERN_DEBUG "aachba: received a read(12) command on id %d.\n", cid));
+ dprintk((KERN_DEBUG "aachba: received a read(12) command on id %d.\n", scmd_id(scsicmd)));
lba = ((u64)scsicmd->cmnd[2] << 24) |
(scsicmd->cmnd[3] << 16) |
@@ -1365,7 +1451,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
(scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
break;
default:
- dprintk((KERN_DEBUG "aachba: received a read(10) command on id %d.\n", cid));
+ dprintk((KERN_DEBUG "aachba: received a read(10) command on id %d.\n", scmd_id(scsicmd)));
lba = ((u64)scsicmd->cmnd[2] << 24) |
(scsicmd->cmnd[3] << 16) |
@@ -1405,7 +1491,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
return 0;
}
-static int aac_write(struct scsi_cmnd * scsicmd, int cid)
+static int aac_write(struct scsi_cmnd * scsicmd)
{
u64 lba;
u32 count;
@@ -1424,7 +1510,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
if (count == 0)
count = 256;
} else if (scsicmd->cmnd[0] == WRITE_16) { /* 16 byte command */
- dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", cid));
+ dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", scmd_id(scsicmd)));
lba = ((u64)scsicmd->cmnd[2] << 56) |
((u64)scsicmd->cmnd[3] << 48) |
@@ -1436,14 +1522,14 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
count = (scsicmd->cmnd[10] << 24) | (scsicmd->cmnd[11] << 16) |
(scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13];
} else if (scsicmd->cmnd[0] == WRITE_12) { /* 12 byte command */
- dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", cid));
+ dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", scmd_id(scsicmd)));
lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16)
| (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
count = (scsicmd->cmnd[6] << 24) | (scsicmd->cmnd[7] << 16)
| (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
} else {
- dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", cid));
+ dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", scmd_id(scsicmd)));
lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
}
@@ -1488,7 +1574,9 @@ static void synchronize_callback(void *context, struct fib *fibptr)
struct scsi_cmnd *cmd;
cmd = context;
- cmd->SCp.phase = AAC_OWNER_MIDLEVEL;
+
+ if (!aac_valid_context(cmd, fibptr))
+ return;
dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n",
smp_processor_id(), jiffies));
@@ -1523,7 +1611,7 @@ static void synchronize_callback(void *context, struct fib *fibptr)
cmd->scsi_done(cmd);
}
-static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
+static int aac_synchronize(struct scsi_cmnd *scsicmd)
{
int status;
struct fib *cmd_fibcontext;
@@ -1568,7 +1656,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
synchronizecmd = fib_data(cmd_fibcontext);
synchronizecmd->command = cpu_to_le32(VM_ContainerConfig);
synchronizecmd->type = cpu_to_le32(CT_FLUSH_CACHE);
- synchronizecmd->cid = cpu_to_le32(cid);
+ synchronizecmd->cid = cpu_to_le32(scmd_id(scsicmd));
synchronizecmd->count =
cpu_to_le32(sizeof(((struct aac_synchronize_reply *)NULL)->data));
@@ -1646,29 +1734,12 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
case TEST_UNIT_READY:
if (dev->in_reset)
return -1;
- spin_unlock_irq(host->host_lock);
- aac_probe_container(dev, cid);
- if ((fsa_dev_ptr[cid].valid & 1) == 0)
- fsa_dev_ptr[cid].valid = 0;
- spin_lock_irq(host->host_lock);
- if (fsa_dev_ptr[cid].valid == 0) {
- scsicmd->result = DID_NO_CONNECT << 16;
- scsicmd->scsi_done(scsicmd);
- return 0;
- }
+ return _aac_probe_container(scsicmd,
+ aac_probe_container_callback2);
default:
break;
}
}
- /*
- * If the target container still doesn't exist,
- * return failure
- */
- if (fsa_dev_ptr[cid].valid == 0) {
- scsicmd->result = DID_BAD_TARGET << 16;
- scsicmd->scsi_done(scsicmd);
- return 0;
- }
} else { /* check for physical non-dasd devices */
if ((dev->nondasd_support == 1) || expose_physicals) {
if (dev->in_reset)
@@ -1733,7 +1804,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type);
inq_data.inqd_pdt = INQD_PDT_DA; /* Direct/random access device */
aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
- return aac_get_container_name(scsicmd, cid);
+ return aac_get_container_name(scsicmd);
}
case SERVICE_ACTION_IN:
if (!(dev->raw_io_interface) ||
@@ -1899,7 +1970,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
min(sizeof(fsa_dev_ptr[cid].devname),
sizeof(scsicmd->request->rq_disk->disk_name) + 1));
- return aac_read(scsicmd, cid);
+ return aac_read(scsicmd);
case WRITE_6:
case WRITE_10:
@@ -1907,11 +1978,11 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
case WRITE_16:
if (dev->in_reset)
return -1;
- return aac_write(scsicmd, cid);
+ return aac_write(scsicmd);
case SYNCHRONIZE_CACHE:
/* Issue FIB to tell Firmware to flush it's cache */
- return aac_synchronize(scsicmd, cid);
+ return aac_synchronize(scsicmd);
default:
/*
@@ -2058,7 +2129,10 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
struct scsi_cmnd *scsicmd;
scsicmd = (struct scsi_cmnd *) context;
- scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
+
+ if (!aac_valid_context(scsicmd, fibptr))
+ return;
+
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
BUG_ON(fibptr == NULL);
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 39ecd0d22eb0..45ca3e801619 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -12,8 +12,8 @@
*----------------------------------------------------------------------------*/
#ifndef AAC_DRIVER_BUILD
-# define AAC_DRIVER_BUILD 2423
-# define AAC_DRIVER_BRANCH "-mh3"
+# define AAC_DRIVER_BUILD 2437
+# define AAC_DRIVER_BRANCH "-mh4"
#endif
#define MAXIMUM_NUM_CONTAINERS 32
@@ -48,49 +48,13 @@ struct diskparm
/*
- * DON'T CHANGE THE ORDER, this is set by the firmware
+ * Firmware constants
*/
#define CT_NONE 0
-#define CT_VOLUME 1
-#define CT_MIRROR 2
-#define CT_STRIPE 3
-#define CT_RAID5 4
-#define CT_SSRW 5
-#define CT_SSRO 6
-#define CT_MORPH 7
-#define CT_PASSTHRU 8
-#define CT_RAID4 9
-#define CT_RAID10 10 /* stripe of mirror */
-#define CT_RAID00 11 /* stripe of stripe */
-#define CT_VOLUME_OF_MIRRORS 12 /* volume of mirror */
-#define CT_PSEUDO_RAID 13 /* really raid4 */
-#define CT_LAST_VOLUME_TYPE 14
#define CT_OK 218
-
-/*
- * Types of objects addressable in some fashion by the client.
- * This is a superset of those objects handled just by the filesystem
- * and includes "raw" objects that an administrator would use to
- * configure containers and filesystems.
- */
-
-#define FT_REG 1 /* regular file */
-#define FT_DIR 2 /* directory */
-#define FT_BLK 3 /* "block" device - reserved */
-#define FT_CHR 4 /* "character special" device - reserved */
-#define FT_LNK 5 /* symbolic link */
-#define FT_SOCK 6 /* socket */
-#define FT_FIFO 7 /* fifo */
#define FT_FILESYS 8 /* ADAPTEC's "FSA"(tm) filesystem */
#define FT_DRIVE 9 /* physical disk - addressable in scsi by bus/id/lun */
-#define FT_SLICE 10 /* virtual disk - raw volume - slice */
-#define FT_PARTITION 11 /* FSA partition - carved out of a slice - building block for containers */
-#define FT_VOLUME 12 /* Container - Volume Set */
-#define FT_STRIPE 13 /* Container - Stripe Set */
-#define FT_MIRROR 14 /* Container - Mirror Set */
-#define FT_RAID5 15 /* Container - Raid 5 Set */
-#define FT_DATABASE 16 /* Storage object with "foreign" content manager */
/*
* Host side memory scatter gather list
@@ -497,6 +461,7 @@ struct adapter_ops
void (*adapter_enable_int)(struct aac_dev *dev);
int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4);
int (*adapter_check_health)(struct aac_dev *dev);
+ int (*adapter_restart)(struct aac_dev *dev, int bled);
/* Transport operations */
int (*adapter_ioremap)(struct aac_dev * dev, u32 size);
irqreturn_t (*adapter_intr)(int irq, void *dev_id);
@@ -833,7 +798,7 @@ struct fib {
*/
struct list_head fiblink;
void *data;
- struct hw_fib *hw_fib; /* Actual shared object */
+ struct hw_fib *hw_fib_va; /* Actual shared object */
dma_addr_t hw_fib_pa; /* physical address of hw_fib*/
};
@@ -878,10 +843,25 @@ struct aac_supplement_adapter_info
__le32 Version;
__le32 FeatureBits;
u8 SlotNumber;
- u8 ReservedPad0[0];
+ u8 ReservedPad0[3];
u8 BuildDate[12];
__le32 CurrentNumberPorts;
- __le32 ReservedGrowth[24];
+ struct {
+ u8 AssemblyPn[8];
+ u8 FruPn[8];
+ u8 BatteryFruPn[8];
+ u8 EcVersionString[8];
+ u8 Tsid[12];
+ } VpdInfo;
+ __le32 FlashFirmwareRevision;
+ __le32 FlashFirmwareBuild;
+ __le32 RaidTypeMorphOptions;
+ __le32 FlashFirmwareBootRevision;
+ __le32 FlashFirmwareBootBuild;
+ u8 MfgPcbaSerialNo[12];
+ u8 MfgWWNName[8];
+ __le32 MoreFeatureBits;
+ __le32 ReservedGrowth[1];
};
#define AAC_FEATURE_FALCON 0x00000010
#define AAC_SIS_VERSION_V3 3
@@ -970,7 +950,6 @@ struct aac_dev
struct fib *fibs;
struct fib *free_fib;
- struct fib *timeout_fib;
spinlock_t fib_lock;
struct aac_queue_block *queues;
@@ -1060,6 +1039,9 @@ struct aac_dev
#define aac_adapter_check_health(dev) \
(dev)->a_ops.adapter_check_health(dev)
+#define aac_adapter_restart(dev,bled) \
+ (dev)->a_ops.adapter_restart(dev,bled)
+
#define aac_adapter_ioremap(dev, size) \
(dev)->a_ops.adapter_ioremap(dev, size)
@@ -1516,8 +1498,7 @@ struct aac_mntent {
struct creation_info create_info; /* if applicable */
__le32 capacity;
__le32 vol; /* substrate structure */
- __le32 obj; /* FT_FILESYS,
- FT_DATABASE, etc. */
+ __le32 obj; /* FT_FILESYS, etc. */
__le32 state; /* unready for mounting,
readonly, etc. */
union aac_contentinfo fileinfo; /* Info specific to content
@@ -1817,7 +1798,7 @@ int aac_fib_send(u16 command, struct fib * context, unsigned long size, int prio
int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry);
void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum);
int aac_fib_complete(struct fib * context);
-#define fib_data(fibctx) ((void *)(fibctx)->hw_fib->data)
+#define fib_data(fibctx) ((void *)(fibctx)->hw_fib_va->data)
struct aac_dev *aac_init_adapter(struct aac_dev *dev);
int aac_get_config_status(struct aac_dev *dev, int commit_flag);
int aac_get_containers(struct aac_dev *dev);
@@ -1840,8 +1821,11 @@ struct aac_driver_ident* aac_get_driver_ident(int devtype);
int aac_get_adapter_info(struct aac_dev* dev);
int aac_send_shutdown(struct aac_dev *dev);
int aac_probe_container(struct aac_dev *dev, int cid);
+int _aac_rx_init(struct aac_dev *dev);
+int aac_rx_select_comm(struct aac_dev *dev, int comm);
extern int numacb;
extern int acbsize;
extern char aac_driver_version[];
extern int startup_timeout;
extern int aif_timeout;
+extern int expose_physicals;
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index e21070f4eac1..72b0393b4596 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -5,7 +5,7 @@
* based on the old aacraid driver that is..
* Adaptec aacraid device driver for Linux.
*
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -64,12 +64,15 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
unsigned size;
int retval;
+ if (dev->in_reset) {
+ return -EBUSY;
+ }
fibptr = aac_fib_alloc(dev);
if(fibptr == NULL) {
return -ENOMEM;
}
- kfib = fibptr->hw_fib;
+ kfib = fibptr->hw_fib_va;
/*
* First copy in the header so that we can check the size field.
*/
@@ -91,9 +94,9 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
goto cleanup;
}
/* Highjack the hw_fib */
- hw_fib = fibptr->hw_fib;
+ hw_fib = fibptr->hw_fib_va;
hw_fib_pa = fibptr->hw_fib_pa;
- fibptr->hw_fib = kfib = pci_alloc_consistent(dev->pdev, size, &fibptr->hw_fib_pa);
+ fibptr->hw_fib_va = kfib = pci_alloc_consistent(dev->pdev, size, &fibptr->hw_fib_pa);
memset(((char *)kfib) + dev->max_fib_size, 0, size - dev->max_fib_size);
memcpy(kfib, hw_fib, dev->max_fib_size);
}
@@ -137,7 +140,7 @@ cleanup:
if (hw_fib) {
pci_free_consistent(dev->pdev, size, kfib, fibptr->hw_fib_pa);
fibptr->hw_fib_pa = hw_fib_pa;
- fibptr->hw_fib = hw_fib;
+ fibptr->hw_fib_va = hw_fib;
}
if (retval != -EINTR)
aac_fib_free(fibptr);
@@ -282,15 +285,15 @@ return_fib:
fib = list_entry(entry, struct fib, fiblink);
fibctx->count--;
spin_unlock_irqrestore(&dev->fib_lock, flags);
- if (copy_to_user(f.fib, fib->hw_fib, sizeof(struct hw_fib))) {
- kfree(fib->hw_fib);
+ if (copy_to_user(f.fib, fib->hw_fib_va, sizeof(struct hw_fib))) {
+ kfree(fib->hw_fib_va);
kfree(fib);
return -EFAULT;
}
/*
* Free the space occupied by this copy of the fib.
*/
- kfree(fib->hw_fib);
+ kfree(fib->hw_fib_va);
kfree(fib);
status = 0;
} else {
@@ -340,7 +343,7 @@ int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context * fibctx)
/*
* Free the space occupied by this copy of the fib.
*/
- kfree(fib->hw_fib);
+ kfree(fib->hw_fib_va);
kfree(fib);
}
/*
@@ -388,10 +391,8 @@ static int close_getadapter_fib(struct aac_dev * dev, void __user *arg)
/*
* Extract the fibctx from the input parameters
*/
- if (fibctx->unique == (u32)(unsigned long)arg) {
- /* We found a winner */
+ if (fibctx->unique == (u32)(ptrdiff_t)arg) /* We found a winner */
break;
- }
entry = entry->next;
fibctx = NULL;
}
@@ -465,16 +466,20 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
void *sg_list[32];
u32 sg_indx = 0;
u32 byte_count = 0;
- u32 actual_fibsize = 0;
+ u32 actual_fibsize64, actual_fibsize = 0;
int i;
+ if (dev->in_reset) {
+ dprintk((KERN_DEBUG"aacraid: send raw srb -EBUSY\n"));
+ return -EBUSY;
+ }
if (!capable(CAP_SYS_ADMIN)){
dprintk((KERN_DEBUG"aacraid: No permission to send raw srb\n"));
return -EPERM;
}
/*
- * Allocate and initialize a Fib then setup a BlockWrite command
+ * Allocate and initialize a Fib then setup a SRB command
*/
if (!(srbfib = aac_fib_alloc(dev))) {
return -ENOMEM;
@@ -541,129 +546,183 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
rcode = -EINVAL;
goto cleanup;
}
- if (dev->dac_support == 1) {
+ actual_fibsize = sizeof(struct aac_srb) - sizeof(struct sgentry) +
+ ((user_srbcmd->sg.count & 0xff) * sizeof(struct sgentry));
+ actual_fibsize64 = actual_fibsize + (user_srbcmd->sg.count & 0xff) *
+ (sizeof(struct sgentry64) - sizeof(struct sgentry));
+ /* User made a mistake - should not continue */
+ if ((actual_fibsize != fibsize) && (actual_fibsize64 != fibsize)) {
+ dprintk((KERN_DEBUG"aacraid: Bad Size specified in "
+ "Raw SRB command calculated fibsize=%lu;%lu "
+ "user_srbcmd->sg.count=%d aac_srb=%lu sgentry=%lu;%lu "
+ "issued fibsize=%d\n",
+ actual_fibsize, actual_fibsize64, user_srbcmd->sg.count,
+ sizeof(struct aac_srb), sizeof(struct sgentry),
+ sizeof(struct sgentry64), fibsize));
+ rcode = -EINVAL;
+ goto cleanup;
+ }
+ if ((data_dir == DMA_NONE) && user_srbcmd->sg.count) {
+ dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
+ rcode = -EINVAL;
+ goto cleanup;
+ }
+ byte_count = 0;
+ if (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64) {
struct user_sgmap64* upsg = (struct user_sgmap64*)&user_srbcmd->sg;
struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg;
- struct user_sgmap* usg;
- byte_count = 0;
/*
* This should also catch if user used the 32 bit sgmap
*/
- actual_fibsize = sizeof(struct aac_srb) -
- sizeof(struct sgentry) +
- ((upsg->count & 0xff) *
- sizeof(struct sgentry));
- if(actual_fibsize != fibsize){ // User made a mistake - should not continue
- dprintk((KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n"));
- rcode = -EINVAL;
- goto cleanup;
- }
- usg = kmalloc(actual_fibsize - sizeof(struct aac_srb)
- + sizeof(struct sgmap), GFP_KERNEL);
- if (!usg) {
- dprintk((KERN_DEBUG"aacraid: Allocation error in Raw SRB command\n"));
- rcode = -ENOMEM;
- goto cleanup;
- }
- memcpy (usg, upsg, actual_fibsize - sizeof(struct aac_srb)
- + sizeof(struct sgmap));
- actual_fibsize = sizeof(struct aac_srb) -
- sizeof(struct sgentry) + ((usg->count & 0xff) *
- sizeof(struct sgentry64));
- if ((data_dir == DMA_NONE) && upsg->count) {
- kfree (usg);
- dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
- rcode = -EINVAL;
- goto cleanup;
- }
+ if (actual_fibsize64 == fibsize) {
+ actual_fibsize = actual_fibsize64;
+ for (i = 0; i < upsg->count; i++) {
+ u64 addr;
+ void* p;
+ /* Does this really need to be GFP_DMA? */
+ p = kmalloc(upsg->sg[i].count,GFP_KERNEL|__GFP_DMA);
+ if(p == 0) {
+ dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
+ upsg->sg[i].count,i,upsg->count));
+ rcode = -ENOMEM;
+ goto cleanup;
+ }
+ addr = (u64)upsg->sg[i].addr[0];
+ addr += ((u64)upsg->sg[i].addr[1]) << 32;
+ sg_user[i] = (void __user *)(ptrdiff_t)addr;
+ sg_list[i] = p; // save so we can clean up later
+ sg_indx = i;
+
+ if( flags & SRB_DataOut ){
+ if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){
+ dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
+ rcode = -EFAULT;
+ goto cleanup;
+ }
+ }
+ addr = pci_map_single(dev->pdev, p, upsg->sg[i].count, data_dir);
- for (i = 0; i < usg->count; i++) {
- u64 addr;
- void* p;
- /* Does this really need to be GFP_DMA? */
- p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);
- if(p == 0) {
- kfree (usg);
- dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
- usg->sg[i].count,i,usg->count));
+ psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
+ psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
+ byte_count += upsg->sg[i].count;
+ psg->sg[i].count = cpu_to_le32(upsg->sg[i].count);
+ }
+ } else {
+ struct user_sgmap* usg;
+ usg = kmalloc(actual_fibsize - sizeof(struct aac_srb)
+ + sizeof(struct sgmap), GFP_KERNEL);
+ if (!usg) {
+ dprintk((KERN_DEBUG"aacraid: Allocation error in Raw SRB command\n"));
rcode = -ENOMEM;
goto cleanup;
}
- sg_user[i] = (void __user *)(long)usg->sg[i].addr;
- sg_list[i] = p; // save so we can clean up later
- sg_indx = i;
-
- if( flags & SRB_DataOut ){
- if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){
+ memcpy (usg, upsg, actual_fibsize - sizeof(struct aac_srb)
+ + sizeof(struct sgmap));
+ actual_fibsize = actual_fibsize64;
+
+ for (i = 0; i < usg->count; i++) {
+ u64 addr;
+ void* p;
+ /* Does this really need to be GFP_DMA? */
+ p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);
+ if(p == 0) {
kfree (usg);
- dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
- rcode = -EFAULT;
+ dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
+ usg->sg[i].count,i,usg->count));
+ rcode = -ENOMEM;
goto cleanup;
}
- }
- addr = pci_map_single(dev->pdev, p, usg->sg[i].count, data_dir);
+ sg_user[i] = (void __user *)(ptrdiff_t)usg->sg[i].addr;
+ sg_list[i] = p; // save so we can clean up later
+ sg_indx = i;
+
+ if( flags & SRB_DataOut ){
+ if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){
+ kfree (usg);
+ dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
+ rcode = -EFAULT;
+ goto cleanup;
+ }
+ }
+ addr = pci_map_single(dev->pdev, p, usg->sg[i].count, data_dir);
- psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
- psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
- psg->sg[i].count = cpu_to_le32(usg->sg[i].count);
- byte_count += usg->sg[i].count;
+ psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
+ psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
+ byte_count += usg->sg[i].count;
+ psg->sg[i].count = cpu_to_le32(usg->sg[i].count);
+ }
+ kfree (usg);
}
- kfree (usg);
-
srbcmd->count = cpu_to_le32(byte_count);
psg->count = cpu_to_le32(sg_indx+1);
status = aac_fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL);
} else {
struct user_sgmap* upsg = &user_srbcmd->sg;
struct sgmap* psg = &srbcmd->sg;
- byte_count = 0;
-
- actual_fibsize = sizeof (struct aac_srb) + (((user_srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry));
- if(actual_fibsize != fibsize){ // User made a mistake - should not continue
- dprintk((KERN_DEBUG"aacraid: Bad Size specified in "
- "Raw SRB command calculated fibsize=%d "
- "user_srbcmd->sg.count=%d aac_srb=%d sgentry=%d "
- "issued fibsize=%d\n",
- actual_fibsize, user_srbcmd->sg.count,
- sizeof(struct aac_srb), sizeof(struct sgentry),
- fibsize));
- rcode = -EINVAL;
- goto cleanup;
- }
- if ((data_dir == DMA_NONE) && upsg->count) {
- dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
- rcode = -EINVAL;
- goto cleanup;
- }
- for (i = 0; i < upsg->count; i++) {
- dma_addr_t addr;
- void* p;
- p = kmalloc(upsg->sg[i].count, GFP_KERNEL);
- if(p == 0) {
- dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
- upsg->sg[i].count, i, upsg->count));
- rcode = -ENOMEM;
- goto cleanup;
- }
- sg_user[i] = (void __user *)(long)upsg->sg[i].addr;
- sg_list[i] = p; // save so we can clean up later
- sg_indx = i;
-
- if( flags & SRB_DataOut ){
- if(copy_from_user(p, sg_user[i],
- upsg->sg[i].count)) {
- dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
- rcode = -EFAULT;
+
+ if (actual_fibsize64 == fibsize) {
+ struct user_sgmap64* usg = (struct user_sgmap64 *)upsg;
+ for (i = 0; i < upsg->count; i++) {
+ u64 addr;
+ void* p;
+ /* Does this really need to be GFP_DMA? */
+ p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);
+ if(p == 0) {
+ dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
+ usg->sg[i].count,i,usg->count));
+ rcode = -ENOMEM;
goto cleanup;
}
+ addr = (u64)usg->sg[i].addr[0];
+ addr += ((u64)usg->sg[i].addr[1]) << 32;
+ sg_user[i] = (void __user *)(ptrdiff_t)addr;
+ sg_list[i] = p; // save so we can clean up later
+ sg_indx = i;
+
+ if( flags & SRB_DataOut ){
+ if(copy_from_user(p,sg_user[i],usg->sg[i].count)){
+ dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
+ rcode = -EFAULT;
+ goto cleanup;
+ }
+ }
+ addr = pci_map_single(dev->pdev, p, usg->sg[i].count, data_dir);
+
+ psg->sg[i].addr = cpu_to_le32(addr & 0xffffffff);
+ byte_count += usg->sg[i].count;
+ psg->sg[i].count = cpu_to_le32(usg->sg[i].count);
}
- addr = pci_map_single(dev->pdev, p,
- upsg->sg[i].count, data_dir);
+ } else {
+ for (i = 0; i < upsg->count; i++) {
+ dma_addr_t addr;
+ void* p;
+ p = kmalloc(upsg->sg[i].count, GFP_KERNEL);
+ if(p == 0) {
+ dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
+ upsg->sg[i].count, i, upsg->count));
+ rcode = -ENOMEM;
+ goto cleanup;
+ }
+ sg_user[i] = (void __user *)(ptrdiff_t)upsg->sg[i].addr;
+ sg_list[i] = p; // save so we can clean up later
+ sg_indx = i;
+
+ if( flags & SRB_DataOut ){
+ if(copy_from_user(p, sg_user[i],
+ upsg->sg[i].count)) {
+ dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
+ rcode = -EFAULT;
+ goto cleanup;
+ }
+ }
+ addr = pci_map_single(dev->pdev, p,
+ upsg->sg[i].count, data_dir);
- psg->sg[i].addr = cpu_to_le32(addr);
- psg->sg[i].count = cpu_to_le32(upsg->sg[i].count);
- byte_count += upsg->sg[i].count;
+ psg->sg[i].addr = cpu_to_le32(addr);
+ byte_count += upsg->sg[i].count;
+ psg->sg[i].count = cpu_to_le32(upsg->sg[i].count);
+ }
}
srbcmd->count = cpu_to_le32(byte_count);
psg->count = cpu_to_le32(sg_indx+1);
@@ -682,7 +741,8 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
if( flags & SRB_DataIn ) {
for(i = 0 ; i <= sg_indx; i++){
- byte_count = le32_to_cpu((dev->dac_support == 1)
+ byte_count = le32_to_cpu(
+ (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)
? ((struct sgmap64*)&srbcmd->sg)->sg[i].count
: srbcmd->sg.sg[i].count);
if(copy_to_user(sg_user[i], sg_list[i], byte_count)){
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index ae34768987a4..33682ce96a5d 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -5,7 +5,7 @@
* based on the old aacraid driver that is..
* Adaptec aacraid device driver for Linux.
*
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -110,7 +110,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
/*
* Align the beginning of Headers to commalign
*/
- align = (commalign - ((unsigned long)(base) & (commalign - 1)));
+ align = (commalign - ((ptrdiff_t)(base) & (commalign - 1)));
base = base + align;
phys = phys + align;
/*
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 1b97f60652ba..5824a757a753 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -5,7 +5,7 @@
* based on the old aacraid driver that is..
* Adaptec aacraid device driver for Linux.
*
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -94,7 +94,7 @@ void aac_fib_map_free(struct aac_dev *dev)
int aac_fib_setup(struct aac_dev * dev)
{
struct fib *fibptr;
- struct hw_fib *hw_fib_va;
+ struct hw_fib *hw_fib;
dma_addr_t hw_fib_pa;
int i;
@@ -106,24 +106,24 @@ int aac_fib_setup(struct aac_dev * dev)
if (i<0)
return -ENOMEM;
- hw_fib_va = dev->hw_fib_va;
+ hw_fib = dev->hw_fib_va;
hw_fib_pa = dev->hw_fib_pa;
- memset(hw_fib_va, 0, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB));
+ memset(hw_fib, 0, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB));
/*
* Initialise the fibs
*/
for (i = 0, fibptr = &dev->fibs[i]; i < (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); i++, fibptr++)
{
fibptr->dev = dev;
- fibptr->hw_fib = hw_fib_va;
- fibptr->data = (void *) fibptr->hw_fib->data;
+ fibptr->hw_fib_va = hw_fib;
+ fibptr->data = (void *) fibptr->hw_fib_va->data;
fibptr->next = fibptr+1; /* Forward chain the fibs */
init_MUTEX_LOCKED(&fibptr->event_wait);
spin_lock_init(&fibptr->event_lock);
- hw_fib_va->header.XferState = cpu_to_le32(0xffffffff);
- hw_fib_va->header.SenderSize = cpu_to_le16(dev->max_fib_size);
+ hw_fib->header.XferState = cpu_to_le32(0xffffffff);
+ hw_fib->header.SenderSize = cpu_to_le16(dev->max_fib_size);
fibptr->hw_fib_pa = hw_fib_pa;
- hw_fib_va = (struct hw_fib *)((unsigned char *)hw_fib_va + dev->max_fib_size);
+ hw_fib = (struct hw_fib *)((unsigned char *)hw_fib + dev->max_fib_size);
hw_fib_pa = hw_fib_pa + dev->max_fib_size;
}
/*
@@ -166,7 +166,7 @@ struct fib *aac_fib_alloc(struct aac_dev *dev)
* Null out fields that depend on being zero at the start of
* each I/O
*/
- fibptr->hw_fib->header.XferState = 0;
+ fibptr->hw_fib_va->header.XferState = 0;
fibptr->callback = NULL;
fibptr->callback_data = NULL;
@@ -178,7 +178,6 @@ struct fib *aac_fib_alloc(struct aac_dev *dev)
* @fibptr: fib to free up
*
* Frees up a fib and places it on the appropriate queue
- * (either free or timed out)
*/
void aac_fib_free(struct fib *fibptr)
@@ -186,19 +185,15 @@ void aac_fib_free(struct fib *fibptr)
unsigned long flags;
spin_lock_irqsave(&fibptr->dev->fib_lock, flags);
- if (fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT) {
+ if (unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT))
aac_config.fib_timeouts++;
- fibptr->next = fibptr->dev->timeout_fib;
- fibptr->dev->timeout_fib = fibptr;
- } else {
- if (fibptr->hw_fib->header.XferState != 0) {
- printk(KERN_WARNING "aac_fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n",
- (void*)fibptr,
- le32_to_cpu(fibptr->hw_fib->header.XferState));
- }
- fibptr->next = fibptr->dev->free_fib;
- fibptr->dev->free_fib = fibptr;
- }
+ if (fibptr->hw_fib_va->header.XferState != 0) {
+ printk(KERN_WARNING "aac_fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n",
+ (void*)fibptr,
+ le32_to_cpu(fibptr->hw_fib_va->header.XferState));
+ }
+ fibptr->next = fibptr->dev->free_fib;
+ fibptr->dev->free_fib = fibptr;
spin_unlock_irqrestore(&fibptr->dev->fib_lock, flags);
}
@@ -211,7 +206,7 @@ void aac_fib_free(struct fib *fibptr)
void aac_fib_init(struct fib *fibptr)
{
- struct hw_fib *hw_fib = fibptr->hw_fib;
+ struct hw_fib *hw_fib = fibptr->hw_fib_va;
hw_fib->header.StructType = FIB_MAGIC;
hw_fib->header.Size = cpu_to_le16(fibptr->dev->max_fib_size);
@@ -231,7 +226,7 @@ void aac_fib_init(struct fib *fibptr)
static void fib_dealloc(struct fib * fibptr)
{
- struct hw_fib *hw_fib = fibptr->hw_fib;
+ struct hw_fib *hw_fib = fibptr->hw_fib_va;
BUG_ON(hw_fib->header.StructType != FIB_MAGIC);
hw_fib->header.XferState = 0;
}
@@ -386,7 +381,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
void *callback_data)
{
struct aac_dev * dev = fibptr->dev;
- struct hw_fib * hw_fib = fibptr->hw_fib;
+ struct hw_fib * hw_fib = fibptr->hw_fib_va;
unsigned long flags = 0;
unsigned long qflags;
@@ -430,7 +425,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
*/
hw_fib->header.Command = cpu_to_le16(command);
hw_fib->header.XferState |= cpu_to_le32(SentFromHost);
- fibptr->hw_fib->header.Flags = 0; /* 0 the flags field - internal only*/
+ fibptr->hw_fib_va->header.Flags = 0; /* 0 the flags field - internal only*/
/*
* Set the size of the Fib we want to send to the adapter
*/
@@ -462,7 +457,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
dprintk((KERN_DEBUG " Command = %d.\n", le32_to_cpu(hw_fib->header.Command)));
dprintk((KERN_DEBUG " SubCommand = %d.\n", le32_to_cpu(((struct aac_query_mount *)fib_data(fibptr))->command)));
dprintk((KERN_DEBUG " XferState = %x.\n", le32_to_cpu(hw_fib->header.XferState)));
- dprintk((KERN_DEBUG " hw_fib va being sent=%p\n",fibptr->hw_fib));
+ dprintk((KERN_DEBUG " hw_fib va being sent=%p\n",fibptr->hw_fib_va));
dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa));
dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr));
@@ -513,22 +508,20 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
}
udelay(5);
}
- } else if (down_interruptible(&fibptr->event_wait)) {
- spin_lock_irqsave(&fibptr->event_lock, flags);
- if (fibptr->done == 0) {
- fibptr->done = 2; /* Tell interrupt we aborted */
- spin_unlock_irqrestore(&fibptr->event_lock, flags);
- return -EINTR;
- }
+ } else
+ (void)down_interruptible(&fibptr->event_wait);
+ spin_lock_irqsave(&fibptr->event_lock, flags);
+ if (fibptr->done == 0) {
+ fibptr->done = 2; /* Tell interrupt we aborted */
spin_unlock_irqrestore(&fibptr->event_lock, flags);
+ return -EINTR;
}
+ spin_unlock_irqrestore(&fibptr->event_lock, flags);
BUG_ON(fibptr->done == 0);
- if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)){
+ if(unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT))
return -ETIMEDOUT;
- } else {
- return 0;
- }
+ return 0;
}
/*
* If the user does not want a response than return success otherwise
@@ -624,7 +617,7 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid)
int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size)
{
- struct hw_fib * hw_fib = fibptr->hw_fib;
+ struct hw_fib * hw_fib = fibptr->hw_fib_va;
struct aac_dev * dev = fibptr->dev;
struct aac_queue * q;
unsigned long nointr = 0;
@@ -688,7 +681,7 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size)
int aac_fib_complete(struct fib *fibptr)
{
- struct hw_fib * hw_fib = fibptr->hw_fib;
+ struct hw_fib * hw_fib = fibptr->hw_fib_va;
/*
* Check for a fib which has already been completed
@@ -774,9 +767,8 @@ void aac_printf(struct aac_dev *dev, u32 val)
#define AIF_SNIFF_TIMEOUT (30*HZ)
static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
{
- struct hw_fib * hw_fib = fibptr->hw_fib;
+ struct hw_fib * hw_fib = fibptr->hw_fib_va;
struct aac_aifcmd * aifcmd = (struct aac_aifcmd *)hw_fib->data;
- int busy;
u32 container;
struct scsi_device *device;
enum {
@@ -988,9 +980,6 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
* behind you.
*/
- busy = 0;
-
-
/*
* Find the scsi_device associated with the SCSI address,
* and mark it as changed, invalidating the cache. This deals
@@ -1035,7 +1024,6 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
static int _aac_reset_adapter(struct aac_dev *aac)
{
int index, quirks;
- u32 ret;
int retval;
struct Scsi_Host *host;
struct scsi_device *dev;
@@ -1059,35 +1047,29 @@ static int _aac_reset_adapter(struct aac_dev *aac)
* If a positive health, means in a known DEAD PANIC
* state and the adapter could be reset to `try again'.
*/
- retval = aac_adapter_check_health(aac);
- if (retval == 0)
- retval = aac_adapter_sync_cmd(aac, IOP_RESET_ALWAYS,
- 0, 0, 0, 0, 0, 0, &ret, NULL, NULL, NULL, NULL);
- if (retval)
- retval = aac_adapter_sync_cmd(aac, IOP_RESET,
- 0, 0, 0, 0, 0, 0, &ret, NULL, NULL, NULL, NULL);
+ retval = aac_adapter_restart(aac, aac_adapter_check_health(aac));
if (retval)
goto out;
- if (ret != 0x00000001) {
- retval = -ENODEV;
- goto out;
- }
/*
* Loop through the fibs, close the synchronous FIBS
*/
- for (index = 0; index < (aac->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); index++) {
+ for (retval = 1, index = 0; index < (aac->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); index++) {
struct fib *fib = &aac->fibs[index];
- if (!(fib->hw_fib->header.XferState & cpu_to_le32(NoResponseExpected | Async)) &&
- (fib->hw_fib->header.XferState & cpu_to_le32(ResponseExpected))) {
+ if (!(fib->hw_fib_va->header.XferState & cpu_to_le32(NoResponseExpected | Async)) &&
+ (fib->hw_fib_va->header.XferState & cpu_to_le32(ResponseExpected))) {
unsigned long flagv;
spin_lock_irqsave(&fib->event_lock, flagv);
up(&fib->event_wait);
spin_unlock_irqrestore(&fib->event_lock, flagv);
schedule();
+ retval = 0;
}
}
+ /* Give some extra time for ioctls to complete. */
+ if (retval == 0)
+ ssleep(2);
index = aac->cardtype;
/*
@@ -1248,7 +1230,7 @@ int aac_check_health(struct aac_dev * aac)
memset(hw_fib, 0, sizeof(struct hw_fib));
memset(fib, 0, sizeof(struct fib));
- fib->hw_fib = hw_fib;
+ fib->hw_fib_va = hw_fib;
fib->dev = aac;
aac_fib_init(fib);
fib->type = FSAFS_NTC_FIB_CONTEXT;
@@ -1354,11 +1336,11 @@ int aac_command_thread(void *data)
* do anything at this point since we don't have
* anything defined for this thread to do.
*/
- hw_fib = fib->hw_fib;
+ hw_fib = fib->hw_fib_va;
memset(fib, 0, sizeof(struct fib));
fib->type = FSAFS_NTC_FIB_CONTEXT;
fib->size = sizeof( struct fib );
- fib->hw_fib = hw_fib;
+ fib->hw_fib_va = hw_fib;
fib->data = hw_fib->data;
fib->dev = dev;
/*
@@ -1485,7 +1467,7 @@ int aac_command_thread(void *data)
*/
memcpy(hw_newfib, hw_fib, sizeof(struct hw_fib));
memcpy(newfib, fib, sizeof(struct fib));
- newfib->hw_fib = hw_newfib;
+ newfib->hw_fib_va = hw_newfib;
/*
* Put the FIB onto the
* fibctx's fibs
diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c
index d38b628be1ad..42c7dcda6d9b 100644
--- a/drivers/scsi/aacraid/dpcsup.c
+++ b/drivers/scsi/aacraid/dpcsup.c
@@ -5,7 +5,7 @@
* based on the old aacraid driver that is..
* Adaptec aacraid device driver for Linux.
*
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,7 +32,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
-#include <linux/pci.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/completion.h>
@@ -73,7 +72,7 @@ unsigned int aac_response_normal(struct aac_queue * q)
u32 index = le32_to_cpu(entry->addr);
fast = index & 0x01;
fib = &dev->fibs[index >> 2];
- hwfib = fib->hw_fib;
+ hwfib = fib->hw_fib_va;
aac_consumer_free(dev, q, HostNormRespQueue);
/*
@@ -84,11 +83,13 @@ unsigned int aac_response_normal(struct aac_queue * q)
* continue. The caller has already been notified that
* the fib timed out.
*/
- if (!(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT))
- dev->queues->queue[AdapNormCmdQueue].numpending--;
- else {
- printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags);
- printk(KERN_DEBUG"aacraid: hwfib=%p fib index=%i fib=%p\n",hwfib, hwfib->header.SenderData,fib);
+ dev->queues->queue[AdapNormCmdQueue].numpending--;
+
+ if (unlikely(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) {
+ spin_unlock_irqrestore(q->lock, flags);
+ aac_fib_complete(fib);
+ aac_fib_free(fib);
+ spin_lock_irqsave(q->lock, flags);
continue;
}
spin_unlock_irqrestore(q->lock, flags);
@@ -193,7 +194,7 @@ unsigned int aac_command_normal(struct aac_queue *q)
INIT_LIST_HEAD(&fib->fiblink);
fib->type = FSAFS_NTC_FIB_CONTEXT;
fib->size = sizeof(struct fib);
- fib->hw_fib = hw_fib;
+ fib->hw_fib_va = hw_fib;
fib->data = hw_fib->data;
fib->dev = dev;
@@ -254,12 +255,13 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index)
return 1;
}
memset(hw_fib, 0, sizeof(struct hw_fib));
- memcpy(hw_fib, (struct hw_fib *)(((unsigned long)(dev->regs.sa)) + (index & ~0x00000002L)), sizeof(struct hw_fib));
+ memcpy(hw_fib, (struct hw_fib *)(((ptrdiff_t)(dev->regs.sa)) +
+ (index & ~0x00000002L)), sizeof(struct hw_fib));
memset(fib, 0, sizeof(struct fib));
INIT_LIST_HEAD(&fib->fiblink);
fib->type = FSAFS_NTC_FIB_CONTEXT;
fib->size = sizeof(struct fib);
- fib->hw_fib = hw_fib;
+ fib->hw_fib_va = hw_fib;
fib->data = hw_fib->data;
fib->dev = dev;
@@ -271,7 +273,7 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index)
} else {
int fast = index & 0x01;
struct fib * fib = &dev->fibs[index >> 2];
- struct hw_fib * hwfib = fib->hw_fib;
+ struct hw_fib * hwfib = fib->hw_fib_va;
/*
* Remove this fib from the Outstanding I/O queue.
@@ -281,14 +283,14 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index)
* continue. The caller has already been notified that
* the fib timed out.
*/
- if ((fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) {
- printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags);
- printk(KERN_DEBUG"aacraid: hwfib=%p index=%i fib=%p\n",hwfib, hwfib->header.SenderData,fib);
+ dev->queues->queue[AdapNormCmdQueue].numpending--;
+
+ if (unlikely(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) {
+ aac_fib_complete(fib);
+ aac_fib_free(fib);
return 0;
}
- dev->queues->queue[AdapNormCmdQueue].numpending--;
-
if (fast) {
/*
* Doctor the fib
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 0f948c2fb609..350ea7feb61d 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -5,7 +5,7 @@
* based on the old aacraid driver that is..
* Adaptec aacraid device driver for Linux.
*
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -82,8 +82,6 @@ static LIST_HEAD(aac_devices);
static int aac_cfg_major = -1;
char aac_driver_version[] = AAC_DRIVER_FULL_VERSION;
-extern int expose_physicals;
-
/*
* Because of the way Linux names scsi devices, the order in this table has
* become important. Check for on-board Raid first, add-in cards second.
@@ -247,7 +245,19 @@ static struct aac_driver_ident aac_drivers[] = {
static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{
+ struct Scsi_Host *host = cmd->device->host;
+ struct aac_dev *dev = (struct aac_dev *)host->hostdata;
+ u32 count = 0;
cmd->scsi_done = done;
+ for (; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
+ struct fib * fib = &dev->fibs[count];
+ struct scsi_cmnd * command;
+ if (fib->hw_fib_va->header.XferState &&
+ ((command = fib->callback_data)) &&
+ (command == cmd) &&
+ (cmd->SCp.phase == AAC_OWNER_FIRMWARE))
+ return 0; /* Already owned by Adapter */
+ }
cmd->SCp.phase = AAC_OWNER_LOWLEVEL;
return (aac_scsi_cmd(cmd) ? FAILED : 0);
}
@@ -446,6 +456,40 @@ static int aac_ioctl(struct scsi_device *sdev, int cmd, void __user * arg)
return aac_do_ioctl(dev, cmd, arg);
}
+static int aac_eh_abort(struct scsi_cmnd* cmd)
+{
+ struct scsi_device * dev = cmd->device;
+ struct Scsi_Host * host = dev->host;
+ struct aac_dev * aac = (struct aac_dev *)host->hostdata;
+ int count;
+ int ret = FAILED;
+
+ printk(KERN_ERR "%s: Host adapter abort request (%d,%d,%d,%d)\n",
+ AAC_DRIVERNAME,
+ host->host_no, sdev_channel(dev), sdev_id(dev), dev->lun);
+ switch (cmd->cmnd[0]) {
+ case SERVICE_ACTION_IN:
+ if (!(aac->raw_io_interface) ||
+ !(aac->raw_io_64) ||
+ ((cmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16))
+ break;
+ case INQUIRY:
+ case READ_CAPACITY:
+ case TEST_UNIT_READY:
+ /* Mark associated FIB to not complete, eh handler does this */
+ for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
+ struct fib * fib = &aac->fibs[count];
+ if (fib->hw_fib_va->header.XferState &&
+ (fib->callback_data == cmd)) {
+ fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT;
+ cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER;
+ ret = SUCCESS;
+ }
+ }
+ }
+ return ret;
+}
+
/*
* aac_eh_reset - Reset command handling
* @scsi_cmd: SCSI command block causing the reset
@@ -457,12 +501,20 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
struct Scsi_Host * host = dev->host;
struct scsi_cmnd * command;
int count;
- struct aac_dev * aac;
+ struct aac_dev * aac = (struct aac_dev *)host->hostdata;
unsigned long flags;
+ /* Mark the associated FIB to not complete, eh handler does this */
+ for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
+ struct fib * fib = &aac->fibs[count];
+ if (fib->hw_fib_va->header.XferState &&
+ (fib->callback_data == cmd)) {
+ fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT;
+ cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER;
+ }
+ }
printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n",
AAC_DRIVERNAME);
- aac = (struct aac_dev *)host->hostdata;
if ((count = aac_check_health(aac)))
return count;
@@ -496,7 +548,7 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
ssleep(1);
}
printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME);
- return -ETIMEDOUT;
+ return SUCCESS; /* Cause an immediate retry of the command with a ten second delay after successful tur */
}
/**
@@ -796,6 +848,7 @@ static struct scsi_host_template aac_driver_template = {
.bios_param = aac_biosparm,
.shost_attrs = aac_attrs,
.slave_configure = aac_slave_configure,
+ .eh_abort_handler = aac_eh_abort,
.eh_host_reset_handler = aac_eh_reset,
.can_queue = AAC_NUM_IO_FIB,
.this_id = MAXIMUM_NUM_CONTAINERS,
diff --git a/drivers/scsi/aacraid/nark.c b/drivers/scsi/aacraid/nark.c
index c76b611b6afb..a8ace5677813 100644
--- a/drivers/scsi/aacraid/nark.c
+++ b/drivers/scsi/aacraid/nark.c
@@ -74,9 +74,6 @@ static int aac_nark_ioremap(struct aac_dev * dev, u32 size)
int aac_nark_init(struct aac_dev * dev)
{
- extern int _aac_rx_init(struct aac_dev *dev);
- extern int aac_rx_select_comm(struct aac_dev *dev, int comm);
-
/*
* Fill in the function dispatch table.
*/
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c
index d953c3fe998a..9c5fcfb398c2 100644
--- a/drivers/scsi/aacraid/rkt.c
+++ b/drivers/scsi/aacraid/rkt.c
@@ -45,7 +45,6 @@
static int aac_rkt_select_comm(struct aac_dev *dev, int comm)
{
int retval;
- extern int aac_rx_select_comm(struct aac_dev *dev, int comm);
retval = aac_rx_select_comm(dev, comm);
if (comm == AAC_COMM_MESSAGE) {
/*
@@ -97,8 +96,6 @@ static int aac_rkt_ioremap(struct aac_dev * dev, u32 size)
int aac_rkt_init(struct aac_dev *dev)
{
- extern int _aac_rx_init(struct aac_dev *dev);
-
/*
* Fill in the function dispatch table.
*/
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index d242e2611d67..0c71315cbf1a 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -5,7 +5,7 @@
* based on the old aacraid driver that is..
* Adaptec aacraid device driver for Linux.
*
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -57,25 +57,25 @@ static irqreturn_t aac_rx_intr_producer(int irq, void *dev_id)
* been enabled.
* Check to see if this is our interrupt. If it isn't just return
*/
- if (intstat & ~(dev->OIMR)) {
+ if (likely(intstat & ~(dev->OIMR))) {
bellbits = rx_readl(dev, OutboundDoorbellReg);
- if (bellbits & DoorBellPrintfReady) {
+ if (unlikely(bellbits & DoorBellPrintfReady)) {
aac_printf(dev, readl (&dev->IndexRegs->Mailbox[5]));
rx_writel(dev, MUnit.ODR,DoorBellPrintfReady);
rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
}
- else if (bellbits & DoorBellAdapterNormCmdReady) {
+ else if (unlikely(bellbits & DoorBellAdapterNormCmdReady)) {
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
}
- else if (bellbits & DoorBellAdapterNormRespReady) {
+ else if (likely(bellbits & DoorBellAdapterNormRespReady)) {
rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
}
- else if (bellbits & DoorBellAdapterNormCmdNotFull) {
+ else if (unlikely(bellbits & DoorBellAdapterNormCmdNotFull)) {
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
}
- else if (bellbits & DoorBellAdapterNormRespNotFull) {
+ else if (unlikely(bellbits & DoorBellAdapterNormRespNotFull)) {
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull);
}
@@ -88,11 +88,11 @@ static irqreturn_t aac_rx_intr_message(int irq, void *dev_id)
{
struct aac_dev *dev = dev_id;
u32 Index = rx_readl(dev, MUnit.OutboundQueue);
- if (Index == 0xFFFFFFFFL)
+ if (unlikely(Index == 0xFFFFFFFFL))
Index = rx_readl(dev, MUnit.OutboundQueue);
- if (Index != 0xFFFFFFFFL) {
+ if (likely(Index != 0xFFFFFFFFL)) {
do {
- if (aac_intr_normal(dev, Index)) {
+ if (unlikely(aac_intr_normal(dev, Index))) {
rx_writel(dev, MUnit.OutboundQueue, Index);
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady);
}
@@ -204,7 +204,7 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command,
*/
msleep(1);
}
- if (ok != 1) {
+ if (unlikely(ok != 1)) {
/*
* Restore interrupt mask even though we timed out
*/
@@ -294,7 +294,7 @@ static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event)
* Start up processing on an i960 based AAC adapter
*/
-void aac_rx_start_adapter(struct aac_dev *dev)
+static void aac_rx_start_adapter(struct aac_dev *dev)
{
struct aac_init *init;
@@ -319,12 +319,12 @@ static int aac_rx_check_health(struct aac_dev *dev)
/*
* Check to see if the board failed any self tests.
*/
- if (status & SELF_TEST_FAILED)
+ if (unlikely(status & SELF_TEST_FAILED))
return -1;
/*
* Check to see if the board panic'd.
*/
- if (status & KERNEL_PANIC) {
+ if (unlikely(status & KERNEL_PANIC)) {
char * buffer;
struct POSTSTATUS {
__le32 Post_Command;
@@ -333,15 +333,15 @@ static int aac_rx_check_health(struct aac_dev *dev)
dma_addr_t paddr, baddr;
int ret;
- if ((status & 0xFF000000L) == 0xBC000000L)
+ if (likely((status & 0xFF000000L) == 0xBC000000L))
return (status >> 16) & 0xFF;
buffer = pci_alloc_consistent(dev->pdev, 512, &baddr);
ret = -2;
- if (buffer == NULL)
+ if (unlikely(buffer == NULL))
return ret;
post = pci_alloc_consistent(dev->pdev,
sizeof(struct POSTSTATUS), &paddr);
- if (post == NULL) {
+ if (unlikely(post == NULL)) {
pci_free_consistent(dev->pdev, 512, buffer, baddr);
return ret;
}
@@ -353,7 +353,7 @@ static int aac_rx_check_health(struct aac_dev *dev)
NULL, NULL, NULL, NULL, NULL);
pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
post, paddr);
- if ((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X'))) {
+ if (likely((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X')))) {
ret = (buffer[2] <= '9') ? (buffer[2] - '0') : (buffer[2] - 'A' + 10);
ret <<= 4;
ret += (buffer[3] <= '9') ? (buffer[3] - '0') : (buffer[3] - 'A' + 10);
@@ -364,7 +364,7 @@ static int aac_rx_check_health(struct aac_dev *dev)
/*
* Wait for the adapter to be up and running.
*/
- if (!(status & KERNEL_UP_AND_RUNNING))
+ if (unlikely(!(status & KERNEL_UP_AND_RUNNING)))
return -3;
/*
* Everything is OK
@@ -387,7 +387,7 @@ static int aac_rx_deliver_producer(struct fib * fib)
unsigned long nointr = 0;
spin_lock_irqsave(q->lock, qflags);
- aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib, 1, fib, &nointr);
+ aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib_va, 1, fib, &nointr);
q->numpending++;
*(q->headers.producer) = cpu_to_le32(Index + 1);
@@ -419,9 +419,9 @@ static int aac_rx_deliver_message(struct fib * fib)
spin_unlock_irqrestore(q->lock, qflags);
for(;;) {
Index = rx_readl(dev, MUnit.InboundQueue);
- if (Index == 0xFFFFFFFFL)
+ if (unlikely(Index == 0xFFFFFFFFL))
Index = rx_readl(dev, MUnit.InboundQueue);
- if (Index != 0xFFFFFFFFL)
+ if (likely(Index != 0xFFFFFFFFL))
break;
if (--count == 0) {
spin_lock_irqsave(q->lock, qflags);
@@ -437,7 +437,7 @@ static int aac_rx_deliver_message(struct fib * fib)
device += sizeof(u32);
writel((u32)(addr >> 32), device);
device += sizeof(u32);
- writel(le16_to_cpu(fib->hw_fib->header.Size), device);
+ writel(le16_to_cpu(fib->hw_fib_va->header.Size), device);
rx_writel(dev, MUnit.InboundQueue, Index);
return 0;
}
@@ -460,22 +460,34 @@ static int aac_rx_ioremap(struct aac_dev * dev, u32 size)
return 0;
}
-static int aac_rx_restart_adapter(struct aac_dev *dev)
+static int aac_rx_restart_adapter(struct aac_dev *dev, int bled)
{
u32 var;
- printk(KERN_ERR "%s%d: adapter kernel panic'd.\n",
- dev->name, dev->id);
-
- if (aac_rx_check_health(dev) <= 0)
- return 1;
- if (rx_sync_cmd(dev, IOP_RESET, 0, 0, 0, 0, 0, 0,
- &var, NULL, NULL, NULL, NULL))
- return 1;
+ if (bled)
+ printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n",
+ dev->name, dev->id, bled);
+ else {
+ bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS,
+ 0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL);
+ if (!bled && (var != 0x00000001))
+ bled = -EINVAL;
+ }
+ if (bled && (bled != -ETIMEDOUT))
+ bled = aac_adapter_sync_cmd(dev, IOP_RESET,
+ 0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL);
+
+ if (bled && (bled != -ETIMEDOUT))
+ return -EINVAL;
+ if (bled || (var == 0x3803000F)) { /* USE_OTHER_METHOD */
+ rx_writel(dev, MUnit.reserved2, 3);
+ msleep(5000); /* Delay 5 seconds */
+ var = 0x00000001;
+ }
if (var != 0x00000001)
- return 1;
+ return -EINVAL;
if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC)
- return 1;
+ return -ENODEV;
return 0;
}
@@ -517,24 +529,29 @@ int _aac_rx_init(struct aac_dev *dev)
{
unsigned long start;
unsigned long status;
- int instance;
- const char * name;
-
- instance = dev->id;
- name = dev->name;
+ int restart = 0;
+ int instance = dev->id;
+ const char * name = dev->name;
if (aac_adapter_ioremap(dev, dev->base_size)) {
printk(KERN_WARNING "%s: unable to map adapter.\n", name);
goto error_iounmap;
}
+ /* Failure to reset here is an option ... */
+ dev->OIMR = status = rx_readb (dev, MUnit.OIMR);
+ if ((((status & 0xff) != 0xff) || reset_devices) &&
+ !aac_rx_restart_adapter(dev, 0))
+ ++restart;
/*
* Check to see if the board panic'd while booting.
*/
status = rx_readl(dev, MUnit.OMRx[0]);
- if (status & KERNEL_PANIC)
- if (aac_rx_restart_adapter(dev))
+ if (status & KERNEL_PANIC) {
+ if (aac_rx_restart_adapter(dev, aac_rx_check_health(dev)))
goto error_iounmap;
+ ++restart;
+ }
/*
* Check to see if the board failed any self tests.
*/
@@ -556,12 +573,23 @@ int _aac_rx_init(struct aac_dev *dev)
*/
while (!((status = rx_readl(dev, MUnit.OMRx[0])) & KERNEL_UP_AND_RUNNING))
{
- if(time_after(jiffies, start+startup_timeout*HZ))
- {
+ if ((restart &&
+ (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) ||
+ time_after(jiffies, start+HZ*startup_timeout)) {
printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n",
dev->name, instance, status);
goto error_iounmap;
}
+ if (!restart &&
+ ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) ||
+ time_after(jiffies, start + HZ *
+ ((startup_timeout > 60)
+ ? (startup_timeout - 60)
+ : (startup_timeout / 2))))) {
+ if (likely(!aac_rx_restart_adapter(dev, aac_rx_check_health(dev))))
+ start = jiffies;
+ ++restart;
+ }
msleep(1);
}
/*
@@ -572,6 +600,7 @@ int _aac_rx_init(struct aac_dev *dev)
dev->a_ops.adapter_notify = aac_rx_notify_adapter;
dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
dev->a_ops.adapter_check_health = aac_rx_check_health;
+ dev->a_ops.adapter_restart = aac_rx_restart_adapter;
/*
* First clear out all interrupts. Then enable the one's that we
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index 6f1a1780efce..f4b5e9742ab0 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -31,7 +31,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
-#include <linux/pci.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/blkdev.h>
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index 1d239f6c0103..cbbfbc9f3e0f 100644
--- a/drivers/scsi/aha1542.c
+++ b/drivers/scsi/aha1542.c
@@ -35,7 +35,6 @@
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <linux/spinlock.h>
-#include <linux/pci.h>
#include <linux/isapnp.h>
#include <linux/blkdev.h>
#include <linux/mca.h>
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx
index 911ea1756e55..5e6620f8dabc 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic79xx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx
@@ -57,18 +57,6 @@ config AIC79XX_BUILD_FIRMWARE
or modify the assembler Makefile or the files it includes if your
build environment is different than that of the author.
-config AIC79XX_ENABLE_RD_STRM
- bool "Enable Read Streaming for All Targets"
- depends on SCSI_AIC79XX
- default n
- help
- Read Streaming is a U320 protocol option that should enhance
- performance. Early U320 drive firmware actually performs slower
- with read streaming enabled so it is disabled by default. Read
- Streaming can be configured in much the same way as tagged queueing
- using the "rd_strm" command line option. See
- drivers/scsi/aic7xxx/README.aic79xx for details.
-
config AIC79XX_DEBUG_ENABLE
bool "Compile in Debugging Code"
depends on SCSI_AIC79XX
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
index cd93f9a8611f..88da670a7915 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
@@ -50,16 +50,6 @@ config AIC7XXX_RESET_DELAY_MS
Default: 5000 (5 seconds)
-config AIC7XXX_PROBE_EISA_VL
- bool "Probe for EISA and VL AIC7XXX Adapters"
- depends on SCSI_AIC7XXX && EISA
- help
- Probe for EISA and VLB Aic7xxx controllers. In many newer systems,
- the invasive probes necessary to detect these controllers can cause
- other devices to fail. For this reason, the non-PCI probe code is
- disabled by default. The current value of this option can be "toggled"
- via the no_probe kernel command line option.
-
config AIC7XXX_BUILD_FIRMWARE
bool "Build Adapter Firmware with Kernel Build"
depends on SCSI_AIC7XXX && !PREVENT_FIRMWARE_BUILD
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 2be03e975d97..6054881f21f1 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -363,6 +363,8 @@ static int ahd_linux_run_command(struct ahd_softc*,
struct scsi_cmnd *);
static void ahd_linux_setup_tag_info_global(char *p);
static int aic79xx_setup(char *c);
+static void ahd_freeze_simq(struct ahd_softc *ahd);
+static void ahd_release_simq(struct ahd_softc *ahd);
static int ahd_linux_unit;
@@ -2016,13 +2018,13 @@ ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd)
cmd->scsi_done(cmd);
}
-void
+static void
ahd_freeze_simq(struct ahd_softc *ahd)
{
scsi_block_requests(ahd->platform_data->host);
}
-void
+static void
ahd_release_simq(struct ahd_softc *ahd)
{
scsi_unblock_requests(ahd->platform_data->host);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index 147c83c456a5..9218f29314fa 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -837,8 +837,6 @@ int ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg);
void ahd_platform_free(struct ahd_softc *ahd);
void ahd_platform_init(struct ahd_softc *ahd);
void ahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb);
-void ahd_freeze_simq(struct ahd_softc *ahd);
-void ahd_release_simq(struct ahd_softc *ahd);
static __inline void
ahd_freeze_scb(struct scb *scb)
diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h
index 954c7c24501d..e1bd57b9f23d 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.h
+++ b/drivers/scsi/aic7xxx/aic7xxx.h
@@ -1278,11 +1278,6 @@ typedef enum {
AHC_QUEUE_TAGGED
} ahc_queue_alg;
-void ahc_set_tags(struct ahc_softc *ahc,
- struct scsi_cmnd *cmd,
- struct ahc_devinfo *devinfo,
- ahc_queue_alg alg);
-
/**************************** Target Mode *************************************/
#ifdef AHC_TARGET_MODE
void ahc_send_lstate_events(struct ahc_softc *,
diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c
index 50ef785224de..75733b09f27a 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_core.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_core.c
@@ -2073,7 +2073,7 @@ ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
/*
* Update the current state of tagged queuing for a given target.
*/
-void
+static void
ahc_set_tags(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
struct ahc_devinfo *devinfo, ahc_queue_alg alg)
{
diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c
index 8f43ff772f23..db6ab1a3b81e 100644
--- a/drivers/scsi/aic94xx/aic94xx_scb.c
+++ b/drivers/scsi/aic94xx/aic94xx_scb.c
@@ -24,7 +24,6 @@
*
*/
-#include <linux/pci.h>
#include <scsi/scsi_host.h>
#include "aic94xx.h"
diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c
index 12497da5529d..03bfed61bffc 100644
--- a/drivers/scsi/arcmsr/arcmsr_attr.c
+++ b/drivers/scsi/arcmsr/arcmsr_attr.c
@@ -49,7 +49,6 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/delay.h>
-#include <linux/pci.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
index 0f920c84ac0f..eff846ae0aff 100644
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -1,19 +1,19 @@
-/*
+/*
* NCR 5380 generic driver routines. These should make it *trivial*
- * to implement 5380 SCSI drivers under Linux with a non-trantor
+ * to implement 5380 SCSI drivers under Linux with a non-trantor
* architecture.
*
* Note that these routines also work with NR53c400 family chips.
*
* Copyright 1993, Drew Eckhardt
- * Visionary Computing
+ * Visionary Computing
* (Unix and Linux consulting and custom programming)
- * drew@colorado.edu
+ * drew@colorado.edu
* +1 (303) 666-5836
*
- * DISTRIBUTION RELEASE 6.
+ * DISTRIBUTION RELEASE 6.
*
- * For more information, please consult
+ * For more information, please consult
*
* NCR 5380 Family
* SCSI Protocol Controller
@@ -57,7 +57,7 @@
* - I've deleted all the stuff for AUTOPROBE_IRQ, REAL_DMA_POLL, PSEUDO_DMA
* and USLEEP, because these were messing up readability and will never be
* needed for Atari SCSI.
- *
+ *
* - I've revised the NCR5380_main() calling scheme (relax the 'main_running'
* stuff), and 'main' is executed in a bottom half if awoken by an
* interrupt.
@@ -69,21 +69,29 @@
*/
/*
- * Further development / testing that should be done :
- * 1. Test linked command handling code after Eric is ready with
+ * Further development / testing that should be done :
+ * 1. Test linked command handling code after Eric is ready with
* the high level code.
*/
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_transport_spi.h>
#if (NDEBUG & NDEBUG_LISTS)
-#define LIST(x,y) \
- { printk("LINE:%d Adding %p to %p\n", __LINE__, (void*)(x), (void*)(y)); \
- if ((x)==(y)) udelay(5); }
-#define REMOVE(w,x,y,z) \
- { printk("LINE:%d Removing: %p->%p %p->%p \n", __LINE__, \
- (void*)(w), (void*)(x), (void*)(y), (void*)(z)); \
- if ((x)==(y)) udelay(5); }
+#define LIST(x, y) \
+ do { \
+ printk("LINE:%d Adding %p to %p\n", \
+ __LINE__, (void*)(x), (void*)(y)); \
+ if ((x) == (y)) \
+ udelay(5); \
+ } while (0)
+#define REMOVE(w, x, y, z) \
+ do { \
+ printk("LINE:%d Removing: %p->%p %p->%p \n", \
+ __LINE__, (void*)(w), (void*)(x), \
+ (void*)(y), (void*)(z)); \
+ if ((x) == (y)) \
+ udelay(5); \
+ } while (0)
#else
#define LIST(x,y)
#define REMOVE(w,x,y,z)
@@ -103,62 +111,62 @@
* more difficult than it has to be.
*
* Also, many of the SCSI drivers were written before the command queuing
- * routines were implemented, meaning their implementations of queued
+ * routines were implemented, meaning their implementations of queued
* commands were hacked on rather than designed in from the start.
*
- * When I designed the Linux SCSI drivers I figured that
+ * When I designed the Linux SCSI drivers I figured that
* while having two different SCSI boards in a system might be useful
* for debugging things, two of the same type wouldn't be used.
* Well, I was wrong and a number of users have mailed me about running
* multiple high-performance SCSI boards in a server.
*
- * Finally, when I get questions from users, I have no idea what
+ * Finally, when I get questions from users, I have no idea what
* revision of my driver they are running.
*
* This driver attempts to address these problems :
- * This is a generic 5380 driver. To use it on a different platform,
+ * This is a generic 5380 driver. To use it on a different platform,
* one simply writes appropriate system specific macros (ie, data
- * transfer - some PC's will use the I/O bus, 68K's must use
+ * transfer - some PC's will use the I/O bus, 68K's must use
* memory mapped) and drops this file in their 'C' wrapper.
*
- * As far as command queueing, two queues are maintained for
+ * As far as command queueing, two queues are maintained for
* each 5380 in the system - commands that haven't been issued yet,
- * and commands that are currently executing. This means that an
- * unlimited number of commands may be queued, letting
- * more commands propagate from the higher driver levels giving higher
- * throughput. Note that both I_T_L and I_T_L_Q nexuses are supported,
- * allowing multiple commands to propagate all the way to a SCSI-II device
+ * and commands that are currently executing. This means that an
+ * unlimited number of commands may be queued, letting
+ * more commands propagate from the higher driver levels giving higher
+ * throughput. Note that both I_T_L and I_T_L_Q nexuses are supported,
+ * allowing multiple commands to propagate all the way to a SCSI-II device
* while a command is already executing.
*
- * To solve the multiple-boards-in-the-same-system problem,
+ * To solve the multiple-boards-in-the-same-system problem,
* there is a separate instance structure for each instance
* of a 5380 in the system. So, multiple NCR5380 drivers will
* be able to coexist with appropriate changes to the high level
- * SCSI code.
+ * SCSI code.
*
* A NCR5380_PUBLIC_REVISION macro is provided, with the release
- * number (updated for each public release) printed by the
- * NCR5380_print_options command, which should be called from the
+ * number (updated for each public release) printed by the
+ * NCR5380_print_options command, which should be called from the
* wrapper detect function, so that I know what release of the driver
* users are using.
*
- * Issues specific to the NCR5380 :
+ * Issues specific to the NCR5380 :
*
- * When used in a PIO or pseudo-dma mode, the NCR5380 is a braindead
- * piece of hardware that requires you to sit in a loop polling for
- * the REQ signal as long as you are connected. Some devices are
- * brain dead (ie, many TEXEL CD ROM drives) and won't disconnect
+ * When used in a PIO or pseudo-dma mode, the NCR5380 is a braindead
+ * piece of hardware that requires you to sit in a loop polling for
+ * the REQ signal as long as you are connected. Some devices are
+ * brain dead (ie, many TEXEL CD ROM drives) and won't disconnect
* while doing long seek operations.
- *
+ *
* The workaround for this is to keep track of devices that have
* disconnected. If the device hasn't disconnected, for commands that
- * should disconnect, we do something like
+ * should disconnect, we do something like
*
* while (!REQ is asserted) { sleep for N usecs; poll for M usecs }
- *
- * Some tweaking of N and M needs to be done. An algorithm based
+ *
+ * Some tweaking of N and M needs to be done. An algorithm based
* on "time to data" would give the best results as long as short time
- * to datas (ie, on the same track) were considered, however these
+ * to datas (ie, on the same track) were considered, however these
* broken devices are the exception rather than the rule and I'd rather
* spend my time optimizing for the normal case.
*
@@ -167,9 +175,9 @@
* At the heart of the design is a coroutine, NCR5380_main,
* which is started when not running by the interrupt handler,
* timer, and queue command function. It attempts to establish
- * I_T_L or I_T_L_Q nexuses by removing the commands from the
- * issue queue and calling NCR5380_select() if a nexus
- * is not established.
+ * I_T_L or I_T_L_Q nexuses by removing the commands from the
+ * issue queue and calling NCR5380_select() if a nexus
+ * is not established.
*
* Once a nexus is established, the NCR5380_information_transfer()
* phase goes through the various phases as instructed by the target.
@@ -183,10 +191,10 @@
* calling NCR5380_intr() which will in turn call NCR5380_reselect
* to reestablish a nexus. This will run main if necessary.
*
- * On command termination, the done function will be called as
+ * On command termination, the done function will be called as
* appropriate.
*
- * SCSI pointers are maintained in the SCp field of SCSI command
+ * SCSI pointers are maintained in the SCp field of SCSI command
* structures, being initialized after the command is connected
* in NCR5380_select, and set as appropriate in NCR5380_information_transfer.
* Note that in violation of the standard, an implicit SAVE POINTERS operation
@@ -196,12 +204,12 @@
/*
* Using this file :
* This file a skeleton Linux SCSI driver for the NCR 5380 series
- * of chips. To use it, you write an architecture specific functions
+ * of chips. To use it, you write an architecture specific functions
* and macros and include this file in your driver.
*
- * These macros control options :
+ * These macros control options :
* AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
- * for commands that return with a CHECK CONDITION status.
+ * for commands that return with a CHECK CONDITION status.
*
* LINKED - if defined, linked commands are supported.
*
@@ -210,18 +218,18 @@
* SUPPORT_TAGS - if defined, SCSI-2 tagged queuing is used where possible
*
* These macros MUST be defined :
- *
+ *
* NCR5380_read(register) - read from the specified register
*
- * NCR5380_write(register, value) - write to the specific register
+ * NCR5380_write(register, value) - write to the specific register
*
* Either real DMA *or* pseudo DMA may be implemented
- * REAL functions :
+ * REAL functions :
* NCR5380_REAL_DMA should be defined if real DMA is to be used.
- * Note that the DMA setup functions should return the number of bytes
+ * Note that the DMA setup functions should return the number of bytes
* that they were able to program the controller for.
*
- * Also note that generic i386/PC versions of these macros are
+ * Also note that generic i386/PC versions of these macros are
* available as NCR5380_i386_dma_write_setup,
* NCR5380_i386_dma_read_setup, and NCR5380_i386_dma_residual.
*
@@ -234,14 +242,14 @@
* NCR5380_pread(instance, dst, count);
*
* If nothing specific to this implementation needs doing (ie, with external
- * hardware), you must also define
- *
+ * hardware), you must also define
+ *
* NCR5380_queue_command
* NCR5380_reset
* NCR5380_abort
* NCR5380_proc_info
*
- * to be the global entry points into the specific driver, ie
+ * to be the global entry points into the specific driver, ie
* #define NCR5380_queue_command t128_queue_command.
*
* If this is not done, the routines will be defined as static functions
@@ -249,7 +257,7 @@
* accessible wrapper function.
*
* The generic driver is initialized by calling NCR5380_init(instance),
- * after setting the appropriate host specific fields and ID. If the
+ * after setting the appropriate host specific fields and ID. If the
* driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance,
* possible) function may be used. Before the specific driver initialization
* code finishes, NCR5380_print_options should be called.
@@ -264,8 +272,9 @@ static struct scsi_host_template *the_template = NULL;
(struct NCR5380_hostdata *)(in)->hostdata
#define HOSTDATA(in) ((struct NCR5380_hostdata *)(in)->hostdata)
-#define NEXT(cmd) ((Scsi_Cmnd *)((cmd)->host_scribble))
-#define NEXTADDR(cmd) ((Scsi_Cmnd **)&((cmd)->host_scribble))
+#define NEXT(cmd) ((Scsi_Cmnd *)(cmd)->host_scribble)
+#define SET_NEXT(cmd,next) ((cmd)->host_scribble = (void *)(next))
+#define NEXTADDR(cmd) ((Scsi_Cmnd **)&(cmd)->host_scribble)
#define HOSTNO instance->host_no
#define H_NO(cmd) (cmd)->device->host->host_no
@@ -312,34 +321,34 @@ static struct scsi_host_template *the_template = NULL;
#define TAG_NONE 0xff
typedef struct {
- DECLARE_BITMAP(allocated, MAX_TAGS);
- int nr_allocated;
- int queue_size;
+ DECLARE_BITMAP(allocated, MAX_TAGS);
+ int nr_allocated;
+ int queue_size;
} TAG_ALLOC;
-static TAG_ALLOC TagAlloc[8][8]; /* 8 targets and 8 LUNs */
+static TAG_ALLOC TagAlloc[8][8]; /* 8 targets and 8 LUNs */
-static void __init init_tags( void )
+static void __init init_tags(void)
{
- int target, lun;
- TAG_ALLOC *ta;
-
- if (!setup_use_tagged_queuing)
- return;
-
- for( target = 0; target < 8; ++target ) {
- for( lun = 0; lun < 8; ++lun ) {
- ta = &TagAlloc[target][lun];
- bitmap_zero(ta->allocated, MAX_TAGS);
- ta->nr_allocated = 0;
- /* At the beginning, assume the maximum queue size we could
- * support (MAX_TAGS). This value will be decreased if the target
- * returns QUEUE_FULL status.
- */
- ta->queue_size = MAX_TAGS;
+ int target, lun;
+ TAG_ALLOC *ta;
+
+ if (!setup_use_tagged_queuing)
+ return;
+
+ for (target = 0; target < 8; ++target) {
+ for (lun = 0; lun < 8; ++lun) {
+ ta = &TagAlloc[target][lun];
+ bitmap_zero(ta->allocated, MAX_TAGS);
+ ta->nr_allocated = 0;
+ /* At the beginning, assume the maximum queue size we could
+ * support (MAX_TAGS). This value will be decreased if the target
+ * returns QUEUE_FULL status.
+ */
+ ta->queue_size = MAX_TAGS;
+ }
}
- }
}
@@ -348,24 +357,24 @@ static void __init init_tags( void )
* check that there is a free tag and the target's queue won't overflow. This
* function should be called with interrupts disabled to avoid race
* conditions.
- */
+ */
-static int is_lun_busy( Scsi_Cmnd *cmd, int should_be_tagged )
+static int is_lun_busy(Scsi_Cmnd *cmd, int should_be_tagged)
{
- SETUP_HOSTDATA(cmd->device->host);
-
- if (hostdata->busy[cmd->device->id] & (1 << cmd->device->lun))
- return( 1 );
- if (!should_be_tagged ||
- !setup_use_tagged_queuing || !cmd->device->tagged_supported)
- return( 0 );
- if (TagAlloc[cmd->device->id][cmd->device->lun].nr_allocated >=
- TagAlloc[cmd->device->id][cmd->device->lun].queue_size ) {
- TAG_PRINTK( "scsi%d: target %d lun %d: no free tags\n",
- H_NO(cmd), cmd->device->id, cmd->device->lun );
- return( 1 );
- }
- return( 0 );
+ SETUP_HOSTDATA(cmd->device->host);
+
+ if (hostdata->busy[cmd->device->id] & (1 << cmd->device->lun))
+ return 1;
+ if (!should_be_tagged ||
+ !setup_use_tagged_queuing || !cmd->device->tagged_supported)
+ return 0;
+ if (TagAlloc[cmd->device->id][cmd->device->lun].nr_allocated >=
+ TagAlloc[cmd->device->id][cmd->device->lun].queue_size) {
+ TAG_PRINTK("scsi%d: target %d lun %d: no free tags\n",
+ H_NO(cmd), cmd->device->id, cmd->device->lun);
+ return 1;
+ }
+ return 0;
}
@@ -374,31 +383,30 @@ static int is_lun_busy( Scsi_Cmnd *cmd, int should_be_tagged )
* untagged.
*/
-static void cmd_get_tag( Scsi_Cmnd *cmd, int should_be_tagged )
+static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged)
{
- SETUP_HOSTDATA(cmd->device->host);
-
- /* If we or the target don't support tagged queuing, allocate the LUN for
- * an untagged command.
- */
- if (!should_be_tagged ||
- !setup_use_tagged_queuing || !cmd->device->tagged_supported) {
- cmd->tag = TAG_NONE;
- hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
- TAG_PRINTK( "scsi%d: target %d lun %d now allocated by untagged "
- "command\n", H_NO(cmd), cmd->device->id, cmd->device->lun );
- }
- else {
- TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
-
- cmd->tag = find_first_zero_bit( ta->allocated, MAX_TAGS );
- set_bit( cmd->tag, ta->allocated );
- ta->nr_allocated++;
- TAG_PRINTK( "scsi%d: using tag %d for target %d lun %d "
- "(now %d tags in use)\n",
- H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun,
- ta->nr_allocated );
- }
+ SETUP_HOSTDATA(cmd->device->host);
+
+ /* If we or the target don't support tagged queuing, allocate the LUN for
+ * an untagged command.
+ */
+ if (!should_be_tagged ||
+ !setup_use_tagged_queuing || !cmd->device->tagged_supported) {
+ cmd->tag = TAG_NONE;
+ hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
+ TAG_PRINTK("scsi%d: target %d lun %d now allocated by untagged "
+ "command\n", H_NO(cmd), cmd->device->id, cmd->device->lun);
+ } else {
+ TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
+
+ cmd->tag = find_first_zero_bit(ta->allocated, MAX_TAGS);
+ set_bit(cmd->tag, ta->allocated);
+ ta->nr_allocated++;
+ TAG_PRINTK("scsi%d: using tag %d for target %d lun %d "
+ "(now %d tags in use)\n",
+ H_NO(cmd), cmd->tag, cmd->device->id,
+ cmd->device->lun, ta->nr_allocated);
+ }
}
@@ -406,44 +414,42 @@ static void cmd_get_tag( Scsi_Cmnd *cmd, int should_be_tagged )
* unlock the LUN.
*/
-static void cmd_free_tag( Scsi_Cmnd *cmd )
+static void cmd_free_tag(Scsi_Cmnd *cmd)
{
- SETUP_HOSTDATA(cmd->device->host);
-
- if (cmd->tag == TAG_NONE) {
- hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
- TAG_PRINTK( "scsi%d: target %d lun %d untagged cmd finished\n",
- H_NO(cmd), cmd->device->id, cmd->device->lun );
- }
- else if (cmd->tag >= MAX_TAGS) {
- printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n",
- H_NO(cmd), cmd->tag );
- }
- else {
- TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
- clear_bit( cmd->tag, ta->allocated );
- ta->nr_allocated--;
- TAG_PRINTK( "scsi%d: freed tag %d for target %d lun %d\n",
- H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun );
- }
+ SETUP_HOSTDATA(cmd->device->host);
+
+ if (cmd->tag == TAG_NONE) {
+ hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+ TAG_PRINTK("scsi%d: target %d lun %d untagged cmd finished\n",
+ H_NO(cmd), cmd->device->id, cmd->device->lun);
+ } else if (cmd->tag >= MAX_TAGS) {
+ printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n",
+ H_NO(cmd), cmd->tag);
+ } else {
+ TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
+ clear_bit(cmd->tag, ta->allocated);
+ ta->nr_allocated--;
+ TAG_PRINTK("scsi%d: freed tag %d for target %d lun %d\n",
+ H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun);
+ }
}
-static void free_all_tags( void )
+static void free_all_tags(void)
{
- int target, lun;
- TAG_ALLOC *ta;
-
- if (!setup_use_tagged_queuing)
- return;
-
- for( target = 0; target < 8; ++target ) {
- for( lun = 0; lun < 8; ++lun ) {
- ta = &TagAlloc[target][lun];
- bitmap_zero(ta->allocated, MAX_TAGS);
- ta->nr_allocated = 0;
+ int target, lun;
+ TAG_ALLOC *ta;
+
+ if (!setup_use_tagged_queuing)
+ return;
+
+ for (target = 0; target < 8; ++target) {
+ for (lun = 0; lun < 8; ++lun) {
+ ta = &TagAlloc[target][lun];
+ bitmap_zero(ta->allocated, MAX_TAGS);
+ ta->nr_allocated = 0;
+ }
}
- }
}
#endif /* SUPPORT_TAGS */
@@ -461,89 +467,94 @@ static void free_all_tags( void )
* assumed to be already transfered into ptr/this_residual.
*/
-static void merge_contiguous_buffers( Scsi_Cmnd *cmd )
+static void merge_contiguous_buffers(Scsi_Cmnd *cmd)
{
- unsigned long endaddr;
+ unsigned long endaddr;
#if (NDEBUG & NDEBUG_MERGING)
- unsigned long oldlen = cmd->SCp.this_residual;
- int cnt = 1;
+ unsigned long oldlen = cmd->SCp.this_residual;
+ int cnt = 1;
#endif
- for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1;
- cmd->SCp.buffers_residual &&
- virt_to_phys(page_address(cmd->SCp.buffer[1].page)+
- cmd->SCp.buffer[1].offset) == endaddr; ) {
- MER_PRINTK("VTOP(%p) == %08lx -> merging\n",
- cmd->SCp.buffer[1].address, endaddr);
+ for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1;
+ cmd->SCp.buffers_residual &&
+ virt_to_phys(page_address(cmd->SCp.buffer[1].page) +
+ cmd->SCp.buffer[1].offset) == endaddr;) {
+ MER_PRINTK("VTOP(%p) == %08lx -> merging\n",
+ page_address(cmd->SCp.buffer[1].page), endaddr);
#if (NDEBUG & NDEBUG_MERGING)
- ++cnt;
+ ++cnt;
#endif
- ++cmd->SCp.buffer;
- --cmd->SCp.buffers_residual;
- cmd->SCp.this_residual += cmd->SCp.buffer->length;
- endaddr += cmd->SCp.buffer->length;
- }
+ ++cmd->SCp.buffer;
+ --cmd->SCp.buffers_residual;
+ cmd->SCp.this_residual += cmd->SCp.buffer->length;
+ endaddr += cmd->SCp.buffer->length;
+ }
#if (NDEBUG & NDEBUG_MERGING)
- if (oldlen != cmd->SCp.this_residual)
- MER_PRINTK("merged %d buffers from %p, new length %08x\n",
- cnt, cmd->SCp.ptr, cmd->SCp.this_residual);
+ if (oldlen != cmd->SCp.this_residual)
+ MER_PRINTK("merged %d buffers from %p, new length %08x\n",
+ cnt, cmd->SCp.ptr, cmd->SCp.this_residual);
#endif
}
/*
* Function : void initialize_SCp(Scsi_Cmnd *cmd)
*
- * Purpose : initialize the saved data pointers for cmd to point to the
+ * Purpose : initialize the saved data pointers for cmd to point to the
* start of the buffer.
*
* Inputs : cmd - Scsi_Cmnd structure to have pointers reset.
*/
-static __inline__ void initialize_SCp(Scsi_Cmnd *cmd)
+static inline void initialize_SCp(Scsi_Cmnd *cmd)
{
- /*
- * Initialize the Scsi Pointer field so that all of the commands in the
- * various queues are valid.
- */
-
- if (cmd->use_sg) {
- cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
- cmd->SCp.buffers_residual = cmd->use_sg - 1;
- cmd->SCp.ptr = (char *)page_address(cmd->SCp.buffer->page)+
- cmd->SCp.buffer->offset;
- cmd->SCp.this_residual = cmd->SCp.buffer->length;
- /* ++roman: Try to merge some scatter-buffers if they are at
- * contiguous physical addresses.
+ /*
+ * Initialize the Scsi Pointer field so that all of the commands in the
+ * various queues are valid.
*/
- merge_contiguous_buffers( cmd );
- } else {
- cmd->SCp.buffer = NULL;
- cmd->SCp.buffers_residual = 0;
- cmd->SCp.ptr = (char *) cmd->request_buffer;
- cmd->SCp.this_residual = cmd->request_bufflen;
- }
+
+ if (cmd->use_sg) {
+ cmd->SCp.buffer = (struct scatterlist *)cmd->request_buffer;
+ cmd->SCp.buffers_residual = cmd->use_sg - 1;
+ cmd->SCp.ptr = (char *)page_address(cmd->SCp.buffer->page) +
+ cmd->SCp.buffer->offset;
+ cmd->SCp.this_residual = cmd->SCp.buffer->length;
+ /* ++roman: Try to merge some scatter-buffers if they are at
+ * contiguous physical addresses.
+ */
+ merge_contiguous_buffers(cmd);
+ } else {
+ cmd->SCp.buffer = NULL;
+ cmd->SCp.buffers_residual = 0;
+ cmd->SCp.ptr = (char *)cmd->request_buffer;
+ cmd->SCp.this_residual = cmd->request_bufflen;
+ }
}
#include <linux/delay.h>
#if NDEBUG
static struct {
- unsigned char mask;
- const char * name;}
-signals[] = {{ SR_DBP, "PARITY"}, { SR_RST, "RST" }, { SR_BSY, "BSY" },
- { SR_REQ, "REQ" }, { SR_MSG, "MSG" }, { SR_CD, "CD" }, { SR_IO, "IO" },
- { SR_SEL, "SEL" }, {0, NULL}},
-basrs[] = {{BASR_ATN, "ATN"}, {BASR_ACK, "ACK"}, {0, NULL}},
-icrs[] = {{ICR_ASSERT_RST, "ASSERT RST"},{ICR_ASSERT_ACK, "ASSERT ACK"},
- {ICR_ASSERT_BSY, "ASSERT BSY"}, {ICR_ASSERT_SEL, "ASSERT SEL"},
- {ICR_ASSERT_ATN, "ASSERT ATN"}, {ICR_ASSERT_DATA, "ASSERT DATA"},
- {0, NULL}},
-mrs[] = {{MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, {MR_TARGET, "MODE TARGET"},
- {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, {MR_ENABLE_PAR_INTR,
- "MODE PARITY INTR"}, {MR_ENABLE_EOP_INTR,"MODE EOP INTR"},
- {MR_MONITOR_BSY, "MODE MONITOR BSY"},
- {MR_DMA_MODE, "MODE DMA"}, {MR_ARBITRATE, "MODE ARBITRATION"},
- {0, NULL}};
+ unsigned char mask;
+ const char *name;
+} signals[] = {
+ { SR_DBP, "PARITY"}, { SR_RST, "RST" }, { SR_BSY, "BSY" },
+ { SR_REQ, "REQ" }, { SR_MSG, "MSG" }, { SR_CD, "CD" }, { SR_IO, "IO" },
+ { SR_SEL, "SEL" }, {0, NULL}
+}, basrs[] = {
+ {BASR_ATN, "ATN"}, {BASR_ACK, "ACK"}, {0, NULL}
+}, icrs[] = {
+ {ICR_ASSERT_RST, "ASSERT RST"},{ICR_ASSERT_ACK, "ASSERT ACK"},
+ {ICR_ASSERT_BSY, "ASSERT BSY"}, {ICR_ASSERT_SEL, "ASSERT SEL"},
+ {ICR_ASSERT_ATN, "ASSERT ATN"}, {ICR_ASSERT_DATA, "ASSERT DATA"},
+ {0, NULL}
+}, mrs[] = {
+ {MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, {MR_TARGET, "MODE TARGET"},
+ {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, {MR_ENABLE_PAR_INTR,
+ "MODE PARITY INTR"}, {MR_ENABLE_EOP_INTR,"MODE EOP INTR"},
+ {MR_MONITOR_BSY, "MODE MONITOR BSY"},
+ {MR_DMA_MODE, "MODE DMA"}, {MR_ARBITRATE, "MODE ARBITRATION"},
+ {0, NULL}
+};
/*
* Function : void NCR5380_print(struct Scsi_Host *instance)
@@ -553,45 +564,47 @@ mrs[] = {{MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, {MR_TARGET, "MODE TARGET"},
* Input : instance - which NCR5380
*/
-static void NCR5380_print(struct Scsi_Host *instance) {
- unsigned char status, data, basr, mr, icr, i;
- unsigned long flags;
-
- local_irq_save(flags);
- data = NCR5380_read(CURRENT_SCSI_DATA_REG);
- status = NCR5380_read(STATUS_REG);
- mr = NCR5380_read(MODE_REG);
- icr = NCR5380_read(INITIATOR_COMMAND_REG);
- basr = NCR5380_read(BUS_AND_STATUS_REG);
- local_irq_restore(flags);
- printk("STATUS_REG: %02x ", status);
- for (i = 0; signals[i].mask ; ++i)
- if (status & signals[i].mask)
- printk(",%s", signals[i].name);
- printk("\nBASR: %02x ", basr);
- for (i = 0; basrs[i].mask ; ++i)
- if (basr & basrs[i].mask)
- printk(",%s", basrs[i].name);
- printk("\nICR: %02x ", icr);
- for (i = 0; icrs[i].mask; ++i)
- if (icr & icrs[i].mask)
- printk(",%s", icrs[i].name);
- printk("\nMODE: %02x ", mr);
- for (i = 0; mrs[i].mask; ++i)
- if (mr & mrs[i].mask)
- printk(",%s", mrs[i].name);
- printk("\n");
+static void NCR5380_print(struct Scsi_Host *instance)
+{
+ unsigned char status, data, basr, mr, icr, i;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ data = NCR5380_read(CURRENT_SCSI_DATA_REG);
+ status = NCR5380_read(STATUS_REG);
+ mr = NCR5380_read(MODE_REG);
+ icr = NCR5380_read(INITIATOR_COMMAND_REG);
+ basr = NCR5380_read(BUS_AND_STATUS_REG);
+ local_irq_restore(flags);
+ printk("STATUS_REG: %02x ", status);
+ for (i = 0; signals[i].mask; ++i)
+ if (status & signals[i].mask)
+ printk(",%s", signals[i].name);
+ printk("\nBASR: %02x ", basr);
+ for (i = 0; basrs[i].mask; ++i)
+ if (basr & basrs[i].mask)
+ printk(",%s", basrs[i].name);
+ printk("\nICR: %02x ", icr);
+ for (i = 0; icrs[i].mask; ++i)
+ if (icr & icrs[i].mask)
+ printk(",%s", icrs[i].name);
+ printk("\nMODE: %02x ", mr);
+ for (i = 0; mrs[i].mask; ++i)
+ if (mr & mrs[i].mask)
+ printk(",%s", mrs[i].name);
+ printk("\n");
}
static struct {
- unsigned char value;
- const char *name;
+ unsigned char value;
+ const char *name;
} phases[] = {
- {PHASE_DATAOUT, "DATAOUT"}, {PHASE_DATAIN, "DATAIN"}, {PHASE_CMDOUT, "CMDOUT"},
- {PHASE_STATIN, "STATIN"}, {PHASE_MSGOUT, "MSGOUT"}, {PHASE_MSGIN, "MSGIN"},
- {PHASE_UNKNOWN, "UNKNOWN"}};
+ {PHASE_DATAOUT, "DATAOUT"}, {PHASE_DATAIN, "DATAIN"}, {PHASE_CMDOUT, "CMDOUT"},
+ {PHASE_STATIN, "STATIN"}, {PHASE_MSGOUT, "MSGOUT"}, {PHASE_MSGIN, "MSGIN"},
+ {PHASE_UNKNOWN, "UNKNOWN"}
+};
-/*
+/*
* Function : void NCR5380_print_phase(struct Scsi_Host *instance)
*
* Purpose : print the current SCSI phase for debugging purposes
@@ -601,30 +614,35 @@ static struct {
static void NCR5380_print_phase(struct Scsi_Host *instance)
{
- unsigned char status;
- int i;
-
- status = NCR5380_read(STATUS_REG);
- if (!(status & SR_REQ))
- printk(KERN_DEBUG "scsi%d: REQ not asserted, phase unknown.\n", HOSTNO);
- else {
- for (i = 0; (phases[i].value != PHASE_UNKNOWN) &&
- (phases[i].value != (status & PHASE_MASK)); ++i);
- printk(KERN_DEBUG "scsi%d: phase %s\n", HOSTNO, phases[i].name);
- }
+ unsigned char status;
+ int i;
+
+ status = NCR5380_read(STATUS_REG);
+ if (!(status & SR_REQ))
+ printk(KERN_DEBUG "scsi%d: REQ not asserted, phase unknown.\n", HOSTNO);
+ else {
+ for (i = 0; (phases[i].value != PHASE_UNKNOWN) &&
+ (phases[i].value != (status & PHASE_MASK)); ++i)
+ ;
+ printk(KERN_DEBUG "scsi%d: phase %s\n", HOSTNO, phases[i].name);
+ }
}
#else /* !NDEBUG */
/* dummies... */
-__inline__ void NCR5380_print(struct Scsi_Host *instance) { };
-__inline__ void NCR5380_print_phase(struct Scsi_Host *instance) { };
+static inline void NCR5380_print(struct Scsi_Host *instance)
+{
+};
+static inline void NCR5380_print_phase(struct Scsi_Host *instance)
+{
+};
#endif
/*
* ++roman: New scheme of calling NCR5380_main()
- *
+ *
* If we're not in an interrupt, we can call our main directly, it cannot be
* already running. Else, we queue it on a task queue, if not 'main_running'
* tells us that a lower level is already executing it. This way,
@@ -638,33 +656,33 @@ __inline__ void NCR5380_print_phase(struct Scsi_Host *instance) { };
#include <linux/workqueue.h>
#include <linux/interrupt.h>
-static volatile int main_running = 0;
-static DECLARE_WORK(NCR5380_tqueue, (void (*)(void*))NCR5380_main, NULL);
+static volatile int main_running;
+static DECLARE_WORK(NCR5380_tqueue, NCR5380_main);
-static __inline__ void queue_main(void)
+static inline void queue_main(void)
{
- if (!main_running) {
- /* If in interrupt and NCR5380_main() not already running,
- queue it on the 'immediate' task queue, to be processed
- immediately after the current interrupt processing has
- finished. */
- schedule_work(&NCR5380_tqueue);
- }
- /* else: nothing to do: the running NCR5380_main() will pick up
- any newly queued command. */
+ if (!main_running) {
+ /* If in interrupt and NCR5380_main() not already running,
+ queue it on the 'immediate' task queue, to be processed
+ immediately after the current interrupt processing has
+ finished. */
+ schedule_work(&NCR5380_tqueue);
+ }
+ /* else: nothing to do: the running NCR5380_main() will pick up
+ any newly queued command. */
}
-static inline void NCR5380_all_init (void)
+static inline void NCR5380_all_init(void)
{
- static int done = 0;
- if (!done) {
- INI_PRINTK("scsi : NCR5380_all_init()\n");
- done = 1;
- }
+ static int done = 0;
+ if (!done) {
+ INI_PRINTK("scsi : NCR5380_all_init()\n");
+ done = 1;
+ }
}
-
+
/*
* Function : void NCR58380_print_options (struct Scsi_Host *instance)
*
@@ -674,23 +692,23 @@ static inline void NCR5380_all_init (void)
* Inputs : instance, pointer to this instance. Unused.
*/
-static void __init NCR5380_print_options (struct Scsi_Host *instance)
+static void __init NCR5380_print_options(struct Scsi_Host *instance)
{
- printk(" generic options"
-#ifdef AUTOSENSE
- " AUTOSENSE"
+ printk(" generic options"
+#ifdef AUTOSENSE
+ " AUTOSENSE"
#endif
#ifdef REAL_DMA
- " REAL DMA"
+ " REAL DMA"
#endif
#ifdef PARITY
- " PARITY"
+ " PARITY"
#endif
#ifdef SUPPORT_TAGS
- " SCSI-2 TAGGED QUEUING"
+ " SCSI-2 TAGGED QUEUING"
#endif
- );
- printk(" generic release=%d", NCR5380_PUBLIC_RELEASE);
+ );
+ printk(" generic release=%d", NCR5380_PUBLIC_RELEASE);
}
/*
@@ -699,27 +717,27 @@ static void __init NCR5380_print_options (struct Scsi_Host *instance)
* Purpose : print commands in the various queues, called from
* NCR5380_abort and NCR5380_debug to aid debugging.
*
- * Inputs : instance, pointer to this instance.
+ * Inputs : instance, pointer to this instance.
*/
-static void NCR5380_print_status (struct Scsi_Host *instance)
+static void NCR5380_print_status(struct Scsi_Host *instance)
{
- char *pr_bfr;
- char *start;
- int len;
-
- NCR_PRINT(NDEBUG_ANY);
- NCR_PRINT_PHASE(NDEBUG_ANY);
-
- pr_bfr = (char *) __get_free_page(GFP_ATOMIC);
- if (!pr_bfr) {
- printk("NCR5380_print_status: no memory for print buffer\n");
- return;
- }
- len = NCR5380_proc_info(pr_bfr, &start, 0, PAGE_SIZE, HOSTNO, 0);
- pr_bfr[len] = 0;
- printk("\n%s\n", pr_bfr);
- free_page((unsigned long) pr_bfr);
+ char *pr_bfr;
+ char *start;
+ int len;
+
+ NCR_PRINT(NDEBUG_ANY);
+ NCR_PRINT_PHASE(NDEBUG_ANY);
+
+ pr_bfr = (char *)__get_free_page(GFP_ATOMIC);
+ if (!pr_bfr) {
+ printk("NCR5380_print_status: no memory for print buffer\n");
+ return;
+ }
+ len = NCR5380_proc_info(instance, pr_bfr, &start, 0, PAGE_SIZE, 0);
+ pr_bfr[len] = 0;
+ printk("\n%s\n", pr_bfr);
+ free_page((unsigned long)pr_bfr);
}
@@ -738,443 +756,478 @@ static void NCR5380_print_status (struct Scsi_Host *instance)
*/
#undef SPRINTF
-#define SPRINTF(fmt,args...) \
- do { if (pos + strlen(fmt) + 20 /* slop */ < buffer + length) \
- pos += sprintf(pos, fmt , ## args); } while(0)
-static
-char *lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length);
-
-static
-int NCR5380_proc_info (struct Scsi_Host *instance, char *buffer, char **start, off_t offset,
- int length, int inout)
+#define SPRINTF(fmt,args...) \
+ do { \
+ if (pos + strlen(fmt) + 20 /* slop */ < buffer + length) \
+ pos += sprintf(pos, fmt , ## args); \
+ } while(0)
+static char *lprint_Scsi_Cmnd(Scsi_Cmnd *cmd, char *pos, char *buffer, int length);
+
+static int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer,
+ char **start, off_t offset, int length, int inout)
{
- char *pos = buffer;
- struct NCR5380_hostdata *hostdata;
- Scsi_Cmnd *ptr;
- unsigned long flags;
- off_t begin = 0;
-#define check_offset() \
- do { \
- if (pos - buffer < offset - begin) { \
- begin += pos - buffer; \
- pos = buffer; \
- } \
- } while (0)
-
- hostdata = (struct NCR5380_hostdata *)instance->hostdata;
-
- if (inout) { /* Has data been written to the file ? */
- return(-ENOSYS); /* Currently this is a no-op */
- }
- SPRINTF("NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
- check_offset();
- local_irq_save(flags);
- SPRINTF("NCR5380: coroutine is%s running.\n", main_running ? "" : "n't");
- check_offset();
- if (!hostdata->connected)
- SPRINTF("scsi%d: no currently connected command\n", HOSTNO);
- else
- pos = lprint_Scsi_Cmnd ((Scsi_Cmnd *) hostdata->connected,
- pos, buffer, length);
- SPRINTF("scsi%d: issue_queue\n", HOSTNO);
- check_offset();
- for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = NEXT(ptr)) {
- pos = lprint_Scsi_Cmnd (ptr, pos, buffer, length);
+ char *pos = buffer;
+ struct NCR5380_hostdata *hostdata;
+ Scsi_Cmnd *ptr;
+ unsigned long flags;
+ off_t begin = 0;
+#define check_offset() \
+ do { \
+ if (pos - buffer < offset - begin) { \
+ begin += pos - buffer; \
+ pos = buffer; \
+ } \
+ } while (0)
+
+ hostdata = (struct NCR5380_hostdata *)instance->hostdata;
+
+ if (inout) /* Has data been written to the file ? */
+ return -ENOSYS; /* Currently this is a no-op */
+ SPRINTF("NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
check_offset();
- }
+ local_irq_save(flags);
+ SPRINTF("NCR5380: coroutine is%s running.\n",
+ main_running ? "" : "n't");
+ check_offset();
+ if (!hostdata->connected)
+ SPRINTF("scsi%d: no currently connected command\n", HOSTNO);
+ else
+ pos = lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected,
+ pos, buffer, length);
+ SPRINTF("scsi%d: issue_queue\n", HOSTNO);
+ check_offset();
+ for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr)) {
+ pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
+ check_offset();
+ }
- SPRINTF("scsi%d: disconnected_queue\n", HOSTNO);
- check_offset();
- for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
- ptr = NEXT(ptr)) {
- pos = lprint_Scsi_Cmnd (ptr, pos, buffer, length);
+ SPRINTF("scsi%d: disconnected_queue\n", HOSTNO);
check_offset();
- }
+ for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
+ ptr = NEXT(ptr)) {
+ pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
+ check_offset();
+ }
- local_irq_restore(flags);
- *start = buffer + (offset - begin);
- if (pos - buffer < offset - begin)
- return 0;
- else if (pos - buffer - (offset - begin) < length)
- return pos - buffer - (offset - begin);
- return length;
+ local_irq_restore(flags);
+ *start = buffer + (offset - begin);
+ if (pos - buffer < offset - begin)
+ return 0;
+ else if (pos - buffer - (offset - begin) < length)
+ return pos - buffer - (offset - begin);
+ return length;
}
-static char *
-lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length)
+static char *lprint_Scsi_Cmnd(Scsi_Cmnd *cmd, char *pos, char *buffer, int length)
{
- int i, s;
- unsigned char *command;
- SPRINTF("scsi%d: destination target %d, lun %d\n",
- H_NO(cmd), cmd->device->id, cmd->device->lun);
- SPRINTF(" command = ");
- command = cmd->cmnd;
- SPRINTF("%2d (0x%02x)", command[0], command[0]);
- for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
- SPRINTF(" %02x", command[i]);
- SPRINTF("\n");
- return pos;
+ int i, s;
+ unsigned char *command;
+ SPRINTF("scsi%d: destination target %d, lun %d\n",
+ H_NO(cmd), cmd->device->id, cmd->device->lun);
+ SPRINTF(" command = ");
+ command = cmd->cmnd;
+ SPRINTF("%2d (0x%02x)", command[0], command[0]);
+ for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
+ SPRINTF(" %02x", command[i]);
+ SPRINTF("\n");
+ return pos;
}
-/*
+/*
* Function : void NCR5380_init (struct Scsi_Host *instance)
*
* Purpose : initializes *instance and corresponding 5380 chip.
*
- * Inputs : instance - instantiation of the 5380 driver.
+ * Inputs : instance - instantiation of the 5380 driver.
*
* Notes : I assume that the host, hostno, and id bits have been
- * set correctly. I don't care about the irq and other fields.
- *
+ * set correctly. I don't care about the irq and other fields.
+ *
*/
-static int NCR5380_init (struct Scsi_Host *instance, int flags)
+static int NCR5380_init(struct Scsi_Host *instance, int flags)
{
- int i;
- SETUP_HOSTDATA(instance);
-
- NCR5380_all_init();
-
- hostdata->aborted = 0;
- hostdata->id_mask = 1 << instance->this_id;
- hostdata->id_higher_mask = 0;
- for (i = hostdata->id_mask; i <= 0x80; i <<= 1)
- if (i > hostdata->id_mask)
- hostdata->id_higher_mask |= i;
- for (i = 0; i < 8; ++i)
- hostdata->busy[i] = 0;
+ int i;
+ SETUP_HOSTDATA(instance);
+
+ NCR5380_all_init();
+
+ hostdata->aborted = 0;
+ hostdata->id_mask = 1 << instance->this_id;
+ hostdata->id_higher_mask = 0;
+ for (i = hostdata->id_mask; i <= 0x80; i <<= 1)
+ if (i > hostdata->id_mask)
+ hostdata->id_higher_mask |= i;
+ for (i = 0; i < 8; ++i)
+ hostdata->busy[i] = 0;
#ifdef SUPPORT_TAGS
- init_tags();
+ init_tags();
#endif
#if defined (REAL_DMA)
- hostdata->dma_len = 0;
+ hostdata->dma_len = 0;
#endif
- hostdata->targets_present = 0;
- hostdata->connected = NULL;
- hostdata->issue_queue = NULL;
- hostdata->disconnected_queue = NULL;
- hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT;
-
- if (!the_template) {
- the_template = instance->hostt;
- first_instance = instance;
- }
-
+ hostdata->targets_present = 0;
+ hostdata->connected = NULL;
+ hostdata->issue_queue = NULL;
+ hostdata->disconnected_queue = NULL;
+ hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT;
+
+ if (!the_template) {
+ the_template = instance->hostt;
+ first_instance = instance;
+ }
#ifndef AUTOSENSE
- if ((instance->cmd_per_lun > 1) || (instance->can_queue > 1))
- printk("scsi%d: WARNING : support for multiple outstanding commands enabled\n"
- " without AUTOSENSE option, contingent allegiance conditions may\n"
- " be incorrectly cleared.\n", HOSTNO);
+ if ((instance->cmd_per_lun > 1) || (instance->can_queue > 1))
+ printk("scsi%d: WARNING : support for multiple outstanding commands enabled\n"
+ " without AUTOSENSE option, contingent allegiance conditions may\n"
+ " be incorrectly cleared.\n", HOSTNO);
#endif /* def AUTOSENSE */
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- NCR5380_write(MODE_REG, MR_BASE);
- NCR5380_write(TARGET_COMMAND_REG, 0);
- NCR5380_write(SELECT_ENABLE_REG, 0);
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+ NCR5380_write(MODE_REG, MR_BASE);
+ NCR5380_write(TARGET_COMMAND_REG, 0);
+ NCR5380_write(SELECT_ENABLE_REG, 0);
- return 0;
+ return 0;
}
-/*
- * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd,
- * void (*done)(Scsi_Cmnd *))
+/*
+ * our own old-style timeout update
+ */
+/*
+ * The strategy is to cause the timer code to call scsi_times_out()
+ * when the soonest timeout is pending.
+ * The arguments are used when we are queueing a new command, because
+ * we do not want to subtract the time used from this time, but when we
+ * set the timer, we want to take this value into account.
+ */
+
+int atari_scsi_update_timeout(Scsi_Cmnd * SCset, int timeout)
+{
+ int rtn;
+
+ /*
+ * We are using the new error handling code to actually register/deregister
+ * timers for timeout.
+ */
+
+ if (!timer_pending(&SCset->eh_timeout))
+ rtn = 0;
+ else
+ rtn = SCset->eh_timeout.expires - jiffies;
+
+ if (timeout == 0) {
+ del_timer(&SCset->eh_timeout);
+ SCset->eh_timeout.data = (unsigned long)NULL;
+ SCset->eh_timeout.expires = 0;
+ } else {
+ if (SCset->eh_timeout.data != (unsigned long)NULL)
+ del_timer(&SCset->eh_timeout);
+ SCset->eh_timeout.data = (unsigned long)SCset;
+ SCset->eh_timeout.expires = jiffies + timeout;
+ add_timer(&SCset->eh_timeout);
+ }
+ return rtn;
+}
+
+/*
+ * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd,
+ * void (*done)(Scsi_Cmnd *))
*
* Purpose : enqueues a SCSI command
*
* Inputs : cmd - SCSI command, done - function called on completion, with
* a pointer to the command descriptor.
- *
+ *
* Returns : 0
*
- * Side effects :
- * cmd is added to the per instance issue_queue, with minor
- * twiddling done to the host specific fields of cmd. If the
+ * Side effects :
+ * cmd is added to the per instance issue_queue, with minor
+ * twiddling done to the host specific fields of cmd. If the
* main coroutine is not running, it is restarted.
*
*/
-static
-int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
+static int NCR5380_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
{
- SETUP_HOSTDATA(cmd->device->host);
- Scsi_Cmnd *tmp;
- int oldto;
- unsigned long flags;
- extern int update_timeout(Scsi_Cmnd * SCset, int timeout);
+ SETUP_HOSTDATA(cmd->device->host);
+ Scsi_Cmnd *tmp;
+ int oldto;
+ unsigned long flags;
+ // extern int update_timeout(Scsi_Cmnd * SCset, int timeout);
#if (NDEBUG & NDEBUG_NO_WRITE)
- switch (cmd->cmnd[0]) {
- case WRITE_6:
- case WRITE_10:
- printk(KERN_NOTICE "scsi%d: WRITE attempted with NO_WRITE debugging flag set\n",
- H_NO(cmd));
- cmd->result = (DID_ERROR << 16);
- done(cmd);
- return 0;
- }
+ switch (cmd->cmnd[0]) {
+ case WRITE_6:
+ case WRITE_10:
+ printk(KERN_NOTICE "scsi%d: WRITE attempted with NO_WRITE debugging flag set\n",
+ H_NO(cmd));
+ cmd->result = (DID_ERROR << 16);
+ done(cmd);
+ return 0;
+ }
#endif /* (NDEBUG & NDEBUG_NO_WRITE) */
-
#ifdef NCR5380_STATS
# if 0
- if (!hostdata->connected && !hostdata->issue_queue &&
- !hostdata->disconnected_queue) {
- hostdata->timebase = jiffies;
- }
+ if (!hostdata->connected && !hostdata->issue_queue &&
+ !hostdata->disconnected_queue) {
+ hostdata->timebase = jiffies;
+ }
# endif
# ifdef NCR5380_STAT_LIMIT
- if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
+ if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
# endif
- switch (cmd->cmnd[0])
- {
- case WRITE:
- case WRITE_6:
- case WRITE_10:
- hostdata->time_write[cmd->device->id] -= (jiffies - hostdata->timebase);
- hostdata->bytes_write[cmd->device->id] += cmd->request_bufflen;
- 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] += cmd->request_bufflen;
- hostdata->pendingr++;
- break;
- }
+ 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] += cmd->request_bufflen;
+ 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] += cmd->request_bufflen;
+ hostdata->pendingr++;
+ break;
+ }
#endif
- /*
- * We use the host_scribble field as a pointer to the next command
- * in a queue
- */
-
- NEXT(cmd) = NULL;
- cmd->scsi_done = done;
-
- cmd->result = 0;
-
-
- /*
- * Insert the cmd into the issue queue. Note that REQUEST SENSE
- * commands are added to the head of the queue since any command will
- * clear the contingent allegiance condition that exists and the
- * sense data is only guaranteed to be valid while the condition exists.
- */
-
- local_irq_save(flags);
- /* ++guenther: now that the issue queue is being set up, we can lock ST-DMA.
- * Otherwise a running NCR5380_main may steal the lock.
- * Lock before actually inserting due to fairness reasons explained in
- * atari_scsi.c. If we insert first, then it's impossible for this driver
- * to release the lock.
- * Stop timer for this command while waiting for the lock, or timeouts
- * may happen (and they really do), and it's no good if the command doesn't
- * appear in any of the queues.
- * ++roman: Just disabling the NCR interrupt isn't sufficient here,
- * because also a timer int can trigger an abort or reset, which would
- * alter queues and touch the lock.
- */
- if (!IS_A_TT()) {
- oldto = update_timeout(cmd, 0);
- falcon_get_lock();
- update_timeout(cmd, oldto);
- }
- if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
- LIST(cmd, hostdata->issue_queue);
- NEXT(cmd) = hostdata->issue_queue;
- hostdata->issue_queue = cmd;
- } else {
- for (tmp = (Scsi_Cmnd *)hostdata->issue_queue;
- NEXT(tmp); tmp = NEXT(tmp))
- ;
- LIST(cmd, tmp);
- NEXT(tmp) = cmd;
- }
- local_irq_restore(flags);
-
- QU_PRINTK("scsi%d: command added to %s of queue\n", H_NO(cmd),
- (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");
-
- /* If queue_command() is called from an interrupt (real one or bottom
- * half), we let queue_main() do the job of taking care about main. If it
- * is already running, this is a no-op, else main will be queued.
- *
- * If we're not in an interrupt, we can call NCR5380_main()
- * unconditionally, because it cannot be already running.
- */
- if (in_interrupt() || ((flags >> 8) & 7) >= 6)
- queue_main();
- else
- NCR5380_main(NULL);
- return 0;
+ /*
+ * We use the host_scribble field as a pointer to the next command
+ * in a queue
+ */
+
+ SET_NEXT(cmd, NULL);
+ cmd->scsi_done = done;
+
+ cmd->result = 0;
+
+ /*
+ * Insert the cmd into the issue queue. Note that REQUEST SENSE
+ * commands are added to the head of the queue since any command will
+ * clear the contingent allegiance condition that exists and the
+ * sense data is only guaranteed to be valid while the condition exists.
+ */
+
+ local_irq_save(flags);
+ /* ++guenther: now that the issue queue is being set up, we can lock ST-DMA.
+ * Otherwise a running NCR5380_main may steal the lock.
+ * Lock before actually inserting due to fairness reasons explained in
+ * atari_scsi.c. If we insert first, then it's impossible for this driver
+ * to release the lock.
+ * Stop timer for this command while waiting for the lock, or timeouts
+ * may happen (and they really do), and it's no good if the command doesn't
+ * appear in any of the queues.
+ * ++roman: Just disabling the NCR interrupt isn't sufficient here,
+ * because also a timer int can trigger an abort or reset, which would
+ * alter queues and touch the lock.
+ */
+ if (!IS_A_TT()) {
+ oldto = atari_scsi_update_timeout(cmd, 0);
+ falcon_get_lock();
+ atari_scsi_update_timeout(cmd, oldto);
+ }
+ if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
+ LIST(cmd, hostdata->issue_queue);
+ SET_NEXT(cmd, hostdata->issue_queue);
+ hostdata->issue_queue = cmd;
+ } else {
+ for (tmp = (Scsi_Cmnd *)hostdata->issue_queue;
+ NEXT(tmp); tmp = NEXT(tmp))
+ ;
+ LIST(cmd, tmp);
+ SET_NEXT(tmp, cmd);
+ }
+ local_irq_restore(flags);
+
+ QU_PRINTK("scsi%d: command added to %s of queue\n", H_NO(cmd),
+ (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");
+
+ /* If queue_command() is called from an interrupt (real one or bottom
+ * half), we let queue_main() do the job of taking care about main. If it
+ * is already running, this is a no-op, else main will be queued.
+ *
+ * If we're not in an interrupt, we can call NCR5380_main()
+ * unconditionally, because it cannot be already running.
+ */
+ if (in_interrupt() || ((flags >> 8) & 7) >= 6)
+ queue_main();
+ else
+ NCR5380_main(NULL);
+ return 0;
}
/*
- * Function : NCR5380_main (void)
+ * Function : NCR5380_main (void)
*
- * Purpose : NCR5380_main is a coroutine that runs as long as more work can
- * be done on the NCR5380 host adapters in a system. Both
- * NCR5380_queue_command() and NCR5380_intr() will try to start it
+ * Purpose : NCR5380_main is a coroutine that runs as long as more work can
+ * be done on the NCR5380 host adapters in a system. Both
+ * NCR5380_queue_command() and NCR5380_intr() will try to start it
* in case it is not running.
- *
- * NOTE : NCR5380_main exits with interrupts *disabled*, the caller should
+ *
+ * NOTE : NCR5380_main exits with interrupts *disabled*, the caller should
* reenable them. This prevents reentrancy and kernel stack overflow.
- */
-
-static void NCR5380_main (void *bl)
+ */
+
+static void NCR5380_main(struct work_struct *work)
{
- Scsi_Cmnd *tmp, *prev;
- struct Scsi_Host *instance = first_instance;
- struct NCR5380_hostdata *hostdata = HOSTDATA(instance);
- int done;
- unsigned long flags;
-
- /*
- * We run (with interrupts disabled) until we're sure that none of
- * the host adapters have anything that can be done, at which point
- * we set main_running to 0 and exit.
- *
- * Interrupts are enabled before doing various other internal
- * instructions, after we've decided that we need to run through
- * the loop again.
- *
- * this should prevent any race conditions.
- *
- * ++roman: Just disabling the NCR interrupt isn't sufficient here,
- * because also a timer int can trigger an abort or reset, which can
- * alter queues and touch the Falcon lock.
- */
-
- /* Tell int handlers main() is now already executing. Note that
- no races are possible here. If an int comes in before
- 'main_running' is set here, and queues/executes main via the
- task queue, it doesn't do any harm, just this instance of main
- won't find any work left to do. */
- if (main_running)
- return;
- main_running = 1;
-
- local_save_flags(flags);
- do {
- local_irq_disable(); /* Freeze request queues */
- done = 1;
-
- if (!hostdata->connected) {
- MAIN_PRINTK( "scsi%d: not connected\n", HOSTNO );
- /*
- * Search through the issue_queue for a command destined
- * for a target that's not busy.
- */
+ Scsi_Cmnd *tmp, *prev;
+ struct Scsi_Host *instance = first_instance;
+ struct NCR5380_hostdata *hostdata = HOSTDATA(instance);
+ int done;
+ unsigned long flags;
+
+ /*
+ * We run (with interrupts disabled) until we're sure that none of
+ * the host adapters have anything that can be done, at which point
+ * we set main_running to 0 and exit.
+ *
+ * Interrupts are enabled before doing various other internal
+ * instructions, after we've decided that we need to run through
+ * the loop again.
+ *
+ * this should prevent any race conditions.
+ *
+ * ++roman: Just disabling the NCR interrupt isn't sufficient here,
+ * because also a timer int can trigger an abort or reset, which can
+ * alter queues and touch the Falcon lock.
+ */
+
+ /* Tell int handlers main() is now already executing. Note that
+ no races are possible here. If an int comes in before
+ 'main_running' is set here, and queues/executes main via the
+ task queue, it doesn't do any harm, just this instance of main
+ won't find any work left to do. */
+ if (main_running)
+ return;
+ main_running = 1;
+
+ local_save_flags(flags);
+ do {
+ local_irq_disable(); /* Freeze request queues */
+ done = 1;
+
+ if (!hostdata->connected) {
+ MAIN_PRINTK("scsi%d: not connected\n", HOSTNO);
+ /*
+ * Search through the issue_queue for a command destined
+ * for a target that's not busy.
+ */
#if (NDEBUG & NDEBUG_LISTS)
- for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL;
- tmp && (tmp != prev); prev = tmp, tmp = NEXT(tmp))
- ;
- /*printk("%p ", tmp);*/
- if ((tmp == prev) && tmp) printk(" LOOP\n");/* else printk("\n");*/
+ for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL;
+ tmp && (tmp != prev); prev = tmp, tmp = NEXT(tmp))
+ ;
+ /*printk("%p ", tmp);*/
+ if ((tmp == prev) && tmp)
+ printk(" LOOP\n");
+ /* else printk("\n"); */
#endif
- for (tmp = (Scsi_Cmnd *) hostdata->issue_queue,
- prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp) ) {
+ for (tmp = (Scsi_Cmnd *) hostdata->issue_queue,
+ prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp)) {
#if (NDEBUG & NDEBUG_LISTS)
- if (prev != tmp)
- printk("MAIN tmp=%p target=%d busy=%d lun=%d\n",
- tmp, tmp->device->id, hostdata->busy[tmp->device->id],
- tmp->device->lun);
+ if (prev != tmp)
+ printk("MAIN tmp=%p target=%d busy=%d lun=%d\n",
+ tmp, tmp->device->id, hostdata->busy[tmp->device->id],
+ tmp->device->lun);
#endif
- /* When we find one, remove it from the issue queue. */
- /* ++guenther: possible race with Falcon locking */
- if (
+ /* When we find one, remove it from the issue queue. */
+ /* ++guenther: possible race with Falcon locking */
+ if (
#ifdef SUPPORT_TAGS
- !is_lun_busy( tmp, tmp->cmnd[0] != REQUEST_SENSE)
+ !is_lun_busy( tmp, tmp->cmnd[0] != REQUEST_SENSE)
#else
- !(hostdata->busy[tmp->device->id] & (1 << tmp->device->lun))
+ !(hostdata->busy[tmp->device->id] & (1 << tmp->device->lun))
#endif
- ) {
- /* ++guenther: just to be sure, this must be atomic */
- local_irq_disable();
- if (prev) {
- REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
- NEXT(prev) = NEXT(tmp);
- } else {
- REMOVE(-1, hostdata->issue_queue, tmp, NEXT(tmp));
- hostdata->issue_queue = NEXT(tmp);
- }
- NEXT(tmp) = NULL;
- falcon_dont_release++;
-
- /* reenable interrupts after finding one */
- local_irq_restore(flags);
-
- /*
- * Attempt to establish an I_T_L nexus here.
- * On success, instance->hostdata->connected is set.
- * On failure, we must add the command back to the
- * issue queue so we can keep trying.
- */
- MAIN_PRINTK("scsi%d: main(): command for target %d "
- "lun %d removed from issue_queue\n",
- HOSTNO, tmp->device->id, tmp->device->lun);
- /*
- * REQUEST SENSE commands are issued without tagged
- * queueing, even on SCSI-II devices because the
- * contingent allegiance condition exists for the
- * entire unit.
- */
- /* ++roman: ...and the standard also requires that
- * REQUEST SENSE command are untagged.
- */
-
+ ) {
+ /* ++guenther: just to be sure, this must be atomic */
+ local_irq_disable();
+ if (prev) {
+ REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
+ SET_NEXT(prev, NEXT(tmp));
+ } else {
+ REMOVE(-1, hostdata->issue_queue, tmp, NEXT(tmp));
+ hostdata->issue_queue = NEXT(tmp);
+ }
+ SET_NEXT(tmp, NULL);
+ falcon_dont_release++;
+
+ /* reenable interrupts after finding one */
+ local_irq_restore(flags);
+
+ /*
+ * Attempt to establish an I_T_L nexus here.
+ * On success, instance->hostdata->connected is set.
+ * On failure, we must add the command back to the
+ * issue queue so we can keep trying.
+ */
+ MAIN_PRINTK("scsi%d: main(): command for target %d "
+ "lun %d removed from issue_queue\n",
+ HOSTNO, tmp->device->id, tmp->device->lun);
+ /*
+ * REQUEST SENSE commands are issued without tagged
+ * queueing, even on SCSI-II devices because the
+ * contingent allegiance condition exists for the
+ * entire unit.
+ */
+ /* ++roman: ...and the standard also requires that
+ * REQUEST SENSE command are untagged.
+ */
+
#ifdef SUPPORT_TAGS
- cmd_get_tag( tmp, tmp->cmnd[0] != REQUEST_SENSE );
+ cmd_get_tag(tmp, tmp->cmnd[0] != REQUEST_SENSE);
#endif
- if (!NCR5380_select(instance, tmp,
- (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE :
- TAG_NEXT)) {
- falcon_dont_release--;
- /* release if target did not response! */
- falcon_release_lock_if_possible( hostdata );
- break;
- } else {
- local_irq_disable();
- LIST(tmp, hostdata->issue_queue);
- NEXT(tmp) = hostdata->issue_queue;
- hostdata->issue_queue = tmp;
+ if (!NCR5380_select(instance, tmp,
+ (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE :
+ TAG_NEXT)) {
+ falcon_dont_release--;
+ /* release if target did not response! */
+ falcon_release_lock_if_possible(hostdata);
+ break;
+ } else {
+ local_irq_disable();
+ LIST(tmp, hostdata->issue_queue);
+ SET_NEXT(tmp, hostdata->issue_queue);
+ hostdata->issue_queue = tmp;
#ifdef SUPPORT_TAGS
- cmd_free_tag( tmp );
+ cmd_free_tag(tmp);
#endif
- falcon_dont_release--;
- local_irq_restore(flags);
- MAIN_PRINTK("scsi%d: main(): select() failed, "
- "returned to issue_queue\n", HOSTNO);
- if (hostdata->connected)
- break;
- }
- } /* if target/lun/target queue is not busy */
- } /* for issue_queue */
- } /* if (!hostdata->connected) */
-
- if (hostdata->connected
+ falcon_dont_release--;
+ local_irq_restore(flags);
+ MAIN_PRINTK("scsi%d: main(): select() failed, "
+ "returned to issue_queue\n", HOSTNO);
+ if (hostdata->connected)
+ break;
+ }
+ } /* if target/lun/target queue is not busy */
+ } /* for issue_queue */
+ } /* if (!hostdata->connected) */
+
+ if (hostdata->connected
#ifdef REAL_DMA
- && !hostdata->dma_len
+ && !hostdata->dma_len
#endif
- ) {
- local_irq_restore(flags);
- MAIN_PRINTK("scsi%d: main: performing information transfer\n",
- HOSTNO);
- NCR5380_information_transfer(instance);
- MAIN_PRINTK("scsi%d: main: done set false\n", HOSTNO);
- done = 0;
- }
- } while (!done);
+ ) {
+ local_irq_restore(flags);
+ MAIN_PRINTK("scsi%d: main: performing information transfer\n",
+ HOSTNO);
+ NCR5380_information_transfer(instance);
+ MAIN_PRINTK("scsi%d: main: done set false\n", HOSTNO);
+ done = 0;
+ }
+ } while (!done);
- /* Better allow ints _after_ 'main_running' has been cleared, else
- an interrupt could believe we'll pick up the work it left for
- us, but we won't see it anymore here... */
- main_running = 0;
- local_irq_restore(flags);
+ /* Better allow ints _after_ 'main_running' has been cleared, else
+ an interrupt could believe we'll pick up the work it left for
+ us, but we won't see it anymore here... */
+ main_running = 0;
+ local_irq_restore(flags);
}
@@ -1183,1441 +1236,1439 @@ static void NCR5380_main (void *bl)
* Function : void NCR5380_dma_complete (struct Scsi_Host *instance)
*
* Purpose : Called by interrupt handler when DMA finishes or a phase
- * mismatch occurs (which would finish the DMA transfer).
+ * mismatch occurs (which would finish the DMA transfer).
*
* Inputs : instance - this instance of the NCR5380.
*
*/
-static void NCR5380_dma_complete( struct Scsi_Host *instance )
+static void NCR5380_dma_complete(struct Scsi_Host *instance)
{
- SETUP_HOSTDATA(instance);
- int transfered, saved_data = 0, overrun = 0, cnt, toPIO;
- unsigned char **data, p;
- volatile int *count;
-
- if (!hostdata->connected) {
- printk(KERN_WARNING "scsi%d: received end of DMA interrupt with "
- "no connected cmd\n", HOSTNO);
- return;
- }
-
- if (atari_read_overruns) {
- p = hostdata->connected->SCp.phase;
- if (p & SR_IO) {
- udelay(10);
- if ((((NCR5380_read(BUS_AND_STATUS_REG)) &
- (BASR_PHASE_MATCH|BASR_ACK)) ==
- (BASR_PHASE_MATCH|BASR_ACK))) {
- saved_data = NCR5380_read(INPUT_DATA_REG);
- overrun = 1;
- DMA_PRINTK("scsi%d: read overrun handled\n", HOSTNO);
- }
+ SETUP_HOSTDATA(instance);
+ int transfered, saved_data = 0, overrun = 0, cnt, toPIO;
+ unsigned char **data, p;
+ volatile int *count;
+
+ if (!hostdata->connected) {
+ printk(KERN_WARNING "scsi%d: received end of DMA interrupt with "
+ "no connected cmd\n", HOSTNO);
+ return;
}
- }
-
- DMA_PRINTK("scsi%d: real DMA transfer complete, basr 0x%X, sr 0x%X\n",
- HOSTNO, NCR5380_read(BUS_AND_STATUS_REG),
- NCR5380_read(STATUS_REG));
-
- (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
- NCR5380_write(MODE_REG, MR_BASE);
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-
- transfered = hostdata->dma_len - NCR5380_dma_residual(instance);
- hostdata->dma_len = 0;
-
- data = (unsigned char **) &(hostdata->connected->SCp.ptr);
- count = &(hostdata->connected->SCp.this_residual);
- *data += transfered;
- *count -= transfered;
-
- if (atari_read_overruns) {
- if ((NCR5380_read(STATUS_REG) & PHASE_MASK) == p && (p & SR_IO)) {
- cnt = toPIO = atari_read_overruns;
- if (overrun) {
- DMA_PRINTK("Got an input overrun, using saved byte\n");
- *(*data)++ = saved_data;
- (*count)--;
- cnt--;
- toPIO--;
- }
- DMA_PRINTK("Doing %d-byte PIO to 0x%08lx\n", cnt, (long)*data);
- NCR5380_transfer_pio(instance, &p, &cnt, data);
- *count -= toPIO - cnt;
+
+ if (atari_read_overruns) {
+ p = hostdata->connected->SCp.phase;
+ if (p & SR_IO) {
+ udelay(10);
+ if ((NCR5380_read(BUS_AND_STATUS_REG) &
+ (BASR_PHASE_MATCH|BASR_ACK)) ==
+ (BASR_PHASE_MATCH|BASR_ACK)) {
+ saved_data = NCR5380_read(INPUT_DATA_REG);
+ overrun = 1;
+ DMA_PRINTK("scsi%d: read overrun handled\n", HOSTNO);
+ }
+ }
+ }
+
+ DMA_PRINTK("scsi%d: real DMA transfer complete, basr 0x%X, sr 0x%X\n",
+ HOSTNO, NCR5380_read(BUS_AND_STATUS_REG),
+ NCR5380_read(STATUS_REG));
+
+ (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+ NCR5380_write(MODE_REG, MR_BASE);
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+
+ transfered = hostdata->dma_len - NCR5380_dma_residual(instance);
+ hostdata->dma_len = 0;
+
+ data = (unsigned char **)&hostdata->connected->SCp.ptr;
+ count = &hostdata->connected->SCp.this_residual;
+ *data += transfered;
+ *count -= transfered;
+
+ if (atari_read_overruns) {
+ if ((NCR5380_read(STATUS_REG) & PHASE_MASK) == p && (p & SR_IO)) {
+ cnt = toPIO = atari_read_overruns;
+ if (overrun) {
+ DMA_PRINTK("Got an input overrun, using saved byte\n");
+ *(*data)++ = saved_data;
+ (*count)--;
+ cnt--;
+ toPIO--;
+ }
+ DMA_PRINTK("Doing %d-byte PIO to 0x%08lx\n", cnt, (long)*data);
+ NCR5380_transfer_pio(instance, &p, &cnt, data);
+ *count -= toPIO - cnt;
+ }
}
- }
}
#endif /* REAL_DMA */
/*
* Function : void NCR5380_intr (int irq)
- *
+ *
* Purpose : handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
- * from the disconnected queue, and restarting NCR5380_main()
+ * from the disconnected queue, and restarting NCR5380_main()
* as required.
*
* Inputs : int irq, irq that caused this interrupt.
*
*/
-static irqreturn_t NCR5380_intr (int irq, void *dev_id)
+static irqreturn_t NCR5380_intr(int irq, void *dev_id)
{
- struct Scsi_Host *instance = first_instance;
- int done = 1, handled = 0;
- unsigned char basr;
-
- INT_PRINTK("scsi%d: NCR5380 irq triggered\n", HOSTNO);
-
- /* Look for pending interrupts */
- basr = NCR5380_read(BUS_AND_STATUS_REG);
- INT_PRINTK("scsi%d: BASR=%02x\n", HOSTNO, basr);
- /* dispatch to appropriate routine if found and done=0 */
- if (basr & BASR_IRQ) {
- NCR_PRINT(NDEBUG_INTR);
- if ((NCR5380_read(STATUS_REG) & (SR_SEL|SR_IO)) == (SR_SEL|SR_IO)) {
- done = 0;
- ENABLE_IRQ();
- INT_PRINTK("scsi%d: SEL interrupt\n", HOSTNO);
- NCR5380_reselect(instance);
- (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
- }
- else if (basr & BASR_PARITY_ERROR) {
- INT_PRINTK("scsi%d: PARITY interrupt\n", HOSTNO);
- (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
- }
- else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) {
- INT_PRINTK("scsi%d: RESET interrupt\n", HOSTNO);
- (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
- }
- else {
- /*
- * The rest of the interrupt conditions can occur only during a
- * DMA transfer
- */
+ struct Scsi_Host *instance = first_instance;
+ int done = 1, handled = 0;
+ unsigned char basr;
+
+ INT_PRINTK("scsi%d: NCR5380 irq triggered\n", HOSTNO);
+
+ /* Look for pending interrupts */
+ basr = NCR5380_read(BUS_AND_STATUS_REG);
+ INT_PRINTK("scsi%d: BASR=%02x\n", HOSTNO, basr);
+ /* dispatch to appropriate routine if found and done=0 */
+ if (basr & BASR_IRQ) {
+ NCR_PRINT(NDEBUG_INTR);
+ if ((NCR5380_read(STATUS_REG) & (SR_SEL|SR_IO)) == (SR_SEL|SR_IO)) {
+ done = 0;
+ ENABLE_IRQ();
+ INT_PRINTK("scsi%d: SEL interrupt\n", HOSTNO);
+ NCR5380_reselect(instance);
+ (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+ } else if (basr & BASR_PARITY_ERROR) {
+ INT_PRINTK("scsi%d: PARITY interrupt\n", HOSTNO);
+ (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+ } else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) {
+ INT_PRINTK("scsi%d: RESET interrupt\n", HOSTNO);
+ (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+ } else {
+ /*
+ * The rest of the interrupt conditions can occur only during a
+ * DMA transfer
+ */
#if defined(REAL_DMA)
- /*
- * We should only get PHASE MISMATCH and EOP interrupts if we have
- * DMA enabled, so do a sanity check based on the current setting
- * of the MODE register.
- */
-
- if ((NCR5380_read(MODE_REG) & MR_DMA_MODE) &&
- ((basr & BASR_END_DMA_TRANSFER) ||
- !(basr & BASR_PHASE_MATCH))) {
-
- INT_PRINTK("scsi%d: PHASE MISM or EOP interrupt\n", HOSTNO);
- NCR5380_dma_complete( instance );
- done = 0;
- ENABLE_IRQ();
- } else
+ /*
+ * We should only get PHASE MISMATCH and EOP interrupts if we have
+ * DMA enabled, so do a sanity check based on the current setting
+ * of the MODE register.
+ */
+
+ if ((NCR5380_read(MODE_REG) & MR_DMA_MODE) &&
+ ((basr & BASR_END_DMA_TRANSFER) ||
+ !(basr & BASR_PHASE_MATCH))) {
+
+ INT_PRINTK("scsi%d: PHASE MISM or EOP interrupt\n", HOSTNO);
+ NCR5380_dma_complete( instance );
+ done = 0;
+ ENABLE_IRQ();
+ } else
#endif /* REAL_DMA */
- {
+ {
/* MS: Ignore unknown phase mismatch interrupts (caused by EOP interrupt) */
- if (basr & BASR_PHASE_MATCH)
- printk(KERN_NOTICE "scsi%d: unknown interrupt, "
- "BASR 0x%x, MR 0x%x, SR 0x%x\n",
- HOSTNO, basr, NCR5380_read(MODE_REG),
- NCR5380_read(STATUS_REG));
- (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
- }
- } /* if !(SELECTION || PARITY) */
- handled = 1;
- } /* BASR & IRQ */
- else {
- printk(KERN_NOTICE "scsi%d: interrupt without IRQ bit set in BASR, "
- "BASR 0x%X, MR 0x%X, SR 0x%x\n", HOSTNO, basr,
- NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG));
- (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
- }
-
- if (!done) {
- INT_PRINTK("scsi%d: in int routine, calling main\n", HOSTNO);
- /* Put a call to NCR5380_main() on the queue... */
- queue_main();
- }
- return IRQ_RETVAL(handled);
+ if (basr & BASR_PHASE_MATCH)
+ printk(KERN_NOTICE "scsi%d: unknown interrupt, "
+ "BASR 0x%x, MR 0x%x, SR 0x%x\n",
+ HOSTNO, basr, NCR5380_read(MODE_REG),
+ NCR5380_read(STATUS_REG));
+ (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+ }
+ } /* if !(SELECTION || PARITY) */
+ handled = 1;
+ } /* BASR & IRQ */ else {
+ printk(KERN_NOTICE "scsi%d: interrupt without IRQ bit set in BASR, "
+ "BASR 0x%X, MR 0x%X, SR 0x%x\n", HOSTNO, basr,
+ NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG));
+ (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+ }
+
+ if (!done) {
+ INT_PRINTK("scsi%d: in int routine, calling main\n", HOSTNO);
+ /* Put a call to NCR5380_main() on the queue... */
+ queue_main();
+ }
+ return IRQ_RETVAL(handled);
}
#ifdef NCR5380_STATS
-static void collect_stats(struct NCR5380_hostdata* hostdata, Scsi_Cmnd* cmd)
+static void collect_stats(struct NCR5380_hostdata* hostdata, Scsi_Cmnd *cmd)
{
# ifdef NCR5380_STAT_LIMIT
- if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
+ if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
# endif
- switch (cmd->cmnd[0])
- {
- case WRITE:
- case WRITE_6:
- case WRITE_10:
- hostdata->time_write[cmd->device->id] += (jiffies - hostdata->timebase);
- /*hostdata->bytes_write[cmd->device->id] += cmd->request_bufflen;*/
- 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] += cmd->request_bufflen;*/
- hostdata->pendingr--;
- break;
- }
+ 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] += cmd->request_bufflen;*/
+ 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] += cmd->request_bufflen;*/
+ hostdata->pendingr--;
+ break;
+ }
}
#endif
-/*
- * Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd,
+/*
+ * Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd,
* int tag);
*
* 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.
+ * 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
+ * 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.
- *
+ *
* Returns : -1 if selection could not execute for some reason,
- * 0 if selection succeeded or failed because the target
- * did not respond.
+ * 0 if selection succeeded or failed because the target
+ * did not respond.
*
- * Side effects :
- * If bus busy, arbitration failed, etc, NCR5380_select() will exit
+ * Side effects :
+ * If bus busy, arbitration failed, etc, NCR5380_select() will exit
* with registers as they should have been on entry - ie
* SELECT_ENABLE will be set appropriately, the NCR5380
* will cease to drive any SCSI bus signals.
*
- * If successful : I_T_L or I_T_L_Q nexus will be established,
- * instance->connected will be set to cmd.
- * SELECT interrupt will be disabled.
+ * If successful : I_T_L or I_T_L_Q nexus will be established,
+ * instance->connected will be set to cmd.
+ * SELECT interrupt will be disabled.
*
- * If failed (no target) : cmd->scsi_done() will be called, and the
+ * If failed (no target) : cmd->scsi_done() will be called, and the
* cmd->result host byte set to DID_BAD_TARGET.
*/
-static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
+static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
{
- SETUP_HOSTDATA(instance);
- unsigned char tmp[3], phase;
- unsigned char *data;
- int len;
- unsigned long timeout;
- unsigned long flags;
-
- hostdata->restart_select = 0;
- NCR_PRINT(NDEBUG_ARBITRATION);
- ARB_PRINTK("scsi%d: starting arbitration, id = %d\n", HOSTNO,
- instance->this_id);
-
- /*
- * Set the phase bits to 0, otherwise the NCR5380 won't drive the
- * data bus during SELECTION.
- */
-
- local_irq_save(flags);
- if (hostdata->connected) {
+ SETUP_HOSTDATA(instance);
+ unsigned char tmp[3], phase;
+ unsigned char *data;
+ int len;
+ unsigned long timeout;
+ unsigned long flags;
+
+ hostdata->restart_select = 0;
+ NCR_PRINT(NDEBUG_ARBITRATION);
+ ARB_PRINTK("scsi%d: starting arbitration, id = %d\n", HOSTNO,
+ instance->this_id);
+
+ /*
+ * Set the phase bits to 0, otherwise the NCR5380 won't drive the
+ * data bus during SELECTION.
+ */
+
+ local_irq_save(flags);
+ if (hostdata->connected) {
+ local_irq_restore(flags);
+ return -1;
+ }
+ NCR5380_write(TARGET_COMMAND_REG, 0);
+
+ /*
+ * Start arbitration.
+ */
+
+ NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
+ NCR5380_write(MODE_REG, MR_ARBITRATE);
+
local_irq_restore(flags);
- return -1;
- }
- NCR5380_write(TARGET_COMMAND_REG, 0);
-
-
- /*
- * Start arbitration.
- */
-
- NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
- NCR5380_write(MODE_REG, MR_ARBITRATE);
-
- local_irq_restore(flags);
-
- /* Wait for arbitration logic to complete */
-#if NCR_TIMEOUT
- {
- unsigned long timeout = jiffies + 2*NCR_TIMEOUT;
-
- while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)
- && time_before(jiffies, timeout) && !hostdata->connected)
- ;
- if (time_after_eq(jiffies, timeout))
- {
- printk("scsi : arbitration timeout at %d\n", __LINE__);
- NCR5380_write(MODE_REG, MR_BASE);
- NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
- return -1;
- }
- }
+
+ /* Wait for arbitration logic to complete */
+#if defined(NCR_TIMEOUT)
+ {
+ unsigned long timeout = jiffies + 2*NCR_TIMEOUT;
+
+ while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) &&
+ time_before(jiffies, timeout) && !hostdata->connected)
+ ;
+ if (time_after_eq(jiffies, timeout)) {
+ printk("scsi : arbitration timeout at %d\n", __LINE__);
+ NCR5380_write(MODE_REG, MR_BASE);
+ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+ return -1;
+ }
+ }
#else /* NCR_TIMEOUT */
- while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)
- && !hostdata->connected);
+ while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) &&
+ !hostdata->connected)
+ ;
#endif
- ARB_PRINTK("scsi%d: arbitration complete\n", HOSTNO);
-
- if (hostdata->connected) {
- NCR5380_write(MODE_REG, MR_BASE);
- return -1;
- }
- /*
- * The arbitration delay is 2.2us, but this is a minimum and there is
- * no maximum so we can safely sleep for ceil(2.2) usecs to accommodate
- * the integral nature of udelay().
- *
- */
-
- udelay(3);
-
- /* Check for lost arbitration */
- if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
- (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) ||
- (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
- hostdata->connected) {
- NCR5380_write(MODE_REG, MR_BASE);
- ARB_PRINTK("scsi%d: lost arbitration, deasserting MR_ARBITRATE\n",
- HOSTNO);
- return -1;
- }
-
- /* after/during arbitration, BSY should be asserted.
- IBM DPES-31080 Version S31Q works now */
- /* Tnx to Thomas_Roesch@m2.maus.de for finding this! (Roman) */
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL |
- ICR_ASSERT_BSY ) ;
-
- if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
- hostdata->connected) {
- NCR5380_write(MODE_REG, MR_BASE);
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- ARB_PRINTK("scsi%d: lost arbitration, deasserting ICR_ASSERT_SEL\n",
- HOSTNO);
- return -1;
- }
+ ARB_PRINTK("scsi%d: arbitration complete\n", HOSTNO);
- /*
- * Again, bus clear + bus settle time is 1.2us, however, this is
- * a minimum so we'll udelay ceil(1.2)
- */
+ if (hostdata->connected) {
+ NCR5380_write(MODE_REG, MR_BASE);
+ return -1;
+ }
+ /*
+ * The arbitration delay is 2.2us, but this is a minimum and there is
+ * no maximum so we can safely sleep for ceil(2.2) usecs to accommodate
+ * the integral nature of udelay().
+ *
+ */
+
+ udelay(3);
+
+ /* Check for lost arbitration */
+ if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
+ (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) ||
+ (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
+ hostdata->connected) {
+ NCR5380_write(MODE_REG, MR_BASE);
+ ARB_PRINTK("scsi%d: lost arbitration, deasserting MR_ARBITRATE\n",
+ HOSTNO);
+ return -1;
+ }
+
+ /* after/during arbitration, BSY should be asserted.
+ IBM DPES-31080 Version S31Q works now */
+ /* Tnx to Thomas_Roesch@m2.maus.de for finding this! (Roman) */
+ NCR5380_write(INITIATOR_COMMAND_REG,
+ ICR_BASE | ICR_ASSERT_SEL | ICR_ASSERT_BSY);
+
+ if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
+ hostdata->connected) {
+ NCR5380_write(MODE_REG, MR_BASE);
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+ ARB_PRINTK("scsi%d: lost arbitration, deasserting ICR_ASSERT_SEL\n",
+ HOSTNO);
+ return -1;
+ }
+
+ /*
+ * Again, bus clear + bus settle time is 1.2us, however, this is
+ * a minimum so we'll udelay ceil(1.2)
+ */
#ifdef CONFIG_ATARI_SCSI_TOSHIBA_DELAY
- /* ++roman: But some targets (see above :-) seem to need a bit more... */
- udelay(15);
+ /* ++roman: But some targets (see above :-) seem to need a bit more... */
+ udelay(15);
#else
- udelay(2);
+ udelay(2);
#endif
-
- if (hostdata->connected) {
+
+ if (hostdata->connected) {
+ NCR5380_write(MODE_REG, MR_BASE);
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+ return -1;
+ }
+
+ ARB_PRINTK("scsi%d: won arbitration\n", HOSTNO);
+
+ /*
+ * Now that we have won arbitration, start Selection process, asserting
+ * the host and target ID's on the SCSI bus.
+ */
+
+ NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << cmd->device->id)));
+
+ /*
+ * Raise ATN while SEL is true before BSY goes false from arbitration,
+ * since this is the only way to guarantee that we'll get a MESSAGE OUT
+ * phase immediately after selection.
+ */
+
+ NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_BSY |
+ ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL ));
NCR5380_write(MODE_REG, MR_BASE);
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- return -1;
- }
- ARB_PRINTK("scsi%d: won arbitration\n", HOSTNO);
+ /*
+ * Reselect interrupts must be turned off prior to the dropping of BSY,
+ * otherwise we will trigger an interrupt.
+ */
+
+ if (hostdata->connected) {
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+ return -1;
+ }
- /*
- * Now that we have won arbitration, start Selection process, asserting
- * the host and target ID's on the SCSI bus.
- */
+ NCR5380_write(SELECT_ENABLE_REG, 0);
+
+ /*
+ * The initiator shall then wait at least two deskew delays and release
+ * the BSY signal.
+ */
+ udelay(1); /* wingel -- wait two bus deskew delay >2*45ns */
+
+ /* Reset BSY */
+ NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA |
+ ICR_ASSERT_ATN | ICR_ASSERT_SEL));
+
+ /*
+ * Something weird happens when we cease to drive BSY - looks
+ * like the board/chip is letting us do another read before the
+ * appropriate propagation delay has expired, and we're confusing
+ * a BSY signal from ourselves as the target's response to SELECTION.
+ *
+ * A small delay (the 'C++' frontend breaks the pipeline with an
+ * unnecessary jump, making it work on my 386-33/Trantor T128, the
+ * tighter 'C' code breaks and requires this) solves the problem -
+ * the 1 us delay is arbitrary, and only used because this delay will
+ * be the same on other platforms and since it works here, it should
+ * work there.
+ *
+ * wingel suggests that this could be due to failing to wait
+ * one deskew delay.
+ */
- NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << cmd->device->id)));
+ udelay(1);
- /*
- * Raise ATN while SEL is true before BSY goes false from arbitration,
- * since this is the only way to guarantee that we'll get a MESSAGE OUT
- * phase immediately after selection.
- */
+ SEL_PRINTK("scsi%d: selecting target %d\n", HOSTNO, cmd->device->id);
- NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_BSY |
- ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL ));
- NCR5380_write(MODE_REG, MR_BASE);
+ /*
+ * The SCSI specification calls for a 250 ms timeout for the actual
+ * selection.
+ */
- /*
- * Reselect interrupts must be turned off prior to the dropping of BSY,
- * otherwise we will trigger an interrupt.
- */
+ timeout = jiffies + 25;
- if (hostdata->connected) {
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- return -1;
- }
-
- NCR5380_write(SELECT_ENABLE_REG, 0);
-
- /*
- * The initiator shall then wait at least two deskew delays and release
- * the BSY signal.
- */
- udelay(1); /* wingel -- wait two bus deskew delay >2*45ns */
-
- /* Reset BSY */
- NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA |
- ICR_ASSERT_ATN | ICR_ASSERT_SEL));
-
- /*
- * Something weird happens when we cease to drive BSY - looks
- * like the board/chip is letting us do another read before the
- * appropriate propagation delay has expired, and we're confusing
- * a BSY signal from ourselves as the target's response to SELECTION.
- *
- * A small delay (the 'C++' frontend breaks the pipeline with an
- * unnecessary jump, making it work on my 386-33/Trantor T128, the
- * tighter 'C' code breaks and requires this) solves the problem -
- * the 1 us delay is arbitrary, and only used because this delay will
- * be the same on other platforms and since it works here, it should
- * work there.
- *
- * wingel suggests that this could be due to failing to wait
- * one deskew delay.
- */
-
- udelay(1);
-
- SEL_PRINTK("scsi%d: selecting target %d\n", HOSTNO, cmd->device->id);
-
- /*
- * The SCSI specification calls for a 250 ms timeout for the actual
- * selection.
- */
-
- timeout = jiffies + 25;
-
- /*
- * XXX very interesting - we're seeing a bounce where the BSY we
- * asserted is being reflected / still asserted (propagation delay?)
- * and it's detecting as true. Sigh.
- */
+ /*
+ * XXX very interesting - we're seeing a bounce where the BSY we
+ * asserted is being reflected / still asserted (propagation delay?)
+ * and it's detecting as true. Sigh.
+ */
#if 0
- /* ++roman: If a target conformed to the SCSI standard, it wouldn't assert
- * IO while SEL is true. But again, there are some disks out the in the
- * world that do that nevertheless. (Somebody claimed that this announces
- * reselection capability of the target.) So we better skip that test and
- * only wait for BSY... (Famous german words: Der Klügere gibt nach :-)
- */
-
- while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) &
- (SR_BSY | SR_IO)));
-
- if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) ==
- (SR_SEL | SR_IO)) {
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- NCR5380_reselect(instance);
- printk (KERN_ERR "scsi%d: reselection after won arbitration?\n",
- HOSTNO);
- NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
- return -1;
- }
+ /* ++roman: If a target conformed to the SCSI standard, it wouldn't assert
+ * IO while SEL is true. But again, there are some disks out the in the
+ * world that do that nevertheless. (Somebody claimed that this announces
+ * reselection capability of the target.) So we better skip that test and
+ * only wait for BSY... (Famous german words: Der Klügere gibt nach :-)
+ */
+
+ while (time_before(jiffies, timeout) &&
+ !(NCR5380_read(STATUS_REG) & (SR_BSY | SR_IO)))
+ ;
+
+ if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+ NCR5380_reselect(instance);
+ printk(KERN_ERR "scsi%d: reselection after won arbitration?\n",
+ HOSTNO);
+ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+ return -1;
+ }
#else
- while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY));
+ while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY))
+ ;
#endif
- /*
- * No less than two deskew delays after the initiator detects the
- * BSY signal is true, it shall release the SEL signal and may
- * change the DATA BUS. -wingel
- */
+ /*
+ * No less than two deskew delays after the initiator detects the
+ * BSY signal is true, it shall release the SEL signal and may
+ * change the DATA BUS. -wingel
+ */
- udelay(1);
+ udelay(1);
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
- if (!(NCR5380_read(STATUS_REG) & SR_BSY)) {
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- if (hostdata->targets_present & (1 << cmd->device->id)) {
- printk(KERN_ERR "scsi%d: weirdness\n", HOSTNO);
- if (hostdata->restart_select)
- printk(KERN_NOTICE "\trestart select\n");
- NCR_PRINT(NDEBUG_ANY);
- NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
- return -1;
- }
- cmd->result = DID_BAD_TARGET << 16;
+ if (!(NCR5380_read(STATUS_REG) & SR_BSY)) {
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+ if (hostdata->targets_present & (1 << cmd->device->id)) {
+ printk(KERN_ERR "scsi%d: weirdness\n", HOSTNO);
+ if (hostdata->restart_select)
+ printk(KERN_NOTICE "\trestart select\n");
+ NCR_PRINT(NDEBUG_ANY);
+ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+ return -1;
+ }
+ cmd->result = DID_BAD_TARGET << 16;
#ifdef NCR5380_STATS
- collect_stats(hostdata, cmd);
+ collect_stats(hostdata, cmd);
#endif
#ifdef SUPPORT_TAGS
- cmd_free_tag( cmd );
+ cmd_free_tag(cmd);
#endif
- cmd->scsi_done(cmd);
- NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
- SEL_PRINTK("scsi%d: target did not respond within 250ms\n", HOSTNO);
- NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
- return 0;
- }
-
- hostdata->targets_present |= (1 << cmd->device->id);
-
- /*
- * Since we followed the SCSI spec, and raised ATN while SEL
- * was true but before BSY was false during selection, the information
- * transfer phase should be a MESSAGE OUT phase so that we can send the
- * IDENTIFY message.
- *
- * If SCSI-II tagged queuing is enabled, we also send a SIMPLE_QUEUE_TAG
- * message (2 bytes) with a tag ID that we increment with every command
- * until it wraps back to 0.
- *
- * XXX - it turns out that there are some broken SCSI-II devices,
- * which claim to support tagged queuing but fail when more than
- * some number of commands are issued at once.
- */
-
- /* Wait for start of REQ/ACK handshake */
- while (!(NCR5380_read(STATUS_REG) & SR_REQ));
-
- SEL_PRINTK("scsi%d: target %d selected, going into MESSAGE OUT phase.\n",
- HOSTNO, cmd->device->id);
- tmp[0] = IDENTIFY(1, cmd->device->lun);
+ cmd->scsi_done(cmd);
+ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+ SEL_PRINTK("scsi%d: target did not respond within 250ms\n", HOSTNO);
+ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+ return 0;
+ }
+
+ hostdata->targets_present |= (1 << cmd->device->id);
+
+ /*
+ * Since we followed the SCSI spec, and raised ATN while SEL
+ * was true but before BSY was false during selection, the information
+ * transfer phase should be a MESSAGE OUT phase so that we can send the
+ * IDENTIFY message.
+ *
+ * If SCSI-II tagged queuing is enabled, we also send a SIMPLE_QUEUE_TAG
+ * message (2 bytes) with a tag ID that we increment with every command
+ * until it wraps back to 0.
+ *
+ * XXX - it turns out that there are some broken SCSI-II devices,
+ * which claim to support tagged queuing but fail when more than
+ * some number of commands are issued at once.
+ */
+
+ /* Wait for start of REQ/ACK handshake */
+ while (!(NCR5380_read(STATUS_REG) & SR_REQ))
+ ;
+
+ SEL_PRINTK("scsi%d: target %d selected, going into MESSAGE OUT phase.\n",
+ HOSTNO, cmd->device->id);
+ tmp[0] = IDENTIFY(1, cmd->device->lun);
#ifdef SUPPORT_TAGS
- if (cmd->tag != TAG_NONE) {
- tmp[1] = hostdata->last_message = SIMPLE_QUEUE_TAG;
- tmp[2] = cmd->tag;
- len = 3;
- } else
- len = 1;
+ if (cmd->tag != TAG_NONE) {
+ tmp[1] = hostdata->last_message = SIMPLE_QUEUE_TAG;
+ tmp[2] = cmd->tag;
+ len = 3;
+ } else
+ len = 1;
#else
- len = 1;
- cmd->tag=0;
+ len = 1;
+ cmd->tag = 0;
#endif /* SUPPORT_TAGS */
- /* Send message(s) */
- data = tmp;
- phase = PHASE_MSGOUT;
- NCR5380_transfer_pio(instance, &phase, &len, &data);
- SEL_PRINTK("scsi%d: nexus established.\n", HOSTNO);
- /* XXX need to handle errors here */
- hostdata->connected = cmd;
+ /* Send message(s) */
+ data = tmp;
+ phase = PHASE_MSGOUT;
+ NCR5380_transfer_pio(instance, &phase, &len, &data);
+ SEL_PRINTK("scsi%d: nexus established.\n", HOSTNO);
+ /* XXX need to handle errors here */
+ hostdata->connected = cmd;
#ifndef SUPPORT_TAGS
- hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
-#endif
-
- initialize_SCp(cmd);
+ hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
+#endif
+ initialize_SCp(cmd);
- return 0;
+ return 0;
}
-/*
- * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance,
+/*
+ * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance,
* unsigned char *phase, int *count, unsigned char **data)
*
* Purpose : transfers data in given phase using polled I/O
*
- * Inputs : instance - instance of driver, *phase - pointer to
- * what phase is expected, *count - pointer to number of
+ * Inputs : instance - instance of driver, *phase - pointer to
+ * what phase is expected, *count - pointer to number of
* bytes to transfer, **data - pointer to data pointer.
- *
+ *
* Returns : -1 when different phase is entered without transferring
* maximum number of bytes, 0 if all bytes are transfered or exit
* is in same phase.
*
- * Also, *phase, *count, *data are modified in place.
+ * Also, *phase, *count, *data are modified in place.
*
* XXX Note : handling for bus free may be useful.
*/
/*
- * Note : this code is not as quick as it could be, however it
+ * Note : this code is not as quick as it could be, however it
* IS 100% reliable, and for the actual data transfer where speed
* counts, we will always do a pseudo DMA or DMA transfer.
*/
-static int NCR5380_transfer_pio( struct Scsi_Host *instance,
- unsigned char *phase, int *count,
- unsigned char **data)
+static int NCR5380_transfer_pio(struct Scsi_Host *instance,
+ unsigned char *phase, int *count,
+ unsigned char **data)
{
- register unsigned char p = *phase, tmp;
- register int c = *count;
- register unsigned char *d = *data;
-
- /*
- * The NCR5380 chip will only drive the SCSI bus when the
- * phase specified in the appropriate bits of the TARGET COMMAND
- * REGISTER match the STATUS REGISTER
- */
-
- NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
-
- do {
- /*
- * Wait for assertion of REQ, after which the phase bits will be
- * valid
+ register unsigned char p = *phase, tmp;
+ register int c = *count;
+ register unsigned char *d = *data;
+
+ /*
+ * The NCR5380 chip will only drive the SCSI bus when the
+ * phase specified in the appropriate bits of the TARGET COMMAND
+ * REGISTER match the STATUS REGISTER
*/
- while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ));
- HSH_PRINTK("scsi%d: REQ detected\n", HOSTNO);
+ NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
- /* Check for phase mismatch */
- if ((tmp & PHASE_MASK) != p) {
- PIO_PRINTK("scsi%d: phase mismatch\n", HOSTNO);
- NCR_PRINT_PHASE(NDEBUG_PIO);
- break;
- }
+ do {
+ /*
+ * Wait for assertion of REQ, after which the phase bits will be
+ * valid
+ */
+ while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ))
+ ;
- /* Do actual transfer from SCSI bus to / from memory */
- if (!(p & SR_IO))
- NCR5380_write(OUTPUT_DATA_REG, *d);
- else
- *d = NCR5380_read(CURRENT_SCSI_DATA_REG);
+ HSH_PRINTK("scsi%d: REQ detected\n", HOSTNO);
- ++d;
+ /* Check for phase mismatch */
+ if ((tmp & PHASE_MASK) != p) {
+ PIO_PRINTK("scsi%d: phase mismatch\n", HOSTNO);
+ NCR_PRINT_PHASE(NDEBUG_PIO);
+ break;
+ }
- /*
- * The SCSI standard suggests that in MSGOUT phase, the initiator
- * should drop ATN on the last byte of the message phase
- * after REQ has been asserted for the handshake but before
- * the initiator raises ACK.
- */
+ /* Do actual transfer from SCSI bus to / from memory */
+ if (!(p & SR_IO))
+ NCR5380_write(OUTPUT_DATA_REG, *d);
+ else
+ *d = NCR5380_read(CURRENT_SCSI_DATA_REG);
- if (!(p & SR_IO)) {
- if (!((p & SR_MSG) && c > 1)) {
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
- ICR_ASSERT_DATA);
- NCR_PRINT(NDEBUG_PIO);
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
- ICR_ASSERT_DATA | ICR_ASSERT_ACK);
- } else {
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
- ICR_ASSERT_DATA | ICR_ASSERT_ATN);
- NCR_PRINT(NDEBUG_PIO);
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
- ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
- }
- } else {
- NCR_PRINT(NDEBUG_PIO);
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
- }
+ ++d;
- while (NCR5380_read(STATUS_REG) & SR_REQ);
+ /*
+ * The SCSI standard suggests that in MSGOUT phase, the initiator
+ * should drop ATN on the last byte of the message phase
+ * after REQ has been asserted for the handshake but before
+ * the initiator raises ACK.
+ */
- HSH_PRINTK("scsi%d: req false, handshake complete\n", HOSTNO);
+ if (!(p & SR_IO)) {
+ if (!((p & SR_MSG) && c > 1)) {
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
+ NCR_PRINT(NDEBUG_PIO);
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
+ ICR_ASSERT_DATA | ICR_ASSERT_ACK);
+ } else {
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
+ ICR_ASSERT_DATA | ICR_ASSERT_ATN);
+ NCR_PRINT(NDEBUG_PIO);
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
+ ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
+ }
+ } else {
+ NCR_PRINT(NDEBUG_PIO);
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
+ }
-/*
- * We have several special cases to consider during REQ/ACK handshaking :
- * 1. We were in MSGOUT phase, and we are on the last byte of the
- * message. ATN must be dropped as ACK is dropped.
- *
- * 2. We are in a MSGIN phase, and we are on the last byte of the
- * message. We must exit with ACK asserted, so that the calling
- * code may raise ATN before dropping ACK to reject the message.
- *
- * 3. ACK and ATN are clear and the target may proceed as normal.
- */
- if (!(p == PHASE_MSGIN && c == 1)) {
- if (p == PHASE_MSGOUT && c > 1)
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
- else
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- }
- } while (--c);
-
- PIO_PRINTK("scsi%d: residual %d\n", HOSTNO, c);
-
- *count = c;
- *data = d;
- tmp = NCR5380_read(STATUS_REG);
- /* The phase read from the bus is valid if either REQ is (already)
- * asserted or if ACK hasn't been released yet. The latter is the case if
- * we're in MSGIN and all wanted bytes have been received. */
- if ((tmp & SR_REQ) || (p == PHASE_MSGIN && c == 0))
- *phase = tmp & PHASE_MASK;
- else
- *phase = PHASE_UNKNOWN;
-
- if (!c || (*phase == p))
- return 0;
- else
- return -1;
+ while (NCR5380_read(STATUS_REG) & SR_REQ)
+ ;
+
+ HSH_PRINTK("scsi%d: req false, handshake complete\n", HOSTNO);
+
+ /*
+ * We have several special cases to consider during REQ/ACK handshaking :
+ * 1. We were in MSGOUT phase, and we are on the last byte of the
+ * message. ATN must be dropped as ACK is dropped.
+ *
+ * 2. We are in a MSGIN phase, and we are on the last byte of the
+ * message. We must exit with ACK asserted, so that the calling
+ * code may raise ATN before dropping ACK to reject the message.
+ *
+ * 3. ACK and ATN are clear and the target may proceed as normal.
+ */
+ if (!(p == PHASE_MSGIN && c == 1)) {
+ if (p == PHASE_MSGOUT && c > 1)
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
+ else
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+ }
+ } while (--c);
+
+ PIO_PRINTK("scsi%d: residual %d\n", HOSTNO, c);
+
+ *count = c;
+ *data = d;
+ tmp = NCR5380_read(STATUS_REG);
+ /* The phase read from the bus is valid if either REQ is (already)
+ * asserted or if ACK hasn't been released yet. The latter is the case if
+ * we're in MSGIN and all wanted bytes have been received.
+ */
+ if ((tmp & SR_REQ) || (p == PHASE_MSGIN && c == 0))
+ *phase = tmp & PHASE_MASK;
+ else
+ *phase = PHASE_UNKNOWN;
+
+ if (!c || (*phase == p))
+ return 0;
+ else
+ return -1;
}
/*
* Function : do_abort (Scsi_Host *host)
- *
- * Purpose : abort the currently established nexus. Should only be
- * called from a routine which can drop into a
- *
+ *
+ * Purpose : abort the currently established nexus. Should only be
+ * called from a routine which can drop into a
+ *
* Returns : 0 on success, -1 on failure.
*/
-static int do_abort (struct Scsi_Host *host)
+static int do_abort(struct Scsi_Host *host)
{
- unsigned char tmp, *msgptr, phase;
- int len;
-
- /* Request message out phase */
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
-
- /*
- * Wait for the target to indicate a valid phase by asserting
- * REQ. Once this happens, we'll have either a MSGOUT phase
- * and can immediately send the ABORT message, or we'll have some
- * other phase and will have to source/sink data.
- *
- * We really don't care what value was on the bus or what value
- * the target sees, so we just handshake.
- */
-
- while (!(tmp = NCR5380_read(STATUS_REG)) & SR_REQ);
-
- NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
-
- if ((tmp & PHASE_MASK) != PHASE_MSGOUT) {
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN |
- ICR_ASSERT_ACK);
- while (NCR5380_read(STATUS_REG) & SR_REQ);
+ unsigned char tmp, *msgptr, phase;
+ int len;
+
+ /* Request message out phase */
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
- }
-
- tmp = ABORT;
- msgptr = &tmp;
- len = 1;
- phase = PHASE_MSGOUT;
- NCR5380_transfer_pio (host, &phase, &len, &msgptr);
-
- /*
- * If we got here, and the command completed successfully,
- * we're about to go into bus free state.
- */
-
- return len ? -1 : 0;
+
+ /*
+ * Wait for the target to indicate a valid phase by asserting
+ * REQ. Once this happens, we'll have either a MSGOUT phase
+ * and can immediately send the ABORT message, or we'll have some
+ * other phase and will have to source/sink data.
+ *
+ * We really don't care what value was on the bus or what value
+ * the target sees, so we just handshake.
+ */
+
+ while (!(tmp = NCR5380_read(STATUS_REG)) & SR_REQ)
+ ;
+
+ NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
+
+ if ((tmp & PHASE_MASK) != PHASE_MSGOUT) {
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN |
+ ICR_ASSERT_ACK);
+ while (NCR5380_read(STATUS_REG) & SR_REQ)
+ ;
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
+ }
+
+ tmp = ABORT;
+ msgptr = &tmp;
+ len = 1;
+ phase = PHASE_MSGOUT;
+ NCR5380_transfer_pio(host, &phase, &len, &msgptr);
+
+ /*
+ * If we got here, and the command completed successfully,
+ * we're about to go into bus free state.
+ */
+
+ return len ? -1 : 0;
}
#if defined(REAL_DMA)
-/*
- * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance,
+/*
+ * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance,
* unsigned char *phase, int *count, unsigned char **data)
*
* Purpose : transfers data in given phase using either real
* or pseudo DMA.
*
- * Inputs : instance - instance of driver, *phase - pointer to
- * what phase is expected, *count - pointer to number of
+ * Inputs : instance - instance of driver, *phase - pointer to
+ * what phase is expected, *count - pointer to number of
* bytes to transfer, **data - pointer to data pointer.
- *
+ *
* Returns : -1 when different phase is entered without transferring
* maximum number of bytes, 0 if all bytes or transfered or exit
* is in same phase.
*
- * Also, *phase, *count, *data are modified in place.
+ * Also, *phase, *count, *data are modified in place.
*
*/
-static int NCR5380_transfer_dma( struct Scsi_Host *instance,
- unsigned char *phase, int *count,
- unsigned char **data)
+static int NCR5380_transfer_dma(struct Scsi_Host *instance,
+ unsigned char *phase, int *count,
+ unsigned char **data)
{
- SETUP_HOSTDATA(instance);
- register int c = *count;
- register unsigned char p = *phase;
- register unsigned char *d = *data;
- unsigned char tmp;
- unsigned long flags;
-
- if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) {
- *phase = tmp;
- return -1;
- }
+ SETUP_HOSTDATA(instance);
+ register int c = *count;
+ register unsigned char p = *phase;
+ register unsigned char *d = *data;
+ unsigned char tmp;
+ unsigned long flags;
+
+ if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) {
+ *phase = tmp;
+ return -1;
+ }
- if (atari_read_overruns && (p & SR_IO)) {
- c -= atari_read_overruns;
- }
+ if (atari_read_overruns && (p & SR_IO))
+ c -= atari_read_overruns;
- DMA_PRINTK("scsi%d: initializing DMA for %s, %d bytes %s %p\n",
- HOSTNO, (p & SR_IO) ? "reading" : "writing",
- c, (p & SR_IO) ? "to" : "from", d);
+ DMA_PRINTK("scsi%d: initializing DMA for %s, %d bytes %s %p\n",
+ HOSTNO, (p & SR_IO) ? "reading" : "writing",
+ c, (p & SR_IO) ? "to" : "from", d);
- NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
+ NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
#ifdef REAL_DMA
- NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY);
+ NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY);
#endif /* def REAL_DMA */
- if (IS_A_TT()) {
- /* On the Medusa, it is a must to initialize the DMA before
- * starting the NCR. This is also the cleaner way for the TT.
- */
- local_irq_save(flags);
- hostdata->dma_len = (p & SR_IO) ?
- NCR5380_dma_read_setup(instance, d, c) :
- NCR5380_dma_write_setup(instance, d, c);
- local_irq_restore(flags);
- }
-
- if (p & SR_IO)
- NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);
- else {
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
- NCR5380_write(START_DMA_SEND_REG, 0);
- }
-
- if (!IS_A_TT()) {
- /* On the Falcon, the DMA setup must be done after the last */
- /* NCR access, else the DMA setup gets trashed!
- */
- local_irq_save(flags);
- hostdata->dma_len = (p & SR_IO) ?
- NCR5380_dma_read_setup(instance, d, c) :
- NCR5380_dma_write_setup(instance, d, c);
- local_irq_restore(flags);
- }
- return 0;
+ if (IS_A_TT()) {
+ /* On the Medusa, it is a must to initialize the DMA before
+ * starting the NCR. This is also the cleaner way for the TT.
+ */
+ local_irq_save(flags);
+ hostdata->dma_len = (p & SR_IO) ?
+ NCR5380_dma_read_setup(instance, d, c) :
+ NCR5380_dma_write_setup(instance, d, c);
+ local_irq_restore(flags);
+ }
+
+ if (p & SR_IO)
+ NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);
+ else {
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
+ NCR5380_write(START_DMA_SEND_REG, 0);
+ }
+
+ if (!IS_A_TT()) {
+ /* On the Falcon, the DMA setup must be done after the last */
+ /* NCR access, else the DMA setup gets trashed!
+ */
+ local_irq_save(flags);
+ hostdata->dma_len = (p & SR_IO) ?
+ NCR5380_dma_read_setup(instance, d, c) :
+ NCR5380_dma_write_setup(instance, d, c);
+ local_irq_restore(flags);
+ }
+ return 0;
}
#endif /* defined(REAL_DMA) */
/*
* Function : NCR5380_information_transfer (struct Scsi_Host *instance)
*
- * Purpose : run through the various SCSI phases and do as the target
- * directs us to. Operates on the currently connected command,
+ * Purpose : run through the various SCSI phases and do as the target
+ * directs us to. Operates on the currently connected command,
* instance->connected.
*
* Inputs : instance, instance for which we are doing commands
*
- * Side effects : SCSI things happen, the disconnected queue will be
+ * Side effects : SCSI things happen, the disconnected queue will be
* modified if a command disconnects, *instance->connected will
* change.
*
- * XXX Note : we need to watch for bus free or a reset condition here
- * to recover from an unexpected bus free condition.
+ * XXX Note : we need to watch for bus free or a reset condition here
+ * to recover from an unexpected bus free condition.
*/
-
-static void NCR5380_information_transfer (struct Scsi_Host *instance)
+
+static void NCR5380_information_transfer(struct Scsi_Host *instance)
{
- SETUP_HOSTDATA(instance);
- unsigned long flags;
- unsigned char msgout = NOP;
- int sink = 0;
- int len;
+ SETUP_HOSTDATA(instance);
+ unsigned long flags;
+ unsigned char msgout = NOP;
+ int sink = 0;
+ int len;
#if defined(REAL_DMA)
- int transfersize;
+ int transfersize;
#endif
- unsigned char *data;
- unsigned char phase, tmp, extended_msg[10], old_phase=0xff;
- Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected;
+ unsigned char *data;
+ unsigned char phase, tmp, extended_msg[10], old_phase = 0xff;
+ Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected;
+
+ while (1) {
+ tmp = NCR5380_read(STATUS_REG);
+ /* We only have a valid SCSI phase when REQ is asserted */
+ if (tmp & SR_REQ) {
+ phase = (tmp & PHASE_MASK);
+ if (phase != old_phase) {
+ old_phase = phase;
+ NCR_PRINT_PHASE(NDEBUG_INFORMATION);
+ }
- while (1) {
- tmp = NCR5380_read(STATUS_REG);
- /* We only have a valid SCSI phase when REQ is asserted */
- if (tmp & SR_REQ) {
- phase = (tmp & PHASE_MASK);
- if (phase != old_phase) {
- old_phase = phase;
- NCR_PRINT_PHASE(NDEBUG_INFORMATION);
- }
-
- if (sink && (phase != PHASE_MSGOUT)) {
- NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
-
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN |
- ICR_ASSERT_ACK);
- while (NCR5380_read(STATUS_REG) & SR_REQ);
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
- ICR_ASSERT_ATN);
- sink = 0;
- continue;
- }
-
- switch (phase) {
- case PHASE_DATAOUT:
+ if (sink && (phase != PHASE_MSGOUT)) {
+ NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
+
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN |
+ ICR_ASSERT_ACK);
+ while (NCR5380_read(STATUS_REG) & SR_REQ)
+ ;
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
+ ICR_ASSERT_ATN);
+ sink = 0;
+ continue;
+ }
+
+ switch (phase) {
+ case PHASE_DATAOUT:
#if (NDEBUG & NDEBUG_NO_DATAOUT)
- printk("scsi%d: NDEBUG_NO_DATAOUT set, attempted DATAOUT "
- "aborted\n", HOSTNO);
- sink = 1;
- do_abort(instance);
- cmd->result = DID_ERROR << 16;
- cmd->done(cmd);
- return;
+ printk("scsi%d: NDEBUG_NO_DATAOUT set, attempted DATAOUT "
+ "aborted\n", HOSTNO);
+ sink = 1;
+ do_abort(instance);
+ cmd->result = DID_ERROR << 16;
+ cmd->done(cmd);
+ return;
#endif
- case PHASE_DATAIN:
- /*
- * If there is no room left in the current buffer in the
- * scatter-gather list, move onto the next one.
- */
-
- if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
- ++cmd->SCp.buffer;
- --cmd->SCp.buffers_residual;
- cmd->SCp.this_residual = cmd->SCp.buffer->length;
- cmd->SCp.ptr = page_address(cmd->SCp.buffer->page)+
- cmd->SCp.buffer->offset;
- /* ++roman: Try to merge some scatter-buffers if
- * they are at contiguous physical addresses.
- */
- merge_contiguous_buffers( cmd );
- INF_PRINTK("scsi%d: %d bytes and %d buffers left\n",
- HOSTNO, cmd->SCp.this_residual,
- cmd->SCp.buffers_residual);
- }
-
- /*
- * The preferred transfer method is going to be
- * PSEUDO-DMA for systems that are strictly PIO,
- * since we can let the hardware do the handshaking.
- *
- * For this to work, we need to know the transfersize
- * ahead of time, since the pseudo-DMA code will sit
- * in an unconditional loop.
- */
-
-/* ++roman: I suggest, this should be
- * #if def(REAL_DMA)
- * instead of leaving REAL_DMA out.
- */
+ case PHASE_DATAIN:
+ /*
+ * If there is no room left in the current buffer in the
+ * scatter-gather list, move onto the next one.
+ */
+
+ if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
+ ++cmd->SCp.buffer;
+ --cmd->SCp.buffers_residual;
+ cmd->SCp.this_residual = cmd->SCp.buffer->length;
+ cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) +
+ cmd->SCp.buffer->offset;
+ /* ++roman: Try to merge some scatter-buffers if
+ * they are at contiguous physical addresses.
+ */
+ merge_contiguous_buffers(cmd);
+ INF_PRINTK("scsi%d: %d bytes and %d buffers left\n",
+ HOSTNO, cmd->SCp.this_residual,
+ cmd->SCp.buffers_residual);
+ }
+
+ /*
+ * The preferred transfer method is going to be
+ * PSEUDO-DMA for systems that are strictly PIO,
+ * since we can let the hardware do the handshaking.
+ *
+ * For this to work, we need to know the transfersize
+ * ahead of time, since the pseudo-DMA code will sit
+ * in an unconditional loop.
+ */
+
+ /* ++roman: I suggest, this should be
+ * #if def(REAL_DMA)
+ * instead of leaving REAL_DMA out.
+ */
#if defined(REAL_DMA)
- if (!cmd->device->borken &&
- (transfersize = NCR5380_dma_xfer_len(instance,cmd,phase)) > 31) {
- len = transfersize;
- cmd->SCp.phase = phase;
- if (NCR5380_transfer_dma(instance, &phase,
- &len, (unsigned char **) &cmd->SCp.ptr)) {
- /*
- * If the watchdog timer fires, all future
- * accesses to this device will use the
- * polled-IO. */
- printk(KERN_NOTICE "scsi%d: switching target %d "
- "lun %d to slow handshake\n", HOSTNO,
- cmd->device->id, cmd->device->lun);
- cmd->device->borken = 1;
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
- ICR_ASSERT_ATN);
- sink = 1;
- do_abort(instance);
- cmd->result = DID_ERROR << 16;
- cmd->done(cmd);
- /* XXX - need to source or sink data here, as appropriate */
- } else {
+ if (!cmd->device->borken &&
+ (transfersize = NCR5380_dma_xfer_len(instance,cmd,phase)) > 31) {
+ len = transfersize;
+ cmd->SCp.phase = phase;
+ if (NCR5380_transfer_dma(instance, &phase,
+ &len, (unsigned char **)&cmd->SCp.ptr)) {
+ /*
+ * If the watchdog timer fires, all future
+ * accesses to this device will use the
+ * polled-IO. */
+ printk(KERN_NOTICE "scsi%d: switching target %d "
+ "lun %d to slow handshake\n", HOSTNO,
+ cmd->device->id, cmd->device->lun);
+ cmd->device->borken = 1;
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
+ ICR_ASSERT_ATN);
+ sink = 1;
+ do_abort(instance);
+ cmd->result = DID_ERROR << 16;
+ cmd->done(cmd);
+ /* XXX - need to source or sink data here, as appropriate */
+ } else {
#ifdef REAL_DMA
- /* ++roman: When using real DMA,
- * information_transfer() should return after
- * starting DMA since it has nothing more to
- * do.
- */
- return;
-#else
- cmd->SCp.this_residual -= transfersize - len;
+ /* ++roman: When using real DMA,
+ * information_transfer() should return after
+ * starting DMA since it has nothing more to
+ * do.
+ */
+ return;
+#else
+ cmd->SCp.this_residual -= transfersize - len;
#endif
- }
- } else
+ }
+ } else
#endif /* defined(REAL_DMA) */
- NCR5380_transfer_pio(instance, &phase,
- (int *) &cmd->SCp.this_residual, (unsigned char **)
- &cmd->SCp.ptr);
- break;
- case PHASE_MSGIN:
- len = 1;
- data = &tmp;
- NCR5380_write(SELECT_ENABLE_REG, 0); /* disable reselects */
- NCR5380_transfer_pio(instance, &phase, &len, &data);
- cmd->SCp.Message = tmp;
-
- switch (tmp) {
- /*
- * Linking lets us reduce the time required to get the
- * next command out to the device, hopefully this will
- * mean we don't waste another revolution due to the delays
- * required by ARBITRATION and another SELECTION.
- *
- * In the current implementation proposal, low level drivers
- * merely have to start the next command, pointed to by
- * next_link, done() is called as with unlinked commands.
- */
+ NCR5380_transfer_pio(instance, &phase,
+ (int *)&cmd->SCp.this_residual,
+ (unsigned char **)&cmd->SCp.ptr);
+ break;
+ case PHASE_MSGIN:
+ len = 1;
+ data = &tmp;
+ NCR5380_write(SELECT_ENABLE_REG, 0); /* disable reselects */
+ NCR5380_transfer_pio(instance, &phase, &len, &data);
+ cmd->SCp.Message = tmp;
+
+ switch (tmp) {
+ /*
+ * Linking lets us reduce the time required to get the
+ * next command out to the device, hopefully this will
+ * mean we don't waste another revolution due to the delays
+ * required by ARBITRATION and another SELECTION.
+ *
+ * In the current implementation proposal, low level drivers
+ * merely have to start the next command, pointed to by
+ * next_link, done() is called as with unlinked commands.
+ */
#ifdef LINKED
- case LINKED_CMD_COMPLETE:
- case LINKED_FLG_CMD_COMPLETE:
- /* Accept message by clearing ACK */
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-
- LNK_PRINTK("scsi%d: target %d lun %d linked command "
- "complete.\n", HOSTNO, cmd->device->id, cmd->device->lun);
-
- /* Enable reselect interrupts */
- NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
- /*
- * Sanity check : A linked command should only terminate
- * with one of these messages if there are more linked
- * commands available.
- */
-
- if (!cmd->next_link) {
- printk(KERN_NOTICE "scsi%d: target %d lun %d "
- "linked command complete, no next_link\n",
- HOSTNO, cmd->device->id, cmd->device->lun);
- sink = 1;
- do_abort (instance);
- return;
- }
-
- initialize_SCp(cmd->next_link);
- /* The next command is still part of this process; copy it
- * and don't free it! */
- cmd->next_link->tag = cmd->tag;
- cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
- LNK_PRINTK("scsi%d: target %d lun %d linked request "
- "done, calling scsi_done().\n",
- HOSTNO, cmd->device->id, cmd->device->lun);
+ case LINKED_CMD_COMPLETE:
+ case LINKED_FLG_CMD_COMPLETE:
+ /* Accept message by clearing ACK */
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+
+ LNK_PRINTK("scsi%d: target %d lun %d linked command "
+ "complete.\n", HOSTNO, cmd->device->id, cmd->device->lun);
+
+ /* Enable reselect interrupts */
+ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+ /*
+ * Sanity check : A linked command should only terminate
+ * with one of these messages if there are more linked
+ * commands available.
+ */
+
+ if (!cmd->next_link) {
+ printk(KERN_NOTICE "scsi%d: target %d lun %d "
+ "linked command complete, no next_link\n",
+ HOSTNO, cmd->device->id, cmd->device->lun);
+ sink = 1;
+ do_abort(instance);
+ return;
+ }
+
+ initialize_SCp(cmd->next_link);
+ /* The next command is still part of this process; copy it
+ * and don't free it! */
+ cmd->next_link->tag = cmd->tag;
+ cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
+ LNK_PRINTK("scsi%d: target %d lun %d linked request "
+ "done, calling scsi_done().\n",
+ HOSTNO, cmd->device->id, cmd->device->lun);
#ifdef NCR5380_STATS
- collect_stats(hostdata, cmd);
+ collect_stats(hostdata, cmd);
#endif
- cmd->scsi_done(cmd);
- cmd = hostdata->connected;
- break;
+ cmd->scsi_done(cmd);
+ cmd = hostdata->connected;
+ break;
#endif /* def LINKED */
- case ABORT:
- case COMMAND_COMPLETE:
- /* Accept message by clearing ACK */
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- /* ++guenther: possible race with Falcon locking */
- falcon_dont_release++;
- hostdata->connected = NULL;
- QU_PRINTK("scsi%d: command for target %d, lun %d "
- "completed\n", HOSTNO, cmd->device->id, cmd->device->lun);
+ case ABORT:
+ case COMMAND_COMPLETE:
+ /* Accept message by clearing ACK */
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+ /* ++guenther: possible race with Falcon locking */
+ falcon_dont_release++;
+ hostdata->connected = NULL;
+ QU_PRINTK("scsi%d: command for target %d, lun %d "
+ "completed\n", HOSTNO, cmd->device->id, cmd->device->lun);
#ifdef SUPPORT_TAGS
- cmd_free_tag( cmd );
- if (status_byte(cmd->SCp.Status) == QUEUE_FULL) {
- /* Turn a QUEUE FULL status into BUSY, I think the
- * mid level cannot handle QUEUE FULL :-( (The
- * command is retried after BUSY). Also update our
- * queue size to the number of currently issued
- * commands now.
- */
- /* ++Andreas: the mid level code knows about
- QUEUE_FULL now. */
- TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
- TAG_PRINTK("scsi%d: target %d lun %d returned "
- "QUEUE_FULL after %d commands\n",
- HOSTNO, cmd->device->id, cmd->device->lun,
- ta->nr_allocated);
- if (ta->queue_size > ta->nr_allocated)
- ta->nr_allocated = ta->queue_size;
- }
+ cmd_free_tag(cmd);
+ if (status_byte(cmd->SCp.Status) == QUEUE_FULL) {
+ /* Turn a QUEUE FULL status into BUSY, I think the
+ * mid level cannot handle QUEUE FULL :-( (The
+ * command is retried after BUSY). Also update our
+ * queue size to the number of currently issued
+ * commands now.
+ */
+ /* ++Andreas: the mid level code knows about
+ QUEUE_FULL now. */
+ TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
+ TAG_PRINTK("scsi%d: target %d lun %d returned "
+ "QUEUE_FULL after %d commands\n",
+ HOSTNO, cmd->device->id, cmd->device->lun,
+ ta->nr_allocated);
+ if (ta->queue_size > ta->nr_allocated)
+ ta->nr_allocated = ta->queue_size;
+ }
#else
- hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+ hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
#endif
- /* Enable reselect interrupts */
- NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-
- /*
- * I'm not sure what the correct thing to do here is :
- *
- * If the command that just executed is NOT a request
- * sense, the obvious thing to do is to set the result
- * code to the values of the stored parameters.
- *
- * If it was a REQUEST SENSE command, we need some way to
- * differentiate between the failure code of the original
- * and the failure code of the REQUEST sense - the obvious
- * case is success, where we fall through and leave the
- * result code unchanged.
- *
- * The non-obvious place is where the REQUEST SENSE failed
- */
-
- if (cmd->cmnd[0] != REQUEST_SENSE)
- cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
- else if (status_byte(cmd->SCp.Status) != GOOD)
- cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
-
-#ifdef AUTOSENSE
- if ((cmd->cmnd[0] != REQUEST_SENSE) &&
- (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) {
- ASEN_PRINTK("scsi%d: performing request sense\n",
- HOSTNO);
- cmd->cmnd[0] = REQUEST_SENSE;
- cmd->cmnd[1] &= 0xe0;
- cmd->cmnd[2] = 0;
- cmd->cmnd[3] = 0;
- cmd->cmnd[4] = sizeof(cmd->sense_buffer);
- cmd->cmnd[5] = 0;
- cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
-
- cmd->use_sg = 0;
- /* this is initialized from initialize_SCp
- cmd->SCp.buffer = NULL;
- cmd->SCp.buffers_residual = 0;
- */
- cmd->request_buffer = (char *) cmd->sense_buffer;
- cmd->request_bufflen = sizeof(cmd->sense_buffer);
+ /* Enable reselect interrupts */
+ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+
+ /*
+ * I'm not sure what the correct thing to do here is :
+ *
+ * If the command that just executed is NOT a request
+ * sense, the obvious thing to do is to set the result
+ * code to the values of the stored parameters.
+ *
+ * If it was a REQUEST SENSE command, we need some way to
+ * differentiate between the failure code of the original
+ * and the failure code of the REQUEST sense - the obvious
+ * case is success, where we fall through and leave the
+ * result code unchanged.
+ *
+ * The non-obvious place is where the REQUEST SENSE failed
+ */
+
+ if (cmd->cmnd[0] != REQUEST_SENSE)
+ cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
+ else if (status_byte(cmd->SCp.Status) != GOOD)
+ cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
- local_irq_save(flags);
- LIST(cmd,hostdata->issue_queue);
- NEXT(cmd) = hostdata->issue_queue;
- hostdata->issue_queue = (Scsi_Cmnd *) cmd;
- local_irq_restore(flags);
- QU_PRINTK("scsi%d: REQUEST SENSE added to head of "
- "issue queue\n", H_NO(cmd));
- } else
+#ifdef AUTOSENSE
+ if ((cmd->cmnd[0] != REQUEST_SENSE) &&
+ (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) {
+ ASEN_PRINTK("scsi%d: performing request sense\n", HOSTNO);
+ cmd->cmnd[0] = REQUEST_SENSE;
+ cmd->cmnd[1] &= 0xe0;
+ cmd->cmnd[2] = 0;
+ cmd->cmnd[3] = 0;
+ cmd->cmnd[4] = sizeof(cmd->sense_buffer);
+ cmd->cmnd[5] = 0;
+ cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
+
+ cmd->use_sg = 0;
+ /* this is initialized from initialize_SCp
+ cmd->SCp.buffer = NULL;
+ cmd->SCp.buffers_residual = 0;
+ */
+ cmd->request_buffer = (char *) cmd->sense_buffer;
+ cmd->request_bufflen = sizeof(cmd->sense_buffer);
+
+ local_irq_save(flags);
+ LIST(cmd,hostdata->issue_queue);
+ SET_NEXT(cmd, hostdata->issue_queue);
+ hostdata->issue_queue = (Scsi_Cmnd *) cmd;
+ local_irq_restore(flags);
+ QU_PRINTK("scsi%d: REQUEST SENSE added to head of "
+ "issue queue\n", H_NO(cmd));
+ } else
#endif /* def AUTOSENSE */
- {
+ {
#ifdef NCR5380_STATS
- collect_stats(hostdata, cmd);
+ collect_stats(hostdata, cmd);
#endif
- cmd->scsi_done(cmd);
- }
-
- NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
- /*
- * Restore phase bits to 0 so an interrupted selection,
- * arbitration can resume.
- */
- NCR5380_write(TARGET_COMMAND_REG, 0);
-
- while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
- barrier();
-
- falcon_dont_release--;
- /* ++roman: For Falcon SCSI, release the lock on the
- * ST-DMA here if no other commands are waiting on the
- * disconnected queue.
- */
- falcon_release_lock_if_possible( hostdata );
- return;
- case MESSAGE_REJECT:
- /* Accept message by clearing ACK */
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- /* Enable reselect interrupts */
- NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
- switch (hostdata->last_message) {
- case HEAD_OF_QUEUE_TAG:
- case ORDERED_QUEUE_TAG:
- case SIMPLE_QUEUE_TAG:
- /* The target obviously doesn't support tagged
- * queuing, even though it announced this ability in
- * its INQUIRY data ?!? (maybe only this LUN?) Ok,
- * clear 'tagged_supported' and lock the LUN, since
- * the command is treated as untagged further on.
- */
- cmd->device->tagged_supported = 0;
- hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
- cmd->tag = TAG_NONE;
- TAG_PRINTK("scsi%d: target %d lun %d rejected "
- "QUEUE_TAG message; tagged queuing "
- "disabled\n",
- HOSTNO, cmd->device->id, cmd->device->lun);
- break;
- }
- break;
- case DISCONNECT:
- /* Accept message by clearing ACK */
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- local_irq_save(flags);
- cmd->device->disconnect = 1;
- LIST(cmd,hostdata->disconnected_queue);
- NEXT(cmd) = hostdata->disconnected_queue;
- hostdata->connected = NULL;
- hostdata->disconnected_queue = cmd;
- local_irq_restore(flags);
- QU_PRINTK("scsi%d: command for target %d lun %d was "
- "moved from connected to the "
- "disconnected_queue\n", HOSTNO,
- cmd->device->id, cmd->device->lun);
- /*
- * Restore phase bits to 0 so an interrupted selection,
- * arbitration can resume.
- */
- NCR5380_write(TARGET_COMMAND_REG, 0);
-
- /* Enable reselect interrupts */
- NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
- /* Wait for bus free to avoid nasty timeouts */
- while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
- barrier();
- return;
- /*
- * The SCSI data pointer is *IMPLICITLY* saved on a disconnect
- * operation, in violation of the SCSI spec so we can safely
- * ignore SAVE/RESTORE pointers calls.
- *
- * Unfortunately, some disks violate the SCSI spec and
- * don't issue the required SAVE_POINTERS message before
- * disconnecting, and we have to break spec to remain
- * compatible.
- */
- case SAVE_POINTERS:
- case RESTORE_POINTERS:
- /* Accept message by clearing ACK */
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- /* Enable reselect interrupts */
- NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
- break;
- case EXTENDED_MESSAGE:
-/*
- * Extended messages are sent in the following format :
- * Byte
- * 0 EXTENDED_MESSAGE == 1
- * 1 length (includes one byte for code, doesn't
- * include first two bytes)
- * 2 code
- * 3..length+1 arguments
- *
- * Start the extended message buffer with the EXTENDED_MESSAGE
- * byte, since spi_print_msg() wants the whole thing.
- */
- extended_msg[0] = EXTENDED_MESSAGE;
- /* Accept first byte by clearing ACK */
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-
- EXT_PRINTK("scsi%d: receiving extended message\n", HOSTNO);
-
- len = 2;
- data = extended_msg + 1;
- phase = PHASE_MSGIN;
- NCR5380_transfer_pio(instance, &phase, &len, &data);
- EXT_PRINTK("scsi%d: length=%d, code=0x%02x\n", HOSTNO,
- (int)extended_msg[1], (int)extended_msg[2]);
-
- if (!len && extended_msg[1] <=
- (sizeof (extended_msg) - 1)) {
- /* Accept third byte by clearing ACK */
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- len = extended_msg[1] - 1;
- data = extended_msg + 3;
- phase = PHASE_MSGIN;
-
- NCR5380_transfer_pio(instance, &phase, &len, &data);
- EXT_PRINTK("scsi%d: message received, residual %d\n",
- HOSTNO, len);
-
- switch (extended_msg[2]) {
- case EXTENDED_SDTR:
- case EXTENDED_WDTR:
- case EXTENDED_MODIFY_DATA_POINTER:
- case EXTENDED_EXTENDED_IDENTIFY:
- tmp = 0;
- }
- } else if (len) {
- printk(KERN_NOTICE "scsi%d: error receiving "
- "extended message\n", HOSTNO);
- tmp = 0;
- } else {
- printk(KERN_NOTICE "scsi%d: extended message "
- "code %02x length %d is too long\n",
- HOSTNO, extended_msg[2], extended_msg[1]);
- tmp = 0;
- }
- /* Fall through to reject message */
-
- /*
- * If we get something weird that we aren't expecting,
- * reject it.
- */
- default:
- if (!tmp) {
- printk(KERN_DEBUG "scsi%d: rejecting message ", HOSTNO);
- spi_print_msg(extended_msg);
- printk("\n");
- } else if (tmp != EXTENDED_MESSAGE)
- printk(KERN_DEBUG "scsi%d: rejecting unknown "
- "message %02x from target %d, lun %d\n",
- HOSTNO, tmp, cmd->device->id, cmd->device->lun);
- else
- printk(KERN_DEBUG "scsi%d: rejecting unknown "
- "extended message "
- "code %02x, length %d from target %d, lun %d\n",
- HOSTNO, extended_msg[1], extended_msg[0],
- cmd->device->id, cmd->device->lun);
-
-
- msgout = MESSAGE_REJECT;
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
- ICR_ASSERT_ATN);
- break;
- } /* switch (tmp) */
- break;
- case PHASE_MSGOUT:
- len = 1;
- data = &msgout;
- hostdata->last_message = msgout;
- NCR5380_transfer_pio(instance, &phase, &len, &data);
- if (msgout == ABORT) {
+ cmd->scsi_done(cmd);
+ }
+
+ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+ /*
+ * Restore phase bits to 0 so an interrupted selection,
+ * arbitration can resume.
+ */
+ NCR5380_write(TARGET_COMMAND_REG, 0);
+
+ while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
+ barrier();
+
+ falcon_dont_release--;
+ /* ++roman: For Falcon SCSI, release the lock on the
+ * ST-DMA here if no other commands are waiting on the
+ * disconnected queue.
+ */
+ falcon_release_lock_if_possible(hostdata);
+ return;
+ case MESSAGE_REJECT:
+ /* Accept message by clearing ACK */
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+ /* Enable reselect interrupts */
+ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+ switch (hostdata->last_message) {
+ case HEAD_OF_QUEUE_TAG:
+ case ORDERED_QUEUE_TAG:
+ case SIMPLE_QUEUE_TAG:
+ /* The target obviously doesn't support tagged
+ * queuing, even though it announced this ability in
+ * its INQUIRY data ?!? (maybe only this LUN?) Ok,
+ * clear 'tagged_supported' and lock the LUN, since
+ * the command is treated as untagged further on.
+ */
+ cmd->device->tagged_supported = 0;
+ hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
+ cmd->tag = TAG_NONE;
+ TAG_PRINTK("scsi%d: target %d lun %d rejected "
+ "QUEUE_TAG message; tagged queuing "
+ "disabled\n",
+ HOSTNO, cmd->device->id, cmd->device->lun);
+ break;
+ }
+ break;
+ case DISCONNECT:
+ /* Accept message by clearing ACK */
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+ local_irq_save(flags);
+ cmd->device->disconnect = 1;
+ LIST(cmd,hostdata->disconnected_queue);
+ SET_NEXT(cmd, hostdata->disconnected_queue);
+ hostdata->connected = NULL;
+ hostdata->disconnected_queue = cmd;
+ local_irq_restore(flags);
+ QU_PRINTK("scsi%d: command for target %d lun %d was "
+ "moved from connected to the "
+ "disconnected_queue\n", HOSTNO,
+ cmd->device->id, cmd->device->lun);
+ /*
+ * Restore phase bits to 0 so an interrupted selection,
+ * arbitration can resume.
+ */
+ NCR5380_write(TARGET_COMMAND_REG, 0);
+
+ /* Enable reselect interrupts */
+ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+ /* Wait for bus free to avoid nasty timeouts */
+ while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
+ barrier();
+ return;
+ /*
+ * The SCSI data pointer is *IMPLICITLY* saved on a disconnect
+ * operation, in violation of the SCSI spec so we can safely
+ * ignore SAVE/RESTORE pointers calls.
+ *
+ * Unfortunately, some disks violate the SCSI spec and
+ * don't issue the required SAVE_POINTERS message before
+ * disconnecting, and we have to break spec to remain
+ * compatible.
+ */
+ case SAVE_POINTERS:
+ case RESTORE_POINTERS:
+ /* Accept message by clearing ACK */
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+ /* Enable reselect interrupts */
+ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+ break;
+ case EXTENDED_MESSAGE:
+ /*
+ * Extended messages are sent in the following format :
+ * Byte
+ * 0 EXTENDED_MESSAGE == 1
+ * 1 length (includes one byte for code, doesn't
+ * include first two bytes)
+ * 2 code
+ * 3..length+1 arguments
+ *
+ * Start the extended message buffer with the EXTENDED_MESSAGE
+ * byte, since spi_print_msg() wants the whole thing.
+ */
+ extended_msg[0] = EXTENDED_MESSAGE;
+ /* Accept first byte by clearing ACK */
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+
+ EXT_PRINTK("scsi%d: receiving extended message\n", HOSTNO);
+
+ len = 2;
+ data = extended_msg + 1;
+ phase = PHASE_MSGIN;
+ NCR5380_transfer_pio(instance, &phase, &len, &data);
+ EXT_PRINTK("scsi%d: length=%d, code=0x%02x\n", HOSTNO,
+ (int)extended_msg[1], (int)extended_msg[2]);
+
+ if (!len && extended_msg[1] <=
+ (sizeof(extended_msg) - 1)) {
+ /* Accept third byte by clearing ACK */
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+ len = extended_msg[1] - 1;
+ data = extended_msg + 3;
+ phase = PHASE_MSGIN;
+
+ NCR5380_transfer_pio(instance, &phase, &len, &data);
+ EXT_PRINTK("scsi%d: message received, residual %d\n",
+ HOSTNO, len);
+
+ switch (extended_msg[2]) {
+ case EXTENDED_SDTR:
+ case EXTENDED_WDTR:
+ case EXTENDED_MODIFY_DATA_POINTER:
+ case EXTENDED_EXTENDED_IDENTIFY:
+ tmp = 0;
+ }
+ } else if (len) {
+ printk(KERN_NOTICE "scsi%d: error receiving "
+ "extended message\n", HOSTNO);
+ tmp = 0;
+ } else {
+ printk(KERN_NOTICE "scsi%d: extended message "
+ "code %02x length %d is too long\n",
+ HOSTNO, extended_msg[2], extended_msg[1]);
+ tmp = 0;
+ }
+ /* Fall through to reject message */
+
+ /*
+ * If we get something weird that we aren't expecting,
+ * reject it.
+ */
+ default:
+ if (!tmp) {
+ printk(KERN_DEBUG "scsi%d: rejecting message ", HOSTNO);
+ spi_print_msg(extended_msg);
+ printk("\n");
+ } else if (tmp != EXTENDED_MESSAGE)
+ printk(KERN_DEBUG "scsi%d: rejecting unknown "
+ "message %02x from target %d, lun %d\n",
+ HOSTNO, tmp, cmd->device->id, cmd->device->lun);
+ else
+ printk(KERN_DEBUG "scsi%d: rejecting unknown "
+ "extended message "
+ "code %02x, length %d from target %d, lun %d\n",
+ HOSTNO, extended_msg[1], extended_msg[0],
+ cmd->device->id, cmd->device->lun);
+
+
+ msgout = MESSAGE_REJECT;
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
+ break;
+ } /* switch (tmp) */
+ break;
+ case PHASE_MSGOUT:
+ len = 1;
+ data = &msgout;
+ hostdata->last_message = msgout;
+ NCR5380_transfer_pio(instance, &phase, &len, &data);
+ if (msgout == ABORT) {
#ifdef SUPPORT_TAGS
- cmd_free_tag( cmd );
+ cmd_free_tag(cmd);
#else
- hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+ hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
#endif
- hostdata->connected = NULL;
- cmd->result = DID_ERROR << 16;
+ hostdata->connected = NULL;
+ cmd->result = DID_ERROR << 16;
#ifdef NCR5380_STATS
- collect_stats(hostdata, cmd);
+ collect_stats(hostdata, cmd);
#endif
- cmd->scsi_done(cmd);
- NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
- falcon_release_lock_if_possible( hostdata );
- return;
- }
- msgout = NOP;
- break;
- case PHASE_CMDOUT:
- len = cmd->cmd_len;
- data = cmd->cmnd;
- /*
- * XXX for performance reasons, on machines with a
- * PSEUDO-DMA architecture we should probably
- * use the dma transfer function.
- */
- NCR5380_transfer_pio(instance, &phase, &len,
- &data);
- break;
- case PHASE_STATIN:
- len = 1;
- data = &tmp;
- NCR5380_transfer_pio(instance, &phase, &len, &data);
- cmd->SCp.Status = tmp;
- break;
- default:
- printk("scsi%d: unknown phase\n", HOSTNO);
- NCR_PRINT(NDEBUG_ANY);
- } /* switch(phase) */
- } /* if (tmp * SR_REQ) */
- } /* while (1) */
+ cmd->scsi_done(cmd);
+ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
+ falcon_release_lock_if_possible(hostdata);
+ return;
+ }
+ msgout = NOP;
+ break;
+ case PHASE_CMDOUT:
+ len = cmd->cmd_len;
+ data = cmd->cmnd;
+ /*
+ * XXX for performance reasons, on machines with a
+ * PSEUDO-DMA architecture we should probably
+ * use the dma transfer function.
+ */
+ NCR5380_transfer_pio(instance, &phase, &len, &data);
+ break;
+ case PHASE_STATIN:
+ len = 1;
+ data = &tmp;
+ NCR5380_transfer_pio(instance, &phase, &len, &data);
+ cmd->SCp.Status = tmp;
+ break;
+ default:
+ printk("scsi%d: unknown phase\n", HOSTNO);
+ NCR_PRINT(NDEBUG_ANY);
+ } /* switch(phase) */
+ } /* if (tmp * SR_REQ) */
+ } /* while (1) */
}
/*
* 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
+ * 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
* nexus has been reestablished,
- *
+ *
* Inputs : instance - this instance of the NCR5380.
*
*/
-static void NCR5380_reselect (struct Scsi_Host *instance)
+static void NCR5380_reselect(struct Scsi_Host *instance)
{
- SETUP_HOSTDATA(instance);
- unsigned char target_mask;
- unsigned char lun, phase;
- int len;
+ SETUP_HOSTDATA(instance);
+ unsigned char target_mask;
+ unsigned char lun, phase;
+ int len;
#ifdef SUPPORT_TAGS
- unsigned char tag;
+ unsigned char tag;
#endif
- unsigned char msg[3];
- unsigned char *data;
- Scsi_Cmnd *tmp = NULL, *prev;
-/* unsigned long flags; */
-
- /*
- * Disable arbitration, etc. since the host adapter obviously
- * lost, and tell an interrupted NCR5380_select() to restart.
- */
-
- NCR5380_write(MODE_REG, MR_BASE);
- hostdata->restart_select = 1;
-
- target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask);
-
- RSL_PRINTK("scsi%d: reselect\n", HOSTNO);
-
- /*
- * At this point, we have detected that our SCSI ID is on the bus,
- * SEL is true and BSY was false for at least one bus settle delay
- * (400 ns).
- *
- * We must assert BSY ourselves, until the target drops the SEL
- * signal.
- */
-
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY);
-
- while (NCR5380_read(STATUS_REG) & SR_SEL);
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-
- /*
- * Wait for target to go into MSGIN.
- */
-
- while (!(NCR5380_read(STATUS_REG) & SR_REQ));
-
- len = 1;
- data = msg;
- phase = PHASE_MSGIN;
- NCR5380_transfer_pio(instance, &phase, &len, &data);
-
- if (!(msg[0] & 0x80)) {
- printk(KERN_DEBUG "scsi%d: expecting IDENTIFY message, got ", HOSTNO);
- spi_print_msg(msg);
- do_abort(instance);
- return;
- }
- lun = (msg[0] & 0x07);
+ unsigned char msg[3];
+ unsigned char *data;
+ Scsi_Cmnd *tmp = NULL, *prev;
+/* unsigned long flags; */
+
+ /*
+ * Disable arbitration, etc. since the host adapter obviously
+ * lost, and tell an interrupted NCR5380_select() to restart.
+ */
+
+ NCR5380_write(MODE_REG, MR_BASE);
+ hostdata->restart_select = 1;
+
+ target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask);
+
+ RSL_PRINTK("scsi%d: reselect\n", HOSTNO);
+
+ /*
+ * At this point, we have detected that our SCSI ID is on the bus,
+ * SEL is true and BSY was false for at least one bus settle delay
+ * (400 ns).
+ *
+ * We must assert BSY ourselves, until the target drops the SEL
+ * signal.
+ */
+
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY);
+
+ while (NCR5380_read(STATUS_REG) & SR_SEL)
+ ;
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+
+ /*
+ * Wait for target to go into MSGIN.
+ */
+
+ while (!(NCR5380_read(STATUS_REG) & SR_REQ))
+ ;
+
+ len = 1;
+ data = msg;
+ phase = PHASE_MSGIN;
+ NCR5380_transfer_pio(instance, &phase, &len, &data);
+
+ if (!(msg[0] & 0x80)) {
+ printk(KERN_DEBUG "scsi%d: expecting IDENTIFY message, got ", HOSTNO);
+ spi_print_msg(msg);
+ do_abort(instance);
+ return;
+ }
+ lun = (msg[0] & 0x07);
#ifdef SUPPORT_TAGS
- /* If the phase is still MSGIN, the target wants to send some more
- * messages. In case it supports tagged queuing, this is probably a
- * SIMPLE_QUEUE_TAG for the I_T_L_Q nexus.
- */
- tag = TAG_NONE;
- if (phase == PHASE_MSGIN && setup_use_tagged_queuing) {
- /* Accept previous IDENTIFY message by clearing ACK */
- NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
- len = 2;
- data = msg+1;
- if (!NCR5380_transfer_pio(instance, &phase, &len, &data) &&
- msg[1] == SIMPLE_QUEUE_TAG)
- tag = msg[2];
- TAG_PRINTK("scsi%d: target mask %02x, lun %d sent tag %d at "
- "reselection\n", HOSTNO, target_mask, lun, tag);
- }
+ /* If the phase is still MSGIN, the target wants to send some more
+ * messages. In case it supports tagged queuing, this is probably a
+ * SIMPLE_QUEUE_TAG for the I_T_L_Q nexus.
+ */
+ tag = TAG_NONE;
+ if (phase == PHASE_MSGIN && setup_use_tagged_queuing) {
+ /* Accept previous IDENTIFY message by clearing ACK */
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+ len = 2;
+ data = msg + 1;
+ if (!NCR5380_transfer_pio(instance, &phase, &len, &data) &&
+ msg[1] == SIMPLE_QUEUE_TAG)
+ tag = msg[2];
+ TAG_PRINTK("scsi%d: target mask %02x, lun %d sent tag %d at "
+ "reselection\n", HOSTNO, target_mask, lun, tag);
+ }
#endif
-
- /*
- * Find the command corresponding to the I_T_L or I_T_L_Q nexus we
- * just reestablished, and remove it from the disconnected queue.
- */
-
- for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL;
- tmp; prev = tmp, tmp = NEXT(tmp) ) {
- if ((target_mask == (1 << tmp->device->id)) && (lun == tmp->device->lun)
+
+ /*
+ * Find the command corresponding to the I_T_L or I_T_L_Q nexus we
+ * just reestablished, and remove it from the disconnected queue.
+ */
+
+ for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL;
+ tmp; prev = tmp, tmp = NEXT(tmp)) {
+ if ((target_mask == (1 << tmp->device->id)) && (lun == tmp->device->lun)
#ifdef SUPPORT_TAGS
- && (tag == tmp->tag)
+ && (tag == tmp->tag)
#endif
- ) {
- /* ++guenther: prevent race with falcon_release_lock */
- falcon_dont_release++;
- if (prev) {
- REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
- NEXT(prev) = NEXT(tmp);
- } else {
- REMOVE(-1, hostdata->disconnected_queue, tmp, NEXT(tmp));
- hostdata->disconnected_queue = NEXT(tmp);
- }
- NEXT(tmp) = NULL;
- break;
+ ) {
+ /* ++guenther: prevent race with falcon_release_lock */
+ falcon_dont_release++;
+ if (prev) {
+ REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
+ SET_NEXT(prev, NEXT(tmp));
+ } else {
+ REMOVE(-1, hostdata->disconnected_queue, tmp, NEXT(tmp));
+ hostdata->disconnected_queue = NEXT(tmp);
+ }
+ SET_NEXT(tmp, NULL);
+ break;
+ }
}
- }
-
- if (!tmp) {
- printk(KERN_WARNING "scsi%d: warning: target bitmask %02x lun %d "
+
+ if (!tmp) {
+ printk(KERN_WARNING "scsi%d: warning: target bitmask %02x lun %d "
#ifdef SUPPORT_TAGS
- "tag %d "
+ "tag %d "
#endif
- "not in disconnected_queue.\n",
- HOSTNO, target_mask, lun
+ "not in disconnected_queue.\n",
+ HOSTNO, target_mask, lun
#ifdef SUPPORT_TAGS
- , tag
+ , tag
#endif
- );
- /*
- * Since we have an established nexus that we can't do anything
- * with, we must abort it.
- */
- do_abort(instance);
- return;
- }
+ );
+ /*
+ * Since we have an established nexus that we can't do anything
+ * with, we must abort it.
+ */
+ do_abort(instance);
+ return;
+ }
- /* Accept message by clearing ACK */
- NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+ /* Accept message by clearing ACK */
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- hostdata->connected = tmp;
- RSL_PRINTK("scsi%d: nexus established, target = %d, lun = %d, tag = %d\n",
- HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag);
- falcon_dont_release--;
+ hostdata->connected = tmp;
+ RSL_PRINTK("scsi%d: nexus established, target = %d, lun = %d, tag = %d\n",
+ HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag);
+ falcon_dont_release--;
}
@@ -2626,362 +2677,361 @@ static void NCR5380_reselect (struct Scsi_Host *instance)
*
* Purpose : abort a command
*
- * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the
- * host byte of the result field to, if zero DID_ABORTED is
+ * 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.
*
* Returns : 0 - success, -1 on failure.
*
- * XXX - there is no way to abort the command that is currently
- * connected, you have to wait for it to complete. If this is
+ * XXX - there is no way to abort the command that is currently
+ * connected, you have to wait for it to complete. If this is
* a problem, we could implement longjmp() / setjmp(), setjmp()
- * called where the loop started in NCR5380_main().
+ * called where the loop started in NCR5380_main().
*/
static
-int NCR5380_abort (Scsi_Cmnd *cmd)
+int NCR5380_abort(Scsi_Cmnd *cmd)
{
- struct Scsi_Host *instance = cmd->device->host;
- SETUP_HOSTDATA(instance);
- Scsi_Cmnd *tmp, **prev;
- unsigned long flags;
+ struct Scsi_Host *instance = cmd->device->host;
+ SETUP_HOSTDATA(instance);
+ Scsi_Cmnd *tmp, **prev;
+ unsigned long flags;
+
+ printk(KERN_NOTICE "scsi%d: aborting command\n", HOSTNO);
+ scsi_print_command(cmd);
- printk(KERN_NOTICE "scsi%d: aborting command\n", HOSTNO);
- scsi_print_command(cmd);
+ NCR5380_print_status(instance);
- NCR5380_print_status (instance);
+ local_irq_save(flags);
- local_irq_save(flags);
-
- if (!IS_A_TT() && !falcon_got_lock)
- printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_abort\n",
- HOSTNO);
+ if (!IS_A_TT() && !falcon_got_lock)
+ printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_abort\n",
+ HOSTNO);
- ABRT_PRINTK("scsi%d: abort called basr 0x%02x, sr 0x%02x\n", HOSTNO,
- NCR5380_read(BUS_AND_STATUS_REG),
- NCR5380_read(STATUS_REG));
+ ABRT_PRINTK("scsi%d: abort called basr 0x%02x, sr 0x%02x\n", HOSTNO,
+ NCR5380_read(BUS_AND_STATUS_REG),
+ NCR5380_read(STATUS_REG));
#if 1
-/*
- * Case 1 : If the command is the currently executing command,
- * we'll set the aborted flag and return control so that
- * information transfer routine can exit cleanly.
- */
+ /*
+ * Case 1 : If the command is the currently executing command,
+ * we'll set the aborted flag and return control so that
+ * information transfer routine can exit cleanly.
+ */
- if (hostdata->connected == cmd) {
+ if (hostdata->connected == cmd) {
- ABRT_PRINTK("scsi%d: aborting connected command\n", HOSTNO);
-/*
- * We should perform BSY checking, and make sure we haven't slipped
- * into BUS FREE.
- */
+ ABRT_PRINTK("scsi%d: aborting connected command\n", HOSTNO);
+ /*
+ * We should perform BSY checking, and make sure we haven't slipped
+ * into BUS FREE.
+ */
-/* NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_ATN); */
-/*
- * Since we can't change phases until we've completed the current
- * handshake, we have to source or sink a byte of data if the current
- * phase is not MSGOUT.
- */
+ /* NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_ATN); */
+ /*
+ * Since we can't change phases until we've completed the current
+ * handshake, we have to source or sink a byte of data if the current
+ * phase is not MSGOUT.
+ */
-/*
- * Return control to the executing NCR drive so we can clear the
- * aborted flag and get back into our main loop.
- */
+ /*
+ * Return control to the executing NCR drive so we can clear the
+ * aborted flag and get back into our main loop.
+ */
- if (do_abort(instance) == 0) {
- hostdata->aborted = 1;
- hostdata->connected = NULL;
- cmd->result = DID_ABORT << 16;
+ if (do_abort(instance) == 0) {
+ hostdata->aborted = 1;
+ hostdata->connected = NULL;
+ cmd->result = DID_ABORT << 16;
#ifdef SUPPORT_TAGS
- cmd_free_tag( cmd );
+ cmd_free_tag(cmd);
#else
- hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+ hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
#endif
- local_irq_restore(flags);
- cmd->scsi_done(cmd);
- falcon_release_lock_if_possible( hostdata );
- return SCSI_ABORT_SUCCESS;
- } else {
-/* local_irq_restore(flags); */
- printk("scsi%d: abort of connected command failed!\n", HOSTNO);
- return SCSI_ABORT_ERROR;
- }
- }
+ local_irq_restore(flags);
+ cmd->scsi_done(cmd);
+ falcon_release_lock_if_possible(hostdata);
+ return SCSI_ABORT_SUCCESS;
+ } else {
+/* local_irq_restore(flags); */
+ printk("scsi%d: abort of connected command failed!\n", HOSTNO);
+ return SCSI_ABORT_ERROR;
+ }
+ }
#endif
-/*
- * Case 2 : If the command hasn't been issued yet, we simply remove it
- * from the issue queue.
- */
- for (prev = (Scsi_Cmnd **) &(hostdata->issue_queue),
- tmp = (Scsi_Cmnd *) hostdata->issue_queue;
- tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp) )
- if (cmd == tmp) {
- REMOVE(5, *prev, tmp, NEXT(tmp));
- (*prev) = NEXT(tmp);
- NEXT(tmp) = NULL;
- tmp->result = DID_ABORT << 16;
- local_irq_restore(flags);
- ABRT_PRINTK("scsi%d: abort removed command from issue queue.\n",
- HOSTNO);
- /* Tagged queuing note: no tag to free here, hasn't been assigned
- * yet... */
- tmp->scsi_done(tmp);
- falcon_release_lock_if_possible( hostdata );
- return SCSI_ABORT_SUCCESS;
+ /*
+ * Case 2 : If the command hasn't been issued yet, we simply remove it
+ * from the issue queue.
+ */
+ for (prev = (Scsi_Cmnd **)&(hostdata->issue_queue),
+ tmp = (Scsi_Cmnd *)hostdata->issue_queue;
+ tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp)) {
+ if (cmd == tmp) {
+ REMOVE(5, *prev, tmp, NEXT(tmp));
+ (*prev) = NEXT(tmp);
+ SET_NEXT(tmp, NULL);
+ tmp->result = DID_ABORT << 16;
+ local_irq_restore(flags);
+ ABRT_PRINTK("scsi%d: abort removed command from issue queue.\n",
+ HOSTNO);
+ /* Tagged queuing note: no tag to free here, hasn't been assigned
+ * yet... */
+ tmp->scsi_done(tmp);
+ falcon_release_lock_if_possible(hostdata);
+ return SCSI_ABORT_SUCCESS;
+ }
}
-/*
- * Case 3 : If any commands are connected, we're going to fail the abort
- * and let the high level SCSI driver retry at a later time or
- * issue a reset.
- *
- * Timeouts, and therefore aborted commands, will be highly unlikely
- * and handling them cleanly in this situation would make the common
- * case of noresets less efficient, and would pollute our code. So,
- * we fail.
- */
+ /*
+ * Case 3 : If any commands are connected, we're going to fail the abort
+ * and let the high level SCSI driver retry at a later time or
+ * issue a reset.
+ *
+ * Timeouts, and therefore aborted commands, will be highly unlikely
+ * and handling them cleanly in this situation would make the common
+ * case of noresets less efficient, and would pollute our code. So,
+ * we fail.
+ */
- if (hostdata->connected) {
- local_irq_restore(flags);
- ABRT_PRINTK("scsi%d: abort failed, command connected.\n", HOSTNO);
- return SCSI_ABORT_SNOOZE;
- }
+ if (hostdata->connected) {
+ local_irq_restore(flags);
+ ABRT_PRINTK("scsi%d: abort failed, command connected.\n", HOSTNO);
+ return SCSI_ABORT_SNOOZE;
+ }
-/*
- * Case 4: If the command is currently disconnected from the bus, and
- * there are no connected commands, we reconnect the I_T_L or
- * I_T_L_Q nexus associated with it, go into message out, and send
- * an abort message.
- *
- * This case is especially ugly. In order to reestablish the nexus, we
- * need to call NCR5380_select(). The easiest way to implement this
- * function was to abort if the bus was busy, and let the interrupt
- * handler triggered on the SEL for reselect take care of lost arbitrations
- * where necessary, meaning interrupts need to be enabled.
- *
- * When interrupts are enabled, the queues may change - so we
- * can't remove it from the disconnected queue before selecting it
- * because that could cause a failure in hashing the nexus if that
- * device reselected.
- *
- * Since the queues may change, we can't use the pointers from when we
- * first locate it.
- *
- * So, we must first locate the command, and if NCR5380_select()
- * succeeds, then issue the abort, relocate the command and remove
- * it from the disconnected queue.
- */
+ /*
+ * Case 4: If the command is currently disconnected from the bus, and
+ * there are no connected commands, we reconnect the I_T_L or
+ * I_T_L_Q nexus associated with it, go into message out, and send
+ * an abort message.
+ *
+ * This case is especially ugly. In order to reestablish the nexus, we
+ * need to call NCR5380_select(). The easiest way to implement this
+ * function was to abort if the bus was busy, and let the interrupt
+ * handler triggered on the SEL for reselect take care of lost arbitrations
+ * where necessary, meaning interrupts need to be enabled.
+ *
+ * When interrupts are enabled, the queues may change - so we
+ * can't remove it from the disconnected queue before selecting it
+ * because that could cause a failure in hashing the nexus if that
+ * device reselected.
+ *
+ * Since the queues may change, we can't use the pointers from when we
+ * first locate it.
+ *
+ * So, we must first locate the command, and if NCR5380_select()
+ * succeeds, then issue the abort, relocate the command and remove
+ * it from the disconnected queue.
+ */
+
+ for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp;
+ tmp = NEXT(tmp)) {
+ if (cmd == tmp) {
+ local_irq_restore(flags);
+ ABRT_PRINTK("scsi%d: aborting disconnected command.\n", HOSTNO);
- for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp;
- tmp = NEXT(tmp))
- if (cmd == tmp) {
- local_irq_restore(flags);
- ABRT_PRINTK("scsi%d: aborting disconnected command.\n", HOSTNO);
-
- if (NCR5380_select (instance, cmd, (int) cmd->tag))
- return SCSI_ABORT_BUSY;
-
- ABRT_PRINTK("scsi%d: nexus reestablished.\n", HOSTNO);
-
- do_abort (instance);
-
- local_irq_save(flags);
- for (prev = (Scsi_Cmnd **) &(hostdata->disconnected_queue),
- tmp = (Scsi_Cmnd *) hostdata->disconnected_queue;
- tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp) )
- if (cmd == tmp) {
- REMOVE(5, *prev, tmp, NEXT(tmp));
- *prev = NEXT(tmp);
- NEXT(tmp) = NULL;
- tmp->result = DID_ABORT << 16;
- /* We must unlock the tag/LUN immediately here, since the
- * target goes to BUS FREE and doesn't send us another
- * message (COMMAND_COMPLETE or the like)
- */
+ if (NCR5380_select(instance, cmd, (int)cmd->tag))
+ return SCSI_ABORT_BUSY;
+
+ ABRT_PRINTK("scsi%d: nexus reestablished.\n", HOSTNO);
+
+ do_abort(instance);
+
+ local_irq_save(flags);
+ for (prev = (Scsi_Cmnd **)&(hostdata->disconnected_queue),
+ tmp = (Scsi_Cmnd *)hostdata->disconnected_queue;
+ tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp)) {
+ if (cmd == tmp) {
+ REMOVE(5, *prev, tmp, NEXT(tmp));
+ *prev = NEXT(tmp);
+ SET_NEXT(tmp, NULL);
+ tmp->result = DID_ABORT << 16;
+ /* We must unlock the tag/LUN immediately here, since the
+ * target goes to BUS FREE and doesn't send us another
+ * message (COMMAND_COMPLETE or the like)
+ */
#ifdef SUPPORT_TAGS
- cmd_free_tag( tmp );
+ cmd_free_tag(tmp);
#else
- hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
+ hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
#endif
- local_irq_restore(flags);
- tmp->scsi_done(tmp);
- falcon_release_lock_if_possible( hostdata );
- return SCSI_ABORT_SUCCESS;
+ local_irq_restore(flags);
+ tmp->scsi_done(tmp);
+ falcon_release_lock_if_possible(hostdata);
+ return SCSI_ABORT_SUCCESS;
+ }
+ }
}
}
-/*
- * Case 5 : If we reached this point, the command was not found in any of
- * the queues.
- *
- * We probably reached this point because of an unlikely race condition
- * between the command completing successfully and the abortion code,
- * so we won't panic, but we will notify the user in case something really
- * broke.
- */
+ /*
+ * Case 5 : If we reached this point, the command was not found in any of
+ * the queues.
+ *
+ * We probably reached this point because of an unlikely race condition
+ * between the command completing successfully and the abortion code,
+ * so we won't panic, but we will notify the user in case something really
+ * broke.
+ */
- local_irq_restore(flags);
- printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully\n"
- KERN_INFO " before abortion\n", HOSTNO);
+ local_irq_restore(flags);
+ printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully\n"
+ KERN_INFO " before abortion\n", HOSTNO);
-/* Maybe it is sufficient just to release the ST-DMA lock... (if
- * possible at all) At least, we should check if the lock could be
- * released after the abort, in case it is kept due to some bug.
- */
- falcon_release_lock_if_possible( hostdata );
+ /* Maybe it is sufficient just to release the ST-DMA lock... (if
+ * possible at all) At least, we should check if the lock could be
+ * released after the abort, in case it is kept due to some bug.
+ */
+ falcon_release_lock_if_possible(hostdata);
- return SCSI_ABORT_NOT_RUNNING;
+ return SCSI_ABORT_NOT_RUNNING;
}
-/*
+/*
* Function : int NCR5380_reset (Scsi_Cmnd *cmd)
- *
+ *
* Purpose : reset the SCSI bus.
*
* Returns : SCSI_RESET_WAKEUP
*
- */
+ */
-static int NCR5380_bus_reset( Scsi_Cmnd *cmd)
+static int NCR5380_bus_reset(Scsi_Cmnd *cmd)
{
- SETUP_HOSTDATA(cmd->device->host);
- int i;
- unsigned long flags;
+ SETUP_HOSTDATA(cmd->device->host);
+ int i;
+ unsigned long flags;
#if 1
- Scsi_Cmnd *connected, *disconnected_queue;
+ Scsi_Cmnd *connected, *disconnected_queue;
#endif
- if (!IS_A_TT() && !falcon_got_lock)
- printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_reset\n",
- H_NO(cmd) );
-
- NCR5380_print_status (cmd->device->host);
-
- /* get in phase */
- NCR5380_write( TARGET_COMMAND_REG,
- PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));
- /* assert RST */
- NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST );
- udelay (40);
- /* reset NCR registers */
- NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
- NCR5380_write( MODE_REG, MR_BASE );
- NCR5380_write( TARGET_COMMAND_REG, 0 );
- NCR5380_write( SELECT_ENABLE_REG, 0 );
- /* ++roman: reset interrupt condition! otherwise no interrupts don't get
- * through anymore ... */
- (void)NCR5380_read( RESET_PARITY_INTERRUPT_REG );
-
-#if 1 /* XXX Should now be done by midlevel code, but it's broken XXX */
- /* XXX see below XXX */
-
- /* MSch: old-style reset: actually abort all command processing here */
-
- /* After the reset, there are no more connected or disconnected commands
- * and no busy units; to avoid problems with re-inserting the commands
- * into the issue_queue (via scsi_done()), the aborted commands are
- * remembered in local variables first.
- */
- local_irq_save(flags);
- connected = (Scsi_Cmnd *)hostdata->connected;
- hostdata->connected = NULL;
- disconnected_queue = (Scsi_Cmnd *)hostdata->disconnected_queue;
- hostdata->disconnected_queue = NULL;
+ if (!IS_A_TT() && !falcon_got_lock)
+ printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_reset\n",
+ H_NO(cmd));
+
+ NCR5380_print_status(cmd->device->host);
+
+ /* get in phase */
+ NCR5380_write(TARGET_COMMAND_REG,
+ PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG)));
+ /* assert RST */
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST);
+ udelay(40);
+ /* reset NCR registers */
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+ NCR5380_write(MODE_REG, MR_BASE);
+ NCR5380_write(TARGET_COMMAND_REG, 0);
+ NCR5380_write(SELECT_ENABLE_REG, 0);
+ /* ++roman: reset interrupt condition! otherwise no interrupts don't get
+ * through anymore ... */
+ (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+
+#if 1 /* XXX Should now be done by midlevel code, but it's broken XXX */
+ /* XXX see below XXX */
+
+ /* MSch: old-style reset: actually abort all command processing here */
+
+ /* After the reset, there are no more connected or disconnected commands
+ * and no busy units; to avoid problems with re-inserting the commands
+ * into the issue_queue (via scsi_done()), the aborted commands are
+ * remembered in local variables first.
+ */
+ local_irq_save(flags);
+ connected = (Scsi_Cmnd *)hostdata->connected;
+ hostdata->connected = NULL;
+ disconnected_queue = (Scsi_Cmnd *)hostdata->disconnected_queue;
+ hostdata->disconnected_queue = NULL;
#ifdef SUPPORT_TAGS
- free_all_tags();
+ free_all_tags();
#endif
- for( i = 0; i < 8; ++i )
- hostdata->busy[i] = 0;
+ for (i = 0; i < 8; ++i)
+ hostdata->busy[i] = 0;
#ifdef REAL_DMA
- hostdata->dma_len = 0;
+ hostdata->dma_len = 0;
#endif
- local_irq_restore(flags);
-
- /* In order to tell the mid-level code which commands were aborted,
- * set the command status to DID_RESET and call scsi_done() !!!
- * This ultimately aborts processing of these commands in the mid-level.
- */
-
- if ((cmd = connected)) {
- ABRT_PRINTK("scsi%d: reset aborted a connected command\n", H_NO(cmd));
- cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
- cmd->scsi_done( cmd );
- }
-
- for (i = 0; (cmd = disconnected_queue); ++i) {
- disconnected_queue = NEXT(cmd);
- NEXT(cmd) = NULL;
- cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
- cmd->scsi_done( cmd );
- }
- if (i > 0)
- ABRT_PRINTK("scsi: reset aborted %d disconnected command(s)\n", i);
-
-/* The Falcon lock should be released after a reset...
- */
-/* ++guenther: moved to atari_scsi_reset(), to prevent a race between
- * unlocking and enabling dma interrupt.
- */
-/* falcon_release_lock_if_possible( hostdata );*/
+ local_irq_restore(flags);
+
+ /* In order to tell the mid-level code which commands were aborted,
+ * set the command status to DID_RESET and call scsi_done() !!!
+ * This ultimately aborts processing of these commands in the mid-level.
+ */
+
+ if ((cmd = connected)) {
+ ABRT_PRINTK("scsi%d: reset aborted a connected command\n", H_NO(cmd));
+ cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
+ cmd->scsi_done(cmd);
+ }
- /* since all commands have been explicitly terminated, we need to tell
- * the midlevel code that the reset was SUCCESSFUL, and there is no
- * need to 'wake up' the commands by a request_sense
- */
- return SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET;
+ for (i = 0; (cmd = disconnected_queue); ++i) {
+ disconnected_queue = NEXT(cmd);
+ SET_NEXT(cmd, NULL);
+ cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
+ cmd->scsi_done(cmd);
+ }
+ if (i > 0)
+ ABRT_PRINTK("scsi: reset aborted %d disconnected command(s)\n", i);
+
+ /* The Falcon lock should be released after a reset...
+ */
+ /* ++guenther: moved to atari_scsi_reset(), to prevent a race between
+ * unlocking and enabling dma interrupt.
+ */
+/* falcon_release_lock_if_possible( hostdata );*/
+
+ /* since all commands have been explicitly terminated, we need to tell
+ * the midlevel code that the reset was SUCCESSFUL, and there is no
+ * need to 'wake up' the commands by a request_sense
+ */
+ return SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET;
#else /* 1 */
- /* MSch: new-style reset handling: let the mid-level do what it can */
-
- /* ++guenther: MID-LEVEL IS STILL BROKEN.
- * Mid-level is supposed to requeue all commands that were active on the
- * various low-level queues. In fact it does this, but that's not enough
- * because all these commands are subject to timeout. And if a timeout
- * happens for any removed command, *_abort() is called but all queues
- * are now empty. Abort then gives up the falcon lock, which is fatal,
- * since the mid-level will queue more commands and must have the lock
- * (it's all happening inside timer interrupt handler!!).
- * Even worse, abort will return NOT_RUNNING for all those commands not
- * on any queue, so they won't be retried ...
- *
- * Conclusion: either scsi.c disables timeout for all resetted commands
- * immediately, or we lose! As of linux-2.0.20 it doesn't.
- */
-
- /* After the reset, there are no more connected or disconnected commands
- * and no busy units; so clear the low-level status here to avoid
- * conflicts when the mid-level code tries to wake up the affected
- * commands!
- */
-
- if (hostdata->issue_queue)
- ABRT_PRINTK("scsi%d: reset aborted issued command(s)\n", H_NO(cmd));
- if (hostdata->connected)
- ABRT_PRINTK("scsi%d: reset aborted a connected command\n", H_NO(cmd));
- if (hostdata->disconnected_queue)
- ABRT_PRINTK("scsi%d: reset aborted disconnected command(s)\n", H_NO(cmd));
-
- local_irq_save(flags);
- hostdata->issue_queue = NULL;
- hostdata->connected = NULL;
- hostdata->disconnected_queue = NULL;
+ /* MSch: new-style reset handling: let the mid-level do what it can */
+
+ /* ++guenther: MID-LEVEL IS STILL BROKEN.
+ * Mid-level is supposed to requeue all commands that were active on the
+ * various low-level queues. In fact it does this, but that's not enough
+ * because all these commands are subject to timeout. And if a timeout
+ * happens for any removed command, *_abort() is called but all queues
+ * are now empty. Abort then gives up the falcon lock, which is fatal,
+ * since the mid-level will queue more commands and must have the lock
+ * (it's all happening inside timer interrupt handler!!).
+ * Even worse, abort will return NOT_RUNNING for all those commands not
+ * on any queue, so they won't be retried ...
+ *
+ * Conclusion: either scsi.c disables timeout for all resetted commands
+ * immediately, or we lose! As of linux-2.0.20 it doesn't.
+ */
+
+ /* After the reset, there are no more connected or disconnected commands
+ * and no busy units; so clear the low-level status here to avoid
+ * conflicts when the mid-level code tries to wake up the affected
+ * commands!
+ */
+
+ if (hostdata->issue_queue)
+ ABRT_PRINTK("scsi%d: reset aborted issued command(s)\n", H_NO(cmd));
+ if (hostdata->connected)
+ ABRT_PRINTK("scsi%d: reset aborted a connected command\n", H_NO(cmd));
+ if (hostdata->disconnected_queue)
+ ABRT_PRINTK("scsi%d: reset aborted disconnected command(s)\n", H_NO(cmd));
+
+ local_irq_save(flags);
+ hostdata->issue_queue = NULL;
+ hostdata->connected = NULL;
+ hostdata->disconnected_queue = NULL;
#ifdef SUPPORT_TAGS
- free_all_tags();
+ free_all_tags();
#endif
- for( i = 0; i < 8; ++i )
- hostdata->busy[i] = 0;
+ for (i = 0; i < 8; ++i)
+ hostdata->busy[i] = 0;
#ifdef REAL_DMA
- hostdata->dma_len = 0;
+ hostdata->dma_len = 0;
#endif
- local_irq_restore(flags);
+ local_irq_restore(flags);
- /* we did no complete reset of all commands, so a wakeup is required */
- return SCSI_RESET_WAKEUP | SCSI_RESET_BUS_RESET;
+ /* we did no complete reset of all commands, so a wakeup is required */
+ return SCSI_RESET_WAKEUP | SCSI_RESET_BUS_RESET;
#endif /* 1 */
}
-
-/* Local Variables: */
-/* tab-width: 8 */
-/* End: */
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c
index 642de7b2b7a2..6f8403b82ba1 100644
--- a/drivers/scsi/atari_scsi.c
+++ b/drivers/scsi/atari_scsi.c
@@ -69,9 +69,9 @@
#define NDEBUG (0)
-#define NDEBUG_ABORT 0x800000
-#define NDEBUG_TAGS 0x1000000
-#define NDEBUG_MERGING 0x2000000
+#define NDEBUG_ABORT 0x00100000
+#define NDEBUG_TAGS 0x00200000
+#define NDEBUG_MERGING 0x00400000
#define AUTOSENSE
/* For the Atari version, use only polled IO or REAL_DMA */
@@ -186,38 +186,37 @@ static inline void DISABLE_IRQ(void)
/***************************** 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 );
+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 );
+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 );
+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 );
+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 = NULL;
-static unsigned char (*atari_scsi_reg_read)( unsigned char reg );
-static void (*atari_scsi_reg_write)( unsigned char reg, unsigned char value );
+static struct Scsi_Host *atari_scsi_host;
+static unsigned char (*atari_scsi_reg_read)(unsigned char reg);
+static void (*atari_scsi_reg_write)(unsigned char reg, unsigned char value);
#ifdef REAL_DMA
static unsigned long atari_dma_residual, atari_dma_startaddr;
static short atari_dma_active;
/* pointer to the dribble buffer */
-static char *atari_dma_buffer = NULL;
+static char *atari_dma_buffer;
/* precalculated physical address of the dribble buffer */
static unsigned long atari_dma_phys_buffer;
/* != 0 tells the Falcon int handler to copy data from the dribble buffer */
@@ -233,7 +232,7 @@ static char *atari_dma_orig_addr;
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 = 0;
+static int atari_read_overruns;
#endif
static int setup_can_queue = -1;
@@ -256,10 +255,10 @@ module_param(setup_hostid, int, 0);
#if defined(REAL_DMA)
-static int scsi_dma_is_ignored_buserr( unsigned char dma_stat )
+static int scsi_dma_is_ignored_buserr(unsigned char dma_stat)
{
int i;
- unsigned long addr = SCSI_DMA_READ_P( dma_addr ), end_addr;
+ unsigned long addr = SCSI_DMA_READ_P(dma_addr), end_addr;
if (dma_stat & 0x01) {
@@ -267,15 +266,14 @@ static int scsi_dma_is_ignored_buserr( unsigned char dma_stat )
* physical memory chunk (DMA prefetch!), but that doesn't hurt.
* Check for this case:
*/
-
- for( i = 0; i < m68k_num_memory; ++i ) {
- end_addr = m68k_memory[i].addr +
- m68k_memory[i].size;
+
+ for (i = 0; i < m68k_num_memory; ++i) {
+ end_addr = m68k_memory[i].addr + m68k_memory[i].size;
if (end_addr <= addr && addr <= end_addr + 4)
- return( 1 );
+ return 1;
}
}
- return( 0 );
+ return 0;
}
@@ -284,28 +282,27 @@ static int scsi_dma_is_ignored_buserr( unsigned char dma_stat )
* end-of-DMA, both SCSI ints are triggered simultaneously, so the NCR int has
* to clear the DMA int pending bit before it allows other level 6 interrupts.
*/
-static void scsi_dma_buserr (int irq, void *dummy)
+static void scsi_dma_buserr(int irq, void *dummy)
{
- unsigned char dma_stat = tt_scsi_dma.dma_ctrl;
+ unsigned char dma_stat = tt_scsi_dma.dma_ctrl;
/* Don't do anything if a NCR interrupt is pending. Probably it's just
* masked... */
- if (atari_irq_pending( IRQ_TT_MFP_SCSI ))
+ if (atari_irq_pending(IRQ_TT_MFP_SCSI))
return;
-
+
printk("Bad SCSI DMA interrupt! dma_addr=0x%08lx dma_stat=%02x dma_cnt=%08lx\n",
SCSI_DMA_READ_P(dma_addr), dma_stat, SCSI_DMA_READ_P(dma_cnt));
if (dma_stat & 0x80) {
- if (!scsi_dma_is_ignored_buserr( dma_stat ))
- printk( "SCSI DMA bus error -- bad DMA programming!\n" );
- }
- else {
+ if (!scsi_dma_is_ignored_buserr(dma_stat))
+ printk("SCSI DMA bus error -- bad DMA programming!\n");
+ } else {
/* Under normal circumstances we never should get to this point,
* since both interrupts are triggered simultaneously and the 5380
* int has higher priority. When this irq is handled, that DMA
* interrupt is cleared. So a warning message is printed here.
*/
- printk( "SCSI DMA intr ?? -- this shouldn't happen!\n" );
+ printk("SCSI DMA intr ?? -- this shouldn't happen!\n");
}
}
#endif
@@ -313,7 +310,7 @@ static void scsi_dma_buserr (int irq, void *dummy)
#endif
-static irqreturn_t scsi_tt_intr (int irq, void *dummy)
+static irqreturn_t scsi_tt_intr(int irq, void *dummy)
{
#ifdef REAL_DMA
int dma_stat;
@@ -327,7 +324,7 @@ static irqreturn_t scsi_tt_intr (int irq, void *dummy)
* is that a bus error occurred...
*/
if (dma_stat & 0x80) {
- if (!scsi_dma_is_ignored_buserr( dma_stat )) {
+ if (!scsi_dma_is_ignored_buserr(dma_stat)) {
printk(KERN_ERR "SCSI DMA caused bus error near 0x%08lx\n",
SCSI_DMA_READ_P(dma_addr));
printk(KERN_CRIT "SCSI DMA bus error -- bad DMA programming!");
@@ -344,8 +341,7 @@ static irqreturn_t scsi_tt_intr (int irq, void *dummy)
* data reg!
*/
if ((dma_stat & 0x02) && !(dma_stat & 0x40)) {
- atari_dma_residual = HOSTDATA_DMALEN - (SCSI_DMA_READ_P( dma_addr ) -
- atari_dma_startaddr);
+ atari_dma_residual = HOSTDATA_DMALEN - (SCSI_DMA_READ_P(dma_addr) - atari_dma_startaddr);
DMA_PRINTK("SCSI DMA: There are %ld residual bytes.\n",
atari_dma_residual);
@@ -353,28 +349,30 @@ static irqreturn_t scsi_tt_intr (int irq, void *dummy)
if ((signed int)atari_dma_residual < 0)
atari_dma_residual = 0;
if ((dma_stat & 1) == 0) {
- /* After read operations, we maybe have to
- transport some rest bytes */
+ /*
+ * After read operations, we maybe have to
+ * transport some rest bytes
+ */
atari_scsi_fetch_restbytes();
- }
- else {
- /* There seems to be a nasty bug in some SCSI-DMA/NCR
- combinations: If a target disconnects while a write
- operation is going on, the address register of the
- DMA may be a few bytes farer than it actually read.
- This is probably due to DMA prefetching and a delay
- between DMA and NCR. Experiments showed that the
- dma_addr is 9 bytes to high, but this could vary.
- The problem is, that the residual is thus calculated
- wrong and the next transfer will start behind where
- it should. So we round up the residual to the next
- multiple of a sector size, if it isn't already a
- multiple and the originally expected transfer size
- was. The latter condition is there to ensure that
- the correction is taken only for "real" data
- transfers and not for, e.g., the parameters of some
- other command. These shouldn't disconnect anyway.
- */
+ } else {
+ /*
+ * There seems to be a nasty bug in some SCSI-DMA/NCR
+ * combinations: If a target disconnects while a write
+ * operation is going on, the address register of the
+ * DMA may be a few bytes farer than it actually read.
+ * This is probably due to DMA prefetching and a delay
+ * between DMA and NCR. Experiments showed that the
+ * dma_addr is 9 bytes to high, but this could vary.
+ * The problem is, that the residual is thus calculated
+ * wrong and the next transfer will start behind where
+ * it should. So we round up the residual to the next
+ * multiple of a sector size, if it isn't already a
+ * multiple and the originally expected transfer size
+ * was. The latter condition is there to ensure that
+ * the correction is taken only for "real" data
+ * transfers and not for, e.g., the parameters of some
+ * other command. These shouldn't disconnect anyway.
+ */
if (atari_dma_residual & 0x1ff) {
DMA_PRINTK("SCSI DMA: DMA bug corrected, "
"difference %ld bytes\n",
@@ -394,18 +392,18 @@ static irqreturn_t scsi_tt_intr (int irq, void *dummy)
}
#endif /* REAL_DMA */
-
- NCR5380_intr (0, 0, 0);
+
+ NCR5380_intr(0, 0);
#if 0
/* To be sure the int is not masked */
- atari_enable_irq( IRQ_TT_MFP_SCSI );
+ atari_enable_irq(IRQ_TT_MFP_SCSI);
#endif
return IRQ_HANDLED;
}
-static irqreturn_t scsi_falcon_intr (int irq, void *dummy)
+static irqreturn_t scsi_falcon_intr(int irq, void *dummy)
{
#ifdef REAL_DMA
int dma_stat;
@@ -430,7 +428,7 @@ static irqreturn_t scsi_falcon_intr (int irq, void *dummy)
* bytes are stuck in the ST-DMA fifo (there's no way to reach them!)
*/
if (atari_dma_active && (dma_stat & 0x02)) {
- unsigned long transferred;
+ unsigned long transferred;
transferred = SCSI_DMA_GETADR() - atari_dma_startaddr;
/* The ST-DMA address is incremented in 2-byte steps, but the
@@ -445,8 +443,7 @@ static irqreturn_t scsi_falcon_intr (int irq, void *dummy)
atari_dma_residual = HOSTDATA_DMALEN - transferred;
DMA_PRINTK("SCSI DMA: There are %ld residual bytes.\n",
atari_dma_residual);
- }
- else
+ } else
atari_dma_residual = 0;
atari_dma_active = 0;
@@ -461,13 +458,13 @@ static irqreturn_t scsi_falcon_intr (int irq, void *dummy)
#endif /* REAL_DMA */
- NCR5380_intr (0, 0, 0);
+ NCR5380_intr(0, 0);
return IRQ_HANDLED;
}
#ifdef REAL_DMA
-static void atari_scsi_fetch_restbytes( void )
+static void atari_scsi_fetch_restbytes(void)
{
int nr;
char *src, *dst;
@@ -505,19 +502,17 @@ static int falcon_dont_release = 0;
* again (but others waiting longer more probably will win).
*/
-static void
-falcon_release_lock_if_possible( struct NCR5380_hostdata * hostdata )
+static void falcon_release_lock_if_possible(struct NCR5380_hostdata *hostdata)
{
unsigned long flags;
-
- if (IS_A_TT()) return;
-
+
+ if (IS_A_TT())
+ return;
+
local_irq_save(flags);
- if (falcon_got_lock &&
- !hostdata->disconnected_queue &&
- !hostdata->issue_queue &&
- !hostdata->connected) {
+ if (falcon_got_lock && !hostdata->disconnected_queue &&
+ !hostdata->issue_queue && !hostdata->connected) {
if (falcon_dont_release) {
#if 0
@@ -528,7 +523,7 @@ falcon_release_lock_if_possible( struct NCR5380_hostdata * hostdata )
}
falcon_got_lock = 0;
stdma_release();
- wake_up( &falcon_fairness_wait );
+ wake_up(&falcon_fairness_wait);
}
local_irq_restore(flags);
@@ -549,31 +544,31 @@ falcon_release_lock_if_possible( struct NCR5380_hostdata * hostdata )
* Complicated, complicated.... Sigh...
*/
-static void falcon_get_lock( void )
+static void falcon_get_lock(void)
{
unsigned long flags;
- if (IS_A_TT()) return;
+ if (IS_A_TT())
+ return;
local_irq_save(flags);
- while( !in_interrupt() && falcon_got_lock && stdma_others_waiting() )
- sleep_on( &falcon_fairness_wait );
+ while (!in_irq() && falcon_got_lock && stdma_others_waiting())
+ sleep_on(&falcon_fairness_wait);
while (!falcon_got_lock) {
- if (in_interrupt())
- panic( "Falcon SCSI hasn't ST-DMA lock in interrupt" );
+ 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 {
- sleep_on( &falcon_try_wait );
+ wake_up(&falcon_try_wait);
+ } else {
+ sleep_on(&falcon_try_wait);
}
- }
+ }
local_irq_restore(flags);
if (!falcon_got_lock)
@@ -587,18 +582,18 @@ static void falcon_get_lock( void )
*/
#if 0
-int atari_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
+int atari_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
{
/* falcon_get_lock();
* ++guenther: moved to NCR5380_queue_command() to prevent
* race condition, see there for an explanation.
*/
- return( NCR5380_queue_command( cmd, done ) );
+ return NCR5380_queue_command(cmd, done);
}
#endif
-int atari_scsi_detect (struct scsi_host_template *host)
+int atari_scsi_detect(struct scsi_host_template *host)
{
static int called = 0;
struct Scsi_Host *instance;
@@ -606,7 +601,7 @@ int atari_scsi_detect (struct scsi_host_template *host)
if (!MACH_IS_ATARI ||
(!ATARIHW_PRESENT(ST_SCSI) && !ATARIHW_PRESENT(TT_SCSI)) ||
called)
- return( 0 );
+ return 0;
host->proc_name = "Atari";
@@ -655,32 +650,33 @@ int atari_scsi_detect (struct scsi_host_template *host)
!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 );
+ printk(KERN_ERR "atari_scsi_detect: can't allocate ST-RAM "
+ "double buffer\n");
+ return 0;
}
- atari_dma_phys_buffer = virt_to_phys( atari_dma_buffer );
+ atari_dma_phys_buffer = virt_to_phys(atari_dma_buffer);
atari_dma_orig_addr = 0;
}
#endif
- instance = scsi_register (host, sizeof (struct NCR5380_hostdata));
- if(instance == NULL)
- {
+ 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! */
+ /*
+ * 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);
+ NCR5380_init(instance, 0);
if (IS_A_TT()) {
@@ -727,11 +723,10 @@ int atari_scsi_detect (struct scsi_host_template *host)
* the rest data bug is fixed, this can be lowered to 1.
*/
atari_read_overruns = 4;
- }
+ }
#endif /*REAL_DMA*/
- }
- else { /* ! IS_A_TT */
-
+ } else { /* ! IS_A_TT */
+
/* Nothing to do for the interrupt: the ST-DMA is initialized
* already by atari_init_INTS()
*/
@@ -756,23 +751,21 @@ int atari_scsi_detect (struct scsi_host_template *host)
setup_use_tagged_queuing ? "yes" : "no",
#endif
instance->hostt->this_id );
- NCR5380_print_options (instance);
- printk ("\n");
+ NCR5380_print_options(instance);
+ printk("\n");
called = 1;
- return( 1 );
+ return 1;
}
-#ifdef MODULE
-int atari_scsi_release (struct Scsi_Host *sh)
+int atari_scsi_release(struct Scsi_Host *sh)
{
if (IS_A_TT())
free_irq(IRQ_TT_MFP_SCSI, scsi_tt_intr);
if (atari_dma_buffer)
- atari_stram_free (atari_dma_buffer);
+ atari_stram_free(atari_dma_buffer);
return 1;
}
-#endif
void __init atari_scsi_setup(char *str, int *ints)
{
@@ -781,9 +774,9 @@ void __init atari_scsi_setup(char *str, int *ints)
* Defaults depend on TT or Falcon, hostid determined at run time.
* Negative values mean don't change.
*/
-
+
if (ints[0] < 1) {
- printk( "atari_scsi_setup: no arguments!\n" );
+ printk("atari_scsi_setup: no arguments!\n");
return;
}
@@ -809,7 +802,7 @@ void __init atari_scsi_setup(char *str, int *ints)
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] );
+ printk("atari_scsi_setup: invalid host ID %d !\n", ints[4]);
}
#ifdef SUPPORT_TAGS
if (ints[0] >= 5) {
@@ -821,7 +814,7 @@ void __init atari_scsi_setup(char *str, int *ints)
int atari_scsi_bus_reset(Scsi_Cmnd *cmd)
{
- int rv;
+ int rv;
struct NCR5380_hostdata *hostdata =
(struct NCR5380_hostdata *)cmd->device->host->hostdata;
@@ -831,13 +824,12 @@ int atari_scsi_bus_reset(Scsi_Cmnd *cmd)
*/
/* And abort a maybe active DMA transfer */
if (IS_A_TT()) {
- atari_turnoff_irq( IRQ_TT_MFP_SCSI );
+ 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 );
+ } else {
+ atari_turnoff_irq(IRQ_MFP_FSCSI);
#ifdef REAL_DMA
st_dma.dma_mode_status = 0x90;
atari_dma_active = 0;
@@ -849,52 +841,51 @@ int atari_scsi_bus_reset(Scsi_Cmnd *cmd)
/* Re-enable ints */
if (IS_A_TT()) {
- atari_turnon_irq( IRQ_TT_MFP_SCSI );
- }
- else {
- atari_turnon_irq( IRQ_MFP_FSCSI );
+ atari_turnon_irq(IRQ_TT_MFP_SCSI);
+ } else {
+ atari_turnon_irq(IRQ_MFP_FSCSI);
}
if ((rv & SCSI_RESET_ACTION) == SCSI_RESET_SUCCESS)
falcon_release_lock_if_possible(hostdata);
- return( rv );
+ return rv;
}
-
+
#ifdef CONFIG_ATARI_SCSI_RESET_BOOT
static void __init atari_scsi_reset_boot(void)
{
unsigned long end;
-
+
/*
* Do a SCSI reset to clean up the bus during initialization. No messing
* with the queues, interrupts, or locks necessary here.
*/
- printk( "Atari SCSI: resetting the SCSI bus..." );
+ printk("Atari SCSI: resetting the SCSI bus...");
/* get in phase */
- NCR5380_write( TARGET_COMMAND_REG,
- PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));
+ NCR5380_write(TARGET_COMMAND_REG,
+ PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG)));
/* assert RST */
- NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST );
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST);
/* The min. reset hold time is 25us, so 40us should be enough */
- udelay( 50 );
+ udelay(50);
/* reset RST and interrupt */
- NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
- NCR5380_read( RESET_PARITY_INTERRUPT_REG );
+ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+ NCR5380_read(RESET_PARITY_INTERRUPT_REG);
end = jiffies + AFTER_RESET_DELAY;
while (time_before(jiffies, end))
barrier();
- printk( " done\n" );
+ printk(" done\n");
}
#endif
-const char * atari_scsi_info (struct Scsi_Host *host)
+const char *atari_scsi_info(struct Scsi_Host *host)
{
/* atari_scsi_detect() is verbose enough... */
static const char string[] = "Atari native SCSI";
@@ -904,10 +895,10 @@ const char * atari_scsi_info (struct Scsi_Host *host)
#if defined(REAL_DMA)
-unsigned long atari_scsi_dma_setup( struct Scsi_Host *instance, void *data,
- unsigned long count, int dir )
+unsigned long atari_scsi_dma_setup(struct Scsi_Host *instance, void *data,
+ unsigned long count, int dir)
{
- unsigned long addr = virt_to_phys( data );
+ unsigned long addr = virt_to_phys(data);
DMA_PRINTK("scsi%d: setting up dma, data = %p, phys = %lx, count = %ld, "
"dir = %d\n", instance->host_no, data, addr, count, dir);
@@ -919,38 +910,37 @@ unsigned long atari_scsi_dma_setup( struct Scsi_Host *instance, void *data,
* wanted address.
*/
if (dir)
- memcpy( atari_dma_buffer, data, count );
+ memcpy(atari_dma_buffer, data, count);
else
atari_dma_orig_addr = data;
addr = atari_dma_phys_buffer;
}
-
+
atari_dma_startaddr = addr; /* Needed for calculating residual later. */
-
+
/* Cache cleanup stuff: On writes, push any dirty cache out before sending
* it to the peripheral. (Must be done before DMA setup, since at least
* the ST-DMA begins to fill internal buffers right after setup. For
* reads, invalidate any cache, may be altered after DMA without CPU
* knowledge.
- *
+ *
* ++roman: For the Medusa, there's no need at all for that cache stuff,
* because the hardware does bus snooping (fine!).
*/
- dma_cache_maintenance( addr, count, dir );
+ dma_cache_maintenance(addr, count, dir);
if (count == 0)
printk(KERN_NOTICE "SCSI warning: DMA programmed for 0 bytes !\n");
if (IS_A_TT()) {
tt_scsi_dma.dma_ctrl = dir;
- SCSI_DMA_WRITE_P( dma_addr, addr );
- SCSI_DMA_WRITE_P( dma_cnt, count );
+ SCSI_DMA_WRITE_P(dma_addr, addr);
+ SCSI_DMA_WRITE_P(dma_cnt, count);
tt_scsi_dma.dma_ctrl = dir | 2;
- }
- else { /* ! IS_A_TT */
-
+ } else { /* ! IS_A_TT */
+
/* set address */
- SCSI_DMA_SETADR( addr );
+ SCSI_DMA_SETADR(addr);
/* toggle direction bit to clear FIFO and set DMA direction */
dir <<= 8;
@@ -968,13 +958,13 @@ unsigned long atari_scsi_dma_setup( struct Scsi_Host *instance, void *data,
atari_dma_active = 1;
}
- return( count );
+ return count;
}
-static long atari_scsi_dma_residual( struct Scsi_Host *instance )
+static long atari_scsi_dma_residual(struct Scsi_Host *instance)
{
- return( atari_dma_residual );
+ return atari_dma_residual;
}
@@ -982,13 +972,13 @@ 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(Scsi_Cmnd *cmd)
{
unsigned char opcode = cmd->cmnd[0];
-
+
if (opcode == READ_DEFECT_DATA || opcode == READ_LONG ||
- opcode == READ_BUFFER)
- return( CMD_SURELY_BYTE_MODE );
+ opcode == READ_BUFFER)
+ return CMD_SURELY_BYTE_MODE;
else if (opcode == READ_6 || opcode == READ_10 ||
opcode == 0xa8 /* READ_12 */ || opcode == READ_REVERSE ||
opcode == RECOVER_BUFFERED_DATA) {
@@ -996,12 +986,11 @@ static int falcon_classify_cmd( Scsi_Cmnd *cmd )
* needed here: The transfer is block-mode only if the 'fixed' bit is
* set! */
if (cmd->device->type == TYPE_TAPE && !(cmd->cmnd[1] & 1))
- return( CMD_SURELY_BYTE_MODE );
+ return CMD_SURELY_BYTE_MODE;
else
- return( CMD_SURELY_BLOCK_MODE );
- }
- else
- return( CMD_MODE_UNKNOWN );
+ return CMD_SURELY_BLOCK_MODE;
+ } else
+ return CMD_MODE_UNKNOWN;
}
@@ -1014,19 +1003,18 @@ static int falcon_classify_cmd( Scsi_Cmnd *cmd )
* the overrun problem, so this question is academic :-)
*/
-static unsigned long atari_dma_xfer_len( unsigned long wanted_len,
- Scsi_Cmnd *cmd,
- int write_flag )
+static unsigned long atari_dma_xfer_len(unsigned long wanted_len,
+ Scsi_Cmnd *cmd, int write_flag)
{
unsigned long possible_len, limit;
#ifndef CONFIG_TT_DMA_EMUL
if (MACH_IS_HADES)
/* Hades has no SCSI DMA at all :-( Always force use of PIO */
- return( 0 );
-#endif
+ return 0;
+#endif
if (IS_A_TT())
/* TT SCSI DMA can transfer arbitrary #bytes */
- return( wanted_len );
+ return wanted_len;
/* ST DMA chip is stupid -- only multiples of 512 bytes! (and max.
* 255*512 bytes, but this should be enough)
@@ -1062,8 +1050,7 @@ static unsigned long atari_dma_xfer_len( unsigned long wanted_len,
* this).
*/
possible_len = wanted_len;
- }
- else {
+ } else {
/* Read operations: if the wanted transfer length is not a multiple of
* 512, we cannot use DMA, since the ST-DMA cannot split transfers
* (no interrupt on DMA finished!)
@@ -1073,15 +1060,15 @@ static unsigned long atari_dma_xfer_len( unsigned long wanted_len,
else {
/* Now classify the command (see above) and decide whether it is
* allowed to do DMA at all */
- switch( falcon_classify_cmd( cmd )) {
- case CMD_SURELY_BLOCK_MODE:
+ switch (falcon_classify_cmd(cmd)) {
+ case CMD_SURELY_BLOCK_MODE:
possible_len = wanted_len;
break;
- case CMD_SURELY_BYTE_MODE:
+ case CMD_SURELY_BYTE_MODE:
possible_len = 0; /* DMA prohibited */
break;
- case CMD_MODE_UNKNOWN:
- default:
+ case CMD_MODE_UNKNOWN:
+ default:
/* For unknown commands assume block transfers if the transfer
* size/allocation length is >= 1024 */
possible_len = (wanted_len < 1024) ? 0 : wanted_len;
@@ -1089,9 +1076,9 @@ static unsigned long atari_dma_xfer_len( unsigned long wanted_len,
}
}
}
-
+
/* Last step: apply the hard limit on DMA transfers */
- limit = (atari_dma_buffer && !STRAM_ADDR( virt_to_phys(cmd->SCp.ptr) )) ?
+ limit = (atari_dma_buffer && !STRAM_ADDR(virt_to_phys(cmd->SCp.ptr))) ?
STRAM_BUFFER_SIZE : 255*512;
if (possible_len > limit)
possible_len = limit;
@@ -1100,7 +1087,7 @@ static unsigned long atari_dma_xfer_len( unsigned long wanted_len,
DMA_PRINTK("Sorry, must cut DMA transfer size to %ld bytes "
"instead of %ld\n", possible_len, wanted_len);
- return( possible_len );
+ return possible_len;
}
@@ -1114,23 +1101,23 @@ static unsigned long atari_dma_xfer_len( unsigned long wanted_len,
* NCR5380_write call these functions via function pointers.
*/
-static unsigned char atari_scsi_tt_reg_read( unsigned char reg )
+static unsigned char atari_scsi_tt_reg_read(unsigned char reg)
{
- return( tt_scsi_regp[reg * 2] );
+ return tt_scsi_regp[reg * 2];
}
-static void atari_scsi_tt_reg_write( unsigned char reg, unsigned char value )
+static void atari_scsi_tt_reg_write(unsigned char reg, unsigned char value)
{
tt_scsi_regp[reg * 2] = value;
}
-static unsigned char atari_scsi_falcon_reg_read( unsigned char reg )
+static unsigned char atari_scsi_falcon_reg_read(unsigned char reg)
{
dma_wd.dma_mode_status= (u_short)(0x88 + reg);
- return( (u_char)dma_wd.fdc_acces_seccount );
+ return (u_char)dma_wd.fdc_acces_seccount;
}
-static void atari_scsi_falcon_reg_write( unsigned char reg, unsigned char value )
+static void atari_scsi_falcon_reg_write(unsigned char reg, unsigned char value)
{
dma_wd.dma_mode_status = (u_short)(0x88 + reg);
dma_wd.fdc_acces_seccount = (u_short)value;
diff --git a/drivers/scsi/atari_scsi.h b/drivers/scsi/atari_scsi.h
index f917bdd09b41..efadb8d567c2 100644
--- a/drivers/scsi/atari_scsi.h
+++ b/drivers/scsi/atari_scsi.h
@@ -21,11 +21,7 @@
int atari_scsi_detect (struct scsi_host_template *);
const char *atari_scsi_info (struct Scsi_Host *);
int atari_scsi_reset (Scsi_Cmnd *, unsigned int);
-#ifdef MODULE
int atari_scsi_release (struct Scsi_Host *);
-#else
-#define atari_scsi_release NULL
-#endif
/* 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!) */
@@ -63,6 +59,32 @@ int atari_scsi_release (struct Scsi_Host *);
#define NCR5380_dma_xfer_len(i,cmd,phase) \
atari_dma_xfer_len(cmd->SCp.this_residual,cmd,((phase) & SR_IO) ? 0 : 1)
+/* former generic SCSI error handling stuff */
+
+#define SCSI_ABORT_SNOOZE 0
+#define SCSI_ABORT_SUCCESS 1
+#define SCSI_ABORT_PENDING 2
+#define SCSI_ABORT_BUSY 3
+#define SCSI_ABORT_NOT_RUNNING 4
+#define SCSI_ABORT_ERROR 5
+
+#define SCSI_RESET_SNOOZE 0
+#define SCSI_RESET_PUNT 1
+#define SCSI_RESET_SUCCESS 2
+#define SCSI_RESET_PENDING 3
+#define SCSI_RESET_WAKEUP 4
+#define SCSI_RESET_NOT_RUNNING 5
+#define SCSI_RESET_ERROR 6
+
+#define SCSI_RESET_SYNCHRONOUS 0x01
+#define SCSI_RESET_ASYNCHRONOUS 0x02
+#define SCSI_RESET_SUGGEST_BUS_RESET 0x04
+#define SCSI_RESET_SUGGEST_HOST_RESET 0x08
+
+#define SCSI_RESET_BUS_RESET 0x100
+#define SCSI_RESET_HOST_RESET 0x200
+#define SCSI_RESET_ACTION 0xff
+
/* Debugging printk definitions:
*
* ARB -> arbitration
@@ -91,144 +113,58 @@ int atari_scsi_release (struct Scsi_Host *);
*
*/
-#if NDEBUG & NDEBUG_ARBITRATION
+#define dprint(flg, format...) \
+({ \
+ if (NDEBUG & (flg)) \
+ printk(KERN_DEBUG format); \
+})
+
#define ARB_PRINTK(format, args...) \
- printk(KERN_DEBUG format , ## args)
-#else
-#define ARB_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_AUTOSENSE
+ dprint(NDEBUG_ARBITRATION, format , ## args)
#define ASEN_PRINTK(format, args...) \
- printk(KERN_DEBUG format , ## args)
-#else
-#define ASEN_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_DMA
+ dprint(NDEBUG_AUTOSENSE, format , ## args)
#define DMA_PRINTK(format, args...) \
- printk(KERN_DEBUG format , ## args)
-#else
-#define DMA_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_HANDSHAKE
+ dprint(NDEBUG_DMA, format , ## args)
#define HSH_PRINTK(format, args...) \
- printk(KERN_DEBUG format , ## args)
-#else
-#define HSH_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_INFORMATION
+ dprint(NDEBUG_HANDSHAKE, format , ## args)
#define INF_PRINTK(format, args...) \
- printk(KERN_DEBUG format , ## args)
-#else
-#define INF_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_INIT
+ dprint(NDEBUG_INFORMATION, format , ## args)
#define INI_PRINTK(format, args...) \
- printk(KERN_DEBUG format , ## args)
-#else
-#define INI_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_INTR
+ dprint(NDEBUG_INIT, format , ## args)
#define INT_PRINTK(format, args...) \
- printk(KERN_DEBUG format , ## args)
-#else
-#define INT_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_LINKED
+ dprint(NDEBUG_INTR, format , ## args)
#define LNK_PRINTK(format, args...) \
- printk(KERN_DEBUG format , ## args)
-#else
-#define LNK_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_MAIN
+ dprint(NDEBUG_LINKED, format , ## args)
#define MAIN_PRINTK(format, args...) \
- printk(KERN_DEBUG format , ## args)
-#else
-#define MAIN_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_NO_DATAOUT
+ dprint(NDEBUG_MAIN, format , ## args)
#define NDAT_PRINTK(format, args...) \
- printk(KERN_DEBUG format , ## args)
-#else
-#define NDAT_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_NO_WRITE
+ dprint(NDEBUG_NO_DATAOUT, format , ## args)
#define NWR_PRINTK(format, args...) \
- printk(KERN_DEBUG format , ## args)
-#else
-#define NWR_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_PIO
+ dprint(NDEBUG_NO_WRITE, format , ## args)
#define PIO_PRINTK(format, args...) \
- printk(KERN_DEBUG format , ## args)
-#else
-#define PIO_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_PSEUDO_DMA
+ dprint(NDEBUG_PIO, format , ## args)
#define PDMA_PRINTK(format, args...) \
- printk(KERN_DEBUG format , ## args)
-#else
-#define PDMA_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_QUEUES
+ dprint(NDEBUG_PSEUDO_DMA, format , ## args)
#define QU_PRINTK(format, args...) \
- printk(KERN_DEBUG format , ## args)
-#else
-#define QU_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_RESELECTION
+ dprint(NDEBUG_QUEUES, format , ## args)
#define RSL_PRINTK(format, args...) \
- printk(KERN_DEBUG format , ## args)
-#else
-#define RSL_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_SELECTION
+ dprint(NDEBUG_RESELECTION, format , ## args)
#define SEL_PRINTK(format, args...) \
- printk(KERN_DEBUG format , ## args)
-#else
-#define SEL_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_USLEEP
+ dprint(NDEBUG_SELECTION, format , ## args)
#define USL_PRINTK(format, args...) \
- printk(KERN_DEBUG format , ## args)
-#else
-#define USL_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_LAST_BYTE_SENT
+ dprint(NDEBUG_USLEEP, format , ## args)
#define LBS_PRINTK(format, args...) \
- printk(KERN_DEBUG format , ## args)
-#else
-#define LBS_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_RESTART_SELECT
+ dprint(NDEBUG_LAST_BYTE_SENT, format , ## args)
#define RSS_PRINTK(format, args...) \
- printk(KERN_DEBUG format , ## args)
-#else
-#define RSS_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_EXTENDED
+ dprint(NDEBUG_RESTART_SELECT, format , ## args)
#define EXT_PRINTK(format, args...) \
- printk(KERN_DEBUG format , ## args)
-#else
-#define EXT_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_ABORT
+ dprint(NDEBUG_EXTENDED, format , ## args)
#define ABRT_PRINTK(format, args...) \
- printk(KERN_DEBUG format , ## args)
-#else
-#define ABRT_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_TAGS
+ dprint(NDEBUG_ABORT, format , ## args)
#define TAG_PRINTK(format, args...) \
- printk(KERN_DEBUG format , ## args)
-#else
-#define TAG_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_MERGING
+ dprint(NDEBUG_TAGS, format , ## args)
#define MER_PRINTK(format, args...) \
- printk(KERN_DEBUG format , ## args)
-#else
-#define MER_PRINTK(format, args...)
-#endif
+ dprint(NDEBUG_MERGING, format , ## args)
/* conditional macros for NCR5380_print_{,phase,status} */
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index 61f6024b61ba..2a458d66b6ff 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -202,31 +202,29 @@ static const char * get_sa_name(const struct value_name_pair * arr,
}
/* attempt to guess cdb length if cdb_len==0 . No trailing linefeed. */
-static void print_opcode_name(unsigned char * cdbp, int cdb_len,
- int start_of_line)
+static void print_opcode_name(unsigned char * cdbp, int cdb_len)
{
int sa, len, cdb0;
const char * name;
- const char * leadin = start_of_line ? KERN_INFO : "";
cdb0 = cdbp[0];
switch(cdb0) {
case VARIABLE_LENGTH_CMD:
len = cdbp[7] + 8;
if (len < 10) {
- printk("%sshort variable length command, "
- "len=%d ext_len=%d", leadin, len, cdb_len);
+ printk("short variable length command, "
+ "len=%d ext_len=%d", len, cdb_len);
break;
}
sa = (cdbp[8] << 8) + cdbp[9];
name = get_sa_name(maint_in_arr, MAINT_IN_SZ, sa);
if (name) {
- printk("%s%s", leadin, name);
+ printk("%s", name);
if ((cdb_len > 0) && (len != cdb_len))
printk(", in_cdb_len=%d, ext_len=%d",
len, cdb_len);
} else {
- printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+ printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
if ((cdb_len > 0) && (len != cdb_len))
printk(", in_cdb_len=%d, ext_len=%d",
len, cdb_len);
@@ -236,83 +234,80 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len,
sa = cdbp[1] & 0x1f;
name = get_sa_name(maint_in_arr, MAINT_IN_SZ, sa);
if (name)
- printk("%s%s", leadin, name);
+ printk("%s", name);
else
- printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+ printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
break;
case MAINTENANCE_OUT:
sa = cdbp[1] & 0x1f;
name = get_sa_name(maint_out_arr, MAINT_OUT_SZ, sa);
if (name)
- printk("%s%s", leadin, name);
+ printk("%s", name);
else
- printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+ printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
break;
case SERVICE_ACTION_IN_12:
sa = cdbp[1] & 0x1f;
name = get_sa_name(serv_in12_arr, SERV_IN12_SZ, sa);
if (name)
- printk("%s%s", leadin, name);
+ printk("%s", name);
else
- printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+ printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
break;
case SERVICE_ACTION_OUT_12:
sa = cdbp[1] & 0x1f;
name = get_sa_name(serv_out12_arr, SERV_OUT12_SZ, sa);
if (name)
- printk("%s%s", leadin, name);
+ printk("%s", name);
else
- printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+ printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
break;
case SERVICE_ACTION_IN_16:
sa = cdbp[1] & 0x1f;
name = get_sa_name(serv_in16_arr, SERV_IN16_SZ, sa);
if (name)
- printk("%s%s", leadin, name);
+ printk("%s", name);
else
- printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+ printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
break;
case SERVICE_ACTION_OUT_16:
sa = cdbp[1] & 0x1f;
name = get_sa_name(serv_out16_arr, SERV_OUT16_SZ, sa);
if (name)
- printk("%s%s", leadin, name);
+ printk("%s", name);
else
- printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+ printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
break;
default:
if (cdb0 < 0xc0) {
name = cdb_byte0_names[cdb0];
if (name)
- printk("%s%s", leadin, name);
+ printk("%s", name);
else
- printk("%scdb[0]=0x%x (reserved)",
- leadin, cdb0);
+ printk("cdb[0]=0x%x (reserved)", cdb0);
} else
- printk("%scdb[0]=0x%x (vendor)", leadin, cdb0);
+ printk("cdb[0]=0x%x (vendor)", cdb0);
break;
}
}
#else /* ifndef CONFIG_SCSI_CONSTANTS */
-static void print_opcode_name(unsigned char * cdbp, int cdb_len,
- int start_of_line)
+static void print_opcode_name(unsigned char * cdbp, int cdb_len)
{
int sa, len, cdb0;
- const char * leadin = start_of_line ? KERN_INFO : "";
cdb0 = cdbp[0];
switch(cdb0) {
case VARIABLE_LENGTH_CMD:
len = cdbp[7] + 8;
if (len < 10) {
- printk("%sshort opcode=0x%x command, len=%d "
- "ext_len=%d", leadin, cdb0, len, cdb_len);
+ printk("short opcode=0x%x command, len=%d "
+ "ext_len=%d", cdb0, len, cdb_len);
break;
}
sa = (cdbp[8] << 8) + cdbp[9];
- printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+ printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
if (len != cdb_len)
printk(", in_cdb_len=%d, ext_len=%d", len, cdb_len);
break;
@@ -323,49 +318,48 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len,
case SERVICE_ACTION_IN_16:
case SERVICE_ACTION_OUT_16:
sa = cdbp[1] & 0x1f;
- printk("%scdb[0]=0x%x, sa=0x%x", leadin, cdb0, sa);
+ printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
break;
default:
if (cdb0 < 0xc0)
- printk("%scdb[0]=0x%x", leadin, cdb0);
+ printk("cdb[0]=0x%x", cdb0);
else
- printk("%scdb[0]=0x%x (vendor)", leadin, cdb0);
+ printk("cdb[0]=0x%x (vendor)", cdb0);
break;
}
}
#endif
-void __scsi_print_command(unsigned char *command)
+void __scsi_print_command(unsigned char *cdb)
{
int k, len;
- print_opcode_name(command, 0, 1);
- if (VARIABLE_LENGTH_CMD == command[0])
- len = command[7] + 8;
+ print_opcode_name(cdb, 0);
+ if (VARIABLE_LENGTH_CMD == cdb[0])
+ len = cdb[7] + 8;
else
- len = COMMAND_SIZE(command[0]);
+ len = COMMAND_SIZE(cdb[0]);
/* print out all bytes in cdb */
for (k = 0; k < len; ++k)
- printk(" %02x", command[k]);
+ printk(" %02x", cdb[k]);
printk("\n");
}
EXPORT_SYMBOL(__scsi_print_command);
-/* This function (perhaps with the addition of peripheral device type)
- * is more approriate than __scsi_print_command(). Perhaps that static
- * can be dropped later if it replaces the __scsi_print_command version.
- */
-static void scsi_print_cdb(unsigned char *cdb, int cdb_len, int start_of_line)
+void scsi_print_command(struct scsi_cmnd *cmd)
{
int k;
- print_opcode_name(cdb, cdb_len, start_of_line);
+ scmd_printk(KERN_INFO, cmd, "CDB: ");
+ print_opcode_name(cmd->cmnd, cmd->cmd_len);
+
/* print out all bytes in cdb */
printk(":");
- for (k = 0; k < cdb_len; ++k)
- printk(" %02x", cdb[k]);
+ for (k = 0; k < cmd->cmd_len; ++k)
+ printk(" %02x", cmd->cmnd[k]);
printk("\n");
}
+EXPORT_SYMBOL(scsi_print_command);
/**
*
@@ -410,7 +404,11 @@ struct error_info {
const char * text;
};
-static struct error_info additional[] =
+/*
+ * The canonical list of T10 Additional Sense Codes is available at:
+ * http://www.t10.org/lists/asc-num.txt
+ */
+static const struct error_info additional[] =
{
{0x0000, "No additional sense information"},
{0x0001, "Filemark detected"},
@@ -714,6 +712,7 @@ static struct error_info additional[] =
{0x2F00, "Commands cleared by another initiator"},
{0x2F01, "Commands cleared by power loss notification"},
+ {0x2F02, "Commands cleared by device server"},
{0x3000, "Incompatible medium installed"},
{0x3001, "Cannot read medium - unknown format"},
@@ -1176,67 +1175,77 @@ scsi_extd_sense_format(unsigned char asc, unsigned char ascq) {
}
EXPORT_SYMBOL(scsi_extd_sense_format);
-/* Print extended sense information; no leadin, no linefeed */
-static void
+void
scsi_show_extd_sense(unsigned char asc, unsigned char ascq)
{
- const char *extd_sense_fmt = scsi_extd_sense_format(asc, ascq);
+ const char *extd_sense_fmt = scsi_extd_sense_format(asc, ascq);
if (extd_sense_fmt) {
if (strstr(extd_sense_fmt, "%x")) {
- printk("Additional sense: ");
+ printk("Add. Sense: ");
printk(extd_sense_fmt, ascq);
} else
- printk("Additional sense: %s", extd_sense_fmt);
+ printk("Add. Sense: %s", extd_sense_fmt);
} else {
if (asc >= 0x80)
- printk("<<vendor>> ASC=0x%x ASCQ=0x%x", asc, ascq);
+ printk("<<vendor>> ASC=0x%x ASCQ=0x%x", asc,
+ ascq);
if (ascq >= 0x80)
- printk("ASC=0x%x <<vendor>> ASCQ=0x%x", asc, ascq);
+ printk("ASC=0x%x <<vendor>> ASCQ=0x%x", asc,
+ ascq);
else
printk("ASC=0x%x ASCQ=0x%x", asc, ascq);
}
+
+ printk("\n");
}
+EXPORT_SYMBOL(scsi_show_extd_sense);
void
-scsi_print_sense_hdr(const char *name, struct scsi_sense_hdr *sshdr)
+scsi_show_sense_hdr(struct scsi_sense_hdr *sshdr)
{
const char *sense_txt;
- /* An example of deferred is when an earlier write to disk cache
- * succeeded, but now the disk discovers that it cannot write the
- * data to the magnetic media.
- */
- const char *error = scsi_sense_is_deferred(sshdr) ?
- "<<DEFERRED>>" : "Current";
- printk(KERN_INFO "%s: %s", name, error);
- if (sshdr->response_code >= 0x72)
- printk(" [descriptor]");
sense_txt = scsi_sense_key_string(sshdr->sense_key);
if (sense_txt)
- printk(": sense key: %s\n", sense_txt);
+ printk("Sense Key : %s ", sense_txt);
else
- printk(": sense key=0x%x\n", sshdr->sense_key);
- printk(KERN_INFO " ");
- scsi_show_extd_sense(sshdr->asc, sshdr->ascq);
+ printk("Sense Key : 0x%x ", sshdr->sense_key);
+
+ printk("%s", scsi_sense_is_deferred(sshdr) ? "[deferred] " :
+ "[current] ");
+
+ if (sshdr->response_code >= 0x72)
+ printk("[descriptor]");
+
printk("\n");
}
+EXPORT_SYMBOL(scsi_show_sense_hdr);
+
+/*
+ * Print normalized SCSI sense header with a prefix.
+ */
+void
+scsi_print_sense_hdr(const char *name, struct scsi_sense_hdr *sshdr)
+{
+ printk(KERN_INFO "%s: ", name);
+ scsi_show_sense_hdr(sshdr);
+ printk(KERN_INFO "%s: ", name);
+ scsi_show_extd_sense(sshdr->asc, sshdr->ascq);
+}
EXPORT_SYMBOL(scsi_print_sense_hdr);
-/* Print sense information */
void
-__scsi_print_sense(const char *name, const unsigned char *sense_buffer,
- int sense_len)
+scsi_decode_sense_buffer(const unsigned char *sense_buffer, int sense_len,
+ struct scsi_sense_hdr *sshdr)
{
int k, num, res;
- unsigned int info;
- struct scsi_sense_hdr ssh;
- res = scsi_normalize_sense(sense_buffer, sense_len, &ssh);
+ res = scsi_normalize_sense(sense_buffer, sense_len, sshdr);
if (0 == res) {
/* this may be SCSI-1 sense data */
num = (sense_len < 32) ? sense_len : 32;
- printk(KERN_INFO "Unrecognized sense data (in hex):");
+ printk("Unrecognized sense data (in hex):");
for (k = 0; k < num; ++k) {
if (0 == (k % 16)) {
printk("\n");
@@ -1247,11 +1256,20 @@ __scsi_print_sense(const char *name, const unsigned char *sense_buffer,
printk("\n");
return;
}
- scsi_print_sense_hdr(name, &ssh);
- if (ssh.response_code < 0x72) {
+}
+
+void
+scsi_decode_sense_extras(const unsigned char *sense_buffer, int sense_len,
+ struct scsi_sense_hdr *sshdr)
+{
+ int k, num, res;
+
+ if (sshdr->response_code < 0x72)
+ {
/* only decode extras for "fixed" format now */
char buff[80];
int blen, fixed_valid;
+ unsigned int info;
fixed_valid = sense_buffer[0] & 0x80;
info = ((sense_buffer[3] << 24) | (sense_buffer[4] << 16) |
@@ -1281,13 +1299,13 @@ __scsi_print_sense(const char *name, const unsigned char *sense_buffer,
res += snprintf(buff + res, blen - res, "ILI");
}
if (res > 0)
- printk(KERN_INFO "%s\n", buff);
- } else if (ssh.additional_length > 0) {
+ printk("%s\n", buff);
+ } else if (sshdr->additional_length > 0) {
/* descriptor format with sense descriptors */
- num = 8 + ssh.additional_length;
+ num = 8 + sshdr->additional_length;
num = (sense_len < num) ? sense_len : num;
- printk(KERN_INFO "Descriptor sense data with sense "
- "descriptors (in hex):");
+ printk("Descriptor sense data with sense descriptors "
+ "(in hex):");
for (k = 0; k < num; ++k) {
if (0 == (k % 16)) {
printk("\n");
@@ -1295,29 +1313,42 @@ __scsi_print_sense(const char *name, const unsigned char *sense_buffer,
}
printk("%02x ", sense_buffer[k]);
}
+
printk("\n");
}
+
}
-EXPORT_SYMBOL(__scsi_print_sense);
-void scsi_print_sense(const char *devclass, struct scsi_cmnd *cmd)
+/* Normalize and print sense buffer with name prefix */
+void __scsi_print_sense(const char *name, const unsigned char *sense_buffer,
+ int sense_len)
{
- const char *name = devclass;
-
- if (cmd->request->rq_disk)
- name = cmd->request->rq_disk->disk_name;
- __scsi_print_sense(name, cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
+ struct scsi_sense_hdr sshdr;
+
+ printk(KERN_INFO "%s: ", name);
+ scsi_decode_sense_buffer(sense_buffer, sense_len, &sshdr);
+ scsi_show_sense_hdr(&sshdr);
+ scsi_decode_sense_extras(sense_buffer, sense_len, &sshdr);
+ printk(KERN_INFO "%s: ", name);
+ scsi_show_extd_sense(sshdr.asc, sshdr.ascq);
}
-EXPORT_SYMBOL(scsi_print_sense);
+EXPORT_SYMBOL(__scsi_print_sense);
-void scsi_print_command(struct scsi_cmnd *cmd)
+/* Normalize and print sense buffer in SCSI command */
+void scsi_print_sense(char *name, struct scsi_cmnd *cmd)
{
- /* Assume appended output (i.e. not at start of line) */
- sdev_printk("", cmd->device, "\n");
- printk(KERN_INFO " command: ");
- scsi_print_cdb(cmd->cmnd, cmd->cmd_len, 0);
+ struct scsi_sense_hdr sshdr;
+
+ scmd_printk(KERN_INFO, cmd, "");
+ scsi_decode_sense_buffer(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE,
+ &sshdr);
+ scsi_show_sense_hdr(&sshdr);
+ scsi_decode_sense_extras(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE,
+ &sshdr);
+ scmd_printk(KERN_INFO, cmd, "");
+ scsi_show_extd_sense(sshdr.asc, sshdr.ascq);
}
-EXPORT_SYMBOL(scsi_print_command);
+EXPORT_SYMBOL(scsi_print_sense);
#ifdef CONFIG_SCSI_CONSTANTS
@@ -1327,25 +1358,6 @@ static const char * const hostbyte_table[]={
"DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY"};
#define NUM_HOSTBYTE_STRS ARRAY_SIZE(hostbyte_table)
-void scsi_print_hostbyte(int scsiresult)
-{
- int hb = host_byte(scsiresult);
-
- printk("Hostbyte=0x%02x", hb);
- if (hb < NUM_HOSTBYTE_STRS)
- printk("(%s) ", hostbyte_table[hb]);
- else
- printk("is invalid ");
-}
-#else
-void scsi_print_hostbyte(int scsiresult)
-{
- printk("Hostbyte=0x%02x ", host_byte(scsiresult));
-}
-#endif
-
-#ifdef CONFIG_SCSI_CONSTANTS
-
static const char * const driverbyte_table[]={
"DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT", "DRIVER_MEDIA", "DRIVER_ERROR",
"DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD", "DRIVER_SENSE"};
@@ -1356,19 +1368,35 @@ static const char * const driversuggest_table[]={"SUGGEST_OK",
"SUGGEST_5", "SUGGEST_6", "SUGGEST_7", "SUGGEST_SENSE"};
#define NUM_SUGGEST_STRS ARRAY_SIZE(driversuggest_table)
-void scsi_print_driverbyte(int scsiresult)
+void scsi_show_result(int result)
{
- int dr = (driver_byte(scsiresult) & DRIVER_MASK);
- int su = ((driver_byte(scsiresult) & SUGGEST_MASK) >> 4);
+ int hb = host_byte(result);
+ int db = (driver_byte(result) & DRIVER_MASK);
+ int su = ((driver_byte(result) & SUGGEST_MASK) >> 4);
- printk("Driverbyte=0x%02x ", driver_byte(scsiresult));
- printk("(%s,%s) ",
- (dr < NUM_DRIVERBYTE_STRS ? driverbyte_table[dr] : "invalid"),
+ printk("Result: hostbyte=%s driverbyte=%s,%s\n",
+ (hb < NUM_HOSTBYTE_STRS ? hostbyte_table[hb] : "invalid"),
+ (db < NUM_DRIVERBYTE_STRS ? driverbyte_table[db] : "invalid"),
(su < NUM_SUGGEST_STRS ? driversuggest_table[su] : "invalid"));
}
+
#else
-void scsi_print_driverbyte(int scsiresult)
+
+void scsi_show_result(int result)
{
- printk("Driverbyte=0x%02x ", driver_byte(scsiresult));
+ printk("Result: hostbyte=0x%02x driverbyte=0x%02x\n",
+ host_byte(result), driver_byte(result));
}
+
#endif
+EXPORT_SYMBOL(scsi_show_result);
+
+
+void scsi_print_result(struct scsi_cmnd *cmd)
+{
+ scmd_printk(KERN_INFO, cmd, "");
+ scsi_show_result(cmd->result);
+}
+EXPORT_SYMBOL(scsi_print_result);
+
+
diff --git a/drivers/scsi/dpt/dpti_i2o.h b/drivers/scsi/dpt/dpti_i2o.h
index 5a49216fe4cf..100b49baca7f 100644
--- a/drivers/scsi/dpt/dpti_i2o.h
+++ b/drivers/scsi/dpt/dpti_i2o.h
@@ -31,7 +31,7 @@
* Tunable parameters first
*/
-/* How many different OSM's are we allowing */
+/* How many different OSM's are we allowing */
#define MAX_I2O_MODULES 64
#define I2O_EVT_CAPABILITY_OTHER 0x01
@@ -63,7 +63,7 @@ struct i2o_message
u16 size;
u32 target_tid:12;
u32 init_tid:12;
- u32 function:8;
+ u32 function:8;
u32 initiator_context;
/* List follows */
};
@@ -77,7 +77,7 @@ struct i2o_device
char dev_name[8]; /* linux /dev name if available */
i2o_lct_entry lct_data;/* Device LCT information */
- u32 flags;
+ u32 flags;
struct proc_dir_entry* proc_entry; /* /proc dir */
struct adpt_device *owner;
struct _adpt_hba *controller; /* Controlling IOP */
@@ -86,7 +86,7 @@ struct i2o_device
/*
* Each I2O controller has one of these objects
*/
-
+
struct i2o_controller
{
char name[16];
@@ -111,9 +111,9 @@ struct i2o_sys_tbl_entry
u32 iop_id:12;
u32 reserved2:20;
u16 seg_num:12;
- u16 i2o_version:4;
- u8 iop_state;
- u8 msg_type;
+ u16 i2o_version:4;
+ u8 iop_state;
+ u8 msg_type;
u16 frame_size;
u16 reserved3;
u32 last_changed;
@@ -124,14 +124,14 @@ struct i2o_sys_tbl_entry
struct i2o_sys_tbl
{
- u8 num_entries;
- u8 version;
- u16 reserved1;
+ u8 num_entries;
+ u8 version;
+ u16 reserved1;
u32 change_ind;
u32 reserved2;
u32 reserved3;
struct i2o_sys_tbl_entry iops[0];
-};
+};
/*
* I2O classes / subclasses
@@ -146,7 +146,7 @@ struct i2o_sys_tbl
/* Class code names
* (from v1.5 Table 6-1 Class Code Assignments.)
*/
-
+
#define I2O_CLASS_EXECUTIVE 0x000
#define I2O_CLASS_DDM 0x001
#define I2O_CLASS_RANDOM_BLOCK_STORAGE 0x010
@@ -166,7 +166,7 @@ struct i2o_sys_tbl
/* Rest of 0x092 - 0x09f reserved for peer-to-peer classes
*/
-
+
#define I2O_CLASS_MATCH_ANYCLASS 0xffffffff
/* Subclasses
@@ -175,7 +175,7 @@ struct i2o_sys_tbl
#define I2O_SUBCLASS_i960 0x001
#define I2O_SUBCLASS_HDM 0x020
#define I2O_SUBCLASS_ISM 0x021
-
+
/* Operation functions */
#define I2O_PARAMS_FIELD_GET 0x0001
@@ -219,7 +219,7 @@ struct i2o_sys_tbl
/*
* Messaging API values
*/
-
+
#define I2O_CMD_ADAPTER_ASSIGN 0xB3
#define I2O_CMD_ADAPTER_READ 0xB2
#define I2O_CMD_ADAPTER_RELEASE 0xB5
@@ -284,16 +284,16 @@ struct i2o_sys_tbl
#define I2O_PRIVATE_MSG 0xFF
/*
- * Init Outbound Q status
+ * Init Outbound Q status
*/
-
+
#define I2O_CMD_OUTBOUND_INIT_IN_PROGRESS 0x01
#define I2O_CMD_OUTBOUND_INIT_REJECTED 0x02
#define I2O_CMD_OUTBOUND_INIT_FAILED 0x03
#define I2O_CMD_OUTBOUND_INIT_COMPLETE 0x04
/*
- * I2O Get Status State values
+ * I2O Get Status State values
*/
#define ADAPTER_STATE_INITIALIZING 0x01
@@ -303,7 +303,7 @@ struct i2o_sys_tbl
#define ADAPTER_STATE_OPERATIONAL 0x08
#define ADAPTER_STATE_FAILED 0x10
#define ADAPTER_STATE_FAULTED 0x11
-
+
/* I2O API function return values */
#define I2O_RTN_NO_ERROR 0
@@ -321,9 +321,9 @@ struct i2o_sys_tbl
/* Reply message status defines for all messages */
-#define I2O_REPLY_STATUS_SUCCESS 0x00
-#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01
-#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02
+#define I2O_REPLY_STATUS_SUCCESS 0x00
+#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01
+#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02
#define I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER 0x03
#define I2O_REPLY_STATUS_ERROR_DIRTY 0x04
#define I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER 0x05
@@ -338,7 +338,7 @@ struct i2o_sys_tbl
#define I2O_PARAMS_STATUS_SUCCESS 0x00
#define I2O_PARAMS_STATUS_BAD_KEY_ABORT 0x01
-#define I2O_PARAMS_STATUS_BAD_KEY_CONTINUE 0x02
+#define I2O_PARAMS_STATUS_BAD_KEY_CONTINUE 0x02
#define I2O_PARAMS_STATUS_BUFFER_FULL 0x03
#define I2O_PARAMS_STATUS_BUFFER_TOO_SMALL 0x04
#define I2O_PARAMS_STATUS_FIELD_UNREADABLE 0x05
@@ -390,7 +390,7 @@ struct i2o_sys_tbl
#define I2O_CLAIM_MANAGEMENT 0x02000000
#define I2O_CLAIM_AUTHORIZED 0x03000000
#define I2O_CLAIM_SECONDARY 0x04000000
-
+
/* Message header defines for VersionOffset */
#define I2OVER15 0x0001
#define I2OVER20 0x0002
diff --git a/drivers/scsi/dpt/dpti_ioctl.h b/drivers/scsi/dpt/dpti_ioctl.h
index 82d24864be0c..cc784e8f6e9d 100644
--- a/drivers/scsi/dpt/dpti_ioctl.h
+++ b/drivers/scsi/dpt/dpti_ioctl.h
@@ -99,7 +99,7 @@ typedef struct {
uCHAR eataVersion; /* EATA Version */
uLONG cpLength; /* EATA Command Packet Length */
uLONG spLength; /* EATA Status Packet Length */
- uCHAR drqNum; /* DRQ Index (0,5,6,7) */
+ uCHAR drqNum; /* DRQ Index (0,5,6,7) */
uCHAR flag1; /* EATA Flags 1 (Byte 9) */
uCHAR flag2; /* EATA Flags 2 (Byte 30) */
} CtrlInfo;
diff --git a/drivers/scsi/dpt/dptsig.h b/drivers/scsi/dpt/dptsig.h
index 4bf447792129..94bc894d1200 100644
--- a/drivers/scsi/dpt/dptsig.h
+++ b/drivers/scsi/dpt/dptsig.h
@@ -145,8 +145,8 @@ typedef unsigned long sigLONG;
#define FT_LOGGER 12 /* Event Logger */
#define FT_INSTALL 13 /* An Install Program */
#define FT_LIBRARY 14 /* Storage Manager Real-Mode Calls */
-#define FT_RESOURCE 15 /* Storage Manager Resource File */
-#define FT_MODEM_DB 16 /* Storage Manager Modem Database */
+#define FT_RESOURCE 15 /* Storage Manager Resource File */
+#define FT_MODEM_DB 16 /* Storage Manager Modem Database */
/* Filetype flags - sigBYTE dsFiletypeFlags; FLAG BITS */
/* ------------------------------------------------------------------ */
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index cd36e81b2d93..f7b9dbd64a96 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -195,8 +195,6 @@ static int adpt_detect(struct scsi_host_template* sht)
pci_dev_get(pDev);
}
}
- if (pDev)
- pci_dev_put(pDev);
/* In INIT state, Activate IOPs */
for (pHba = hba_chain; pHba; pHba = pHba->next) {
diff --git a/drivers/scsi/eata_generic.h b/drivers/scsi/eata_generic.h
index 635c14861f86..5016af5cf860 100644
--- a/drivers/scsi/eata_generic.h
+++ b/drivers/scsi/eata_generic.h
@@ -18,13 +18,6 @@
* Misc. definitions *
*********************************************/
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-
#define R_LIMIT 0x20000
#define MAXISA 4
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index fbc1d5c3b0a7..b10eefe735c5 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -85,7 +85,7 @@
static int max_id = 64;
static int max_channel = 3;
static int init_timeout = 5;
-static int max_requests = 50;
+static int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT;
#define IBMVSCSI_VERSION "1.5.8"
@@ -538,7 +538,8 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
int request_status;
int rc;
- /* If we have exhausted our request limit, just fail this request.
+ /* If we have exhausted our request limit, just fail this request,
+ * unless it is for a reset or abort.
* Note that there are rare cases involving driver generated requests
* (such as task management requests) that the mid layer may think we
* can handle more requests (can_queue) when we actually can't
@@ -551,9 +552,30 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
*/
if (request_status < -1)
goto send_error;
- /* Otherwise, if we have run out of requests */
- else if (request_status < 0)
- goto send_busy;
+ /* Otherwise, we may have run out of requests. */
+ /* Abort and reset calls should make it through.
+ * Nothing except abort and reset should use the last two
+ * slots unless we had two or less to begin with.
+ */
+ else if (request_status < 2 &&
+ evt_struct->iu.srp.cmd.opcode != SRP_TSK_MGMT) {
+ /* In the case that we have less than two requests
+ * available, check the server limit as a combination
+ * of the request limit and the number of requests
+ * in-flight (the size of the send list). If the
+ * server limit is greater than 2, return busy so
+ * that the last two are reserved for reset and abort.
+ */
+ int server_limit = request_status;
+ struct srp_event_struct *tmp_evt;
+
+ list_for_each_entry(tmp_evt, &hostdata->sent, list) {
+ server_limit++;
+ }
+
+ if (server_limit > 2)
+ goto send_busy;
+ }
}
/* Copy the IU into the transfer area */
@@ -572,6 +594,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
printk(KERN_ERR "ibmvscsi: send error %d\n",
rc);
+ atomic_inc(&hostdata->request_limit);
goto send_error;
}
@@ -581,7 +604,8 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev);
free_event_struct(&hostdata->pool, evt_struct);
- return SCSI_MLQUEUE_HOST_BUSY;
+ atomic_inc(&hostdata->request_limit);
+ return SCSI_MLQUEUE_HOST_BUSY;
send_error:
unmap_cmd_data(&evt_struct->iu.srp.cmd, evt_struct, hostdata->dev);
@@ -831,23 +855,16 @@ static void login_rsp(struct srp_event_struct *evt_struct)
printk(KERN_INFO "ibmvscsi: SRP_LOGIN succeeded\n");
- if (evt_struct->xfer_iu->srp.login_rsp.req_lim_delta >
- (max_requests - 2))
- evt_struct->xfer_iu->srp.login_rsp.req_lim_delta =
- max_requests - 2;
+ if (evt_struct->xfer_iu->srp.login_rsp.req_lim_delta < 0)
+ printk(KERN_ERR "ibmvscsi: Invalid request_limit.\n");
- /* Now we know what the real request-limit is */
+ /* Now we know what the real request-limit is.
+ * This value is set rather than added to request_limit because
+ * request_limit could have been set to -1 by this client.
+ */
atomic_set(&hostdata->request_limit,
evt_struct->xfer_iu->srp.login_rsp.req_lim_delta);
- hostdata->host->can_queue =
- evt_struct->xfer_iu->srp.login_rsp.req_lim_delta - 2;
-
- if (hostdata->host->can_queue < 1) {
- printk(KERN_ERR "ibmvscsi: Invalid request_limit_delta\n");
- return;
- }
-
/* If we had any pending I/Os, kick them */
scsi_unblock_requests(hostdata->host);
@@ -1337,6 +1354,27 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata,
return rc;
}
+/**
+ * ibmvscsi_slave_configure: Set the "allow_restart" flag for each disk.
+ * @sdev: struct scsi_device device to configure
+ *
+ * Enable allow_restart for a device if it is a disk. Adjust the
+ * queue_depth here also as is required by the documentation for
+ * struct scsi_host_template.
+ */
+static int ibmvscsi_slave_configure(struct scsi_device *sdev)
+{
+ struct Scsi_Host *shost = sdev->host;
+ unsigned long lock_flags = 0;
+
+ spin_lock_irqsave(shost->host_lock, lock_flags);
+ if (sdev->type == TYPE_DISK)
+ sdev->allow_restart = 1;
+ scsi_adjust_queue_depth(sdev, 0, shost->cmd_per_lun);
+ spin_unlock_irqrestore(shost->host_lock, lock_flags);
+ return 0;
+}
+
/* ------------------------------------------------------------
* sysfs attributes
*/
@@ -1482,8 +1520,9 @@ static struct scsi_host_template driver_template = {
.queuecommand = ibmvscsi_queuecommand,
.eh_abort_handler = ibmvscsi_eh_abort_handler,
.eh_device_reset_handler = ibmvscsi_eh_device_reset_handler,
+ .slave_configure = ibmvscsi_slave_configure,
.cmd_per_lun = 16,
- .can_queue = 1, /* Updated after SRP_LOGIN */
+ .can_queue = IBMVSCSI_MAX_REQUESTS_DEFAULT,
.this_id = -1,
.sg_tablesize = SG_ALL,
.use_clustering = ENABLE_CLUSTERING,
@@ -1503,6 +1542,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
vdev->dev.driver_data = NULL;
+ driver_template.can_queue = max_requests;
host = scsi_host_alloc(&driver_template, sizeof(*hostdata));
if (!host) {
printk(KERN_ERR "ibmvscsi: couldn't allocate host data\n");
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
index 5c6d93582929..77cc1d40f5bb 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.h
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h
@@ -44,6 +44,8 @@ struct Scsi_Host;
*/
#define MAX_INDIRECT_BUFS 10
+#define IBMVSCSI_MAX_REQUESTS_DEFAULT 100
+
/* ------------------------------------------------------------
* Data Structures
*/
diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c
index a39a478bb39a..6d223dd76440 100644
--- a/drivers/scsi/ibmvscsi/ibmvstgt.c
+++ b/drivers/scsi/ibmvscsi/ibmvstgt.c
@@ -35,7 +35,7 @@
#include "ibmvscsi.h"
#define INITIAL_SRP_LIMIT 16
-#define DEFAULT_MAX_SECTORS 512
+#define DEFAULT_MAX_SECTORS 256
#define TGT_NAME "ibmvstgt"
@@ -248,8 +248,8 @@ static int ibmvstgt_rdma(struct scsi_cmnd *sc, struct scatterlist *sg, int nsg,
md[i].va + mdone);
if (err != H_SUCCESS) {
- eprintk("rdma error %d %d\n", dir, slen);
- goto out;
+ eprintk("rdma error %d %d %ld\n", dir, slen, err);
+ return -EIO;
}
mlen -= slen;
@@ -265,45 +265,35 @@ static int ibmvstgt_rdma(struct scsi_cmnd *sc, struct scatterlist *sg, int nsg,
if (sidx > nsg) {
eprintk("out of sg %p %d %d\n",
iue, sidx, nsg);
- goto out;
+ return -EIO;
}
}
};
rest -= mlen;
}
-out:
-
return 0;
}
-static int ibmvstgt_transfer_data(struct scsi_cmnd *sc,
- void (*done)(struct scsi_cmnd *))
-{
- struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr;
- int err;
-
- err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1);
-
- done(sc);
-
- return err;
-}
-
static int ibmvstgt_cmd_done(struct scsi_cmnd *sc,
void (*done)(struct scsi_cmnd *))
{
unsigned long flags;
struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr;
struct srp_target *target = iue->target;
+ int err = 0;
- dprintk("%p %p %x\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0]);
+ dprintk("%p %p %x %u\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0],
+ cmd->usg_sg);
+
+ if (sc->use_sg)
+ err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1);
spin_lock_irqsave(&target->lock, flags);
list_del(&iue->ilist);
spin_unlock_irqrestore(&target->lock, flags);
- if (sc->result != SAM_STAT_GOOD) {
+ if (err|| sc->result != SAM_STAT_GOOD) {
eprintk("operation failed %p %d %x\n",
iue, sc->result, vio_iu(iue)->srp.cmd.cdb[0]);
send_rsp(iue, sc, HARDWARE_ERROR, 0x00);
@@ -503,7 +493,8 @@ static void process_iu(struct viosrp_crq *crq, struct srp_target *target)
{
struct vio_port *vport = target_to_port(target);
struct iu_entry *iue;
- long err, done;
+ long err;
+ int done = 1;
iue = srp_iu_get(target);
if (!iue) {
@@ -518,7 +509,6 @@ static void process_iu(struct viosrp_crq *crq, struct srp_target *target)
if (err != H_SUCCESS) {
eprintk("%ld transferring data error %p\n", err, iue);
- done = 1;
goto out;
}
@@ -794,7 +784,6 @@ static struct scsi_host_template ibmvstgt_sht = {
.use_clustering = DISABLE_CLUSTERING,
.max_sectors = DEFAULT_MAX_SECTORS,
.transfer_response = ibmvstgt_cmd_done,
- .transfer_data = ibmvstgt_transfer_data,
.eh_abort_handler = ibmvstgt_eh_abort_handler,
.tsk_mgmt_response = ibmvstgt_tsk_mgmt_response,
.shost_attrs = ibmvstgt_attrs,
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index e9bd29975db4..2c7b77e833f9 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -89,10 +89,9 @@ static unsigned int ipr_log_level = IPR_DEFAULT_LOG_LEVEL;
static unsigned int ipr_max_speed = 1;
static int ipr_testmode = 0;
static unsigned int ipr_fastfail = 0;
-static unsigned int ipr_transop_timeout = IPR_OPERATIONAL_TIMEOUT;
+static unsigned int ipr_transop_timeout = 0;
static unsigned int ipr_enable_cache = 1;
static unsigned int ipr_debug = 0;
-static int ipr_auto_create = 1;
static DEFINE_SPINLOCK(ipr_driver_lock);
/* This table describes the differences between DMA controller chips */
@@ -159,15 +158,13 @@ module_param_named(enable_cache, ipr_enable_cache, int, 0);
MODULE_PARM_DESC(enable_cache, "Enable adapter's non-volatile write cache (default: 1)");
module_param_named(debug, ipr_debug, int, 0);
MODULE_PARM_DESC(debug, "Enable device driver debugging logging. Set to 1 to enable. (default: 0)");
-module_param_named(auto_create, ipr_auto_create, int, 0);
-MODULE_PARM_DESC(auto_create, "Auto-create single device RAID 0 arrays when initialized (default: 1)");
MODULE_LICENSE("GPL");
MODULE_VERSION(IPR_DRIVER_VERSION);
/* A constant array of IOASCs/URCs/Error Messages */
static const
struct ipr_error_table_t ipr_error_table[] = {
- {0x00000000, 1, 1,
+ {0x00000000, 1, IPR_DEFAULT_LOG_LEVEL,
"8155: An unknown error was received"},
{0x00330000, 0, 0,
"Soft underlength error"},
@@ -175,37 +172,37 @@ struct ipr_error_table_t ipr_error_table[] = {
"Command to be cancelled not found"},
{0x00808000, 0, 0,
"Qualified success"},
- {0x01080000, 1, 1,
+ {0x01080000, 1, IPR_DEFAULT_LOG_LEVEL,
"FFFE: Soft device bus error recovered by the IOA"},
- {0x01088100, 0, 1,
+ {0x01088100, 0, IPR_DEFAULT_LOG_LEVEL,
"4101: Soft device bus fabric error"},
- {0x01170600, 0, 1,
+ {0x01170600, 0, IPR_DEFAULT_LOG_LEVEL,
"FFF9: Device sector reassign successful"},
- {0x01170900, 0, 1,
+ {0x01170900, 0, IPR_DEFAULT_LOG_LEVEL,
"FFF7: Media error recovered by device rewrite procedures"},
- {0x01180200, 0, 1,
+ {0x01180200, 0, IPR_DEFAULT_LOG_LEVEL,
"7001: IOA sector reassignment successful"},
- {0x01180500, 0, 1,
+ {0x01180500, 0, IPR_DEFAULT_LOG_LEVEL,
"FFF9: Soft media error. Sector reassignment recommended"},
- {0x01180600, 0, 1,
+ {0x01180600, 0, IPR_DEFAULT_LOG_LEVEL,
"FFF7: Media error recovered by IOA rewrite procedures"},
- {0x01418000, 0, 1,
+ {0x01418000, 0, IPR_DEFAULT_LOG_LEVEL,
"FF3D: Soft PCI bus error recovered by the IOA"},
- {0x01440000, 1, 1,
+ {0x01440000, 1, IPR_DEFAULT_LOG_LEVEL,
"FFF6: Device hardware error recovered by the IOA"},
- {0x01448100, 0, 1,
+ {0x01448100, 0, IPR_DEFAULT_LOG_LEVEL,
"FFF6: Device hardware error recovered by the device"},
- {0x01448200, 1, 1,
+ {0x01448200, 1, IPR_DEFAULT_LOG_LEVEL,
"FF3D: Soft IOA error recovered by the IOA"},
- {0x01448300, 0, 1,
+ {0x01448300, 0, IPR_DEFAULT_LOG_LEVEL,
"FFFA: Undefined device response recovered by the IOA"},
- {0x014A0000, 1, 1,
+ {0x014A0000, 1, IPR_DEFAULT_LOG_LEVEL,
"FFF6: Device bus error, message or command phase"},
- {0x014A8000, 0, 1,
+ {0x014A8000, 0, IPR_DEFAULT_LOG_LEVEL,
"FFFE: Task Management Function failed"},
- {0x015D0000, 0, 1,
+ {0x015D0000, 0, IPR_DEFAULT_LOG_LEVEL,
"FFF6: Failure prediction threshold exceeded"},
- {0x015D9200, 0, 1,
+ {0x015D9200, 0, IPR_DEFAULT_LOG_LEVEL,
"8009: Impending cache battery pack failure"},
{0x02040400, 0, 0,
"34FF: Disk device format in progress"},
@@ -215,85 +212,85 @@ struct ipr_error_table_t ipr_error_table[] = {
"No ready, IOA shutdown"},
{0x025A0000, 0, 0,
"Not ready, IOA has been shutdown"},
- {0x02670100, 0, 1,
+ {0x02670100, 0, IPR_DEFAULT_LOG_LEVEL,
"3020: Storage subsystem configuration error"},
{0x03110B00, 0, 0,
"FFF5: Medium error, data unreadable, recommend reassign"},
{0x03110C00, 0, 0,
"7000: Medium error, data unreadable, do not reassign"},
- {0x03310000, 0, 1,
+ {0x03310000, 0, IPR_DEFAULT_LOG_LEVEL,
"FFF3: Disk media format bad"},
- {0x04050000, 0, 1,
+ {0x04050000, 0, IPR_DEFAULT_LOG_LEVEL,
"3002: Addressed device failed to respond to selection"},
- {0x04080000, 1, 1,
+ {0x04080000, 1, IPR_DEFAULT_LOG_LEVEL,
"3100: Device bus error"},
- {0x04080100, 0, 1,
+ {0x04080100, 0, IPR_DEFAULT_LOG_LEVEL,
"3109: IOA timed out a device command"},
{0x04088000, 0, 0,
"3120: SCSI bus is not operational"},
- {0x04088100, 0, 1,
+ {0x04088100, 0, IPR_DEFAULT_LOG_LEVEL,
"4100: Hard device bus fabric error"},
- {0x04118000, 0, 1,
+ {0x04118000, 0, IPR_DEFAULT_LOG_LEVEL,
"9000: IOA reserved area data check"},
- {0x04118100, 0, 1,
+ {0x04118100, 0, IPR_DEFAULT_LOG_LEVEL,
"9001: IOA reserved area invalid data pattern"},
- {0x04118200, 0, 1,
+ {0x04118200, 0, IPR_DEFAULT_LOG_LEVEL,
"9002: IOA reserved area LRC error"},
- {0x04320000, 0, 1,
+ {0x04320000, 0, IPR_DEFAULT_LOG_LEVEL,
"102E: Out of alternate sectors for disk storage"},
- {0x04330000, 1, 1,
+ {0x04330000, 1, IPR_DEFAULT_LOG_LEVEL,
"FFF4: Data transfer underlength error"},
- {0x04338000, 1, 1,
+ {0x04338000, 1, IPR_DEFAULT_LOG_LEVEL,
"FFF4: Data transfer overlength error"},
- {0x043E0100, 0, 1,
+ {0x043E0100, 0, IPR_DEFAULT_LOG_LEVEL,
"3400: Logical unit failure"},
- {0x04408500, 0, 1,
+ {0x04408500, 0, IPR_DEFAULT_LOG_LEVEL,
"FFF4: Device microcode is corrupt"},
- {0x04418000, 1, 1,
+ {0x04418000, 1, IPR_DEFAULT_LOG_LEVEL,
"8150: PCI bus error"},
{0x04430000, 1, 0,
"Unsupported device bus message received"},
- {0x04440000, 1, 1,
+ {0x04440000, 1, IPR_DEFAULT_LOG_LEVEL,
"FFF4: Disk device problem"},
- {0x04448200, 1, 1,
+ {0x04448200, 1, IPR_DEFAULT_LOG_LEVEL,
"8150: Permanent IOA failure"},
- {0x04448300, 0, 1,
+ {0x04448300, 0, IPR_DEFAULT_LOG_LEVEL,
"3010: Disk device returned wrong response to IOA"},
- {0x04448400, 0, 1,
+ {0x04448400, 0, IPR_DEFAULT_LOG_LEVEL,
"8151: IOA microcode error"},
{0x04448500, 0, 0,
"Device bus status error"},
- {0x04448600, 0, 1,
+ {0x04448600, 0, IPR_DEFAULT_LOG_LEVEL,
"8157: IOA error requiring IOA reset to recover"},
{0x04448700, 0, 0,
"ATA device status error"},
{0x04490000, 0, 0,
"Message reject received from the device"},
- {0x04449200, 0, 1,
+ {0x04449200, 0, IPR_DEFAULT_LOG_LEVEL,
"8008: A permanent cache battery pack failure occurred"},
- {0x0444A000, 0, 1,
+ {0x0444A000, 0, IPR_DEFAULT_LOG_LEVEL,
"9090: Disk unit has been modified after the last known status"},
- {0x0444A200, 0, 1,
+ {0x0444A200, 0, IPR_DEFAULT_LOG_LEVEL,
"9081: IOA detected device error"},
- {0x0444A300, 0, 1,
+ {0x0444A300, 0, IPR_DEFAULT_LOG_LEVEL,
"9082: IOA detected device error"},
- {0x044A0000, 1, 1,
+ {0x044A0000, 1, IPR_DEFAULT_LOG_LEVEL,
"3110: Device bus error, message or command phase"},
- {0x044A8000, 1, 1,
+ {0x044A8000, 1, IPR_DEFAULT_LOG_LEVEL,
"3110: SAS Command / Task Management Function failed"},
- {0x04670400, 0, 1,
+ {0x04670400, 0, IPR_DEFAULT_LOG_LEVEL,
"9091: Incorrect hardware configuration change has been detected"},
- {0x04678000, 0, 1,
+ {0x04678000, 0, IPR_DEFAULT_LOG_LEVEL,
"9073: Invalid multi-adapter configuration"},
- {0x04678100, 0, 1,
+ {0x04678100, 0, IPR_DEFAULT_LOG_LEVEL,
"4010: Incorrect connection between cascaded expanders"},
- {0x04678200, 0, 1,
+ {0x04678200, 0, IPR_DEFAULT_LOG_LEVEL,
"4020: Connections exceed IOA design limits"},
- {0x04678300, 0, 1,
+ {0x04678300, 0, IPR_DEFAULT_LOG_LEVEL,
"4030: Incorrect multipath connection"},
- {0x04679000, 0, 1,
+ {0x04679000, 0, IPR_DEFAULT_LOG_LEVEL,
"4110: Unsupported enclosure function"},
- {0x046E0000, 0, 1,
+ {0x046E0000, 0, IPR_DEFAULT_LOG_LEVEL,
"FFF4: Command to logical unit failed"},
{0x05240000, 1, 0,
"Illegal request, invalid request type or request packet"},
@@ -313,101 +310,103 @@ struct ipr_error_table_t ipr_error_table[] = {
"Illegal request, command sequence error"},
{0x052C8000, 1, 0,
"Illegal request, dual adapter support not enabled"},
- {0x06040500, 0, 1,
+ {0x06040500, 0, IPR_DEFAULT_LOG_LEVEL,
"9031: Array protection temporarily suspended, protection resuming"},
- {0x06040600, 0, 1,
+ {0x06040600, 0, IPR_DEFAULT_LOG_LEVEL,
"9040: Array protection temporarily suspended, protection resuming"},
- {0x06288000, 0, 1,
+ {0x06288000, 0, IPR_DEFAULT_LOG_LEVEL,
"3140: Device bus not ready to ready transition"},
- {0x06290000, 0, 1,
+ {0x06290000, 0, IPR_DEFAULT_LOG_LEVEL,
"FFFB: SCSI bus was reset"},
{0x06290500, 0, 0,
"FFFE: SCSI bus transition to single ended"},
{0x06290600, 0, 0,
"FFFE: SCSI bus transition to LVD"},
- {0x06298000, 0, 1,
+ {0x06298000, 0, IPR_DEFAULT_LOG_LEVEL,
"FFFB: SCSI bus was reset by another initiator"},
- {0x063F0300, 0, 1,
+ {0x063F0300, 0, IPR_DEFAULT_LOG_LEVEL,
"3029: A device replacement has occurred"},
- {0x064C8000, 0, 1,
+ {0x064C8000, 0, IPR_DEFAULT_LOG_LEVEL,
"9051: IOA cache data exists for a missing or failed device"},
- {0x064C8100, 0, 1,
+ {0x064C8100, 0, IPR_DEFAULT_LOG_LEVEL,
"9055: Auxiliary cache IOA contains cache data needed by the primary IOA"},
- {0x06670100, 0, 1,
+ {0x06670100, 0, IPR_DEFAULT_LOG_LEVEL,
"9025: Disk unit is not supported at its physical location"},
- {0x06670600, 0, 1,
+ {0x06670600, 0, IPR_DEFAULT_LOG_LEVEL,
"3020: IOA detected a SCSI bus configuration error"},
- {0x06678000, 0, 1,
+ {0x06678000, 0, IPR_DEFAULT_LOG_LEVEL,
"3150: SCSI bus configuration error"},
- {0x06678100, 0, 1,
+ {0x06678100, 0, IPR_DEFAULT_LOG_LEVEL,
"9074: Asymmetric advanced function disk configuration"},
- {0x06678300, 0, 1,
+ {0x06678300, 0, IPR_DEFAULT_LOG_LEVEL,
"4040: Incomplete multipath connection between IOA and enclosure"},
- {0x06678400, 0, 1,
+ {0x06678400, 0, IPR_DEFAULT_LOG_LEVEL,
"4041: Incomplete multipath connection between enclosure and device"},
- {0x06678500, 0, 1,
+ {0x06678500, 0, IPR_DEFAULT_LOG_LEVEL,
"9075: Incomplete multipath connection between IOA and remote IOA"},
- {0x06678600, 0, 1,
+ {0x06678600, 0, IPR_DEFAULT_LOG_LEVEL,
"9076: Configuration error, missing remote IOA"},
- {0x06679100, 0, 1,
+ {0x06679100, 0, IPR_DEFAULT_LOG_LEVEL,
"4050: Enclosure does not support a required multipath function"},
- {0x06690200, 0, 1,
+ {0x06690200, 0, IPR_DEFAULT_LOG_LEVEL,
"9041: Array protection temporarily suspended"},
- {0x06698200, 0, 1,
+ {0x06698200, 0, IPR_DEFAULT_LOG_LEVEL,
"9042: Corrupt array parity detected on specified device"},
- {0x066B0200, 0, 1,
+ {0x066B0200, 0, IPR_DEFAULT_LOG_LEVEL,
"9030: Array no longer protected due to missing or failed disk unit"},
- {0x066B8000, 0, 1,
+ {0x066B8000, 0, IPR_DEFAULT_LOG_LEVEL,
"9071: Link operational transition"},
- {0x066B8100, 0, 1,
+ {0x066B8100, 0, IPR_DEFAULT_LOG_LEVEL,
"9072: Link not operational transition"},
- {0x066B8200, 0, 1,
+ {0x066B8200, 0, IPR_DEFAULT_LOG_LEVEL,
"9032: Array exposed but still protected"},
- {0x066B9100, 0, 1,
+ {0x066B8300, 0, IPR_DEFAULT_LOG_LEVEL + 1,
+ "70DD: Device forced failed by disrupt device command"},
+ {0x066B9100, 0, IPR_DEFAULT_LOG_LEVEL,
"4061: Multipath redundancy level got better"},
- {0x066B9200, 0, 1,
+ {0x066B9200, 0, IPR_DEFAULT_LOG_LEVEL,
"4060: Multipath redundancy level got worse"},
{0x07270000, 0, 0,
"Failure due to other device"},
- {0x07278000, 0, 1,
+ {0x07278000, 0, IPR_DEFAULT_LOG_LEVEL,
"9008: IOA does not support functions expected by devices"},
- {0x07278100, 0, 1,
+ {0x07278100, 0, IPR_DEFAULT_LOG_LEVEL,
"9010: Cache data associated with attached devices cannot be found"},
- {0x07278200, 0, 1,
+ {0x07278200, 0, IPR_DEFAULT_LOG_LEVEL,
"9011: Cache data belongs to devices other than those attached"},
- {0x07278400, 0, 1,
+ {0x07278400, 0, IPR_DEFAULT_LOG_LEVEL,
"9020: Array missing 2 or more devices with only 1 device present"},
- {0x07278500, 0, 1,
+ {0x07278500, 0, IPR_DEFAULT_LOG_LEVEL,
"9021: Array missing 2 or more devices with 2 or more devices present"},
- {0x07278600, 0, 1,
+ {0x07278600, 0, IPR_DEFAULT_LOG_LEVEL,
"9022: Exposed array is missing a required device"},
- {0x07278700, 0, 1,
+ {0x07278700, 0, IPR_DEFAULT_LOG_LEVEL,
"9023: Array member(s) not at required physical locations"},
- {0x07278800, 0, 1,
+ {0x07278800, 0, IPR_DEFAULT_LOG_LEVEL,
"9024: Array not functional due to present hardware configuration"},
- {0x07278900, 0, 1,
+ {0x07278900, 0, IPR_DEFAULT_LOG_LEVEL,
"9026: Array not functional due to present hardware configuration"},
- {0x07278A00, 0, 1,
+ {0x07278A00, 0, IPR_DEFAULT_LOG_LEVEL,
"9027: Array is missing a device and parity is out of sync"},
- {0x07278B00, 0, 1,
+ {0x07278B00, 0, IPR_DEFAULT_LOG_LEVEL,
"9028: Maximum number of arrays already exist"},
- {0x07278C00, 0, 1,
+ {0x07278C00, 0, IPR_DEFAULT_LOG_LEVEL,
"9050: Required cache data cannot be located for a disk unit"},
- {0x07278D00, 0, 1,
+ {0x07278D00, 0, IPR_DEFAULT_LOG_LEVEL,
"9052: Cache data exists for a device that has been modified"},
- {0x07278F00, 0, 1,
+ {0x07278F00, 0, IPR_DEFAULT_LOG_LEVEL,
"9054: IOA resources not available due to previous problems"},
- {0x07279100, 0, 1,
+ {0x07279100, 0, IPR_DEFAULT_LOG_LEVEL,
"9092: Disk unit requires initialization before use"},
- {0x07279200, 0, 1,
+ {0x07279200, 0, IPR_DEFAULT_LOG_LEVEL,
"9029: Incorrect hardware configuration change has been detected"},
- {0x07279600, 0, 1,
+ {0x07279600, 0, IPR_DEFAULT_LOG_LEVEL,
"9060: One or more disk pairs are missing from an array"},
- {0x07279700, 0, 1,
+ {0x07279700, 0, IPR_DEFAULT_LOG_LEVEL,
"9061: One or more disks are missing from an array"},
- {0x07279800, 0, 1,
+ {0x07279800, 0, IPR_DEFAULT_LOG_LEVEL,
"9062: One or more disks are missing from an array"},
- {0x07279900, 0, 1,
+ {0x07279900, 0, IPR_DEFAULT_LOG_LEVEL,
"9063: Maximum number of functional arrays has been exceeded"},
{0x0B260000, 0, 0,
"Aborted command, invalid descriptor"},
@@ -481,12 +480,16 @@ static void ipr_reinit_ipr_cmnd(struct ipr_cmnd *ipr_cmd)
{
struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
struct ipr_ioasa *ioasa = &ipr_cmd->ioasa;
+ dma_addr_t dma_addr = be32_to_cpu(ioarcb->ioarcb_host_pci_addr);
memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt));
ioarcb->write_data_transfer_length = 0;
ioarcb->read_data_transfer_length = 0;
ioarcb->write_ioadl_len = 0;
ioarcb->read_ioadl_len = 0;
+ ioarcb->write_ioadl_addr =
+ cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, ioadl));
+ ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
ioasa->ioasc = 0;
ioasa->residual_data_len = 0;
ioasa->u.gata.status = 0;
@@ -1610,7 +1613,7 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg,
/* Set indication we have logged an error */
ioa_cfg->errors_logged++;
- if (ioa_cfg->log_level < IPR_DEFAULT_LOG_LEVEL)
+ if (ioa_cfg->log_level < ipr_error_table[error_index].log_hcam)
return;
if (be32_to_cpu(hostrcb->hcam.length) > sizeof(hostrcb->hcam.u.raw))
hostrcb->hcam.length = cpu_to_be32(sizeof(hostrcb->hcam.u.raw));
@@ -3850,6 +3853,8 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd)
if (ipr_cmd->ioarcb.res_handle == res->cfgte.res_handle) {
if (ipr_cmd->scsi_cmd)
ipr_cmd->done = ipr_scsi_eh_done;
+ if (ipr_cmd->qc)
+ ipr_cmd->done = ipr_sata_eh_done;
if (ipr_cmd->qc && !(ipr_cmd->qc->flags & ATA_QCFLAG_FAILED)) {
ipr_cmd->qc->err_mask |= AC_ERR_TIMEOUT;
ipr_cmd->qc->flags |= ATA_QCFLAG_FAILED;
@@ -4230,6 +4235,14 @@ static int ipr_build_ioadl(struct ipr_ioa_cfg *ioa_cfg,
sglist = scsi_cmd->request_buffer;
+ if (ipr_cmd->dma_use_sg <= ARRAY_SIZE(ioarcb->add_data.u.ioadl)) {
+ ioadl = ioarcb->add_data.u.ioadl;
+ ioarcb->write_ioadl_addr =
+ cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) +
+ offsetof(struct ipr_ioarcb, add_data));
+ ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
+ }
+
for (i = 0; i < ipr_cmd->dma_use_sg; i++) {
ioadl[i].flags_and_data_len =
cpu_to_be32(ioadl_flags | sg_dma_len(&sglist[i]));
@@ -4260,6 +4273,11 @@ static int ipr_build_ioadl(struct ipr_ioa_cfg *ioa_cfg,
scsi_cmd->sc_data_direction);
if (likely(!pci_dma_mapping_error(ipr_cmd->dma_handle))) {
+ ioadl = ioarcb->add_data.u.ioadl;
+ ioarcb->write_ioadl_addr =
+ cpu_to_be32(be32_to_cpu(ioarcb->ioarcb_host_pci_addr) +
+ offsetof(struct ipr_ioarcb, add_data));
+ ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
ipr_cmd->dma_use_sg = 1;
ioadl[0].flags_and_data_len =
cpu_to_be32(ioadl_flags | length | IPR_IOADL_FLAGS_LAST);
@@ -4346,11 +4364,9 @@ static void ipr_erp_done(struct ipr_cmnd *ipr_cmd)
**/
static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd)
{
- struct ipr_ioarcb *ioarcb;
- struct ipr_ioasa *ioasa;
-
- ioarcb = &ipr_cmd->ioarcb;
- ioasa = &ipr_cmd->ioasa;
+ struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
+ struct ipr_ioasa *ioasa = &ipr_cmd->ioasa;
+ dma_addr_t dma_addr = be32_to_cpu(ioarcb->ioarcb_host_pci_addr);
memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt));
ioarcb->write_data_transfer_length = 0;
@@ -4359,6 +4375,9 @@ static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd)
ioarcb->read_ioadl_len = 0;
ioasa->ioasc = 0;
ioasa->residual_data_len = 0;
+ ioarcb->write_ioadl_addr =
+ cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, ioadl));
+ ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
}
/**
@@ -4457,12 +4476,13 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg,
{
int i;
u16 data_len;
- u32 ioasc;
+ u32 ioasc, fd_ioasc;
struct ipr_ioasa *ioasa = &ipr_cmd->ioasa;
__be32 *ioasa_data = (__be32 *)ioasa;
int error_index;
ioasc = be32_to_cpu(ioasa->ioasc) & IPR_IOASC_IOASC_MASK;
+ fd_ioasc = be32_to_cpu(ioasa->fd_ioasc) & IPR_IOASC_IOASC_MASK;
if (0 == ioasc)
return;
@@ -4470,13 +4490,19 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg,
if (ioa_cfg->log_level < IPR_DEFAULT_LOG_LEVEL)
return;
- error_index = ipr_get_error(ioasc);
+ if (ioasc == IPR_IOASC_BUS_WAS_RESET && fd_ioasc)
+ error_index = ipr_get_error(fd_ioasc);
+ else
+ error_index = ipr_get_error(ioasc);
if (ioa_cfg->log_level < IPR_MAX_LOG_LEVEL) {
/* Don't log an error if the IOA already logged one */
if (ioasa->ilid != 0)
return;
+ if (!ipr_is_gscsi(res))
+ return;
+
if (ipr_error_table[error_index].log_ioasa == 0)
return;
}
@@ -4636,11 +4662,11 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg,
return;
}
- if (ipr_is_gscsi(res))
- ipr_dump_ioasa(ioa_cfg, ipr_cmd, res);
- else
+ if (!ipr_is_gscsi(res))
ipr_gen_sense(ipr_cmd);
+ ipr_dump_ioasa(ioa_cfg, ipr_cmd, res);
+
switch (ioasc & IPR_IOASC_IOASC_MASK) {
case IPR_IOASC_ABORTED_CMD_TERM_BY_HOST:
if (ipr_is_naca_model(res))
@@ -5121,7 +5147,7 @@ static unsigned int ipr_qc_issue(struct ata_queued_cmd *qc)
struct ipr_ioarcb_ata_regs *regs;
if (unlikely(!ioa_cfg->allow_cmds || ioa_cfg->ioa_is_dead))
- return -EIO;
+ return AC_ERR_SYSTEM;
ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
ioarcb = &ipr_cmd->ioarcb;
@@ -5166,7 +5192,7 @@ static unsigned int ipr_qc_issue(struct ata_queued_cmd *qc)
default:
WARN_ON(1);
- return -1;
+ return AC_ERR_INVALID;
}
mb();
@@ -6188,7 +6214,7 @@ static int ipr_reset_enable_ioa(struct ipr_cmnd *ipr_cmd)
dev_info(&ioa_cfg->pdev->dev, "Initializing IOA.\n");
ipr_cmd->timer.data = (unsigned long) ipr_cmd;
- ipr_cmd->timer.expires = jiffies + (ipr_transop_timeout * HZ);
+ ipr_cmd->timer.expires = jiffies + (ioa_cfg->transop_timeout * HZ);
ipr_cmd->timer.function = (void (*)(unsigned long))ipr_oper_timeout;
ipr_cmd->done = ipr_reset_ioa_job;
add_timer(&ipr_cmd->timer);
@@ -6385,6 +6411,7 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd)
rc = pci_write_config_byte(ioa_cfg->pdev, PCI_BIST, PCI_BIST_START);
if (rc != PCIBIOS_SUCCESSFUL) {
+ pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev);
ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR);
rc = IPR_RC_JOB_CONTINUE;
} else {
@@ -7117,8 +7144,6 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg,
ioa_cfg->pdev = pdev;
ioa_cfg->log_level = ipr_log_level;
ioa_cfg->doorbell = IPR_DOORBELL;
- if (!ipr_auto_create)
- ioa_cfg->doorbell |= IPR_RUNTIME_RESET;
sprintf(ioa_cfg->eye_catcher, IPR_EYECATCHER);
sprintf(ioa_cfg->trace_start, IPR_TRACE_START_LABEL);
sprintf(ioa_cfg->ipr_free_label, IPR_FREEQ_LABEL);
@@ -7233,6 +7258,13 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
goto out_scsi_host_put;
}
+ if (ipr_transop_timeout)
+ ioa_cfg->transop_timeout = ipr_transop_timeout;
+ else if (dev_id->driver_data & IPR_USE_LONG_TRANSOP_TIMEOUT)
+ ioa_cfg->transop_timeout = IPR_LONG_OPERATIONAL_TIMEOUT;
+ else
+ ioa_cfg->transop_timeout = IPR_OPERATIONAL_TIMEOUT;
+
ipr_regs_pci = pci_resource_start(pdev, 0);
rc = pci_request_regions(pdev, IPR_NAME);
@@ -7540,29 +7572,45 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = {
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571A, 0, 0, 0 },
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE,
- PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575B, 0, 0, 0 },
+ PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575B, 0, 0,
+ IPR_USE_LONG_TRANSOP_TIMEOUT },
{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, 0 },
{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 },
{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
- PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, 0 },
+ PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0,
+ IPR_USE_LONG_TRANSOP_TIMEOUT },
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, 0 },
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 },
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
- PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0, 0 },
+ PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0,
+ IPR_USE_LONG_TRANSOP_TIMEOUT },
+ { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
+ PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_574E, 0, 0, 0 },
+ { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
+ PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575D, 0, 0,
+ IPR_USE_LONG_TRANSOP_TIMEOUT },
+ { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
+ PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B3, 0, 0, 0 },
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
- PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0, 0 },
+ PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0,
+ IPR_USE_LONG_TRANSOP_TIMEOUT },
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780, 0, 0, 0 },
{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571E, 0, 0, 0 },
{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP,
- PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F, 0, 0, 0 },
+ PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F, 0, 0,
+ IPR_USE_LONG_TRANSOP_TIMEOUT },
{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP,
- PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F, 0, 0, 0 },
+ PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F, 0, 0,
+ IPR_USE_LONG_TRANSOP_TIMEOUT },
+ { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SCAMP_E,
+ PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_574D, 0, 0,
+ IPR_USE_LONG_TRANSOP_TIMEOUT },
{ }
};
MODULE_DEVICE_TABLE(pci, ipr_pci_table);
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 88f285de97bb..bc53d7cebe0a 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -37,8 +37,8 @@
/*
* Literals
*/
-#define IPR_DRIVER_VERSION "2.3.1"
-#define IPR_DRIVER_DATE "(January 23, 2007)"
+#define IPR_DRIVER_VERSION "2.3.2"
+#define IPR_DRIVER_DATE "(March 23, 2007)"
/*
* IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
@@ -55,6 +55,7 @@
#define IPR_NUM_BASE_CMD_BLKS 100
#define PCI_DEVICE_ID_IBM_OBSIDIAN_E 0x0339
+#define PCI_DEVICE_ID_IBM_SCAMP_E 0x034A
#define IPR_SUBS_DEV_ID_2780 0x0264
#define IPR_SUBS_DEV_ID_5702 0x0266
@@ -69,8 +70,12 @@
#define IPR_SUBS_DEV_ID_572A 0x02C1
#define IPR_SUBS_DEV_ID_572B 0x02C2
#define IPR_SUBS_DEV_ID_572F 0x02C3
+#define IPR_SUBS_DEV_ID_574D 0x030B
+#define IPR_SUBS_DEV_ID_574E 0x030A
#define IPR_SUBS_DEV_ID_575B 0x030D
#define IPR_SUBS_DEV_ID_575C 0x0338
+#define IPR_SUBS_DEV_ID_575D 0x033E
+#define IPR_SUBS_DEV_ID_57B3 0x033A
#define IPR_SUBS_DEV_ID_57B7 0x0360
#define IPR_SUBS_DEV_ID_57B8 0x02C2
@@ -104,6 +109,9 @@
#define IPR_IOASC_IOA_WAS_RESET 0x10000001
#define IPR_IOASC_PCI_ACCESS_ERROR 0x10000002
+/* Driver data flags */
+#define IPR_USE_LONG_TRANSOP_TIMEOUT 0x00000001
+
#define IPR_DEFAULT_MAX_ERROR_DUMP 984
#define IPR_NUM_LOG_HCAMS 2
#define IPR_NUM_CFG_CHG_HCAMS 2
@@ -179,6 +187,7 @@
#define IPR_SET_SUP_DEVICE_TIMEOUT (2 * 60 * HZ)
#define IPR_REQUEST_SENSE_TIMEOUT (10 * HZ)
#define IPR_OPERATIONAL_TIMEOUT (5 * 60)
+#define IPR_LONG_OPERATIONAL_TIMEOUT (12 * 60)
#define IPR_WAIT_FOR_RESET_TIMEOUT (2 * HZ)
#define IPR_CHECK_FOR_RESET_TIMEOUT (HZ / 10)
#define IPR_WAIT_FOR_BIST_TIMEOUT (2 * HZ)
@@ -413,9 +422,25 @@ struct ipr_ioarcb_ata_regs {
u8 ctl;
}__attribute__ ((packed, aligned(4)));
+struct ipr_ioadl_desc {
+ __be32 flags_and_data_len;
+#define IPR_IOADL_FLAGS_MASK 0xff000000
+#define IPR_IOADL_GET_FLAGS(x) (be32_to_cpu(x) & IPR_IOADL_FLAGS_MASK)
+#define IPR_IOADL_DATA_LEN_MASK 0x00ffffff
+#define IPR_IOADL_GET_DATA_LEN(x) (be32_to_cpu(x) & IPR_IOADL_DATA_LEN_MASK)
+#define IPR_IOADL_FLAGS_READ 0x48000000
+#define IPR_IOADL_FLAGS_READ_LAST 0x49000000
+#define IPR_IOADL_FLAGS_WRITE 0x68000000
+#define IPR_IOADL_FLAGS_WRITE_LAST 0x69000000
+#define IPR_IOADL_FLAGS_LAST 0x01000000
+
+ __be32 address;
+}__attribute__((packed, aligned (8)));
+
struct ipr_ioarcb_add_data {
union {
struct ipr_ioarcb_ata_regs regs;
+ struct ipr_ioadl_desc ioadl[5];
__be32 add_cmd_parms[10];
}u;
}__attribute__ ((packed, aligned(4)));
@@ -447,21 +472,6 @@ struct ipr_ioarcb {
struct ipr_ioarcb_add_data add_data;
}__attribute__((packed, aligned (4)));
-struct ipr_ioadl_desc {
- __be32 flags_and_data_len;
-#define IPR_IOADL_FLAGS_MASK 0xff000000
-#define IPR_IOADL_GET_FLAGS(x) (be32_to_cpu(x) & IPR_IOADL_FLAGS_MASK)
-#define IPR_IOADL_DATA_LEN_MASK 0x00ffffff
-#define IPR_IOADL_GET_DATA_LEN(x) (be32_to_cpu(x) & IPR_IOADL_DATA_LEN_MASK)
-#define IPR_IOADL_FLAGS_READ 0x48000000
-#define IPR_IOADL_FLAGS_READ_LAST 0x49000000
-#define IPR_IOADL_FLAGS_WRITE 0x68000000
-#define IPR_IOADL_FLAGS_WRITE_LAST 0x69000000
-#define IPR_IOADL_FLAGS_LAST 0x01000000
-
- __be32 address;
-}__attribute__((packed, aligned (8)));
-
struct ipr_ioasa_vset {
__be32 failing_lba_hi;
__be32 failing_lba_lo;
@@ -1119,6 +1129,7 @@ struct ipr_ioa_cfg {
struct ipr_bus_attributes bus_attr[IPR_MAX_NUM_BUSES];
+ unsigned int transop_timeout;
const struct ipr_chip_cfg_t *chip_cfg;
void __iomem *hdw_dma_regs; /* iomapped PCI memory space */
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 8f55e1431433..c9a3abf9e7b6 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -527,12 +527,12 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn)
* than 8K, but there are no targets that currently do this.
* For now we fail until we find a vendor that needs it
*/
- if (DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH <
+ if (ISCSI_DEF_MAX_RECV_SEG_LEN <
tcp_conn->in.datalen) {
printk(KERN_ERR "iscsi_tcp: received buffer of len %u "
"but conn buffer is only %u (opcode %0x)\n",
tcp_conn->in.datalen,
- DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, opcode);
+ ISCSI_DEF_MAX_RECV_SEG_LEN, opcode);
rc = ISCSI_ERR_PROTO;
break;
}
@@ -1762,7 +1762,7 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
* due to strange issues with iser these are not set
* in iscsi_conn_setup
*/
- conn->max_recv_dlength = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
+ conn->max_recv_dlength = ISCSI_DEF_MAX_RECV_SEG_LEN;
tcp_conn = kzalloc(sizeof(*tcp_conn), GFP_KERNEL);
if (!tcp_conn)
@@ -1777,14 +1777,24 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0,
CRYPTO_ALG_ASYNC);
tcp_conn->tx_hash.flags = 0;
- if (IS_ERR(tcp_conn->tx_hash.tfm))
+ if (IS_ERR(tcp_conn->tx_hash.tfm)) {
+ printk(KERN_ERR "Could not create connection due to crc32c "
+ "loading error %ld. Make sure the crc32c module is "
+ "built as a module or into the kernel\n",
+ PTR_ERR(tcp_conn->tx_hash.tfm));
goto free_tcp_conn;
+ }
tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0,
CRYPTO_ALG_ASYNC);
tcp_conn->rx_hash.flags = 0;
- if (IS_ERR(tcp_conn->rx_hash.tfm))
+ if (IS_ERR(tcp_conn->rx_hash.tfm)) {
+ printk(KERN_ERR "Could not create connection due to crc32c "
+ "loading error %ld. Make sure the crc32c module is "
+ "built as a module or into the kernel\n",
+ PTR_ERR(tcp_conn->rx_hash.tfm));
goto free_tx_tfm;
+ }
return cls_conn;
@@ -2138,6 +2148,7 @@ static struct scsi_host_template iscsi_sht = {
.change_queue_depth = iscsi_change_queue_depth,
.can_queue = ISCSI_XMIT_CMDS_MAX - 1,
.sg_tablesize = ISCSI_SG_TABLESIZE,
+ .max_sectors = 0xFFFF,
.cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
.eh_abort_handler = iscsi_eh_abort,
.eh_host_reset_handler = iscsi_eh_host_reset,
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 7c75771c77ff..3f5b9b445b29 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -25,6 +25,7 @@
#include <linux/mutex.h>
#include <linux/kfifo.h>
#include <linux/delay.h>
+#include <asm/unaligned.h>
#include <net/tcp.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
@@ -269,14 +270,14 @@ invalid_datalen:
goto out;
}
- senselen = be16_to_cpu(*(__be16 *)data);
+ senselen = be16_to_cpu(get_unaligned((__be16 *) data));
if (datalen < senselen)
goto invalid_datalen;
memcpy(sc->sense_buffer, data + 2,
min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
debug_scsi("copied %d bytes of sense\n",
- min(senselen, SCSI_SENSE_BUFFERSIZE));
+ min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
}
if (sc->sc_data_direction == DMA_TO_DEVICE)
@@ -577,7 +578,7 @@ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
}
EXPORT_SYMBOL_GPL(iscsi_conn_failure);
-static int iscsi_xmit_imm_task(struct iscsi_conn *conn)
+static int iscsi_xmit_mtask(struct iscsi_conn *conn)
{
struct iscsi_hdr *hdr = conn->mtask->hdr;
int rc, was_logout = 0;
@@ -591,6 +592,9 @@ static int iscsi_xmit_imm_task(struct iscsi_conn *conn)
if (rc)
return rc;
+ /* done with this in-progress mtask */
+ conn->mtask = NULL;
+
if (was_logout) {
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
return -ENODATA;
@@ -643,11 +647,9 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
conn->ctask = NULL;
}
if (conn->mtask) {
- rc = iscsi_xmit_imm_task(conn);
+ rc = iscsi_xmit_mtask(conn);
if (rc)
goto again;
- /* done with this in-progress mtask */
- conn->mtask = NULL;
}
/* process immediate first */
@@ -658,12 +660,10 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
list_add_tail(&conn->mtask->running,
&conn->mgmt_run_list);
spin_unlock_bh(&conn->session->lock);
- rc = iscsi_xmit_imm_task(conn);
+ rc = iscsi_xmit_mtask(conn);
if (rc)
goto again;
}
- /* done with this mtask */
- conn->mtask = NULL;
}
/* process command queue */
@@ -701,12 +701,10 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
list_add_tail(&conn->mtask->running,
&conn->mgmt_run_list);
spin_unlock_bh(&conn->session->lock);
- rc = tt->xmit_mgmt_task(conn, conn->mtask);
- if (rc)
+ rc = iscsi_xmit_mtask(conn);
+ if (rc)
goto again;
}
- /* done with this mtask */
- conn->mtask = NULL;
}
return -ENODATA;
@@ -1523,7 +1521,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
}
spin_unlock_bh(&session->lock);
- data = kmalloc(DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, GFP_KERNEL);
+ data = kmalloc(ISCSI_DEF_MAX_RECV_SEG_LEN, GFP_KERNEL);
if (!data)
goto login_mtask_data_alloc_fail;
conn->login_mtask->data = conn->data = data;
@@ -1597,6 +1595,9 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
wake_up(&conn->ehwait);
}
+ /* flush queued up work because we free the connection below */
+ scsi_flush_work(session->host);
+
spin_lock_bh(&session->lock);
kfree(conn->data);
kfree(conn->persistent_address);
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index dc70c180e115..e34442e405e8 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -22,7 +22,6 @@
*
*/
-#include <linux/pci.h>
#include <linux/scatterlist.h>
#include "sas_internal.h"
diff --git a/drivers/scsi/libsrp.c b/drivers/scsi/libsrp.c
index 89403b00e042..5631c199a8eb 100644
--- a/drivers/scsi/libsrp.c
+++ b/drivers/scsi/libsrp.c
@@ -22,7 +22,6 @@
#include <linux/kfifo.h>
#include <linux/scatterlist.h>
#include <linux/dma-mapping.h>
-#include <linux/pci.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_tcq.h>
@@ -225,8 +224,7 @@ static int srp_indirect_data(struct scsi_cmnd *sc, struct srp_cmd *cmd,
struct srp_direct_buf *md = NULL;
struct scatterlist dummy, *sg = NULL;
dma_addr_t token = 0;
- long err;
- unsigned int done = 0;
+ int err = 0;
int nmd, nsg = 0, len;
if (dma_map || ext_desc) {
@@ -258,8 +256,8 @@ static int srp_indirect_data(struct scsi_cmnd *sc, struct srp_cmd *cmd,
sg_dma_address(&dummy) = token;
err = rdma_io(sc, &dummy, 1, &id->table_desc, 1, DMA_TO_DEVICE,
id->table_desc.len);
- if (err < 0) {
- eprintk("Error copying indirect table %ld\n", err);
+ if (err) {
+ eprintk("Error copying indirect table %d\n", err);
goto free_mem;
}
} else {
@@ -272,6 +270,7 @@ rdma:
nsg = dma_map_sg(iue->target->dev, sg, sc->use_sg, DMA_BIDIRECTIONAL);
if (!nsg) {
eprintk("fail to map %p %d\n", iue, sc->use_sg);
+ err = -EIO;
goto free_mem;
}
len = min(sc->request_bufflen, id->len);
@@ -287,7 +286,7 @@ free_mem:
if (token && dma_map)
dma_free_coherent(iue->target->dev, id->table_desc.len, md, token);
- return done;
+ return err;
}
static int data_out_desc_size(struct srp_cmd *cmd)
@@ -352,7 +351,7 @@ int srp_transfer_data(struct scsi_cmnd *sc, struct srp_cmd *cmd,
break;
default:
eprintk("Unknown format %d %x\n", dir, format);
- break;
+ err = -EINVAL;
}
return err;
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 057fd7e0e379..dcf6106f557a 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -671,7 +671,7 @@ static int
lpfc_parse_vpd(struct lpfc_hba * phba, uint8_t * vpd, int len)
{
uint8_t lenlo, lenhi;
- uint32_t Length;
+ int Length;
int i, j;
int finished = 0;
int index = 0;
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 0aa3304f6b9b..7fc6e06ea7e1 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -2088,7 +2088,7 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor)
static inline int
make_local_pdev(adapter_t *adapter, struct pci_dev **pdev)
{
- *pdev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
+ *pdev = alloc_pci_dev();
if( *pdev == NULL ) return -1;
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index a967fadb7439..08060fb478b6 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -87,6 +87,7 @@ MODULE_AUTHOR("Willem Riede");
MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE);
module_param(max_dev, int, 0444);
MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
diff --git a/drivers/scsi/pci2000.h b/drivers/scsi/pci2000.h
deleted file mode 100644
index 0ebd8ce9e1de..000000000000
--- a/drivers/scsi/pci2000.h
+++ /dev/null
@@ -1,197 +0,0 @@
-/****************************************************************************
- * Perceptive Solutions, Inc. PCI-2000 device driver for Linux.
- *
- * pci2000.h - Linux Host Driver for PCI-2000 IntelliCache SCSI Adapters
- *
- * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
- * All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that redistributions of source
- * code retain the above copyright notice and this comment without
- * modification.
- *
- * Technical updates and product information at:
- * http://www.psidisk.com
- *
- * Please send questions, comments, bug reports to:
- * tech@psidisk.com Technical Support
- *
- ****************************************************************************/
-#ifndef _PCI2000_H
-#define _PCI2000_H
-
-#include <linux/types.h>
-
-#ifndef PSI_EIDE_SCSIOP
-#define PSI_EIDE_SCSIOP 1
-
-#define LINUXVERSION(v,p,s) (((v)<<16) + ((p)<<8) + (s))
-
-/************************************************/
-/* definition of standard data types */
-/************************************************/
-#define CHAR char
-#define UCHAR unsigned char
-#define SHORT short
-#define USHORT unsigned short
-#define BOOL long
-#define LONG long
-#define ULONG unsigned long
-#define VOID void
-
-typedef CHAR *PCHAR;
-typedef UCHAR *PUCHAR;
-typedef SHORT *PSHORT;
-typedef USHORT *PUSHORT;
-typedef BOOL *PBOOL;
-typedef LONG *PLONG;
-typedef ULONG *PULONG;
-typedef VOID *PVOID;
-
-
-/************************************************/
-/* Misc. macros */
-/************************************************/
-#define ANY2SCSI(up, p) \
-((UCHAR *)up)[0] = (((ULONG)(p)) >> 8); \
-((UCHAR *)up)[1] = ((ULONG)(p));
-
-#define SCSI2LONG(up) \
-( (((long)*(((UCHAR *)up))) << 16) \
-+ (((long)(((UCHAR *)up)[1])) << 8) \
-+ ((long)(((UCHAR *)up)[2])) )
-
-#define XANY2SCSI(up, p) \
-((UCHAR *)up)[0] = ((long)(p)) >> 24; \
-((UCHAR *)up)[1] = ((long)(p)) >> 16; \
-((UCHAR *)up)[2] = ((long)(p)) >> 8; \
-((UCHAR *)up)[3] = ((long)(p));
-
-#define XSCSI2LONG(up) \
-( (((long)(((UCHAR *)up)[0])) << 24) \
-+ (((long)(((UCHAR *)up)[1])) << 16) \
-+ (((long)(((UCHAR *)up)[2])) << 8) \
-+ ((long)(((UCHAR *)up)[3])) )
-
-/************************************************/
-/* SCSI CDB operation codes */
-/************************************************/
-#define SCSIOP_TEST_UNIT_READY 0x00
-#define SCSIOP_REZERO_UNIT 0x01
-#define SCSIOP_REWIND 0x01
-#define SCSIOP_REQUEST_BLOCK_ADDR 0x02
-#define SCSIOP_REQUEST_SENSE 0x03
-#define SCSIOP_FORMAT_UNIT 0x04
-#define SCSIOP_READ_BLOCK_LIMITS 0x05
-#define SCSIOP_REASSIGN_BLOCKS 0x07
-#define SCSIOP_READ6 0x08
-#define SCSIOP_RECEIVE 0x08
-#define SCSIOP_WRITE6 0x0A
-#define SCSIOP_PRINT 0x0A
-#define SCSIOP_SEND 0x0A
-#define SCSIOP_SEEK6 0x0B
-#define SCSIOP_TRACK_SELECT 0x0B
-#define SCSIOP_SLEW_PRINT 0x0B
-#define SCSIOP_SEEK_BLOCK 0x0C
-#define SCSIOP_PARTITION 0x0D
-#define SCSIOP_READ_REVERSE 0x0F
-#define SCSIOP_WRITE_FILEMARKS 0x10
-#define SCSIOP_FLUSH_BUFFER 0x10
-#define SCSIOP_SPACE 0x11
-#define SCSIOP_INQUIRY 0x12
-#define SCSIOP_VERIFY6 0x13
-#define SCSIOP_RECOVER_BUF_DATA 0x14
-#define SCSIOP_MODE_SELECT 0x15
-#define SCSIOP_RESERVE_UNIT 0x16
-#define SCSIOP_RELEASE_UNIT 0x17
-#define SCSIOP_COPY 0x18
-#define SCSIOP_ERASE 0x19
-#define SCSIOP_MODE_SENSE 0x1A
-#define SCSIOP_START_STOP_UNIT 0x1B
-#define SCSIOP_STOP_PRINT 0x1B
-#define SCSIOP_LOAD_UNLOAD 0x1B
-#define SCSIOP_RECEIVE_DIAGNOSTIC 0x1C
-#define SCSIOP_SEND_DIAGNOSTIC 0x1D
-#define SCSIOP_MEDIUM_REMOVAL 0x1E
-#define SCSIOP_READ_CAPACITY 0x25
-#define SCSIOP_READ 0x28
-#define SCSIOP_WRITE 0x2A
-#define SCSIOP_SEEK 0x2B
-#define SCSIOP_LOCATE 0x2B
-#define SCSIOP_WRITE_VERIFY 0x2E
-#define SCSIOP_VERIFY 0x2F
-#define SCSIOP_SEARCH_DATA_HIGH 0x30
-#define SCSIOP_SEARCH_DATA_EQUAL 0x31
-#define SCSIOP_SEARCH_DATA_LOW 0x32
-#define SCSIOP_SET_LIMITS 0x33
-#define SCSIOP_READ_POSITION 0x34
-#define SCSIOP_SYNCHRONIZE_CACHE 0x35
-#define SCSIOP_COMPARE 0x39
-#define SCSIOP_COPY_COMPARE 0x3A
-#define SCSIOP_WRITE_DATA_BUFF 0x3B
-#define SCSIOP_READ_DATA_BUFF 0x3C
-#define SCSIOP_CHANGE_DEFINITION 0x40
-#define SCSIOP_READ_SUB_CHANNEL 0x42
-#define SCSIOP_READ_TOC 0x43
-#define SCSIOP_READ_HEADER 0x44
-#define SCSIOP_PLAY_AUDIO 0x45
-#define SCSIOP_PLAY_AUDIO_MSF 0x47
-#define SCSIOP_PLAY_TRACK_INDEX 0x48
-#define SCSIOP_PLAY_TRACK_RELATIVE 0x49
-#define SCSIOP_PAUSE_RESUME 0x4B
-#define SCSIOP_LOG_SELECT 0x4C
-#define SCSIOP_LOG_SENSE 0x4D
-#define SCSIOP_MODE_SELECT10 0x55
-#define SCSIOP_MODE_SENSE10 0x5A
-#define SCSIOP_LOAD_UNLOAD_SLOT 0xA6
-#define SCSIOP_MECHANISM_STATUS 0xBD
-#define SCSIOP_READ_CD 0xBE
-
-// SCSI read capacity structure
-typedef struct _READ_CAPACITY_DATA
- {
- ULONG blks; /* total blocks (converted to little endian) */
- ULONG blksiz; /* size of each (converted to little endian) */
- } READ_CAPACITY_DATA, *PREAD_CAPACITY_DATA;
-
-// SCSI inquiry data
-typedef struct _INQUIRYDATA
- {
- UCHAR DeviceType :5;
- UCHAR DeviceTypeQualifier :3;
- UCHAR DeviceTypeModifier :7;
- UCHAR RemovableMedia :1;
- UCHAR Versions;
- UCHAR ResponseDataFormat;
- UCHAR AdditionalLength;
- UCHAR Reserved[2];
- UCHAR SoftReset :1;
- UCHAR CommandQueue :1;
- UCHAR Reserved2 :1;
- UCHAR LinkedCommands :1;
- UCHAR Synchronous :1;
- UCHAR Wide16Bit :1;
- UCHAR Wide32Bit :1;
- UCHAR RelativeAddressing :1;
- UCHAR VendorId[8];
- UCHAR ProductId[16];
- UCHAR ProductRevisionLevel[4];
- UCHAR VendorSpecific[20];
- UCHAR Reserved3[40];
- } INQUIRYDATA, *PINQUIRYDATA;
-
-#endif
-
-// function prototypes
-int Pci2000_Detect (struct scsi_host_template *tpnt);
-int Pci2000_Command (Scsi_Cmnd *SCpnt);
-int Pci2000_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
-int Pci2000_Abort (Scsi_Cmnd *SCpnt);
-int Pci2000_Reset (Scsi_Cmnd *SCpnt, unsigned int flags);
-int Pci2000_Release (struct Scsi_Host *pshost);
-int Pci2000_BiosParam (struct scsi_device *sdev,
- struct block_device *bdev,
- sector_t capacity, int geom[]);
-
-#endif
diff --git a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig
index eac8e179cfff..7dd787f6ab27 100644
--- a/drivers/scsi/pcmcia/Kconfig
+++ b/drivers/scsi/pcmcia/Kconfig
@@ -3,11 +3,11 @@
#
menu "PCMCIA SCSI adapter support"
- depends on SCSI!=n && PCMCIA!=n && MODULES
+ depends on SCSI!=n && PCMCIA!=n
config PCMCIA_AHA152X
tristate "Adaptec AHA152X PCMCIA support"
- depends on m && !64BIT
+ depends on !64BIT
select SCSI_SPI_ATTRS
help
Say Y here if you intend to attach this type of PCMCIA SCSI host
@@ -18,7 +18,6 @@ config PCMCIA_AHA152X
config PCMCIA_FDOMAIN
tristate "Future Domain PCMCIA support"
- depends on m
help
Say Y here if you intend to attach this type of PCMCIA SCSI host
adapter to your computer.
@@ -28,7 +27,7 @@ config PCMCIA_FDOMAIN
config PCMCIA_NINJA_SCSI
tristate "NinjaSCSI-3 / NinjaSCSI-32Bi (16bit) PCMCIA support"
- depends on m && !64BIT
+ depends on !64BIT
help
If you intend to attach this type of PCMCIA SCSI host adapter to
your computer, say Y here and read
@@ -62,7 +61,6 @@ config PCMCIA_NINJA_SCSI
config PCMCIA_QLOGIC
tristate "Qlogic PCMCIA support"
- depends on m
help
Say Y here if you intend to attach this type of PCMCIA SCSI host
adapter to your computer.
@@ -72,7 +70,6 @@ config PCMCIA_QLOGIC
config PCMCIA_SYM53C500
tristate "Symbios 53c500 PCMCIA support"
- depends on m
help
Say Y here if you have a New Media Bus Toaster or other PCMCIA
SCSI adapter based on the Symbios 53c500 controller.
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 05f4f2a378eb..e8948b679f5b 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1478,14 +1478,17 @@ typedef union {
uint32_t b24 : 24;
struct {
- uint8_t d_id[3];
- uint8_t rsvd_1;
- } r;
-
- struct {
+#ifdef __BIG_ENDIAN
+ uint8_t domain;
+ uint8_t area;
+ uint8_t al_pa;
+#elif __LITTLE_ENDIAN
uint8_t al_pa;
uint8_t area;
uint8_t domain;
+#else
+#error "__BIG_ENDIAN or __LITTLE_ENDIAN must be defined!"
+#endif
uint8_t rsvd_1;
} b;
} port_id_t;
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 98c01cd5e1a8..3e296ab845b6 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -11,6 +11,11 @@
#include "qla_devtbl.h"
+#ifdef CONFIG_SPARC
+#include <asm/prom.h>
+#include <asm/pbm.h>
+#endif
+
/* XXX(hch): this is ugly, but we don't want to pull in exioctl.h */
#ifndef EXT_IS_LUN_BIT_SET
#define EXT_IS_LUN_BIT_SET(P,L) \
@@ -88,12 +93,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n");
- rval = ha->isp_ops.nvram_config(ha);
- if (rval) {
- DEBUG2(printk("scsi(%ld): Unable to verify NVRAM data.\n",
- ha->host_no));
- return rval;
- }
+ ha->isp_ops.nvram_config(ha);
if (ha->flags.disable_serdes) {
/* Mask HBA via NVRAM settings? */
@@ -1393,6 +1393,28 @@ qla2x00_set_model_info(scsi_qla_host_t *ha, uint8_t *model, size_t len, char *de
}
}
+/* On sparc systems, obtain port and node WWN from firmware
+ * properties.
+ */
+static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *ha, nvram_t *nv)
+{
+#ifdef CONFIG_SPARC
+ struct pci_dev *pdev = ha->pdev;
+ struct pcidev_cookie *pcp = pdev->sysdata;
+ struct device_node *dp = pcp->prom_node;
+ u8 *val;
+ int len;
+
+ val = of_get_property(dp, "port-wwn", &len);
+ if (val && len >= WWN_SIZE)
+ memcpy(nv->port_name, val, WWN_SIZE);
+
+ val = of_get_property(dp, "node-wwn", &len);
+ if (val && len >= WWN_SIZE)
+ memcpy(nv->node_name, val, WWN_SIZE);
+#endif
+}
+
/*
* NVRAM configuration for ISP 2xxx
*
@@ -1409,6 +1431,7 @@ qla2x00_set_model_info(scsi_qla_host_t *ha, uint8_t *model, size_t len, char *de
int
qla2x00_nvram_config(scsi_qla_host_t *ha)
{
+ int rval;
uint8_t chksum = 0;
uint16_t cnt;
uint8_t *dptr1, *dptr2;
@@ -1417,6 +1440,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
uint8_t *ptr = (uint8_t *)ha->request_ring;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+ rval = QLA_SUCCESS;
+
/* Determine NVRAM starting address. */
ha->nvram_size = sizeof(nvram_t);
ha->nvram_base = 0;
@@ -1440,7 +1465,57 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: "
"checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0],
nv->nvram_version);
- return QLA_FUNCTION_FAILED;
+ qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
+ "invalid -- WWPN) defaults.\n");
+
+ /*
+ * Set default initialization control block.
+ */
+ memset(nv, 0, ha->nvram_size);
+ nv->parameter_block_version = ICB_VERSION;
+
+ if (IS_QLA23XX(ha)) {
+ nv->firmware_options[0] = BIT_2 | BIT_1;
+ nv->firmware_options[1] = BIT_7 | BIT_5;
+ nv->add_firmware_options[0] = BIT_5;
+ nv->add_firmware_options[1] = BIT_5 | BIT_4;
+ nv->frame_payload_size = __constant_cpu_to_le16(2048);
+ nv->special_options[1] = BIT_7;
+ } else if (IS_QLA2200(ha)) {
+ nv->firmware_options[0] = BIT_2 | BIT_1;
+ nv->firmware_options[1] = BIT_7 | BIT_5;
+ nv->add_firmware_options[0] = BIT_5;
+ nv->add_firmware_options[1] = BIT_5 | BIT_4;
+ nv->frame_payload_size = __constant_cpu_to_le16(1024);
+ } else if (IS_QLA2100(ha)) {
+ nv->firmware_options[0] = BIT_3 | BIT_1;
+ nv->firmware_options[1] = BIT_5;
+ nv->frame_payload_size = __constant_cpu_to_le16(1024);
+ }
+
+ nv->max_iocb_allocation = __constant_cpu_to_le16(256);
+ nv->execution_throttle = __constant_cpu_to_le16(16);
+ nv->retry_count = 8;
+ nv->retry_delay = 1;
+
+ nv->port_name[0] = 33;
+ nv->port_name[3] = 224;
+ nv->port_name[4] = 139;
+
+ qla2xxx_nvram_wwn_from_ofw(ha, nv);
+
+ nv->login_timeout = 4;
+
+ /*
+ * Set default host adapter parameters
+ */
+ nv->host_p[1] = BIT_2;
+ nv->reset_delay = 5;
+ nv->port_down_retry_count = 8;
+ nv->max_luns_per_target = __constant_cpu_to_le16(8);
+ nv->link_down_timeout = 60;
+
+ rval = 1;
}
#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
@@ -1653,7 +1728,11 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
}
}
- return QLA_SUCCESS;
+ if (rval) {
+ DEBUG2_3(printk(KERN_WARNING
+ "scsi(%ld): NVRAM configuration failed!\n", ha->host_no));
+ }
+ return (rval);
}
static void
@@ -3071,9 +3150,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
ha->isp_ops.get_flash_version(ha, ha->request_ring);
- rval = ha->isp_ops.nvram_config(ha);
- if (rval)
- goto isp_abort_retry;
+ ha->isp_ops.nvram_config(ha);
if (!qla2x00_restart_isp(ha)) {
clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
@@ -3103,7 +3180,6 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
}
}
} else { /* failed the ISP abort */
-isp_abort_retry:
ha->flags.online = 1;
if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) {
if (ha->isp_abort_cnt == 0) {
@@ -3290,9 +3366,32 @@ qla24xx_reset_adapter(scsi_qla_host_t *ha)
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
+/* On sparc systems, obtain port and node WWN from firmware
+ * properties.
+ */
+static void qla24xx_nvram_wwn_from_ofw(scsi_qla_host_t *ha, struct nvram_24xx *nv)
+{
+#ifdef CONFIG_SPARC
+ struct pci_dev *pdev = ha->pdev;
+ struct pcidev_cookie *pcp = pdev->sysdata;
+ struct device_node *dp = pcp->prom_node;
+ u8 *val;
+ int len;
+
+ val = of_get_property(dp, "port-wwn", &len);
+ if (val && len >= WWN_SIZE)
+ memcpy(nv->port_name, val, WWN_SIZE);
+
+ val = of_get_property(dp, "node-wwn", &len);
+ if (val && len >= WWN_SIZE)
+ memcpy(nv->node_name, val, WWN_SIZE);
+#endif
+}
+
int
qla24xx_nvram_config(scsi_qla_host_t *ha)
{
+ int rval;
struct init_cb_24xx *icb;
struct nvram_24xx *nv;
uint32_t *dptr;
@@ -3300,6 +3399,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
uint32_t chksum;
uint16_t cnt;
+ rval = QLA_SUCCESS;
icb = (struct init_cb_24xx *)ha->init_cb;
nv = (struct nvram_24xx *)ha->request_ring;
@@ -3332,7 +3432,52 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: "
"checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0],
le16_to_cpu(nv->nvram_version));
- return QLA_FUNCTION_FAILED;
+ qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
+ "invalid -- WWPN) defaults.\n");
+
+ /*
+ * Set default initialization control block.
+ */
+ memset(nv, 0, ha->nvram_size);
+ nv->nvram_version = __constant_cpu_to_le16(ICB_VERSION);
+ nv->version = __constant_cpu_to_le16(ICB_VERSION);
+ nv->frame_payload_size = __constant_cpu_to_le16(2048);
+ nv->execution_throttle = __constant_cpu_to_le16(0xFFFF);
+ nv->exchange_count = __constant_cpu_to_le16(0);
+ nv->hard_address = __constant_cpu_to_le16(124);
+ nv->port_name[0] = 0x21;
+ nv->port_name[1] = 0x00 + PCI_FUNC(ha->pdev->devfn);
+ nv->port_name[2] = 0x00;
+ nv->port_name[3] = 0xe0;
+ nv->port_name[4] = 0x8b;
+ nv->port_name[5] = 0x1c;
+ nv->port_name[6] = 0x55;
+ nv->port_name[7] = 0x86;
+ nv->node_name[0] = 0x20;
+ nv->node_name[1] = 0x00;
+ nv->node_name[2] = 0x00;
+ nv->node_name[3] = 0xe0;
+ nv->node_name[4] = 0x8b;
+ nv->node_name[5] = 0x1c;
+ nv->node_name[6] = 0x55;
+ nv->node_name[7] = 0x86;
+ qla24xx_nvram_wwn_from_ofw(ha, nv);
+ nv->login_retry_count = __constant_cpu_to_le16(8);
+ nv->interrupt_delay_timer = __constant_cpu_to_le16(0);
+ nv->login_timeout = __constant_cpu_to_le16(0);
+ nv->firmware_options_1 =
+ __constant_cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1);
+ nv->firmware_options_2 = __constant_cpu_to_le32(2 << 4);
+ nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_12);
+ nv->firmware_options_3 = __constant_cpu_to_le32(2 << 13);
+ nv->host_p = __constant_cpu_to_le32(BIT_11|BIT_10);
+ nv->efi_parameters = __constant_cpu_to_le32(0);
+ nv->reset_delay = 5;
+ nv->max_luns_per_target = __constant_cpu_to_le16(128);
+ nv->port_down_retry_count = __constant_cpu_to_le16(30);
+ nv->link_down_timeout = __constant_cpu_to_le16(30);
+
+ rval = 1;
}
/* Reset Initialization control block */
@@ -3479,7 +3624,11 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
ha->flags.process_response_queue = 1;
}
- return QLA_SUCCESS;
+ if (rval) {
+ DEBUG2_3(printk(KERN_WARNING
+ "scsi(%ld): NVRAM configuration failed!\n", ha->host_no));
+ }
+ return (rval);
}
static int
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 83376f6ac3db..71e32a248528 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -1280,14 +1280,14 @@ qla2x00_get_port_name(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t *name,
} else {
if (name != NULL) {
/* This function returns name in big endian. */
- name[0] = LSB(mcp->mb[2]);
- name[1] = MSB(mcp->mb[2]);
- name[2] = LSB(mcp->mb[3]);
- name[3] = MSB(mcp->mb[3]);
- name[4] = LSB(mcp->mb[6]);
- name[5] = MSB(mcp->mb[6]);
- name[6] = LSB(mcp->mb[7]);
- name[7] = MSB(mcp->mb[7]);
+ name[0] = MSB(mcp->mb[2]);
+ name[1] = LSB(mcp->mb[2]);
+ name[2] = MSB(mcp->mb[3]);
+ name[3] = LSB(mcp->mb[3]);
+ name[4] = MSB(mcp->mb[6]);
+ name[5] = LSB(mcp->mb[6]);
+ name[6] = MSB(mcp->mb[7]);
+ name[7] = LSB(mcp->mb[7]);
}
DEBUG11(printk("qla2x00_get_port_name(%ld): done.\n",
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 68f5d24b938b..b78919a318e2 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -62,7 +62,7 @@ MODULE_PARM_DESC(ql2xallocfwdump,
"vary by ISP type. Default is 1 - allocate memory.");
int ql2xextended_error_logging;
-module_param(ql2xextended_error_logging, int, S_IRUGO|S_IRUSR);
+module_param(ql2xextended_error_logging, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xextended_error_logging,
"Option to enable extended error logging, "
"Default is 0 - no logging. 1 - log errors.");
@@ -157,6 +157,8 @@ static struct scsi_host_template qla24xx_driver_template = {
.slave_alloc = qla2xxx_slave_alloc,
.slave_destroy = qla2xxx_slave_destroy,
+ .scan_finished = qla2xxx_scan_finished,
+ .scan_start = qla2xxx_scan_start,
.change_queue_depth = qla2x00_change_queue_depth,
.change_queue_type = qla2x00_change_queue_type,
.this_id = -1,
@@ -1705,6 +1707,7 @@ qla2x00_remove_one(struct pci_dev *pdev)
scsi_host_put(ha->host);
+ pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
}
@@ -1747,8 +1750,6 @@ qla2x00_free_device(scsi_qla_host_t *ha)
if (ha->iobase)
iounmap(ha->iobase);
pci_release_regions(ha->pdev);
-
- pci_disable_device(ha->pdev);
}
static inline void
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index ff1dd4175a7f..206bda093da2 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -466,6 +466,7 @@ qla24xx_read_flash_dword(scsi_qla_host_t *ha, uint32_t addr)
udelay(10);
else
rval = QLA_FUNCTION_TIMEOUT;
+ cond_resched();
}
/* TODO: What happens if we time out? */
@@ -508,6 +509,7 @@ qla24xx_write_flash_dword(scsi_qla_host_t *ha, uint32_t addr, uint32_t data)
udelay(10);
else
rval = QLA_FUNCTION_TIMEOUT;
+ cond_resched();
}
return rval;
}
@@ -1255,6 +1257,7 @@ qla2x00_poll_flash(scsi_qla_host_t *ha, uint32_t addr, uint8_t poll_data,
}
udelay(10);
barrier();
+ cond_resched();
}
return status;
}
@@ -1403,6 +1406,7 @@ qla2x00_read_flash_data(scsi_qla_host_t *ha, uint8_t *tmp_buf, uint32_t saddr,
if (saddr % 100)
udelay(10);
*tmp_buf = data;
+ cond_resched();
}
}
@@ -1449,7 +1453,6 @@ uint8_t *
qla2x00_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
uint32_t offset, uint32_t length)
{
- unsigned long flags;
uint32_t addr, midpoint;
uint8_t *data;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
@@ -1458,7 +1461,6 @@ qla2x00_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
qla2x00_suspend_hba(ha);
/* Go with read. */
- spin_lock_irqsave(&ha->hardware_lock, flags);
midpoint = ha->optrom_size / 2;
qla2x00_flash_enable(ha);
@@ -1473,7 +1475,6 @@ qla2x00_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
*data = qla2x00_read_flash_byte(ha, addr);
}
qla2x00_flash_disable(ha);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
/* Resume HBA. */
qla2x00_resume_hba(ha);
@@ -1487,7 +1488,6 @@ qla2x00_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
{
int rval;
- unsigned long flags;
uint8_t man_id, flash_id, sec_number, data;
uint16_t wd;
uint32_t addr, liter, sec_mask, rest_addr;
@@ -1500,7 +1500,6 @@ qla2x00_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
sec_number = 0;
/* Reset ISP chip. */
- spin_lock_irqsave(&ha->hardware_lock, flags);
WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
pci_read_config_word(ha->pdev, PCI_COMMAND, &wd);
@@ -1689,10 +1688,10 @@ update_flash:
rval = QLA_FUNCTION_FAILED;
break;
}
+ cond_resched();
}
} while (0);
qla2x00_flash_disable(ha);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
/* Resume HBA. */
qla2x00_resume_hba(ha);
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 61347aee55ce..dc85495c337f 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,7 +7,7 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "8.01.07-k5"
+#define QLA2XXX_VERSION "8.01.07-k6"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 1
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 1c89ee3e69ba..4c1e31334765 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -344,7 +344,6 @@ void scsi_destroy_command_freelist(struct Scsi_Host *shost)
void scsi_log_send(struct scsi_cmnd *cmd)
{
unsigned int level;
- struct scsi_device *sdev;
/*
* If ML QUEUE log level is greater than or equal to:
@@ -361,22 +360,17 @@ void scsi_log_send(struct scsi_cmnd *cmd)
level = SCSI_LOG_LEVEL(SCSI_LOG_MLQUEUE_SHIFT,
SCSI_LOG_MLQUEUE_BITS);
if (level > 1) {
- sdev = cmd->device;
- sdev_printk(KERN_INFO, sdev, "send ");
+ scmd_printk(KERN_INFO, cmd, "Send: ");
if (level > 2)
printk("0x%p ", cmd);
- /*
- * spaces to match disposition and cmd->result
- * output in scsi_log_completion.
- */
- printk(" ");
+ printk("\n");
scsi_print_command(cmd);
if (level > 3) {
printk(KERN_INFO "buffer = 0x%p, bufflen = %d,"
" done = 0x%p, queuecommand 0x%p\n",
cmd->request_buffer, cmd->request_bufflen,
cmd->done,
- sdev->host->hostt->queuecommand);
+ cmd->device->host->hostt->queuecommand);
}
}
@@ -386,7 +380,6 @@ void scsi_log_send(struct scsi_cmnd *cmd)
void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
{
unsigned int level;
- struct scsi_device *sdev;
/*
* If ML COMPLETE log level is greater than or equal to:
@@ -405,8 +398,7 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
SCSI_LOG_MLCOMPLETE_BITS);
if (((level > 0) && (cmd->result || disposition != SUCCESS)) ||
(level > 1)) {
- sdev = cmd->device;
- sdev_printk(KERN_INFO, sdev, "done ");
+ scmd_printk(KERN_INFO, cmd, "Done: ");
if (level > 2)
printk("0x%p ", cmd);
/*
@@ -415,40 +407,35 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
*/
switch (disposition) {
case SUCCESS:
- printk("SUCCESS");
+ printk("SUCCESS\n");
break;
case NEEDS_RETRY:
- printk("RETRY ");
+ printk("RETRY\n");
break;
case ADD_TO_MLQUEUE:
- printk("MLQUEUE");
+ printk("MLQUEUE\n");
break;
case FAILED:
- printk("FAILED ");
+ printk("FAILED\n");
break;
case TIMEOUT_ERROR:
/*
* If called via scsi_times_out.
*/
- printk("TIMEOUT");
+ printk("TIMEOUT\n");
break;
default:
- printk("UNKNOWN");
+ printk("UNKNOWN\n");
}
- printk(" %8x ", cmd->result);
+ scsi_print_result(cmd);
scsi_print_command(cmd);
- if (status_byte(cmd->result) & CHECK_CONDITION) {
- /*
- * XXX The scsi_print_sense formatting/prefix
- * doesn't match this function.
- */
+ if (status_byte(cmd->result) & CHECK_CONDITION)
scsi_print_sense("", cmd);
- }
- if (level > 3) {
- printk(KERN_INFO "scsi host busy %d failed %d\n",
- sdev->host->host_busy,
- sdev->host->host_failed);
- }
+ if (level > 3)
+ scmd_printk(KERN_INFO, cmd,
+ "scsi host busy %d failed %d\n",
+ cmd->device->host->host_busy,
+ cmd->device->host->host_failed);
}
}
}
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 918bb6019540..3963e7013bd9 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -184,10 +184,19 @@ int scsi_delete_timer(struct scsi_cmnd *scmd)
**/
void scsi_times_out(struct scsi_cmnd *scmd)
{
+ enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *);
+
scsi_log_completion(scmd, TIMEOUT_ERROR);
if (scmd->device->host->transportt->eh_timed_out)
- switch (scmd->device->host->transportt->eh_timed_out(scmd)) {
+ eh_timed_out = scmd->device->host->transportt->eh_timed_out;
+ else if (scmd->device->host->hostt->eh_timed_out)
+ eh_timed_out = scmd->device->host->hostt->eh_timed_out;
+ else
+ eh_timed_out = NULL;
+
+ if (eh_timed_out)
+ switch (eh_timed_out(scmd)) {
case EH_HANDLED:
__scsi_done(scmd);
return;
@@ -923,10 +932,12 @@ static int scsi_eh_try_stu(struct scsi_cmnd *scmd)
static unsigned char stu_command[6] = {START_STOP, 0, 0, 0, 1, 0};
if (scmd->device->allow_restart) {
- int rtn;
+ int i, rtn = NEEDS_RETRY;
+
+ for (i = 0; rtn == NEEDS_RETRY && i < 2; i++)
+ rtn = scsi_send_eh_cmnd(scmd, stu_command, 6,
+ START_UNIT_TIMEOUT, 0);
- rtn = scsi_send_eh_cmnd(scmd, stu_command, 6,
- START_UNIT_TIMEOUT, 0);
if (rtn == SUCCESS)
return 0;
}
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 05d79af5ab90..61fbcdcbb009 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -848,8 +848,8 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
memcpy(req->sense, cmd->sense_buffer, len);
req->sense_len = len;
}
- } else
- req->data_len = cmd->resid;
+ }
+ req->data_len = cmd->resid;
}
/*
@@ -968,9 +968,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
}
if (result) {
if (!(req->cmd_flags & REQ_QUIET)) {
- scmd_printk(KERN_INFO, cmd,
- "SCSI error: return code = 0x%08x\n",
- result);
+ scsi_print_result(cmd);
if (driver_byte(result) & DRIVER_SENSE)
scsi_print_sense("", cmd);
}
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 0949145304ea..a67f315244d7 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -181,10 +181,8 @@ int scsi_complete_async_scans(void)
return 0;
}
-#ifdef MODULE
/* Only exported for the benefit of scsi_wait_scan */
EXPORT_SYMBOL_GPL(scsi_complete_async_scans);
-#endif
/**
* scsi_unlock_floptical - unlock device via a special MODE SENSE command
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 939de0de18bc..67a38a1409ba 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -276,8 +276,22 @@ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv)
return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
}
+static int scsi_bus_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ int i = 0;
+ int length = 0;
+
+ add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
+ "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type);
+ envp[i] = NULL;
+ return 0;
+}
+
static int scsi_bus_suspend(struct device * dev, pm_message_t state)
{
+ struct device_driver *drv = dev->driver;
struct scsi_device *sdev = to_scsi_device(dev);
struct scsi_host_template *sht = sdev->host->hostt;
int err;
@@ -286,28 +300,51 @@ static int scsi_bus_suspend(struct device * dev, pm_message_t state)
if (err)
return err;
- if (sht->suspend)
+ /* call HLD suspend first */
+ if (drv && drv->suspend) {
+ err = drv->suspend(dev, state);
+ if (err)
+ return err;
+ }
+
+ /* then, call host suspend */
+ if (sht->suspend) {
err = sht->suspend(sdev, state);
+ if (err) {
+ if (drv && drv->resume)
+ drv->resume(dev);
+ return err;
+ }
+ }
- return err;
+ return 0;
}
static int scsi_bus_resume(struct device * dev)
{
+ struct device_driver *drv = dev->driver;
struct scsi_device *sdev = to_scsi_device(dev);
struct scsi_host_template *sht = sdev->host->hostt;
- int err = 0;
+ int err = 0, err2 = 0;
+ /* call host resume first */
if (sht->resume)
err = sht->resume(sdev);
+ /* then, call HLD resume */
+ if (drv && drv->resume)
+ err2 = drv->resume(dev);
+
scsi_device_resume(sdev);
- return err;
+
+ /* favor LLD failure */
+ return err ? err : err2;;
}
struct bus_type scsi_bus_type = {
.name = "scsi",
.match = scsi_bus_match,
+ .uevent = scsi_bus_uevent,
.suspend = scsi_bus_suspend,
.resume = scsi_bus_resume,
};
@@ -547,6 +584,14 @@ show_sdev_iostat(iorequest_cnt);
show_sdev_iostat(iodone_cnt);
show_sdev_iostat(ioerr_cnt);
+static ssize_t
+sdev_show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct scsi_device *sdev;
+ sdev = to_scsi_device(dev);
+ return snprintf (buf, 20, SCSI_DEVICE_MODALIAS_FMT "\n", sdev->type);
+}
+static DEVICE_ATTR(modalias, S_IRUGO, sdev_show_modalias, NULL);
/* Default template for device attributes. May NOT be modified */
static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
@@ -566,6 +611,7 @@ static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
&dev_attr_iorequest_cnt,
&dev_attr_iodone_cnt,
&dev_attr_ioerr_cnt,
+ &dev_attr_modalias,
NULL
};
diff --git a/drivers/scsi/scsi_tgt_if.c b/drivers/scsi/scsi_tgt_if.c
index 0e08817fdecf..ca22ddf81746 100644
--- a/drivers/scsi/scsi_tgt_if.c
+++ b/drivers/scsi/scsi_tgt_if.c
@@ -179,10 +179,12 @@ static int event_recv_msg(struct tgt_event *ev)
switch (ev->hdr.type) {
case TGT_UEVENT_CMD_RSP:
err = scsi_tgt_kspace_exec(ev->p.cmd_rsp.host_no,
- ev->p.cmd_rsp.tag,
ev->p.cmd_rsp.result,
- ev->p.cmd_rsp.len,
+ ev->p.cmd_rsp.tag,
ev->p.cmd_rsp.uaddr,
+ ev->p.cmd_rsp.len,
+ ev->p.cmd_rsp.sense_uaddr,
+ ev->p.cmd_rsp.sense_len,
ev->p.cmd_rsp.rw);
break;
case TGT_UEVENT_TSK_MGMT_RSP:
diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c
index d402aff5f314..2570f48a69c7 100644
--- a/drivers/scsi/scsi_tgt_lib.c
+++ b/drivers/scsi/scsi_tgt_lib.c
@@ -28,7 +28,6 @@
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tgt.h>
-#include <../drivers/md/dm-bio-list.h>
#include "scsi_tgt_priv.h"
@@ -42,16 +41,12 @@ static struct kmem_cache *scsi_tgt_cmd_cache;
struct scsi_tgt_cmd {
/* TODO replace work with James b's code */
struct work_struct work;
- /* TODO replace the lists with a large bio */
- struct bio_list xfer_done_list;
- struct bio_list xfer_list;
+ /* TODO fix limits of some drivers */
+ struct bio *bio;
struct list_head hash_list;
struct request *rq;
u64 tag;
-
- void *buffer;
- unsigned bufflen;
};
#define TGT_HASH_ORDER 4
@@ -93,7 +88,12 @@ struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost,
if (!tcmd)
goto put_dev;
- rq = blk_get_request(shost->uspace_req_q, write, gfp_mask);
+ /*
+ * The blk helpers are used to the READ/WRITE requests
+ * transfering data from a initiator point of view. Since
+ * we are in target mode we want the opposite.
+ */
+ rq = blk_get_request(shost->uspace_req_q, !write, gfp_mask);
if (!rq)
goto free_tcmd;
@@ -111,8 +111,6 @@ struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost,
rq->cmd_flags |= REQ_TYPE_BLOCK_PC;
rq->end_io_data = tcmd;
- bio_list_init(&tcmd->xfer_list);
- bio_list_init(&tcmd->xfer_done_list);
tcmd->rq = rq;
return cmd;
@@ -157,22 +155,6 @@ void scsi_host_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
}
EXPORT_SYMBOL_GPL(scsi_host_put_command);
-static void scsi_unmap_user_pages(struct scsi_tgt_cmd *tcmd)
-{
- struct bio *bio;
-
- /* must call bio_endio in case bio was bounced */
- while ((bio = bio_list_pop(&tcmd->xfer_done_list))) {
- bio_endio(bio, bio->bi_size, 0);
- bio_unmap_user(bio);
- }
-
- while ((bio = bio_list_pop(&tcmd->xfer_list))) {
- bio_endio(bio, bio->bi_size, 0);
- bio_unmap_user(bio);
- }
-}
-
static void cmd_hashlist_del(struct scsi_cmnd *cmd)
{
struct request_queue *q = cmd->request->q;
@@ -185,6 +167,11 @@ static void cmd_hashlist_del(struct scsi_cmnd *cmd)
spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags);
}
+static void scsi_unmap_user_pages(struct scsi_tgt_cmd *tcmd)
+{
+ blk_rq_unmap_user(tcmd->bio);
+}
+
static void scsi_tgt_cmd_destroy(struct work_struct *work)
{
struct scsi_tgt_cmd *tcmd =
@@ -193,16 +180,6 @@ static void scsi_tgt_cmd_destroy(struct work_struct *work)
dprintk("cmd %p %d %lu\n", cmd, cmd->sc_data_direction,
rq_data_dir(cmd->request));
- /*
- * We fix rq->cmd_flags here since when we told bio_map_user
- * to write vm for WRITE commands, blk_rq_bio_prep set
- * rq_data_dir the flags to READ.
- */
- if (cmd->sc_data_direction == DMA_TO_DEVICE)
- cmd->request->cmd_flags |= REQ_RW;
- else
- cmd->request->cmd_flags &= ~REQ_RW;
-
scsi_unmap_user_pages(tcmd);
scsi_host_put_command(scsi_tgt_cmd_to_host(cmd), cmd);
}
@@ -215,6 +192,7 @@ static void init_scsi_tgt_cmd(struct request *rq, struct scsi_tgt_cmd *tcmd,
struct list_head *head;
tcmd->tag = tag;
+ tcmd->bio = NULL;
INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy);
spin_lock_irqsave(&qdata->cmd_hash_lock, flags);
head = &qdata->cmd_hash[cmd_hashfn(tag)];
@@ -349,10 +327,14 @@ static void scsi_tgt_cmd_done(struct scsi_cmnd *cmd)
dprintk("cmd %p %lu\n", cmd, rq_data_dir(cmd->request));
scsi_tgt_uspace_send_status(cmd, tcmd->tag);
+
+ if (cmd->request_buffer)
+ scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len);
+
queue_work(scsi_tgtd, &tcmd->work);
}
-static int __scsi_tgt_transfer_response(struct scsi_cmnd *cmd)
+static int scsi_tgt_transfer_response(struct scsi_cmnd *cmd)
{
struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd);
int err;
@@ -365,30 +347,12 @@ static int __scsi_tgt_transfer_response(struct scsi_cmnd *cmd)
case SCSI_MLQUEUE_DEVICE_BUSY:
return -EAGAIN;
}
-
return 0;
}
-static void scsi_tgt_transfer_response(struct scsi_cmnd *cmd)
-{
- struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data;
- int err;
-
- err = __scsi_tgt_transfer_response(cmd);
- if (!err)
- return;
-
- cmd->result = DID_BUS_BUSY << 16;
- err = scsi_tgt_uspace_send_status(cmd, tcmd->tag);
- if (err <= 0)
- /* the eh will have to pick this up */
- printk(KERN_ERR "Could not send cmd %p status\n", cmd);
-}
-
static int scsi_tgt_init_cmd(struct scsi_cmnd *cmd, gfp_t gfp_mask)
{
struct request *rq = cmd->request;
- struct scsi_tgt_cmd *tcmd = rq->end_io_data;
int count;
cmd->use_sg = rq->nr_phys_segments;
@@ -398,143 +362,54 @@ static int scsi_tgt_init_cmd(struct scsi_cmnd *cmd, gfp_t gfp_mask)
cmd->request_bufflen = rq->data_len;
- dprintk("cmd %p addr %p cnt %d %lu\n", cmd, tcmd->buffer, cmd->use_sg,
- rq_data_dir(rq));
+ dprintk("cmd %p cnt %d %lu\n", cmd, cmd->use_sg, rq_data_dir(rq));
count = blk_rq_map_sg(rq->q, rq, cmd->request_buffer);
if (likely(count <= cmd->use_sg)) {
cmd->use_sg = count;
return 0;
}
- eprintk("cmd %p addr %p cnt %d\n", cmd, tcmd->buffer, cmd->use_sg);
+ eprintk("cmd %p cnt %d\n", cmd, cmd->use_sg);
scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len);
return -EINVAL;
}
/* TODO: test this crap and replace bio_map_user with new interface maybe */
static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd,
- int rw)
+ unsigned long uaddr, unsigned int len, int rw)
{
struct request_queue *q = cmd->request->q;
struct request *rq = cmd->request;
- void *uaddr = tcmd->buffer;
- unsigned int len = tcmd->bufflen;
- struct bio *bio;
int err;
- while (len > 0) {
- dprintk("%lx %u\n", (unsigned long) uaddr, len);
- bio = bio_map_user(q, NULL, (unsigned long) uaddr, len, rw);
- if (IS_ERR(bio)) {
- err = PTR_ERR(bio);
- dprintk("fail to map %lx %u %d %x\n",
- (unsigned long) uaddr, len, err, cmd->cmnd[0]);
- goto unmap_bios;
- }
-
- uaddr += bio->bi_size;
- len -= bio->bi_size;
-
+ dprintk("%lx %u\n", uaddr, len);
+ err = blk_rq_map_user(q, rq, (void *)uaddr, len);
+ if (err) {
/*
- * The first bio is added and merged. We could probably
- * try to add others using scsi_merge_bio() but for now
- * we keep it simple. The first bio should be pretty large
- * (either hitting the 1 MB bio pages limit or a queue limit)
- * already but for really large IO we may want to try and
- * merge these.
+ * TODO: need to fixup sg_tablesize, max_segment_size,
+ * max_sectors, etc for modern HW and software drivers
+ * where this value is bogus.
+ *
+ * TODO2: we can alloc a reserve buffer of max size
+ * we can handle and do the slow copy path for really large
+ * IO.
*/
- if (!rq->bio) {
- blk_rq_bio_prep(q, rq, bio);
- rq->data_len = bio->bi_size;
- } else
- /* put list of bios to transfer in next go around */
- bio_list_add(&tcmd->xfer_list, bio);
+ eprintk("Could not handle request of size %u.\n", len);
+ return err;
}
- cmd->offset = 0;
+ tcmd->bio = rq->bio;
err = scsi_tgt_init_cmd(cmd, GFP_KERNEL);
if (err)
- goto unmap_bios;
+ goto unmap_rq;
return 0;
-unmap_bios:
- if (rq->bio) {
- bio_unmap_user(rq->bio);
- while ((bio = bio_list_pop(&tcmd->xfer_list)))
- bio_unmap_user(bio);
- }
-
+unmap_rq:
+ scsi_unmap_user_pages(tcmd);
return err;
}
-static int scsi_tgt_transfer_data(struct scsi_cmnd *);
-
-static void scsi_tgt_data_transfer_done(struct scsi_cmnd *cmd)
-{
- struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data;
- struct bio *bio;
- int err;
-
- /* should we free resources here on error ? */
- if (cmd->result) {
-send_uspace_err:
- err = scsi_tgt_uspace_send_status(cmd, tcmd->tag);
- if (err <= 0)
- /* the tgt uspace eh will have to pick this up */
- printk(KERN_ERR "Could not send cmd %p status\n", cmd);
- return;
- }
-
- dprintk("cmd %p request_bufflen %u bufflen %u\n",
- cmd, cmd->request_bufflen, tcmd->bufflen);
-
- scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len);
- bio_list_add(&tcmd->xfer_done_list, cmd->request->bio);
-
- tcmd->buffer += cmd->request_bufflen;
- cmd->offset += cmd->request_bufflen;
-
- if (!tcmd->xfer_list.head) {
- scsi_tgt_transfer_response(cmd);
- return;
- }
-
- dprintk("cmd2 %p request_bufflen %u bufflen %u\n",
- cmd, cmd->request_bufflen, tcmd->bufflen);
-
- bio = bio_list_pop(&tcmd->xfer_list);
- BUG_ON(!bio);
-
- blk_rq_bio_prep(cmd->request->q, cmd->request, bio);
- cmd->request->data_len = bio->bi_size;
- err = scsi_tgt_init_cmd(cmd, GFP_ATOMIC);
- if (err) {
- cmd->result = DID_ERROR << 16;
- goto send_uspace_err;
- }
-
- if (scsi_tgt_transfer_data(cmd)) {
- cmd->result = DID_NO_CONNECT << 16;
- goto send_uspace_err;
- }
-}
-
-static int scsi_tgt_transfer_data(struct scsi_cmnd *cmd)
-{
- int err;
- struct Scsi_Host *host = scsi_tgt_cmd_to_host(cmd);
-
- err = host->hostt->transfer_data(cmd, scsi_tgt_data_transfer_done);
- switch (err) {
- case SCSI_MLQUEUE_HOST_BUSY:
- case SCSI_MLQUEUE_DEVICE_BUSY:
- return -EAGAIN;
- default:
- return 0;
- }
-}
-
static int scsi_tgt_copy_sense(struct scsi_cmnd *cmd, unsigned long uaddr,
unsigned len)
{
@@ -584,8 +459,9 @@ static struct request *tgt_cmd_hash_lookup(struct request_queue *q, u64 tag)
return rq;
}
-int scsi_tgt_kspace_exec(int host_no, u64 tag, int result, u32 len,
- unsigned long uaddr, u8 rw)
+int scsi_tgt_kspace_exec(int host_no, int result, u64 tag,
+ unsigned long uaddr, u32 len, unsigned long sense_uaddr,
+ u32 sense_len, u8 rw)
{
struct Scsi_Host *shost;
struct scsi_cmnd *cmd;
@@ -617,8 +493,9 @@ int scsi_tgt_kspace_exec(int host_no, u64 tag, int result, u32 len,
}
cmd = rq->special;
- dprintk("cmd %p result %d len %d bufflen %u %lu %x\n", cmd,
- result, len, cmd->request_bufflen, rq_data_dir(rq), cmd->cmnd[0]);
+ dprintk("cmd %p scb %x result %d len %d bufflen %u %lu %x\n",
+ cmd, cmd->cmnd[0], result, len, cmd->request_bufflen,
+ rq_data_dir(rq), cmd->cmnd[0]);
if (result == TASK_ABORTED) {
scsi_tgt_abort_cmd(shost, cmd);
@@ -629,36 +506,36 @@ int scsi_tgt_kspace_exec(int host_no, u64 tag, int result, u32 len,
* in the request_* values
*/
tcmd = cmd->request->end_io_data;
- tcmd->buffer = (void *)uaddr;
- tcmd->bufflen = len;
cmd->result = result;
- if (!tcmd->bufflen || cmd->request_buffer) {
- err = __scsi_tgt_transfer_response(cmd);
- goto done;
- }
+ if (cmd->result == SAM_STAT_CHECK_CONDITION)
+ scsi_tgt_copy_sense(cmd, sense_uaddr, sense_len);
- /*
- * TODO: Do we need to handle case where request does not
- * align with LLD.
- */
- err = scsi_map_user_pages(rq->end_io_data, cmd, rw);
- if (err) {
- eprintk("%p %d\n", cmd, err);
- err = -EAGAIN;
- goto done;
- }
+ if (len) {
+ err = scsi_map_user_pages(rq->end_io_data, cmd, uaddr, len, rw);
+ if (err) {
+ /*
+ * user-space daemon bugs or OOM
+ * TODO: we can do better for OOM.
+ */
+ struct scsi_tgt_queuedata *qdata;
+ struct list_head *head;
+ unsigned long flags;
- /* userspace failure */
- if (cmd->result) {
- if (status_byte(cmd->result) == CHECK_CONDITION)
- scsi_tgt_copy_sense(cmd, uaddr, len);
- err = __scsi_tgt_transfer_response(cmd);
- goto done;
- }
- /* ask the target LLD to transfer the data to the buffer */
- err = scsi_tgt_transfer_data(cmd);
+ eprintk("cmd %p ret %d uaddr %lx len %d rw %d\n",
+ cmd, err, uaddr, len, rw);
+
+ qdata = shost->uspace_req_q->queuedata;
+ head = &qdata->cmd_hash[cmd_hashfn(tcmd->tag)];
+
+ spin_lock_irqsave(&qdata->cmd_hash_lock, flags);
+ list_add(&tcmd->hash_list, head);
+ spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags);
+ goto done;
+ }
+ }
+ err = scsi_tgt_transfer_response(cmd);
done:
scsi_host_put(shost);
return err;
diff --git a/drivers/scsi/scsi_tgt_priv.h b/drivers/scsi/scsi_tgt_priv.h
index 84488c51ff62..e9e6db1c417f 100644
--- a/drivers/scsi/scsi_tgt_priv.h
+++ b/drivers/scsi/scsi_tgt_priv.h
@@ -18,8 +18,9 @@ extern int scsi_tgt_if_init(void);
extern int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun,
u64 tag);
extern int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag);
-extern int scsi_tgt_kspace_exec(int host_no, u64 tag, int result, u32 len,
- unsigned long uaddr, u8 rw);
+extern int scsi_tgt_kspace_exec(int host_no, int result, u64 tag,
+ unsigned long uaddr, u32 len, unsigned long sense_uaddr,
+ u32 sense_len, u8 rw);
extern int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag,
struct scsi_lun *scsilun, void *data);
extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result);
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 58afdb401703..14c4f065b2b8 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -200,6 +200,8 @@ static const struct {
{ FC_PORTSPEED_2GBIT, "2 Gbit" },
{ FC_PORTSPEED_4GBIT, "4 Gbit" },
{ FC_PORTSPEED_10GBIT, "10 Gbit" },
+ { FC_PORTSPEED_8GBIT, "8 Gbit" },
+ { FC_PORTSPEED_16GBIT, "16 Gbit" },
{ FC_PORTSPEED_NOT_NEGOTIATED, "Not Negotiated" },
};
fc_bitfield_name_search(port_speed, fc_port_speed_names)
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index aabaa0576ab4..caf1836bbeca 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -49,7 +49,7 @@ struct iscsi_internal {
struct class_device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1];
};
-static int iscsi_session_nr; /* sysfs session id for next new session */
+static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
/*
* list of registered transports and lock that must
@@ -300,7 +300,7 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
int err;
ihost = shost->shost_data;
- session->sid = iscsi_session_nr++;
+ session->sid = atomic_add_return(1, &iscsi_session_nr);
session->target_id = target_id;
snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u",
@@ -1419,6 +1419,8 @@ static __init int iscsi_transport_init(void)
printk(KERN_INFO "Loading iSCSI transport class v%s.\n",
ISCSI_TRANSPORT_VERSION);
+ atomic_set(&iscsi_session_nr, 0);
+
err = class_register(&iscsi_transport_class);
if (err)
return err;
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 5a8f55fea5ff..00e46662296f 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -58,16 +58,10 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_ioctl.h>
#include <scsi/scsicam.h>
+#include <scsi/sd.h>
#include "scsi_logging.h"
-/*
- * More than enough for everybody ;) The huge number of majors
- * is a leftover from 16bit dev_t days, we don't really need that
- * much numberspace.
- */
-#define SD_MAJORS 16
-
MODULE_AUTHOR("Eric Youngdale");
MODULE_DESCRIPTION("SCSI disk (sd) driver");
MODULE_LICENSE("GPL");
@@ -88,45 +82,9 @@ MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK12_MAJOR);
MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK13_MAJOR);
MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK14_MAJOR);
MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_DISK15_MAJOR);
-
-/*
- * This is limited by the naming scheme enforced in sd_probe,
- * add another character to it if you really need more disks.
- */
-#define SD_MAX_DISKS (((26 * 26) + 26 + 1) * 26)
-
-/*
- * Time out in seconds for disks and Magneto-opticals (which are slower).
- */
-#define SD_TIMEOUT (30 * HZ)
-#define SD_MOD_TIMEOUT (75 * HZ)
-
-/*
- * Number of allowed retries
- */
-#define SD_MAX_RETRIES 5
-#define SD_PASSTHROUGH_RETRIES 1
-
-/*
- * Size of the initial data buffer for mode and read capacity data
- */
-#define SD_BUF_SIZE 512
-
-struct scsi_disk {
- struct scsi_driver *driver; /* always &sd_template */
- struct scsi_device *device;
- struct class_device cdev;
- struct gendisk *disk;
- unsigned int openers; /* protected by BKL for now, yuck */
- sector_t capacity; /* size in 512-byte sectors */
- u32 index;
- u8 media_present;
- u8 write_prot;
- unsigned WCE : 1; /* state of disk WCE bit */
- unsigned RCD : 1; /* state of disk RCD bit, unused */
- unsigned DPOFUA : 1; /* state of disk DPOFUA bit */
-};
-#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,cdev)
+MODULE_ALIAS_SCSI_DEVICE(TYPE_DISK);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_MOD);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC);
static DEFINE_IDR(sd_index_idr);
static DEFINE_SPINLOCK(sd_index_lock);
@@ -136,20 +94,6 @@ static DEFINE_SPINLOCK(sd_index_lock);
* object after last put) */
static DEFINE_MUTEX(sd_ref_mutex);
-static int sd_revalidate_disk(struct gendisk *disk);
-static void sd_rw_intr(struct scsi_cmnd * SCpnt);
-
-static int sd_probe(struct device *);
-static int sd_remove(struct device *);
-static void sd_shutdown(struct device *dev);
-static void sd_rescan(struct device *);
-static int sd_init_command(struct scsi_cmnd *);
-static int sd_issue_flush(struct device *, sector_t *);
-static void sd_prepare_flush(request_queue_t *, struct request *);
-static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
- unsigned char *buffer);
-static void scsi_disk_release(struct class_device *cdev);
-
static const char *sd_cache_types[] = {
"write through", "none", "write back",
"write back, no read (daft)"
@@ -199,13 +143,27 @@ static ssize_t sd_store_cache_type(struct class_device *cdev, const char *buf,
if (scsi_mode_select(sdp, 1, sp, 8, buffer_data, len, SD_TIMEOUT,
SD_MAX_RETRIES, &data, &sshdr)) {
if (scsi_sense_valid(&sshdr))
- scsi_print_sense_hdr(sdkp->disk->disk_name, &sshdr);
+ sd_print_sense_hdr(sdkp, &sshdr);
return -EINVAL;
}
sd_revalidate_disk(sdkp->disk);
return count;
}
+static ssize_t sd_store_manage_start_stop(struct class_device *cdev,
+ const char *buf, size_t count)
+{
+ struct scsi_disk *sdkp = to_scsi_disk(cdev);
+ struct scsi_device *sdp = sdkp->device;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+
+ sdp->manage_start_stop = simple_strtoul(buf, NULL, 10);
+
+ return count;
+}
+
static ssize_t sd_store_allow_restart(struct class_device *cdev, const char *buf,
size_t count)
{
@@ -238,6 +196,14 @@ static ssize_t sd_show_fua(struct class_device *cdev, char *buf)
return snprintf(buf, 20, "%u\n", sdkp->DPOFUA);
}
+static ssize_t sd_show_manage_start_stop(struct class_device *cdev, char *buf)
+{
+ struct scsi_disk *sdkp = to_scsi_disk(cdev);
+ struct scsi_device *sdp = sdkp->device;
+
+ return snprintf(buf, 20, "%u\n", sdp->manage_start_stop);
+}
+
static ssize_t sd_show_allow_restart(struct class_device *cdev, char *buf)
{
struct scsi_disk *sdkp = to_scsi_disk(cdev);
@@ -251,6 +217,8 @@ static struct class_device_attribute sd_disk_attrs[] = {
__ATTR(FUA, S_IRUGO, sd_show_fua, NULL),
__ATTR(allow_restart, S_IRUGO|S_IWUSR, sd_show_allow_restart,
sd_store_allow_restart),
+ __ATTR(manage_start_stop, S_IRUGO|S_IWUSR, sd_show_manage_start_stop,
+ sd_store_manage_start_stop),
__ATTR_NULL,
};
@@ -267,6 +235,8 @@ static struct scsi_driver sd_template = {
.name = "sd",
.probe = sd_probe,
.remove = sd_remove,
+ .suspend = sd_suspend,
+ .resume = sd_resume,
.shutdown = sd_shutdown,
},
.rescan = sd_rescan,
@@ -371,15 +341,19 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
unsigned int this_count = SCpnt->request_bufflen >> 9;
unsigned int timeout = sdp->timeout;
- SCSI_LOG_HLQUEUE(1, printk("sd_init_command: disk=%s, block=%llu, "
- "count=%d\n", disk->disk_name,
- (unsigned long long)block, this_count));
+ SCSI_LOG_HLQUEUE(1, scmd_printk(KERN_INFO, SCpnt,
+ "sd_init_command: block=%llu, "
+ "count=%d\n",
+ (unsigned long long)block,
+ this_count));
if (!sdp || !scsi_device_online(sdp) ||
block + rq->nr_sectors > get_capacity(disk)) {
- SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n",
- rq->nr_sectors));
- SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt));
+ SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt,
+ "Finishing %ld sectors\n",
+ rq->nr_sectors));
+ SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt,
+ "Retry with 0x%p\n", SCpnt));
return 0;
}
@@ -391,8 +365,8 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
/* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */
return 0;
}
- SCSI_LOG_HLQUEUE(2, printk("%s : block=%llu\n",
- disk->disk_name, (unsigned long long)block));
+ SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "block=%llu\n",
+ (unsigned long long)block));
/*
* If we have a 1K hardware sectorsize, prevent access to single
@@ -407,7 +381,8 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
*/
if (sdp->sector_size == 1024) {
if ((block & 1) || (rq->nr_sectors & 1)) {
- printk(KERN_ERR "sd: Bad block number requested");
+ scmd_printk(KERN_ERR, SCpnt,
+ "Bad block number requested\n");
return 0;
} else {
block = block >> 1;
@@ -416,7 +391,8 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
}
if (sdp->sector_size == 2048) {
if ((block & 3) || (rq->nr_sectors & 3)) {
- printk(KERN_ERR "sd: Bad block number requested");
+ scmd_printk(KERN_ERR, SCpnt,
+ "Bad block number requested\n");
return 0;
} else {
block = block >> 2;
@@ -425,7 +401,8 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
}
if (sdp->sector_size == 4096) {
if ((block & 7) || (rq->nr_sectors & 7)) {
- printk(KERN_ERR "sd: Bad block number requested");
+ scmd_printk(KERN_ERR, SCpnt,
+ "Bad block number requested\n");
return 0;
} else {
block = block >> 3;
@@ -442,13 +419,15 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
SCpnt->cmnd[0] = READ_6;
SCpnt->sc_data_direction = DMA_FROM_DEVICE;
} else {
- printk(KERN_ERR "sd: Unknown command %x\n", rq->cmd_flags);
+ scmd_printk(KERN_ERR, SCpnt, "Unknown command %x\n", rq->cmd_flags);
return 0;
}
- SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n",
- disk->disk_name, (rq_data_dir(rq) == WRITE) ?
- "writing" : "reading", this_count, rq->nr_sectors));
+ SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt,
+ "%s %d/%ld 512 byte blocks.\n",
+ (rq_data_dir(rq) == WRITE) ?
+ "writing" : "reading", this_count,
+ rq->nr_sectors));
SCpnt->cmnd[1] = 0;
@@ -490,7 +469,8 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
* during operation and thus turned off
* use_10_for_rw.
*/
- printk(KERN_ERR "sd: FUA write on READ/WRITE(6) drive\n");
+ scmd_printk(KERN_ERR, SCpnt,
+ "FUA write on READ/WRITE(6) drive\n");
return 0;
}
@@ -549,7 +529,7 @@ static int sd_open(struct inode *inode, struct file *filp)
return -ENXIO;
- SCSI_LOG_HLQUEUE(3, printk("sd_open: disk=%s\n", disk->disk_name));
+ SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_open\n"));
sdev = sdkp->device;
@@ -619,7 +599,7 @@ static int sd_release(struct inode *inode, struct file *filp)
struct scsi_disk *sdkp = scsi_disk(disk);
struct scsi_device *sdev = sdkp->device;
- SCSI_LOG_HLQUEUE(3, printk("sd_release: disk=%s\n", disk->disk_name));
+ SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_release\n"));
if (!--sdkp->openers && sdev->removable) {
if (scsi_block_when_processing_errors(sdev))
@@ -732,8 +712,7 @@ static int sd_media_changed(struct gendisk *disk)
struct scsi_device *sdp = sdkp->device;
int retval;
- SCSI_LOG_HLQUEUE(3, printk("sd_media_changed: disk=%s\n",
- disk->disk_name));
+ SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_media_changed\n"));
if (!sdp->removable)
return 0;
@@ -786,9 +765,10 @@ not_present:
return 1;
}
-static int sd_sync_cache(struct scsi_device *sdp)
+static int sd_sync_cache(struct scsi_disk *sdkp)
{
int retries, res;
+ struct scsi_device *sdp = sdkp->device;
struct scsi_sense_hdr sshdr;
if (!scsi_device_online(sdp))
@@ -809,28 +789,27 @@ static int sd_sync_cache(struct scsi_device *sdp)
break;
}
- if (res) { printk(KERN_WARNING "FAILED\n status = %x, message = %02x, "
- "host = %d, driver = %02x\n ",
- status_byte(res), msg_byte(res),
- host_byte(res), driver_byte(res));
- if (driver_byte(res) & DRIVER_SENSE)
- scsi_print_sense_hdr("sd", &sshdr);
+ if (res) {
+ sd_print_result(sdkp, res);
+ if (driver_byte(res) & DRIVER_SENSE)
+ sd_print_sense_hdr(sdkp, &sshdr);
}
- return res;
+ if (res)
+ return -EIO;
+ return 0;
}
static int sd_issue_flush(struct device *dev, sector_t *error_sector)
{
int ret = 0;
- struct scsi_device *sdp = to_scsi_device(dev);
struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
if (!sdkp)
return -ENODEV;
if (sdkp->WCE)
- ret = sd_sync_cache(sdp);
+ ret = sd_sync_cache(sdkp);
scsi_disk_put(sdkp);
return ret;
}
@@ -928,12 +907,14 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt)
sense_deferred = scsi_sense_is_deferred(&sshdr);
}
#ifdef CONFIG_SCSI_LOGGING
- SCSI_LOG_HLCOMPLETE(1, printk("sd_rw_intr: %s: res=0x%x\n",
- SCpnt->request->rq_disk->disk_name, result));
+ SCSI_LOG_HLCOMPLETE(1, scsi_print_result(SCpnt));
if (sense_valid) {
- SCSI_LOG_HLCOMPLETE(1, printk("sd_rw_intr: sb[respc,sk,asc,"
- "ascq]=%x,%x,%x,%x\n", sshdr.response_code,
- sshdr.sense_key, sshdr.asc, sshdr.ascq));
+ SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, SCpnt,
+ "sd_rw_intr: sb[respc,sk,asc,"
+ "ascq]=%x,%x,%x,%x\n",
+ sshdr.response_code,
+ sshdr.sense_key, sshdr.asc,
+ sshdr.ascq));
}
#endif
if (driver_byte(result) != DRIVER_SENSE &&
@@ -1025,7 +1006,7 @@ static int media_not_present(struct scsi_disk *sdkp,
* spinup disk - called only in sd_revalidate_disk()
*/
static void
-sd_spinup_disk(struct scsi_disk *sdkp, char *diskname)
+sd_spinup_disk(struct scsi_disk *sdkp)
{
unsigned char cmd[10];
unsigned long spintime_expire = 0;
@@ -1069,9 +1050,10 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname)
if ((driver_byte(the_result) & DRIVER_SENSE) == 0) {
/* no sense, TUR either succeeded or failed
* with a status error */
- if(!spintime && !scsi_status_is_good(the_result))
- printk(KERN_NOTICE "%s: Unit Not Ready, "
- "error = 0x%x\n", diskname, the_result);
+ if(!spintime && !scsi_status_is_good(the_result)) {
+ sd_printk(KERN_NOTICE, sdkp, "Unit Not Ready\n");
+ sd_print_result(sdkp, the_result);
+ }
break;
}
@@ -1096,8 +1078,7 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname)
*/
} else if (sense_valid && sshdr.sense_key == NOT_READY) {
if (!spintime) {
- printk(KERN_NOTICE "%s: Spinning up disk...",
- diskname);
+ sd_printk(KERN_NOTICE, sdkp, "Spinning up disk...");
cmd[0] = START_STOP;
cmd[1] = 1; /* Return immediately */
memset((void *) &cmd[2], 0, 8);
@@ -1130,9 +1111,8 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname)
/* we don't understand the sense code, so it's
* probably pointless to loop */
if(!spintime) {
- printk(KERN_NOTICE "%s: Unit Not Ready, "
- "sense:\n", diskname);
- scsi_print_sense_hdr("", &sshdr);
+ sd_printk(KERN_NOTICE, sdkp, "Unit Not Ready\n");
+ sd_print_sense_hdr(sdkp, &sshdr);
}
break;
}
@@ -1151,8 +1131,7 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname)
* read disk capacity
*/
static void
-sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
- unsigned char *buffer)
+sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer)
{
unsigned char cmd[16];
int the_result, retries;
@@ -1191,18 +1170,12 @@ repeat:
} while (the_result && retries);
if (the_result && !longrc) {
- printk(KERN_NOTICE "%s : READ CAPACITY failed.\n"
- "%s : status=%x, message=%02x, host=%d, driver=%02x \n",
- diskname, diskname,
- status_byte(the_result),
- msg_byte(the_result),
- host_byte(the_result),
- driver_byte(the_result));
-
+ sd_printk(KERN_NOTICE, sdkp, "READ CAPACITY failed\n");
+ sd_print_result(sdkp, the_result);
if (driver_byte(the_result) & DRIVER_SENSE)
- scsi_print_sense_hdr("sd", &sshdr);
+ sd_print_sense_hdr(sdkp, &sshdr);
else
- printk("%s : sense not available. \n", diskname);
+ sd_printk(KERN_NOTICE, sdkp, "Sense not available.\n");
/* Set dirty bit for removable devices if not ready -
* sometimes drives will not report this properly. */
@@ -1218,16 +1191,10 @@ repeat:
return;
} else if (the_result && longrc) {
/* READ CAPACITY(16) has been failed */
- printk(KERN_NOTICE "%s : READ CAPACITY(16) failed.\n"
- "%s : status=%x, message=%02x, host=%d, driver=%02x \n",
- diskname, diskname,
- status_byte(the_result),
- msg_byte(the_result),
- host_byte(the_result),
- driver_byte(the_result));
- printk(KERN_NOTICE "%s : use 0xffffffff as device size\n",
- diskname);
-
+ sd_printk(KERN_NOTICE, sdkp, "READ CAPACITY(16) failed\n");
+ sd_print_result(sdkp, the_result);
+ sd_printk(KERN_NOTICE, sdkp, "Use 0xffffffff as device size\n");
+
sdkp->capacity = 1 + (sector_t) 0xffffffff;
goto got_data;
}
@@ -1238,14 +1205,14 @@ repeat:
if (buffer[0] == 0xff && buffer[1] == 0xff &&
buffer[2] == 0xff && buffer[3] == 0xff) {
if(sizeof(sdkp->capacity) > 4) {
- printk(KERN_NOTICE "%s : very big device. try to use"
- " READ CAPACITY(16).\n", diskname);
+ sd_printk(KERN_NOTICE, sdkp, "Very big device. "
+ "Trying to use READ CAPACITY(16).\n");
longrc = 1;
goto repeat;
}
- printk(KERN_ERR "%s: too big for this kernel. Use a "
- "kernel compiled with support for large block "
- "devices.\n", diskname);
+ sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use "
+ "a kernel compiled with support for large "
+ "block devices.\n");
sdkp->capacity = 0;
goto got_data;
}
@@ -1284,8 +1251,8 @@ repeat:
got_data:
if (sector_size == 0) {
sector_size = 512;
- printk(KERN_NOTICE "%s : sector size 0 reported, "
- "assuming 512.\n", diskname);
+ sd_printk(KERN_NOTICE, sdkp, "Sector size 0 reported, "
+ "assuming 512.\n");
}
if (sector_size != 512 &&
@@ -1293,8 +1260,8 @@ got_data:
sector_size != 2048 &&
sector_size != 4096 &&
sector_size != 256) {
- printk(KERN_NOTICE "%s : unsupported sector size "
- "%d.\n", diskname, sector_size);
+ sd_printk(KERN_NOTICE, sdkp, "Unsupported sector size %d.\n",
+ sector_size);
/*
* The user might want to re-format the drive with
* a supported sectorsize. Once this happens, it
@@ -1327,10 +1294,10 @@ got_data:
mb -= sz - 974;
sector_div(mb, 1950);
- printk(KERN_NOTICE "SCSI device %s: "
- "%llu %d-byte hdwr sectors (%llu MB)\n",
- diskname, (unsigned long long)sdkp->capacity,
- hard_sector, (unsigned long long)mb);
+ sd_printk(KERN_NOTICE, sdkp,
+ "%llu %d-byte hardware sectors (%llu MB)\n",
+ (unsigned long long)sdkp->capacity,
+ hard_sector, (unsigned long long)mb);
}
/* Rescale capacity to 512-byte units */
@@ -1362,8 +1329,7 @@ sd_do_mode_sense(struct scsi_device *sdp, int dbd, int modepage,
* called with buffer of length SD_BUF_SIZE
*/
static void
-sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname,
- unsigned char *buffer)
+sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer)
{
int res;
struct scsi_device *sdp = sdkp->device;
@@ -1371,7 +1337,7 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname,
set_disk_ro(sdkp->disk, 0);
if (sdp->skip_ms_page_3f) {
- printk(KERN_NOTICE "%s: assuming Write Enabled\n", diskname);
+ sd_printk(KERN_NOTICE, sdkp, "Assuming Write Enabled\n");
return;
}
@@ -1403,15 +1369,16 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname,
}
if (!scsi_status_is_good(res)) {
- printk(KERN_WARNING
- "%s: test WP failed, assume Write Enabled\n", diskname);
+ sd_printk(KERN_WARNING, sdkp,
+ "Test WP failed, assume Write Enabled\n");
} else {
sdkp->write_prot = ((data.device_specific & 0x80) != 0);
set_disk_ro(sdkp->disk, sdkp->write_prot);
- printk(KERN_NOTICE "%s: Write Protect is %s\n", diskname,
- sdkp->write_prot ? "on" : "off");
- printk(KERN_DEBUG "%s: Mode Sense: %02x %02x %02x %02x\n",
- diskname, buffer[0], buffer[1], buffer[2], buffer[3]);
+ sd_printk(KERN_NOTICE, sdkp, "Write Protect is %s\n",
+ sdkp->write_prot ? "on" : "off");
+ sd_printk(KERN_DEBUG, sdkp,
+ "Mode Sense: %02x %02x %02x %02x\n",
+ buffer[0], buffer[1], buffer[2], buffer[3]);
}
}
@@ -1420,8 +1387,7 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname,
* called with buffer of length SD_BUF_SIZE
*/
static void
-sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
- unsigned char *buffer)
+sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
{
int len = 0, res;
struct scsi_device *sdp = sdkp->device;
@@ -1450,8 +1416,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
if (!data.header_length) {
modepage = 6;
- printk(KERN_ERR "%s: missing header in MODE_SENSE response\n",
- diskname);
+ sd_printk(KERN_ERR, sdkp, "Missing header in MODE_SENSE response\n");
}
/* that went OK, now ask for the proper length */
@@ -1478,13 +1443,12 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
int offset = data.header_length + data.block_descriptor_length;
if (offset >= SD_BUF_SIZE - 2) {
- printk(KERN_ERR "%s: malformed MODE SENSE response",
- diskname);
+ sd_printk(KERN_ERR, sdkp, "Malformed MODE SENSE response\n");
goto defaults;
}
if ((buffer[offset] & 0x3f) != modepage) {
- printk(KERN_ERR "%s: got wrong page\n", diskname);
+ sd_printk(KERN_ERR, sdkp, "Got wrong page\n");
goto defaults;
}
@@ -1498,14 +1462,13 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
sdkp->DPOFUA = (data.device_specific & 0x10) != 0;
if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw) {
- printk(KERN_NOTICE "SCSI device %s: uses "
- "READ/WRITE(6), disabling FUA\n", diskname);
+ sd_printk(KERN_NOTICE, sdkp,
+ "Uses READ/WRITE(6), disabling FUA\n");
sdkp->DPOFUA = 0;
}
- printk(KERN_NOTICE "SCSI device %s: "
- "write cache: %s, read cache: %s, %s\n",
- diskname,
+ sd_printk(KERN_NOTICE, sdkp,
+ "Write cache: %s, read cache: %s, %s\n",
sdkp->WCE ? "enabled" : "disabled",
sdkp->RCD ? "disabled" : "enabled",
sdkp->DPOFUA ? "supports DPO and FUA"
@@ -1518,15 +1481,13 @@ bad_sense:
if (scsi_sense_valid(&sshdr) &&
sshdr.sense_key == ILLEGAL_REQUEST &&
sshdr.asc == 0x24 && sshdr.ascq == 0x0)
- printk(KERN_NOTICE "%s: cache data unavailable\n",
- diskname); /* Invalid field in CDB */
+ /* Invalid field in CDB */
+ sd_printk(KERN_NOTICE, sdkp, "Cache data unavailable\n");
else
- printk(KERN_ERR "%s: asking for cache data failed\n",
- diskname);
+ sd_printk(KERN_ERR, sdkp, "Asking for cache data failed\n");
defaults:
- printk(KERN_ERR "%s: assuming drive cache: write through\n",
- diskname);
+ sd_printk(KERN_ERR, sdkp, "Assuming drive cache: write through\n");
sdkp->WCE = 0;
sdkp->RCD = 0;
sdkp->DPOFUA = 0;
@@ -1544,7 +1505,8 @@ static int sd_revalidate_disk(struct gendisk *disk)
unsigned char *buffer;
unsigned ordered;
- SCSI_LOG_HLQUEUE(3, printk("sd_revalidate_disk: disk=%s\n", disk->disk_name));
+ SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp,
+ "sd_revalidate_disk\n"));
/*
* If the device is offline, don't try and read capacity or any
@@ -1555,8 +1517,8 @@ static int sd_revalidate_disk(struct gendisk *disk)
buffer = kmalloc(SD_BUF_SIZE, GFP_KERNEL | __GFP_DMA);
if (!buffer) {
- printk(KERN_WARNING "(sd_revalidate_disk:) Memory allocation "
- "failure.\n");
+ sd_printk(KERN_WARNING, sdkp, "sd_revalidate_disk: Memory "
+ "allocation failure.\n");
goto out;
}
@@ -1568,16 +1530,16 @@ static int sd_revalidate_disk(struct gendisk *disk)
sdkp->WCE = 0;
sdkp->RCD = 0;
- sd_spinup_disk(sdkp, disk->disk_name);
+ sd_spinup_disk(sdkp);
/*
* Without media there is no reason to ask; moreover, some devices
* react badly if we do.
*/
if (sdkp->media_present) {
- sd_read_capacity(sdkp, disk->disk_name, buffer);
- sd_read_write_protect_flag(sdkp, disk->disk_name, buffer);
- sd_read_cache_type(sdkp, disk->disk_name, buffer);
+ sd_read_capacity(sdkp, buffer);
+ sd_read_write_protect_flag(sdkp, buffer);
+ sd_read_cache_type(sdkp, buffer);
}
/*
@@ -1709,8 +1671,8 @@ static int sd_probe(struct device *dev)
dev_set_drvdata(dev, sdkp);
add_disk(gd);
- sdev_printk(KERN_NOTICE, sdp, "Attached scsi %sdisk %s\n",
- sdp->removable ? "removable " : "", gd->disk_name);
+ sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
+ sdp->removable ? "removable " : "");
return 0;
@@ -1774,6 +1736,31 @@ static void scsi_disk_release(struct class_device *cdev)
kfree(sdkp);
}
+static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
+{
+ unsigned char cmd[6] = { START_STOP }; /* START_VALID */
+ struct scsi_sense_hdr sshdr;
+ struct scsi_device *sdp = sdkp->device;
+ int res;
+
+ if (start)
+ cmd[4] |= 1; /* START */
+
+ if (!scsi_device_online(sdp))
+ return -ENODEV;
+
+ res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
+ SD_TIMEOUT, SD_MAX_RETRIES);
+ if (res) {
+ sd_printk(KERN_WARNING, sdkp, "START_STOP FAILED\n");
+ sd_print_result(sdkp, res);
+ if (driver_byte(res) & DRIVER_SENSE)
+ sd_print_sense_hdr(sdkp, &sshdr);
+ }
+
+ return res;
+}
+
/*
* Send a SYNCHRONIZE CACHE instruction down to the device through
* the normal SCSI command structure. Wait for the command to
@@ -1781,20 +1768,62 @@ static void scsi_disk_release(struct class_device *cdev)
*/
static void sd_shutdown(struct device *dev)
{
- struct scsi_device *sdp = to_scsi_device(dev);
struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
if (!sdkp)
return; /* this can happen */
if (sdkp->WCE) {
- printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: \n",
- sdkp->disk->disk_name);
- sd_sync_cache(sdp);
+ sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
+ sd_sync_cache(sdkp);
+ }
+
+ if (system_state != SYSTEM_RESTART && sdkp->device->manage_start_stop) {
+ sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
+ sd_start_stop_device(sdkp, 0);
}
+
scsi_disk_put(sdkp);
}
+static int sd_suspend(struct device *dev, pm_message_t mesg)
+{
+ struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
+ int ret;
+
+ if (!sdkp)
+ return 0; /* this can happen */
+
+ if (sdkp->WCE) {
+ sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
+ ret = sd_sync_cache(sdkp);
+ if (ret)
+ return ret;
+ }
+
+ if (mesg.event == PM_EVENT_SUSPEND &&
+ sdkp->device->manage_start_stop) {
+ sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
+ ret = sd_start_stop_device(sdkp, 0);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int sd_resume(struct device *dev)
+{
+ struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
+
+ if (!sdkp->device->manage_start_stop)
+ return 0;
+
+ sd_printk(KERN_NOTICE, sdkp, "Starting disk\n");
+
+ return sd_start_stop_device(sdkp, 1);
+}
+
/**
* init_sd - entry point for this driver (both when built in or when
* a module).
@@ -1852,3 +1881,19 @@ static void __exit exit_sd(void)
module_init(init_sd);
module_exit(exit_sd);
+
+static void sd_print_sense_hdr(struct scsi_disk *sdkp,
+ struct scsi_sense_hdr *sshdr)
+{
+ sd_printk(KERN_INFO, sdkp, "");
+ scsi_show_sense_hdr(sshdr);
+ sd_printk(KERN_INFO, sdkp, "");
+ scsi_show_extd_sense(sshdr->asc, sshdr->ascq);
+}
+
+static void sd_print_result(struct scsi_disk *sdkp, int result)
+{
+ sd_printk(KERN_INFO, sdkp, "");
+ scsi_show_result(result);
+}
+
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 81e3bc7b02a1..570977cf9efb 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -917,6 +917,8 @@ sg_ioctl(struct inode *inode, struct file *filp,
return result;
if (val < 0)
return -EINVAL;
+ val = min_t(int, val,
+ sdp->device->request_queue->max_sectors * 512);
if (val != sfp->reserve.bufflen) {
if (sg_res_in_use(sfp) || sfp->mmap_called)
return -EBUSY;
@@ -925,7 +927,8 @@ sg_ioctl(struct inode *inode, struct file *filp,
}
return 0;
case SG_GET_RESERVED_SIZE:
- val = (int) sfp->reserve.bufflen;
+ val = min_t(int, sfp->reserve.bufflen,
+ sdp->device->request_queue->max_sectors * 512);
return put_user(val, ip);
case SG_SET_COMMAND_Q:
result = get_user(val, ip);
@@ -1061,6 +1064,9 @@ sg_ioctl(struct inode *inode, struct file *filp,
if (sdp->detached)
return -ENODEV;
return scsi_ioctl(sdp->device, cmd_in, p);
+ case BLKSECTGET:
+ return put_user(sdp->device->request_queue->max_sectors * 512,
+ ip);
default:
if (read_only)
return -EPERM; /* don't know so take safe approach */
@@ -2339,6 +2345,7 @@ sg_add_sfp(Sg_device * sdp, int dev)
{
Sg_fd *sfp;
unsigned long iflags;
+ int bufflen;
sfp = kzalloc(sizeof(*sfp), GFP_ATOMIC | __GFP_NOWARN);
if (!sfp)
@@ -2369,7 +2376,9 @@ sg_add_sfp(Sg_device * sdp, int dev)
if (unlikely(sg_big_buff != def_reserved_size))
sg_big_buff = def_reserved_size;
- sg_build_reserve(sfp, sg_big_buff);
+ bufflen = min_t(int, sg_big_buff,
+ sdp->device->request_queue->max_sectors * 512);
+ sg_build_reserve(sfp, bufflen);
SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: bufflen=%d, k_use_sg=%d\n",
sfp->reserve.bufflen, sfp->reserve.k_use_sg));
return sfp;
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 1857d68e7195..f9a52af7f5b4 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -62,6 +62,8 @@
MODULE_DESCRIPTION("SCSI cdrom (sr) driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_CDROM_MAJOR);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_ROM);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_WORM);
#define SR_DISKS 256
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 98d8411bbccc..55bfeccf68a2 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -89,6 +89,7 @@ MODULE_AUTHOR("Kai Makisara");
MODULE_DESCRIPTION("SCSI tape (st) driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS_CHARDEV_MAJOR(SCSI_TAPE_MAJOR);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE);
/* Set 'perm' (4th argument) to 0 to disable module_param's definition
* of sysfs parameters (which module_param doesn't yet support).
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
index a583e89238fc..3158949ffa62 100644
--- a/drivers/scsi/tmscsim.c
+++ b/drivers/scsi/tmscsim.c
@@ -2680,7 +2680,7 @@ static int __init dc390_module_init(void)
printk (KERN_INFO "DC390: Using safe settings.\n");
}
- return pci_module_init(&dc390_driver);
+ return pci_register_driver(&dc390_driver);
}
static void __exit dc390_module_exit(void)