Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (87 commits)
  [SCSI] fusion: fix domain validation loops
  [SCSI] qla2xxx: fix regression on sparc64
  [SCSI] modalias for scsi devices
  [SCSI] sg: cap reserved_size values at max_sectors
  [SCSI] BusLogic: stop using check_region
  [SCSI] tgt: fix rdma transfer bugs
  [SCSI] aacraid: fix aacraid not finding device
  [SCSI] aacraid: Correct SMC products in aacraid.txt
  [SCSI] scsi_error.c: Add EH Start Unit retry
  [SCSI] aacraid: [Fastboot] Panics for AACRAID driver during 'insmod' for kexec test.
  [SCSI] ipr: Driver version to 2.3.2
  [SCSI] ipr: Faster sg list fetch
  [SCSI] ipr: Return better qc_issue errors
  [SCSI] ipr: Disrupt device error
  [SCSI] ipr: Improve async error logging level control
  [SCSI] ipr: PCI unblock config access fix
  [SCSI] ipr: Fix for oops following SATA request sense
  [SCSI] ipr: Log error for SAS dual path switch
  [SCSI] ipr: Enable logging of debug error data for all devices
  [SCSI] ipr: Add new PCI-E IDs to device table
  ...
This commit is contained in:
Linus Torvalds 2007-05-05 13:30:44 -07:00
commit 4f7a307dc6
77 changed files with 1990 additions and 1659 deletions

View File

@ -37,7 +37,11 @@ Supported Cards/Chipsets
9005:0286:9005:029d Adaptec 2420SA (Intruder HP release)
9005:0286:9005:02ac Adaptec 1800 (Typhoon44)
9005:0285:9005:02b5 Adaptec 5445 (Voodoo44)
9005:0285:15d9:02b5 SMC AOC-USAS-S4i
9005:0285:15d9:02c9 SMC AOC-USAS-S4iR
9005:0285:9005:02b6 Adaptec 5805 (Voodoo80)
9005:0285:15d9:02b6 SMC AOC-USAS-S8i
9005:0285:15d9:02ca SMC AOC-USAS-S8iR
9005:0285:9005:02b7 Adaptec 5085 (Voodoo08)
9005:0285:9005:02bb Adaptec 3405 (Marauder40LP)
9005:0285:9005:02bc Adaptec 3805 (Marauder80LP)
@ -93,6 +97,9 @@ Supported Cards/Chipsets
9005:0286:9005:02ae (Aurora Lite ARK)
9005:0285:9005:02b0 (Sunrise Lake ARK)
9005:0285:9005:02b1 Adaptec (Voodoo 8 internal 8 external)
9005:0285:108e:7aac SUN STK RAID REM (Voodoo44 Coyote)
9005:0285:108e:0286 SUN SG-XPCIESAS-R-IN (Cougar)
9005:0285:108e:0287 SUN SG-XPCIESAS-R-EX (Prometheus)
People
-------------------------

View File

@ -562,11 +562,6 @@ if only one has a flaw for some SCSI feature, you can disable the
support by the driver of this feature at linux start-up and enable
this feature after boot-up only for devices that support it safely.
CONFIG_SCSI_NCR53C8XX_PROFILE_SUPPORT (default answer: n)
This option must be set for profiling information to be gathered
and printed out through the proc file system. This features may
impact performances.
CONFIG_SCSI_NCR53C8XX_IOMAPPED (default answer: n)
Answer "y" if you suspect your mother board to not allow memory mapped I/O.
May slow down performance a little. This option is required by

View File

@ -1925,6 +1925,8 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS);
blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
q->sg_reserved_size = INT_MAX;
/*
* all done
*/

View File

@ -78,7 +78,9 @@ static int sg_set_timeout(request_queue_t *q, int __user *p)
static int sg_get_reserved_size(request_queue_t *q, int __user *p)
{
return put_user(q->sg_reserved_size, p);
unsigned val = min(q->sg_reserved_size, q->max_sectors << 9);
return put_user(val, p);
}
static int sg_set_reserved_size(request_queue_t *q, int __user *p)

View File

@ -201,7 +201,7 @@ static int iser_post_receive_control(struct iscsi_conn *conn)
* what's common for both schemes is that the connection is not started
*/
if (conn->c_stage != ISCSI_CONN_STARTED)
rx_data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
rx_data_size = ISCSI_DEF_MAX_RECV_SEG_LEN;
else /* FIXME till user space sets conn->max_recv_dlength correctly */
rx_data_size = 128;

View File

@ -1531,6 +1531,7 @@ mpt_resume(struct pci_dev *pdev)
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
u32 device_state = pdev->current_state;
int recovery_state;
int err;
printk(MYIOC_s_INFO_FMT
"pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
@ -1538,7 +1539,9 @@ mpt_resume(struct pci_dev *pdev)
pci_set_power_state(pdev, 0);
pci_restore_state(pdev);
pci_enable_device(pdev);
err = pci_enable_device(pdev);
if (err)
return err;
/* enable interrupts */
CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
@ -4739,12 +4742,8 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
}
/**
* mpt_inactive_raid_list_free
*
* This clears this link list.
*
* @ioc - pointer to per adapter structure
*
* mpt_inactive_raid_list_free - This clears this link list.
* @ioc : pointer to per adapter structure
**/
static void
mpt_inactive_raid_list_free(MPT_ADAPTER *ioc)
@ -4764,15 +4763,11 @@ mpt_inactive_raid_list_free(MPT_ADAPTER *ioc)
}
/**
* mpt_inactive_raid_volumes
*
* This sets up link list of phy_disk_nums for devices belonging in an inactive volume
*
* @ioc - pointer to per adapter structure
* @channel - volume channel
* @id - volume target id
*
* mpt_inactive_raid_volumes - sets up link list of phy_disk_nums for devices belonging in an inactive volume
*
* @ioc : pointer to per adapter structure
* @channel : volume channel
* @id : volume target id
**/
static void
mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id)
@ -6663,7 +6658,7 @@ union loginfo_type {
/**
* mpt_iocstatus_info_config - IOCSTATUS information for config pages
* @ioc: Pointer to MPT_ADAPTER structure
* ioc_status: U32 IOCStatus word from IOC
* @ioc_status: U32 IOCStatus word from IOC
* @mf: Pointer to MPT request frame
*
* Refer to lsi/mpi.h.

View File

@ -994,6 +994,7 @@ typedef struct _MPT_SCSI_HOST {
int scandv_wait_done;
long last_queue_full;
u16 tm_iocstatus;
u16 spi_pending;
struct list_head target_reset_list;
} MPT_SCSI_HOST;

View File

@ -819,9 +819,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
sc->resid=0;
case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
if (scsi_status == MPI_SCSI_STATUS_BUSY)
sc->result = (DID_BUS_BUSY << 16) | scsi_status;
else
sc->result = (DID_OK << 16) | scsi_status;
if (scsi_state == 0) {
;
@ -1188,20 +1185,7 @@ mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
int
mptscsih_resume(struct pci_dev *pdev)
{
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
struct Scsi_Host *host = ioc->sh;
MPT_SCSI_HOST *hd;
mpt_resume(pdev);
if(!host)
return 0;
hd = (MPT_SCSI_HOST *)host->hostdata;
if(!hd)
return 0;
return 0;
return mpt_resume(pdev);
}
#endif
@ -1537,21 +1521,23 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptscsih_TMHandler - Generic handler for SCSI Task Management.
* Fall through to mpt_HardResetHandler if: not operational, too many
* failed TM requests or handshake failure.
*
* @ioc: Pointer to MPT_ADAPTER structure
* @hd: Pointer to MPT SCSI HOST structure
* @type: Task Management type
* @channel: channel number for task management
* @id: Logical Target ID for reset (if appropriate)
* @lun: Logical Unit for reset (if appropriate)
* @ctx2abort: Context for the task to be aborted (if appropriate)
* @timeout: timeout for task management control
*
* Fall through to mpt_HardResetHandler if: not operational, too many
* failed TM requests or handshake failure.
*
* Remark: Currently invoked from a non-interrupt thread (_bh).
*
* Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
* will be active.
*
* Returns 0 for SUCCESS, or FAILED.
* Returns 0 for SUCCESS, or %FAILED.
**/
int
mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
@ -1650,9 +1636,11 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c
* mptscsih_IssueTaskMgmt - Generic send Task Management function.
* @hd: Pointer to MPT_SCSI_HOST structure
* @type: Task Management type
* @channel: channel number for task management
* @id: Logical Target ID for reset (if appropriate)
* @lun: Logical Unit for reset (if appropriate)
* @ctx2abort: Context for the task to be aborted (if appropriate)
* @timeout: timeout for task management control
*
* Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
* or a non-interrupt thread. In the former, must not call schedule().
@ -2022,6 +2010,7 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
/**
* mptscsih_tm_wait_for_completion - wait for completion of TM task
* @hd: Pointer to MPT host structure.
* @timeout: timeout value
*
* Returns {SUCCESS,FAILED}.
*/

View File

@ -96,14 +96,13 @@ static int mptspiTaskCtx = -1;
static int mptspiInternalCtx = -1; /* Used only for internal commands */
/**
* mptspi_setTargetNegoParms - Update the target negotiation
* parameters based on the the Inquiry data, adapter capabilities,
* and NVRAM settings
*
* mptspi_setTargetNegoParms - Update the target negotiation parameters
* @hd: Pointer to a SCSI Host Structure
* @vtarget: per target private data
* @target: per target private data
* @sdev: SCSI device
*
* Update the target negotiation parameters based on the the Inquiry
* data, adapter capabilities, and NVRAM settings.
**/
static void
mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
@ -234,7 +233,7 @@ mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
/**
* mptspi_writeIOCPage4 - write IOC Page 4
* @hd: Pointer to a SCSI Host Structure
* @channel:
* @channel: channel number
* @id: write IOC Page4 for this ID & Bus
*
* Return: -EAGAIN if unable to obtain a Message Frame
@ -446,7 +445,7 @@ static int mptspi_target_alloc(struct scsi_target *starget)
return 0;
}
void
static void
mptspi_target_destroy(struct scsi_target *starget)
{
if (starget->hostdata)
@ -677,7 +676,9 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,
return;
}
hd->spi_pending |= (1 << sdev->id);
spi_dv_device(sdev);
hd->spi_pending &= ~(1 << sdev->id);
if (sdev->channel == 1 &&
mptscsih_quiesce_raid(hd, 0, vtarget->channel, vtarget->id) < 0)
@ -1203,11 +1204,27 @@ mptspi_dv_renegotiate_work(struct work_struct *work)
container_of(work, struct work_queue_wrapper, work);
struct _MPT_SCSI_HOST *hd = wqw->hd;
struct scsi_device *sdev;
struct scsi_target *starget;
struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;
u32 nego;
kfree(wqw);
if (hd->spi_pending) {
shost_for_each_device(sdev, hd->ioc->sh) {
if (hd->spi_pending & (1 << sdev->id))
continue;
starget = scsi_target(sdev);
nego = mptspi_getRP(starget);
pg1.RequestedParameters = cpu_to_le32(nego);
pg1.Reserved = 0;
pg1.Configuration = 0;
mptspi_write_spi_device_pg1(starget, &pg1);
}
} else {
shost_for_each_device(sdev, hd->ioc->sh)
mptspi_dv_device(hd, sdev);
}
}
static void
@ -1453,6 +1470,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
init_waitqueue_head(&hd->scandv_waitq);
hd->scandv_wait_done = 0;
hd->last_queue_full = 0;
hd->spi_pending = 0;
/* Some versions of the firmware don't support page 0; without
* that we can't get the parameters */

View File

@ -186,7 +186,7 @@ void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout)
{
fsf_req->timer.function = zfcp_fsf_request_timeout_handler;
fsf_req->timer.data = (unsigned long) fsf_req->adapter;
fsf_req->timer.expires = timeout;
fsf_req->timer.expires = jiffies + timeout;
add_timer(&fsf_req->timer);
}

View File

@ -299,9 +299,10 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
}
/* log additional information provided by FSF (if any) */
if (unlikely(qtcb->header.log_length)) {
if (likely(qtcb->header.log_length)) {
/* do not trust them ;-) */
if (qtcb->header.log_start > sizeof(struct fsf_qtcb)) {
if (unlikely(qtcb->header.log_start >
sizeof(struct fsf_qtcb))) {
ZFCP_LOG_NORMAL
("bug: ULP (FSF logging) log data starts "
"beyond end of packet header. Ignored. "
@ -310,8 +311,9 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
sizeof(struct fsf_qtcb));
goto forget_log;
}
if ((size_t) (qtcb->header.log_start + qtcb->header.log_length)
> sizeof(struct fsf_qtcb)) {
if (unlikely((size_t) (qtcb->header.log_start +
qtcb->header.log_length) >
sizeof(struct fsf_qtcb))) {
ZFCP_LOG_NORMAL("bug: ULP (FSF logging) log data ends "
"beyond end of packet header. Ignored. "
"(start=%i, length=%i, size=%li)\n",

View File

@ -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.
*/
@ -2246,16 +2271,6 @@ static int __init BusLogic_init(void)
and Electronic Mail Address.
*/
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);

View File

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

View File

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

View File

@ -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);
status = aac_probe_container(dev, index);
dinfo->command = cpu_to_le32(VM_NameServe);
dinfo->count = cpu_to_le32(index);
dinfo->type = cpu_to_le32(FT_FILESYS);
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,6 +444,153 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
return -1;
}
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 (*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;
int status;
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 (!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_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,
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) {
/* Inherit results from VM_NameServe, if any */
dresp->status = cpu_to_le32(ST_OK);
return _aac_probe_container2(context, fibptr);
}
return 0;
}
static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(struct scsi_cmnd *))
{
struct fib * fibptr;
int status = -ENOMEM;
if ((fibptr = aac_fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata))) {
struct aac_query_mount *dinfo;
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;
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;
}
/**
* aac_probe_container - query a logical volume
* @dev: device to query
@ -481,77 +599,37 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
* 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 fsa_dev_info *fsa_dev_ptr;
struct scsi_cmnd *scsicmd = kmalloc(sizeof(*scsicmd), GFP_KERNEL);
struct scsi_device *scsidev = kmalloc(sizeof(*scsidev), GFP_KERNEL);
int status;
struct aac_query_mount *dinfo;
struct aac_mount *dresp;
struct fib * fibptr;
unsigned instance;
fsa_dev_ptr = dev->fsa_dev;
if (!fsa_dev_ptr)
if (!scsicmd || !scsidev) {
kfree(scsicmd);
kfree(scsidev);
return -ENOMEM;
instance = dev->scsi_host_ptr->unique_id;
if (!(fibptr = aac_fib_alloc(dev)))
return -ENOMEM;
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->type = cpu_to_le32(FT_FILESYS);
status = aac_fib_send(ContainerCommand,
fibptr,
sizeof(struct aac_query_mount),
FsaNormal,
1, 1,
NULL, NULL);
if (status < 0) {
printk(KERN_WARNING "aacraid: aac_probe_container query failed.\n");
goto error;
}
scsicmd->list.next = NULL;
scsicmd->scsi_done = (void (*)(struct scsi_cmnd*))_aac_probe_container1;
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(cid);
dinfo->type = cpu_to_le32(FT_FILESYS);
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;
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;
}
error:
aac_fib_complete(fibptr);
aac_fib_free(fibptr);
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);

View File

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

View File

@ -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,24 +546,70 @@ 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;
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);
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) {
@ -568,15 +619,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
}
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;
}
actual_fibsize = actual_fibsize64;
for (i = 0; i < usg->count; i++) {
u64 addr;
@ -590,7 +633,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
rcode = -ENOMEM;
goto cleanup;
}
sg_user[i] = (void __user *)(long)usg->sg[i].addr;
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;
@ -606,36 +649,51 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
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].count = cpu_to_le32(usg->sg[i].count);
}
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;
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;
}
if ((data_dir == DMA_NONE) && upsg->count) {
dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
rcode = -EINVAL;
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);
}
} else {
for (i = 0; i < upsg->count; i++) {
dma_addr_t addr;
void* p;
@ -646,7 +704,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
rcode = -ENOMEM;
goto cleanup;
}
sg_user[i] = (void __user *)(long)upsg->sg[i].addr;
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;
@ -662,8 +720,9 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
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].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)){

View File

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

View File

@ -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) {
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->header.XferState));
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,7 +508,8 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
}
udelay(5);
}
} else if (down_interruptible(&fibptr->event_wait)) {
} 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 */
@ -521,15 +517,12 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
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;
}
}
/*
* If the user does not want a response than return success otherwise
* return pending
@ -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

View File

@ -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
@ -72,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);
/*
@ -83,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);
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);
@ -192,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;
@ -253,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;
@ -270,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.
@ -280,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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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);
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,30 +1313,43 @@ __scsi_print_sense(const char *name, const unsigned char *sense_buffer,
}
printk("%02x ", sense_buffer[k]);
}
printk("\n");
}
}
/* Normalize and print sense buffer with name prefix */
void __scsi_print_sense(const char *name, const unsigned char *sense_buffer,
int sense_len)
{
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);
void scsi_print_sense(const char *devclass, struct scsi_cmnd *cmd)
/* Normalize and print sense buffer in SCSI command */
void scsi_print_sense(char *name, struct scsi_cmnd *cmd)
{
const char *name = devclass;
struct scsi_sense_hdr sshdr;
if (cmd->request->rq_disk)
name = cmd->request->rq_disk->disk_name;
__scsi_print_sense(name, cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
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_sense);
void scsi_print_command(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);
}
EXPORT_SYMBOL(scsi_print_command);
#ifdef CONFIG_SCSI_CONSTANTS
static const char * const hostbyte_table[]={
@ -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);

View File

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

View File

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

View File

@ -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,10 +552,31 @@ 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)
/* 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 */
*evt_struct->xfer_iu = evt_struct->iu;
@ -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,6 +604,7 @@ 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);
atomic_inc(&hostdata->request_limit);
return SCSI_MLQUEUE_HOST_BUSY;
send_error:
@ -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");

View File

@ -44,6 +44,8 @@ struct Scsi_Host;
*/
#define MAX_INDIRECT_BUFS 10
#define IBMVSCSI_MAX_REQUESTS_DEFAULT 100
/* ------------------------------------------------------------
* Data Structures
*/

View File

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

View File

@ -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,6 +4490,9 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg,
if (ioa_cfg->log_level < IPR_DEFAULT_LOG_LEVEL)
return;
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) {
@ -4477,6 +4500,9 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg,
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_57B7, 0, 0, 0 },
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,
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);

View File

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

View File

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

View File

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

View File

@ -224,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) {
@ -257,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 {
@ -271,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);
@ -286,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)
@ -351,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;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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);
if (rtn == SUCCESS)
return 0;
}

View File

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

View File

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

View File

@ -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)
err = sht->suspend(sdev, state);
/* 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 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
};

View File

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

View File

@ -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 (len) {
err = scsi_map_user_pages(rq->end_io_data, cmd, uaddr, len, rw);
if (err) {
eprintk("%p %d\n", cmd, err);
err = -EAGAIN;
/*
* 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;
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;
}
/* 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);
err = scsi_tgt_transfer_response(cmd);
done:
scsi_host_put(shost);
return err;

View File

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

View File

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

View File

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

View File

@ -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",
SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt,
"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,
"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 (res) {
sd_print_result(sdkp, res);
if (driver_byte(res) & DRIVER_SENSE)
scsi_print_sense_hdr("sd", &sshdr);
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,15 +1191,9 @@ 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,9 +1294,9 @@ 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,
sd_printk(KERN_NOTICE, sdkp,
"%llu %d-byte hardware sectors (%llu MB)\n",
(unsigned long long)sdkp->capacity,
hard_sector, (unsigned long long)mb);
}
@ -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,
sd_printk(KERN_NOTICE, sdkp, "Write Protect is %s\n",
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_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);
}

View File

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

View File

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

View File

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

View File

@ -588,7 +588,17 @@ struct iscsi_reject {
#define VALUE_MAXLEN 255
#define TARGET_NAME_MAXLEN VALUE_MAXLEN
#define DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH 8192
#define ISCSI_DEF_MAX_RECV_SEG_LEN 8192
#define ISCSI_MIN_MAX_RECV_SEG_LEN 512
#define ISCSI_MAX_MAX_RECV_SEG_LEN 16777215
#define ISCSI_DEF_FIRST_BURST_LEN 65536
#define ISCSI_MIN_FIRST_BURST_LEN 512
#define ISCSI_MAX_FIRST_BURST_LEN 16777215
#define ISCSI_DEF_MAX_BURST_LEN 262144
#define ISCSI_MIN_MAX_BURST_LEN 512
#define ISCSI_MAX_MAX_BURST_LEN 16777215
/************************* RFC 3720 End *****************************/

View File

@ -203,6 +203,7 @@ static inline int scsi_status_is_good(int status)
/*
* DEVICE TYPES
* Please keep them in 0x%02x format for $MODALIAS to work
*/
#define TYPE_DISK 0x00

View File

@ -73,9 +73,6 @@ struct scsi_cmnd {
unsigned short use_sg; /* Number of pieces of scatter-gather */
unsigned short sglist_len; /* size of malloc'd scatter-gather list */
/* offset in cmd we are at (for multi-transfer tgt cmds) */
unsigned offset;
unsigned underflow; /* Return error if less than
this amount is transferred */

View File

@ -5,14 +5,16 @@ struct scsi_cmnd;
struct scsi_sense_hdr;
extern void scsi_print_command(struct scsi_cmnd *);
extern void scsi_print_sense_hdr(const char *, struct scsi_sense_hdr *);
extern void __scsi_print_command(unsigned char *);
extern void scsi_print_sense(const char *, struct scsi_cmnd *);
extern void scsi_show_extd_sense(unsigned char, unsigned char);
extern void scsi_show_sense_hdr(struct scsi_sense_hdr *);
extern void scsi_print_sense_hdr(const char *, struct scsi_sense_hdr *);
extern void scsi_print_sense(char *, struct scsi_cmnd *);
extern void __scsi_print_sense(const char *name,
const unsigned char *sense_buffer,
int sense_len);
extern void scsi_print_driverbyte(int);
extern void scsi_print_hostbyte(int);
extern void scsi_show_result(int);
extern void scsi_print_result(struct scsi_cmnd *);
extern void scsi_print_status(unsigned char);
extern const char *scsi_sense_key_string(unsigned char);
extern const char *scsi_extd_sense_format(unsigned char, unsigned char);

View File

@ -5,6 +5,7 @@
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/blkdev.h>
#include <asm/atomic.h>
struct request_queue;
@ -119,6 +120,7 @@ struct scsi_device {
unsigned use_192_bytes_for_3f:1; /* ask for 192 bytes from page 0x3f */
unsigned no_start_on_add:1; /* do not issue start on add */
unsigned allow_restart:1; /* issue START_UNIT in error handler */
unsigned manage_start_stop:1; /* Let HLD (sd) manage start/stop */
unsigned no_uld_attach:1; /* disable connecting to upper level drivers */
unsigned select_no_atn:1;
unsigned fix_capacity:1; /* READ_CAPACITY is too high by 1 */
@ -155,7 +157,10 @@ struct scsi_device {
dev_printk(prefix, &(sdev)->sdev_gendev, fmt, ##a)
#define scmd_printk(prefix, scmd, fmt, a...) \
dev_printk(prefix, &(scmd)->device->sdev_gendev, fmt, ##a)
(scmd)->request->rq_disk ? \
sdev_printk(prefix, (scmd)->device, "[%s] " fmt, \
(scmd)->request->rq_disk->disk_name, ##a) : \
sdev_printk(prefix, (scmd)->device, fmt, ##a)
enum scsi_target_state {
STARGET_RUNNING = 1,
@ -353,4 +358,9 @@ static inline int scsi_device_qas(struct scsi_device *sdev)
return 0;
return sdev->inquiry[56] & 0x02;
}
#define MODULE_ALIAS_SCSI_DEVICE(type) \
MODULE_ALIAS("scsi:t-" __stringify(type) "*")
#define SCSI_DEVICE_MODALIAS_FMT "scsi:t-0x%02x"
#endif /* _SCSI_SCSI_DEVICE_H */

View File

@ -129,6 +129,11 @@ struct scsi_host_template {
* the LLD. When the driver is finished processing the command
* the done callback is invoked.
*
* This is called to inform the LLD to transfer
* cmd->request_bufflen bytes. The cmd->use_sg speciefies the
* number of scatterlist entried in the command and
* cmd->request_buffer contains the scatterlist.
*
* return values: see queuecommand
*
* If the LLD accepts the cmd, it should set the result to an
@ -139,20 +144,6 @@ struct scsi_host_template {
/* TODO: rename */
int (* transfer_response)(struct scsi_cmnd *,
void (*done)(struct scsi_cmnd *));
/*
* This is called to inform the LLD to transfer cmd->request_bufflen
* bytes of the cmd at cmd->offset in the cmd. The cmd->use_sg
* speciefies the number of scatterlist entried in the command
* and cmd->request_buffer contains the scatterlist.
*
* If the command cannot be processed in one transfer_data call
* becuase a scatterlist within the LLD's limits cannot be
* created then transfer_data will be called multiple times.
* It is initially called from process context, and later
* calls are from the interrup context.
*/
int (* transfer_data)(struct scsi_cmnd *,
void (*done)(struct scsi_cmnd *));
/* Used as callback for the completion of task management request. */
int (* tsk_mgmt_response)(u64 mid, int result);
@ -334,6 +325,19 @@ struct scsi_host_template {
*/
int (*proc_info)(struct Scsi_Host *, char *, char **, off_t, int, int);
/*
* This is an optional routine that allows the transport to become
* involved when a scsi io timer fires. The return value tells the
* timer routine how to finish the io timeout handling:
* EH_HANDLED: I fixed the error, please complete the command
* EH_RESET_TIMER: I need more time, reset the timer and
* begin counting again
* EH_NOT_HANDLED Begin normal error recovery
*
* Status: OPTIONAL
*/
enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *);
/*
* suspend support
*/

View File

@ -45,11 +45,13 @@ struct tgt_event {
/* user-> kernel */
struct {
int host_no;
uint32_t len;
int result;
aligned_u64 uaddr;
uint8_t rw;
aligned_u64 tag;
aligned_u64 uaddr;
aligned_u64 sense_uaddr;
uint32_t len;
uint32_t sense_len;
uint8_t rw;
} cmd_rsp;
struct {
int host_no;

View File

@ -108,6 +108,8 @@ enum fc_port_state {
#define FC_PORTSPEED_2GBIT 2
#define FC_PORTSPEED_4GBIT 4
#define FC_PORTSPEED_10GBIT 8
#define FC_PORTSPEED_8GBIT 0x10
#define FC_PORTSPEED_16GBIT 0x20
#define FC_PORTSPEED_NOT_NEGOTIATED (1 << 15) /* Speed not established */
/*

72
include/scsi/sd.h Normal file
View File

@ -0,0 +1,72 @@
#ifndef _SCSI_DISK_H
#define _SCSI_DISK_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
/*
* 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)
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 int sd_suspend(struct device *dev, pm_message_t state);
static int sd_resume(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, unsigned char *buffer);
static void scsi_disk_release(struct class_device *cdev);
static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *);
static void sd_print_result(struct scsi_disk *, int);
#define sd_printk(prefix, sdsk, fmt, a...) \
(sdsk)->disk ? \
sdev_printk(prefix, (sdsk)->device, "[%s] " fmt, \
(sdsk)->disk->disk_name, ##a) : \
sdev_printk(prefix, (sdsk)->device, fmt, ##a)
#endif /* _SCSI_DISK_H */