From 928a763b415e09e4dccfecaf61199a3912f30358 Mon Sep 17 00:00:00 2001 From: johann <johann> Date: Sun, 17 Feb 2008 09:32:07 +0000 Subject: [PATCH] Branch b1_6 b=14618 Downgrad the MPT Fusion driver in the RHEL4 kernel from 3.02.99.00 to 3.02.73 until the problem regression is fixed. --- lustre/ChangeLog | 55 +- ...pt-fusion-downgrade-to-3_02_73-rhel4.patch | 27949 ++++++++++++++++ lustre/kernel_patches/series/2.6-rhel4.series | 1 + 3 files changed, 27982 insertions(+), 23 deletions(-) create mode 100644 lustre/kernel_patches/patches/mpt-fusion-downgrade-to-3_02_73-rhel4.patch diff --git a/lustre/ChangeLog b/lustre/ChangeLog index f409470e0e..eb923db265 100644 --- a/lustre/ChangeLog +++ b/lustre/ChangeLog @@ -30,25 +30,25 @@ Frequency : rare on shutdown ost Bugzilla : 13196 Description: Don't allow skipping OSTs if index has been specified. Details : Don't allow skipping OSTs if index has been specified, make locking - in internal create lots better. + in internal create lots better. Severity : normal Bugzilla : 14421 Description: ASSERTION(!PageDirty(page)) failed Details : Wrong check could lead to an assertion failure under specific - load patterns. + load patterns. Severity : normal Bugzilla : 12228 Description: LBUG in ptlrpc_check_set() bad phase ebc0de00 Details : access to bitfield in structure is always rounded to long - and this produce problem with not atomic change any bit. + and this produce problem with not atomic change any bit. Severity : normal Bugzilla : 13647 Description: Lustre make rpms failed. Details : Remove ldiskfs spec file to avoids rpmbuild be confused when - builds Lustre rpms from tarball. + builds Lustre rpms from tarball. Severity : enhancement Bugzilla : 14498 @@ -58,9 +58,9 @@ Severity : normal Frequency : rare on shutdown ost Bugzilla : 14608 Description: If llog cancel was not send before clean_exports phase, this can - produce deadlock in llog code. + produce deadlock in llog code. Details : If llog thread has last reference to obd and call class_import_put - this produce deadlock because llog_cleanup_commit_master wait when + this produce deadlock because llog_cleanup_commit_master wait when last llog_commit_thread exited, but this never success because was called from llog_commit_thread. @@ -91,7 +91,7 @@ Bugzilla : 12702 Frequency : rare, in recovery and (or) destroy lovobjid file. Description: rewrite lov objid code. Details : Cleanup for lov objid code, remove scability problems and wrong - locking. Fix sending last_id into ost. + locking. Fix sending last_id into ost. Severity : enhancement Bugzilla : 14388 @@ -107,8 +107,8 @@ Bugzilla : 14260 Frequency : rare, at shutdown Description: access already free / zero obd_namespace. Details : if client_disconnect_export was called without force flag set, - and exist connect request in flight, this can produce access to - NULL pointer (or already free pointer) when connect_interpret + and exist connect request in flight, this can produce access to + NULL pointer (or already free pointer) when connect_interpret store ocd flags in obd_namespace. Severity : minor @@ -116,7 +116,7 @@ Bugzilla : 14418 Frequency : only at startup Description: not alloc memory with spinlock held. Details : allocation memory with GFP_KERNEL can produce sleep deadlock, - if any spinlock held. + if any spinlock held. Severity : major Frequency : always @@ -128,7 +128,7 @@ Severity : normal Bugzilla : 11791 Description: Inconsistent usage of lustre_pack_reply() Details : Standardize the usage of lustre_pack_reply() such that it - always generate a CERROR on failure. + always generate a CERROR on failure. Severity : normal Frequency : very rare @@ -157,11 +157,11 @@ Description: Update to RHEL4 kernel-2.6.9-55.0.12.EL. Severity : enhancement Bugzilla : 13690 Description: Build SLES10 patchless client fails -Details : The configure was broken by run ./configure with +Details : The configure was broken by run ./configure with --with-linux-obj=.... argument for patchless client. When the configure use --with-linux-obj, the LINUXINCLUDE= -Iinclude - can't search header adequately. Use absolute path such as - -I($LINUX)/include instead. + can't search header adequately. Use absolute path such as + -I($LINUX)/include instead. Severity : enhancement Bugzilla : 11622 @@ -184,7 +184,7 @@ Bugzilla : 13888 Description: interrupt oig_wait produce painc on resend. Details : brw_redo_request can be used for resend requests from ptlrpcd and private set, and this produce situation when rq_ptlrpcd_data not - copyed to new allocated request and triggered LBUG on assert + copyed to new allocated request and triggered LBUG on assert req->rq_ptlrpcd_data != NULL. But this member used only for wakeup ptlrpcd set if request is changed and can be safety changed to use rq_set directly. @@ -200,7 +200,7 @@ Details : Change the structure of stats under obdfilter and mds to | + uuids +- nid#2... +- clear - The "uuid"s file would list the uuids of _active_ exports. + The "uuid"s file would list the uuids of _active_ exports. And the clear entry is to clear all stats and stale nids. Severity : normal @@ -234,21 +234,21 @@ Severity : normal Bugzilla : 12749 Description: Root Squash Functionality Details : Implementation of NFS-like root squash capability. Specifically, - don't allow someone with root access on a client node to be able - to manipulate files owned by root on a server node. + don't allow someone with root access on a client node to be able + to manipulate files owned by root on a server node. Severity : normal Bugzilla : 10718 Description: Slow trucate/writes to huge files at high offsets. Details : Directly associate cached pages to lock that protect those pages, - this allows us to quickly find what pages to write and remove + this allows us to quickly find what pages to write and remove once lock callback is received. Severity : normal Bugzilla : 14379 Description: Too many locks accumulating on client during NFS usage Details : mds_open improperly used accmode to find out access mode to a - file. Also mdc_intent_lock logic to find out if we already have + file. Also mdc_intent_lock logic to find out if we already have lock similar to just received was flawed since introduction of skiplists - locks are now added to the front of the granted queue. @@ -268,10 +268,10 @@ Details : Console messages can now be disabled via lnet.printk. Severity : normal Bugzilla : 14614 -Description: User code with malformed file open parameter crashes client node +Description: User code with malformed file open parameter crashes client node Details : Before packing join_file req, all the related reference should be - checked carefully in case some malformed flags cause fake - join_file req on client. + checked carefully in case some malformed flags cause fake join_file + req on client. Severity : normal Frequency : always @@ -313,6 +313,15 @@ Details : A lot of unlink operations with concurrent I/O can lead to a max_rpcs_in_flight per OSC and LDLM_FL_DISCARD_DATA blocking callbacks are processed in priority. +Severity : normal +Frequency : RHEL4 only +Bugzilla : 14618 +Description: mkfs is very slow on IA64/RHEL4 +Details : A performance regression has been discovered in the MPT Fusion + driver between versions 3.02.73rh and 3.02.99.00rh. As a + consequence, we have downgraded the MPT Fusion driver in the RHEL4 + kernel from 3.02.99.00 to 3.02.73 until this problem is fixed. + -------------------------------------------------------------------------------- 2007-12-07 Cluster File Systems, Inc. <info@clusterfs.com> diff --git a/lustre/kernel_patches/patches/mpt-fusion-downgrade-to-3_02_73-rhel4.patch b/lustre/kernel_patches/patches/mpt-fusion-downgrade-to-3_02_73-rhel4.patch new file mode 100644 index 0000000000..7bb3440921 --- /dev/null +++ b/lustre/kernel_patches/patches/mpt-fusion-downgrade-to-3_02_73-rhel4.patch @@ -0,0 +1,27949 @@ +diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/csmi/csmisas.c linux-2.6.9-55.0.12/drivers/message/fusion/csmi/csmisas.c +--- linux-2.6.9-67.0.1/drivers/message/fusion/csmi/csmisas.c 2007-12-21 11:40:54.000000000 +0100 ++++ linux-2.6.9-55.0.12/drivers/message/fusion/csmi/csmisas.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,5894 +0,0 @@ +-#define MPT_CSMI_DESCRIPTION "LSI Logic Corporation: Fusion MPT Driver "MPT_LINUX_VERSION_COMMON +-#define csmisas_is_this_sas_cntr(ioc) (ioc->bus_type == SAS) ? 1 : 0 +- +-static int csmisas_do_raid(MPT_ADAPTER *ioc, u8 action, u8 PhysDiskNum, u8 VolumeBus, +- u8 VolumeId, pMpiRaidActionReply_t reply); +-static u8 map_sas_status_to_csmi(u8 mpi_sas_status); +- +-/** +- * reverse_byte_order64 +- * +- * @data64 +- * +- **/ +-static u64 +-reverse_byte_order64(u64 data64) +-{ +- int i; +- u64 rc; +- u8 *inWord = (u8*)&data64, *outWord = (u8*)&rc; +- +- for (i = 0 ; i < 8 ; i++) +- outWord[i] = inWord[7-i]; +- +- return rc; +-} +- +-/** +- * csmisas_is_sata +- * +- * @phys_disk +- * +- **/ +-static int +-csmisas_is_sata(RaidPhysDiskPage0_t *phys_disk) +-{ +- if ((phys_disk->ExtDiskIdentifier[0] == 'A') && +- (phys_disk->ExtDiskIdentifier[1] == 'T') && +- (phys_disk->ExtDiskIdentifier[2] == 'A')) +- return 1; +- else +- return 0; +-} +- +-/** +- * csmisas_is_end_device +- * +- * @attached +- * +- **/ +-static inline int +-csmisas_is_end_device(struct mptsas_devinfo * attached) +-{ +- if ((attached->sas_address) && +- (attached->device_info & +- MPI_SAS_DEVICE_INFO_END_DEVICE) && +- ((attached->device_info & +- MPI_SAS_DEVICE_INFO_SSP_TARGET) | +- (attached->device_info & +- MPI_SAS_DEVICE_INFO_STP_TARGET) | +- (attached->device_info & +- MPI_SAS_DEVICE_INFO_SATA_DEVICE))) +- return 1; +- else +- return 0; +-} +- +-/** +- * csmisas_is_phys_disk +- * +- * returns (1) success (0) fail - not a phys disk +- **/ +-int +-csmisas_is_phys_disk(MPT_ADAPTER *ioc, int channel, int id) +-{ +- struct inactive_raid_component_info *component_info; +- int i; +- int rc = 0; +- +- if (!ioc->raid_data.pIocPg3) +- goto out; +- for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { +- if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) && +- (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) { +- rc = 1; +- goto out; +- } +- } +- +- /* +- * Check inactive list for matching phys disks +- */ +- if (list_empty(&ioc->raid_data.inactive_list)) +- goto out; +- +- down(&ioc->raid_data.inactive_list_mutex); +- list_for_each_entry(component_info, &ioc->raid_data.inactive_list, +- list) { +- if ((component_info->d.PhysDiskID == id) && +- (component_info->d.PhysDiskBus == channel)) +- rc = 1; +- } +- up(&ioc->raid_data.inactive_list_mutex); +- +- out: +- return rc; +-} +- +-/** +- * csmisas_raid_id_to_num +- * +- * Obtains the phys disk num for given H:C:T nexus +- * +- * input (channel/id) +- * output (phys disk number - used by SCSI_IO_PASSTHRU to access hidden component) +- * +- * returns - signed return means failure +- **/ +-s8 +-csmisas_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) +-{ +- struct inactive_raid_component_info *component_info; +- int i; +- s8 rc = -ENXIO; +- +- if (!ioc->raid_data.pIocPg3) +- goto out; +- for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { +- if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) && +- (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) { +- rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum; +- goto out; +- } +- } +- +- /* +- * Check inactive list for matching phys disks +- */ +- if (list_empty(&ioc->raid_data.inactive_list)) +- goto out; +- +- down(&ioc->raid_data.inactive_list_mutex); +- list_for_each_entry(component_info, &ioc->raid_data.inactive_list, +- list) { +- if ((component_info->d.PhysDiskID == id) && +- (component_info->d.PhysDiskBus == channel)) +- rc = component_info->d.PhysDiskNum; +- } +- up(&ioc->raid_data.inactive_list_mutex); +- +- out: +- return rc; +-} +- +-/** +- * csmisas_get_device_component_by_os +- * +- * Obtain device component object by operating system mapping +- * +- * @ioc +- * @channel +- * @id +- * +- **/ +-static struct sas_device_info * +-csmisas_get_device_component_by_os(MPT_ADAPTER *ioc, u8 channel, u8 id) +-{ +- struct sas_device_info *sas_info, *p; +- +- sas_info = NULL; +- +- down(&ioc->sas_device_info_mutex); +- list_for_each_entry(p, &ioc->sas_device_info_list, list) { +- if (p->os.channel == channel && p->os.id == id) { +- sas_info = p; +- goto out; +- } +- } +- +- out: +- up(&ioc->sas_device_info_mutex); +- return sas_info; +-} +- +-/** +- * csmisas_get_device_component +- * +- * Obtain device component object by firmware system mapping +- * +- * @ioc +- * @channel +- * @id +- * +- **/ +-static struct sas_device_info * +-csmisas_get_device_component_by_fw(MPT_ADAPTER *ioc, u8 channel, u8 id) +-{ +- struct sas_device_info *sas_info, *p; +- +- sas_info = NULL; +- +- down(&ioc->sas_device_info_mutex); +- list_for_each_entry(p, &ioc->sas_device_info_list, list) { +- if (p->fw.channel == channel && p->fw.id == id) { +- sas_info = p; +- goto out; +- } +- } +- +- out: +- up(&ioc->sas_device_info_mutex); +- return sas_info; +-} +- +- +-/** +- * csmisas_get_device_component_by_sas_addr +- * +- * Obtain device component object by sas address +- * +- * @ioc +- * @channel +- * @id +- * +- **/ +-static struct sas_device_info * +-csmisas_get_device_component_by_sas_addr(MPT_ADAPTER *ioc, u64 sas_address) +-{ +- struct sas_device_info *sas_info, *p; +- +- sas_info = NULL; +- +- down(&ioc->sas_device_info_mutex); +- list_for_each_entry(p, &ioc->sas_device_info_list, list) { +- dcsmisasprintk((KERN_ERR +- ":%s()" +- " looking for SASAddress=%llX entry SASAddress=%llX\n", +- __FUNCTION__, sas_address, p->sas_address)); +- if (p->sas_address == sas_address) { +- sas_info = p; +- dcsmisasprintk((KERN_ERR +- ":%s()" +- " found SASAddress=%llX\n", +- __FUNCTION__, sas_address)); +- goto out; +- } +- } +- +- out: +- up(&ioc->sas_device_info_mutex); +- return sas_info; +-} +- +-/** +- * csmisas_send_command_wait +- * +- * Send mf to firmware +- * +- * @ioc +- * @mf +- * @timeout - timeout +- * +- * Return: 0 for success +- * non-zero, failure +- **/ +-static int +-csmisas_send_command_wait(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, int timeout) +-{ +- int rc; +- int mf_timeout; +- +- mf_timeout = max_t(int, MPT_IOCTL_DEFAULT_TIMEOUT, timeout); +- INITIALIZE_IOCTL_STATUS(ioc->ioctl->status) +- ioc->ioctl->wait_done = 0; +- rc = 0; +- +-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) +- ioc->ioctl->timer.expires = jiffies + (MPT_JIFFY * mf_timeout); +- ioc->ioctl->status |= MPT_IOCTL_STATUS_TIMER_ACTIVE; +- ADD_TIMER(&ioc->ioctl->timer); +-#endif +- +- mpt_put_msg_frame(mptctl_id, ioc, mf); +- +-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) +- WAIT_EVENT(mptctl_wait, ioc->ioctl->wait_done); +-#else +- if ((wait_event_timeout(mptctl_wait, +- ioc->ioctl->wait_done == 1, HZ * mf_timeout) <=0) && +- ioc->ioctl->wait_done != 1 ) { +- mpt_free_msg_frame(ioc, mf); +- mptctl_timeout_expired(ioc->ioctl); +- rc = -1; +- } +-#endif +- +- if (rc != 0) +- dfailprintk((KERN_ERR "%s@%d::%s() - " +- "%s IOCTL timeout (%d)\n", +- __FILE__, __LINE__, __FUNCTION__, +- ioc->name, mf_timeout)); +- +- return rc; +-} +- +-/** +- * csmisas_send_handshake_wait +- * +- * Handshake a mf to firmware +- * +- * @ioc +- * @mf +- * @mf_size +- * @timeout - timeout +- * +- * Return: 0 for success +- * non-zero, failure +- **/ +-static int +-csmisas_send_handshake_wait(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, int timeout) +-{ +- int rc; +- int mf_timeout; +- +- mf_timeout = max_t(int, MPT_IOCTL_DEFAULT_TIMEOUT, timeout); +- INITIALIZE_IOCTL_STATUS(ioc->ioctl->status) +- ioc->ioctl->wait_done = 0; +- rc = 0; +- +-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) +- ioc->ioctl->timer.expires = jiffies + (MPT_JIFFY * mf_timeout); +- ioc->ioctl->status |= MPT_IOCTL_STATUS_TIMER_ACTIVE; +- ADD_TIMER(&ioc->ioctl->timer); +-#endif +- +- rc = mpt_send_handshake_request(mptctl_id, ioc, +- sizeof(SCSITaskMgmt_t), (u32*)mf,timeout, CAN_SLEEP); +- if (rc != 0) +- return rc; +- +-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) +- WAIT_EVENT(mptctl_wait, ioc->ioctl->wait_done); +-#else +- if ((wait_event_timeout(mptctl_wait, +- ioc->ioctl->wait_done == 1, HZ * mf_timeout) <=0) && +- ioc->ioctl->wait_done != 1 ) { +- mpt_free_msg_frame(ioc, mf); +- mptctl_timeout_expired(ioc->ioctl); +- rc = -1; +- } +-#endif +- +- if (rc != 0) +- dfailprintk((KERN_ERR "%s@%d::%s() - " +- "%s IOCTL timeout (%d)\n", __FILE__, __LINE__, +- __FUNCTION__, ioc->name, mf_timeout)); +- +- return rc; +-} +- +-/** +- * csmisas_get_manufacture_pg0 - Manufacturing Page 0. +- * @ioc: Pointer to MPT_ADAPTER structure +- * @mfgPage0: read only info set at manufacturing time +- * +- * Return: 0 for success +- * -ENOMEM if no memory available +- * -EPERM if not allowed due to ISR context +- * -EAGAIN if no msg frames currently available +- * -EFAULT for non-successful reply or no reply (timeout) +- **/ +-static int +-csmisas_get_manufacture_pg0(MPT_ADAPTER *ioc, ManufacturingPage0_t *mfgPage0) +-{ +- +- ConfigPageHeader_t hdr; +- CONFIGPARMS cfg; +- ManufacturingPage0_t *buffer = NULL; +- dma_addr_t dma_handle; +- int data_sz; +- int rc; +- +- /* +- * Get Manufacturing Page 0 header +- */ +- data_sz = 0; +- hdr.PageVersion = MPI_MANUFACTURING0_PAGEVERSION; +- hdr.PageLength = 0; +- hdr.PageNumber = 0; +- hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING; +- cfg.cfghdr.hdr = &hdr; +- cfg.physAddr = -1; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.dir = 0; +- cfg.pageAddr = 0; +- cfg.timeout = 0; +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) +- goto get_manufacture_pg0_out; +- +- if (hdr.PageLength == 0) { +- rc = -EFAULT; +- goto get_manufacture_pg0_out; +- } +- +- data_sz = hdr.PageLength * 4; +- buffer = (ManufacturingPage0_t *) pci_alloc_consistent(ioc->pcidev, +- data_sz, &dma_handle); +- if (!buffer) { +- rc = -ENOMEM; +- goto get_manufacture_pg0_out; +- } +- +- memset((u8 *)buffer, 0, data_sz); +- cfg.physAddr = dma_handle; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) +- goto get_manufacture_pg0_out; +- +- strncpy(mfgPage0->ChipName, buffer->ChipName, 16); +- strncpy(mfgPage0->ChipRevision, buffer->ChipRevision, 8); +- strncpy(mfgPage0->BoardName, buffer->BoardName, 16); +- strncpy(mfgPage0->BoardAssembly, buffer->BoardAssembly, 16); +- strncpy(mfgPage0->BoardTracerNumber, buffer->BoardTracerNumber, 16); +- +- dcsmisasprintk(("ChipName=%s\n",buffer->ChipName)); +- dcsmisasprintk(("ChipRevision=%s\n",buffer->ChipRevision)); +- dcsmisasprintk(("BoardName=%s\n",buffer->BoardName)); +- dcsmisasprintk(("BoardAssembly=%s\n",buffer->BoardAssembly)); +- dcsmisasprintk(("BoardTracerNumber=%s\n",buffer->BoardTracerNumber)); +- +- get_manufacture_pg0_out: +- +- if (buffer) +- pci_free_consistent(ioc->pcidev, data_sz, +- (u8 *) buffer, dma_handle); +- +- +- return rc; +-} +- +-/** +- * csmisas_get_number_hotspares - returns num hot spares in this ioc +- * @ioc: Pointer to MPT_ADAPTER structure +- * +- * Return: number of hotspares +- * +- **/ +-static int +-csmisas_get_number_hotspares(MPT_ADAPTER *ioc) +-{ +- ConfigPageHeader_t hdr; +- CONFIGPARMS cfg; +- IOCPage5_t *buffer = NULL; +- dma_addr_t dma_handle; +- int data_sz; +- int rc; +- +- memset(&hdr, 0, sizeof(ConfigPageHeader_t)); +- memset(&cfg, 0, sizeof(CONFIGPARMS)); +- +- rc = 0; +- data_sz = 0; +- hdr.PageNumber = 5; +- hdr.PageType = MPI_CONFIG_PAGETYPE_IOC; +- cfg.cfghdr.hdr = &hdr; +- cfg.physAddr = -1; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; +- +- if (mpt_config(ioc, &cfg) != 0) +- goto get_ioc_pg5; +- +- if (hdr.PageLength == 0) +- goto get_ioc_pg5; +- +- data_sz = hdr.PageLength * 4; +- buffer = (IOCPage5_t *) pci_alloc_consistent(ioc->pcidev, +- data_sz, &dma_handle); +- if (!buffer) +- goto get_ioc_pg5; +- +- memset((u8 *)buffer, 0, data_sz); +- cfg.physAddr = dma_handle; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- +- if (mpt_config(ioc, &cfg) != 0) +- goto get_ioc_pg5; +- +- rc = buffer->NumHotSpares; +- +- get_ioc_pg5: +- +- if (buffer) +- pci_free_consistent(ioc->pcidev, data_sz, +- (u8 *) buffer, dma_handle); +- +- return rc; +-} +- +- +-/** +- * csmisas_get_ioc_pg5 - ioc Page 5 hot spares +- * @ioc: Pointer to MPT_ADAPTER structure +- * @pIocPage5: ioc page 5 +- * @data_size: expected data size(units=bytes) +- * +- * Return: 0 for success +- * -ENOMEM if no memory available +- * -EPERM if not allowed due to ISR context +- * -EAGAIN if no msg frames currently available +- * -EFAULT for non-successful reply or no reply (timeout) +- **/ +-static int +-csmisas_get_ioc_pg5(MPT_ADAPTER *ioc, IOCPage5_t *iocPage5, int data_size) +-{ +- ConfigPageHeader_t hdr; +- CONFIGPARMS cfg; +- IOCPage5_t *buffer = NULL; +- dma_addr_t dma_handle; +- int data_sz; +- int rc; +- +- memset(&hdr, 0, sizeof(ConfigPageHeader_t)); +- memset(&cfg, 0, sizeof(CONFIGPARMS)); +- +- rc = 0; +- data_sz = 0; +- hdr.PageNumber = 5; +- hdr.PageType = MPI_CONFIG_PAGETYPE_IOC; +- cfg.cfghdr.hdr = &hdr; +- cfg.physAddr = -1; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) +- goto get_ioc_pg5; +- +- if (hdr.PageLength == 0) { +- rc = -EFAULT; +- goto get_ioc_pg5; +- } +- +- data_sz = hdr.PageLength * 4; +- buffer = (IOCPage5_t *) pci_alloc_consistent(ioc->pcidev, +- data_sz, &dma_handle); +- if (!buffer) { +- rc = -ENOMEM; +- goto get_ioc_pg5; +- } +- +- memset((u8 *)buffer, 0, data_sz); +- cfg.physAddr = dma_handle; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) +- goto get_ioc_pg5; +- +- memcpy(iocPage5, buffer, data_size); +- +- get_ioc_pg5: +- +- if (buffer) +- pci_free_consistent(ioc->pcidev, data_sz, +- (u8 *) buffer, dma_handle); +- +- return rc; +-} +- +-/** +- * csmisas_sas_device_pg0 - sas device page 0 +- * @ioc: Pointer to MPT_ADAPTER structure +- * @mptsas_devinfo: structure found in mptsas.h +- * @form, @form_specific - defines the Page Address field in the config page +- * (pls refer to chapter 5.1 in the mpi spec) +- * +- * Return: 0 for success +- * -ENOMEM if no memory available +- * -EPERM if not allowed due to ISR context +- * -EAGAIN if no msg frames currently available +- * -EFAULT for non-successful reply or no reply (timeout) +- **/ +-static int +-csmisas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, +- u32 form, u32 form_specific) +-{ +- ConfigExtendedPageHeader_t hdr; +- CONFIGPARMS cfg; +- SasDevicePage0_t *buffer; +- dma_addr_t dma_handle; +- u64 sas_address; +- int rc; +- +- rc = 0; +- hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION; +- hdr.ExtPageLength = 0; +- hdr.PageNumber = 0; +- hdr.Reserved1 = 0; +- hdr.Reserved2 = 0; +- hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; +- hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE; +- +- cfg.cfghdr.ehdr = &hdr; +- cfg.pageAddr = form + form_specific; +- cfg.physAddr = -1; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.dir = 0; /* read */ +- cfg.timeout = 10; +- +- memset(device_info, 0, sizeof(struct mptsas_devinfo)); +- if ((rc = mpt_config(ioc, &cfg)) != 0) +- goto out; +- +- if (!hdr.ExtPageLength) { +- rc = -ENXIO; +- goto out; +- } +- +- buffer = pci_alloc_consistent(ioc->pcidev, +- hdr.ExtPageLength * 4, &dma_handle); +- if (!buffer) { +- rc = -ENOMEM; +- goto out; +- } +- +- cfg.physAddr = dma_handle; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) +- goto out_free_consistent; +- +- device_info->handle = le16_to_cpu(buffer->DevHandle); +- device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle); +- device_info->handle_enclosure = +- le16_to_cpu(buffer->EnclosureHandle); +- device_info->slot = le16_to_cpu(buffer->Slot); +- device_info->phy_id = buffer->PhyNum; +- device_info->port_id = buffer->PhysicalPort; +- device_info->id = buffer->TargetID; +- device_info->channel = buffer->Bus; +- memcpy(&sas_address, &buffer->SASAddress, sizeof(u64)); +- device_info->sas_address = le64_to_cpu(sas_address); +- device_info->device_info = +- le32_to_cpu(buffer->DeviceInfo); +- +- out_free_consistent: +- pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, +- buffer, dma_handle); +- out: +- return rc; +-} +- +-/** +- * Routine for the CSMI Sas Get Driver Info command. +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- * -ENODEV if no such device/adapter +- **/ +-static int +-csmisas_get_driver_info(unsigned long arg) +-{ +- +- CSMI_SAS_DRIVER_INFO_BUFFER __user *uarg = (void __user *) arg; +- CSMI_SAS_DRIVER_INFO_BUFFER karg; +- MPT_ADAPTER *ioc = NULL; +- int iocnum; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- +- if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s - " +- "Unable to read in csmi_sas_get_driver_info_buffer struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, +- &ioc)) < 0) || (ioc == NULL)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not found!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- if (!csmisas_is_this_sas_cntr(ioc)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not SAS controller!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- /* Fill in the data and return the structure to the calling +- * program +- */ +- memcpy( karg.Information.szName, MPT_MISCDEV_BASENAME, +- sizeof(MPT_MISCDEV_BASENAME)); +- memcpy( karg.Information.szDescription, MPT_CSMI_DESCRIPTION, +- sizeof(MPT_CSMI_DESCRIPTION)); +- +- karg.Information.usMajorRevision = MPT_LINUX_MAJOR_VERSION; +- karg.Information.usMinorRevision = MPT_LINUX_MINOR_VERSION; +- karg.Information.usBuildRevision = MPT_LINUX_BUILD_VERSION; +- karg.Information.usReleaseRevision = MPT_LINUX_RELEASE_VERSION; +- +- karg.Information.usCSMIMajorRevision = CSMI_MAJOR_REVISION; +- karg.Information.usCSMIMinorRevision = CSMI_MINOR_REVISION; +- +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; +- +- /* Copy the data from kernel memory to user memory +- */ +- if (copy_to_user((char *)arg, &karg, +- sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s - " +- "Unable to write out csmi_sas_get_driver_info_buffer @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- dcsmisasprintk(("%s exit.\n",__FUNCTION__)); +- return 0; +-} +- +-/** +- * Prototype Routine for the CSMI_SAS_GET_CNTLR_CONFIG command. +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- * -ENODEV if no such device/adapter +- **/ +-static int +-csmisas_get_cntlr_config(unsigned long arg) +-{ +- +- CSMI_SAS_CNTLR_CONFIG_BUFFER __user *uarg = (void __user *) arg; +- CSMI_SAS_CNTLR_CONFIG_BUFFER karg; +- MPT_ADAPTER *ioc = NULL; +- int iocnum; +- int ii,msize,psize; +- unsigned int reg; +- u32 l; +- ManufacturingPage0_t mfgPage0; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- +- if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_CNTLR_CONFIG_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s - " +- "Unable to read in csmi_sas_get_cntlr_config_buffer struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, +- &ioc)) < 0) || (ioc == NULL)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not found!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER; +- return -ENODEV; +- } +- +- if (!csmisas_is_this_sas_cntr(ioc)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not SAS controller!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- /* Clear the struct before filling in data. */ +- memset( &karg.Configuration, 0, sizeof(CSMI_SAS_CNTLR_CONFIG)); +- +- /* Fill in the data and return the structure to the calling +- * program +- */ +- +- /* Get Base IO and Mem Mapped Addresses. */ +-msize = psize = 0; +-for(ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) { +- reg = PCI_BASE_ADDRESS_0 + (ii << 2); +- pci_read_config_dword(ioc->pcidev, reg, &l); +- +- if ((l & PCI_BASE_ADDRESS_SPACE) == +- PCI_BASE_ADDRESS_SPACE_MEMORY) { +- if(msize) +- continue; +- msize=1; +- karg.Configuration.BaseMemoryAddress.uLowPart = +- l & PCI_BASE_ADDRESS_MEM_MASK; +- +- if ((l & (PCI_BASE_ADDRESS_SPACE | +- PCI_BASE_ADDRESS_MEM_TYPE_MASK)) +- == (PCI_BASE_ADDRESS_SPACE_MEMORY | +- PCI_BASE_ADDRESS_MEM_TYPE_64)) { +- pci_read_config_dword(ioc->pcidev, reg+4, &l); +- karg.Configuration.BaseMemoryAddress.uHighPart = l; +- } +- } +- +- +- else { +- if(psize) +- continue; +- psize=1; +- karg.Configuration.uBaseIoAddress = +- l & PCI_BASE_ADDRESS_IO_MASK; +- } +- +- } +- +- karg.Configuration.uBoardID = (ioc->pcidev->subsystem_device << 16) | +- (ioc->pcidev->subsystem_vendor); +- +- karg.Configuration.usSlotNumber = +- (ioc->pci_slot_number = 0xff) ? +- SLOT_NUMBER_UNKNOWN : ioc->pci_slot_number; +- karg.Configuration.bControllerClass = CSMI_SAS_CNTLR_CLASS_HBA; +- karg.Configuration.bIoBusType = CSMI_SAS_BUS_TYPE_PCI; +- karg.Configuration.BusAddress.PciAddress.bBusNumber = +- ioc->pcidev->bus->number; +- karg.Configuration.BusAddress.PciAddress.bDeviceNumber = +- PCI_SLOT(ioc->pcidev->devfn); +- karg.Configuration.BusAddress.PciAddress.bFunctionNumber = +- PCI_FUNC(ioc->pcidev->devfn); +- karg.Configuration.BusAddress.PciAddress.bReserved = 0; +- if (!csmisas_get_manufacture_pg0(ioc, &mfgPage0)) +- memcpy( &karg.Configuration.szSerialNumber, +- mfgPage0.BoardTracerNumber, 16 ); +- karg.Configuration.usMajorRevision = ioc->facts.FWVersion.Struct.Major; +- karg.Configuration.usMinorRevision = ioc->facts.FWVersion.Struct.Minor; +- karg.Configuration.usBuildRevision = ioc->facts.FWVersion.Struct.Unit; +- karg.Configuration.usReleaseRevision = ioc->facts.FWVersion.Struct.Dev; +- karg.Configuration.usBIOSMajorRevision = +- (ioc->biosVersion & 0xFF000000) >> 24; +- karg.Configuration.usBIOSMinorRevision = +- (ioc->biosVersion & 0x00FF0000) >> 16; +- karg.Configuration.usBIOSBuildRevision = +- (ioc->biosVersion & 0x0000FF00) >> 8; +- karg.Configuration.usBIOSReleaseRevision = +- (ioc->biosVersion & 0x000000FF); +- karg.Configuration.uControllerFlags = CSMI_SAS_CNTLR_SAS_HBA | +- CSMI_SAS_CNTLR_FWD_SUPPORT | CSMI_SAS_CNTLR_FWD_ONLINE | +- CSMI_SAS_CNTLR_FWD_SRESET ; +- +- /* +- * Enabling CSMI_SAS_CNTLR_SAS_RAID bit when IR fw detected +- */ +- if (ioc->ir_firmware) +- karg.Configuration.uControllerFlags |= CSMI_SAS_CNTLR_SAS_RAID; +- +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; +- +- /* All Rrom entries will be zero. Skip them. */ +- /* bReserved will also be zeros. */ +- /* Copy the data from kernel memory to user memory +- */ +- if (copy_to_user((char *)arg, &karg, +- sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s - " +- "Unable to write out csmi_sas_get_driver_info_buffer @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- dcsmisasprintk(("%s exit.\n",__FUNCTION__)); +- return 0; +-} +- +-/** +- * Prototype Routine for the CSMI Sas Get Controller Status command. +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- * -ENODEV if no such device/adapter +- **/ +-static int +-csmisas_get_cntlr_status(unsigned long arg) +-{ +- +- CSMI_SAS_CNTLR_STATUS_BUFFER __user *uarg = (void __user *) arg; +- MPT_ADAPTER *ioc = NULL; +- CSMI_SAS_CNTLR_STATUS_BUFFER karg; +- int iocnum; +- int rc; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- +- if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_CNTLR_STATUS_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s - " +- "Unable to read in csmi_sas_get_cntlr_status_buffer struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, +- &ioc)) < 0) || (ioc == NULL)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not found!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- if (!csmisas_is_this_sas_cntr(ioc)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not SAS controller!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- /* Fill in the data and return the structure to the calling +- * program +- */ +- +- rc = mpt_GetIocState(ioc, 1); +- switch (rc) { +- case MPI_IOC_STATE_OPERATIONAL: +- karg.Status.uStatus = CSMI_SAS_CNTLR_STATUS_GOOD; +- karg.Status.uOfflineReason = 0; +- break; +- +- case MPI_IOC_STATE_FAULT: +- karg.Status.uStatus = CSMI_SAS_CNTLR_STATUS_FAILED; +- karg.Status.uOfflineReason = 0; +- break; +- +- case MPI_IOC_STATE_RESET: +- case MPI_IOC_STATE_READY: +- default: +- karg.Status.uStatus = CSMI_SAS_CNTLR_STATUS_OFFLINE; +- karg.Status.uOfflineReason = +- CSMI_SAS_OFFLINE_REASON_INITIALIZING; +- break; +- } +- +- memset(&karg.Status.bReserved, 0, 28); +- +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; +- +- /* Copy the data from kernel memory to user memory +- */ +- if (copy_to_user((char *)arg, &karg, +- sizeof(CSMI_SAS_CNTLR_STATUS_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s - " +- "Unable to write out csmi_sas_get_cntlr_status @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- dcsmisasprintk(("%s exit.\n",__FUNCTION__)); +- return 0; +-} +- +-/** +- * Prototype Routine for the CSMI Sas Get Phy Info command. +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- * -ENODEV if no such device/adapter +- **/ +-static int +-csmisas_get_phy_info(unsigned long arg) +-{ +- CSMI_SAS_PHY_INFO_BUFFER __user *uarg = (void __user *) arg; +- CSMI_SAS_PHY_INFO_BUFFER karg; +- MPT_ADAPTER *ioc = NULL; +- ConfigExtendedPageHeader_t hdr; +- CONFIGPARMS cfg; +- SasIOUnitPage0_t *sasIoUnitPg0; +- dma_addr_t sasIoUnitPg0_dma; +- int sasIoUnitPg0_data_sz; +- SasPhyPage0_t *sasPhyPg0; +- dma_addr_t sasPhyPg0_dma; +- int sasPhyPg0_data_sz; +- u16 protocol; +- int iocnum; +- int rc; +- int ii; +- u64 sas_address; +- struct mptsas_devinfo device_info; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- sasIoUnitPg0=NULL; +- sasPhyPg0=NULL; +- sasIoUnitPg0_data_sz=0; +- sasPhyPg0_data_sz=0; +- +- if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_PHY_INFO_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s - " +- "Unable to read in csmisas_get_phy_info_buffer struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, +- &ioc)) < 0) || (ioc == NULL)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not found!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- if (!csmisas_is_this_sas_cntr(ioc)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not SAS controller!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- /* Fill in the data and return the structure to the calling +- * program +- */ +- memset(&karg.Information, 0, sizeof(CSMI_SAS_PHY_INFO)); +- +- /* Issue a config request to get the number of phys +- */ +- hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION; +- hdr.ExtPageLength = 0; +- hdr.PageNumber = 0; +- hdr.Reserved1 = 0; +- hdr.Reserved2 = 0; +- hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; +- hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; +- +- cfg.cfghdr.ehdr = &hdr; +- cfg.physAddr = -1; +- cfg.pageAddr = 0; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.dir = 0; /* read */ +- cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) { +- /* Don't check if this failed. Already in a +- * failure case. +- */ +- dcsmisasprintk(( +- ": FAILED: MPI_SASIOUNITPAGE0_PAGEVERSION: HEADER\n")); +- dcsmisasprintk((": rc=%x\n",rc)); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto sas_get_phy_info_exit; +- } +- +- if (hdr.ExtPageLength == 0) { +- /* Don't check if this failed. Already in a +- * failure case. +- */ +- dcsmisasprintk((": hdr.ExtPageLength == 0\n")); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto sas_get_phy_info_exit; +- } +- +- sasIoUnitPg0_data_sz = hdr.ExtPageLength * 4; +- rc = -ENOMEM; +- +- sasIoUnitPg0 = (SasIOUnitPage0_t *) pci_alloc_consistent(ioc->pcidev, +- sasIoUnitPg0_data_sz, &sasIoUnitPg0_dma); +- +- if (!sasIoUnitPg0) { +- dcsmisasprintk((": pci_alloc_consistent: FAILED\n")); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto sas_get_phy_info_exit; +- } +- +- memset((u8 *)sasIoUnitPg0, 0, sasIoUnitPg0_data_sz); +- cfg.physAddr = sasIoUnitPg0_dma; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) { +- +- /* Don't check if this failed. Already in a +- * failure case. +- */ +- dcsmisasprintk(( +- ": FAILED: MPI_SASIOUNITPAGE0_PAGEVERSION: PAGE\n")); +- dcsmisasprintk((": rc=%x\n",rc)); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto sas_get_phy_info_exit; +- } +- +- /* Number of Phys. */ +- karg.Information.bNumberOfPhys = sasIoUnitPg0->NumPhys; +- +- /* Fill in information for each phy. */ +- for (ii = 0; ii < karg.Information.bNumberOfPhys; ii++) { +- +-/* EDM : dump IO Unit Page 0 data*/ +- dcsmisasprintk(("---- IO UNIT PAGE 0 ------------\n")); +- dcsmisasprintk(("Handle=0x%X\n", +- le16_to_cpu(sasIoUnitPg0->PhyData[ii].AttachedDeviceHandle))); +- dcsmisasprintk(("Controller Handle=0x%X\n", +- le16_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerDevHandle))); +- dcsmisasprintk(("Port=0x%X\n", +- sasIoUnitPg0->PhyData[ii].Port)); +- dcsmisasprintk(("Port Flags=0x%X\n", +- sasIoUnitPg0->PhyData[ii].PortFlags)); +- dcsmisasprintk(("PHY Flags=0x%X\n", +- sasIoUnitPg0->PhyData[ii].PhyFlags)); +- dcsmisasprintk(("Negotiated Link Rate=0x%X\n", +- sasIoUnitPg0->PhyData[ii].NegotiatedLinkRate)); +- dcsmisasprintk(("Controller PHY Device Info=0x%X\n", +- le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo))); +- dcsmisasprintk(("DiscoveryStatus=0x%X\n", +- le32_to_cpu(sasIoUnitPg0->PhyData[ii].DiscoveryStatus))); +- dcsmisasprintk(("\n")); +-/* EDM : debug data */ +- +- /* PHY stuff. */ +- karg.Information.Phy[ii].bPortIdentifier = +- sasIoUnitPg0->PhyData[ii].Port; +- +- /* Get the negotiated link rate for the phy. */ +- switch (sasIoUnitPg0->PhyData[ii].NegotiatedLinkRate) { +- +- case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED: +- karg.Information.Phy[ii].bNegotiatedLinkRate = +- CSMI_SAS_PHY_DISABLED; +- break; +- +- case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION: +- karg.Information.Phy[ii].bNegotiatedLinkRate = +- CSMI_SAS_LINK_RATE_FAILED; +- break; +- +- case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE: +- break; +- +- case MPI_SAS_IOUNIT0_RATE_1_5: +- karg.Information.Phy[ii].bNegotiatedLinkRate = +- CSMI_SAS_LINK_RATE_1_5_GBPS; +- break; +- +- case MPI_SAS_IOUNIT0_RATE_3_0: +- karg.Information.Phy[ii].bNegotiatedLinkRate = +- CSMI_SAS_LINK_RATE_3_0_GBPS; +- break; +- +- case MPI_SAS_IOUNIT0_RATE_UNKNOWN: +- default: +- karg.Information.Phy[ii].bNegotiatedLinkRate = +- CSMI_SAS_LINK_RATE_UNKNOWN; +- break; +- } +- +- if (sasIoUnitPg0->PhyData[ii].PortFlags & +- MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS) { +- karg.Information.Phy[ii].bAutoDiscover = +- CSMI_SAS_DISCOVER_IN_PROGRESS; +- } else { +- karg.Information.Phy[ii].bAutoDiscover = +- CSMI_SAS_DISCOVER_COMPLETE; +- } +- +- /* Issue a config request to get +- * phy information. +- */ +- hdr.PageVersion = MPI_SASPHY0_PAGEVERSION; +- hdr.ExtPageLength = 0; +- hdr.PageNumber = 0; +- hdr.Reserved1 = 0; +- hdr.Reserved2 = 0; +- hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; +- hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY; +- +- cfg.cfghdr.ehdr = &hdr; +- cfg.physAddr = -1; +- cfg.pageAddr = ii; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.dir = 0; /* read */ +- cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) { +- dcsmisasprintk(( +- ": FAILED: MPI_SASPHY0_PAGEVERSION: HEADER\n")); +- dcsmisasprintk((": rc=%x\n",rc)); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto sas_get_phy_info_exit; +- } +- +- if (hdr.ExtPageLength == 0) { +- dcsmisasprintk((": pci_alloc_consistent: FAILED\n")); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto sas_get_phy_info_exit; +- } +- +- sasPhyPg0_data_sz = hdr.ExtPageLength * 4; +- rc = -ENOMEM; +- +- sasPhyPg0 = (SasPhyPage0_t *) pci_alloc_consistent( +- ioc->pcidev, sasPhyPg0_data_sz, &sasPhyPg0_dma); +- +- if (! sasPhyPg0) { +- dcsmisasprintk((": pci_alloc_consistent: FAILED\n")); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto sas_get_phy_info_exit; +- } +- +- memset((u8 *)sasPhyPg0, 0, sasPhyPg0_data_sz); +- cfg.physAddr = sasPhyPg0_dma; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) { +- dcsmisasprintk(( +- ": FAILED: MPI_SASPHY0_PAGEVERSION: PAGE\n")); +- dcsmisasprintk((": rc=%x\n",rc)); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz, +- (u8 *) sasPhyPg0, sasPhyPg0_dma); +- goto sas_get_phy_info_exit; +- } +- +-/* EDM : dump PHY Page 0 data*/ +- memcpy(&sas_address, &sasPhyPg0->SASAddress, sizeof(u64)); +- dcsmisasprintk(("---- SAS PHY PAGE 0 ------------\n")); +- dcsmisasprintk(("Handle=0x%X\n", +- le16_to_cpu(sasPhyPg0->AttachedDevHandle))); +- dcsmisasprintk(("SAS Address=0x%llX\n", +- (unsigned long long)sas_address)); +- dcsmisasprintk(("Attached PHY Identifier=0x%X\n", +- sasPhyPg0->AttachedPhyIdentifier)); +- dcsmisasprintk(("Attached Device Info=0x%X\n", +- le32_to_cpu(sasPhyPg0->AttachedDeviceInfo))); +- dcsmisasprintk(("Programmed Link Rate=0x%X\n", +- sasPhyPg0->ProgrammedLinkRate)); +- dcsmisasprintk(("Hardware Link Rate=0x%X\n", +- sasPhyPg0->HwLinkRate)); +- dcsmisasprintk(("Change Count=0x%X\n", +- sasPhyPg0->ChangeCount)); +- dcsmisasprintk(("PHY Info=0x%X\n", +- le32_to_cpu(sasPhyPg0->PhyInfo))); +- dcsmisasprintk(("\n")); +-/* EDM : debug data */ +- +- /* save the data */ +- +- /* Set Max hardware link rate. +- * This value is hard coded +- * because the HW link rate +- * is currently being +- * overwritten in FW. +- */ +- +- /* Set Max hardware link rate. */ +- switch (sasPhyPg0->HwLinkRate & +- MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) { +- +- case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5: +- karg.Information.Phy[ii].bMaximumLinkRate = +- CSMI_SAS_LINK_RATE_1_5_GBPS; +- break; +- +- case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0: +- karg.Information.Phy[ii].bMaximumLinkRate = +- CSMI_SAS_LINK_RATE_3_0_GBPS; +- break; +- default: +- break; +- } +- +- /* Set Max programmed link rate. */ +- switch (sasPhyPg0->ProgrammedLinkRate & +- MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) { +- +- case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5: +- karg.Information.Phy[ii].bMaximumLinkRate |= +- (CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS << 4); +- break; +- +- case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0: +- karg.Information.Phy[ii].bMaximumLinkRate |= +- (CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS << 4); +- break; +- default: +- break; +- } +- +- /* Set Min hardware link rate. */ +- switch (sasPhyPg0->HwLinkRate & +- MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) { +- +- case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5: +- karg.Information.Phy[ii].bMinimumLinkRate = +- CSMI_SAS_LINK_RATE_1_5_GBPS; +- break; +- +- case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0: +- karg.Information.Phy[ii].bMinimumLinkRate = +- CSMI_SAS_LINK_RATE_3_0_GBPS; +- break; +- default: +- break; +- } +- +- /* Set Min programmed link rate. */ +- switch (sasPhyPg0->ProgrammedLinkRate & +- MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) { +- +- case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5: +- karg.Information.Phy[ii].bMinimumLinkRate |= +- (CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS << 4); +- break; +- +- case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0: +- karg.Information.Phy[ii].bMinimumLinkRate |= +- (CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS << 4); +- break; +- default: +- break; +- } +- +- karg.Information.Phy[ii].bPhyChangeCount = sasPhyPg0->ChangeCount; +- if( sasPhyPg0->PhyInfo & MPI_SAS_PHY0_PHYINFO_VIRTUAL_PHY ) +- karg.Information.Phy[ii].bPhyFeatures = CSMI_SAS_PHY_VIRTUAL_SMP; +- +- /* Fill in Attached Device +- * Initiator Port Protocol. +- * Bits 6:3 +- * More than one bit can be set. +- */ +- protocol = le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) & 0x78; +- karg.Information.Phy[ii].Attached.bInitiatorPortProtocol = 0; +- if (protocol & MPI_SAS_DEVICE_INFO_SSP_INITIATOR) +- karg.Information.Phy[ii].Attached.bInitiatorPortProtocol = +- CSMI_SAS_PROTOCOL_SSP; +- if (protocol & MPI_SAS_DEVICE_INFO_STP_INITIATOR) +- karg.Information.Phy[ii].Attached.bInitiatorPortProtocol |= +- CSMI_SAS_PROTOCOL_STP; +- if (protocol & MPI_SAS_DEVICE_INFO_SMP_INITIATOR) +- karg.Information.Phy[ii].Attached.bInitiatorPortProtocol |= +- CSMI_SAS_PROTOCOL_SMP; +- if (protocol & MPI_SAS_DEVICE_INFO_SATA_HOST) +- karg.Information.Phy[ii].Attached.bInitiatorPortProtocol |= +- CSMI_SAS_PROTOCOL_SATA; +- +- /* Fill in Phy Target Port +- * Protocol. Bits 10:7 +- * More than one bit can be set. +- */ +- protocol = le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) & 0x780; +- karg.Information.Phy[ii].Attached.bTargetPortProtocol = 0; +- if (protocol & MPI_SAS_DEVICE_INFO_SSP_TARGET) +- karg.Information.Phy[ii].Attached.bTargetPortProtocol |= +- CSMI_SAS_PROTOCOL_SSP; +- if (protocol & MPI_SAS_DEVICE_INFO_STP_TARGET) +- karg.Information.Phy[ii].Attached.bTargetPortProtocol |= +- CSMI_SAS_PROTOCOL_STP; +- if (protocol & MPI_SAS_DEVICE_INFO_SMP_TARGET) +- karg.Information.Phy[ii].Attached.bTargetPortProtocol |= +- CSMI_SAS_PROTOCOL_SMP; +- if (protocol & MPI_SAS_DEVICE_INFO_SATA_DEVICE) +- karg.Information.Phy[ii].Attached.bTargetPortProtocol |= +- CSMI_SAS_PROTOCOL_SATA; +- +- +- /* Fill in Attached device type */ +- switch (le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) & +- MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) { +- +- case MPI_SAS_DEVICE_INFO_NO_DEVICE: +- karg.Information.Phy[ii].Attached.bDeviceType = +- CSMI_SAS_NO_DEVICE_ATTACHED; +- break; +- +- case MPI_SAS_DEVICE_INFO_END_DEVICE: +- karg.Information.Phy[ii].Attached.bDeviceType = +- CSMI_SAS_END_DEVICE; +- break; +- +- case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER: +- karg.Information.Phy[ii].Attached.bDeviceType = +- CSMI_SAS_EDGE_EXPANDER_DEVICE; +- break; +- +- case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER: +- karg.Information.Phy[ii].Attached.bDeviceType = +- CSMI_SAS_FANOUT_EXPANDER_DEVICE; +- break; +- } +- +- /* Identify Info. */ +- switch (le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo) & +- MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) { +- +- case MPI_SAS_DEVICE_INFO_NO_DEVICE: +- karg.Information.Phy[ii].Identify.bDeviceType = +- CSMI_SAS_NO_DEVICE_ATTACHED; +- break; +- +- case MPI_SAS_DEVICE_INFO_END_DEVICE: +- karg.Information.Phy[ii].Identify.bDeviceType = +- CSMI_SAS_END_DEVICE; +- break; +- +- case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER: +- karg.Information.Phy[ii].Identify.bDeviceType = +- CSMI_SAS_EDGE_EXPANDER_DEVICE; +- break; +- +- case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER: +- karg.Information.Phy[ii].Identify.bDeviceType = +- CSMI_SAS_FANOUT_EXPANDER_DEVICE; +- break; +- } +- +- /* Fill in Phy Initiator Port Protocol. Bits 6:3 +- * More than one bit can be set, fall through cases. +- */ +- protocol = le32_to_cpu( +- sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo) & 0x78; +- karg.Information.Phy[ii].Identify.bInitiatorPortProtocol = 0; +- if( protocol & MPI_SAS_DEVICE_INFO_SSP_INITIATOR ) +- karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |= +- CSMI_SAS_PROTOCOL_SSP; +- if( protocol & MPI_SAS_DEVICE_INFO_STP_INITIATOR ) +- karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |= +- CSMI_SAS_PROTOCOL_STP; +- if( protocol & MPI_SAS_DEVICE_INFO_SMP_INITIATOR ) +- karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |= +- CSMI_SAS_PROTOCOL_SMP; +- if( protocol & MPI_SAS_DEVICE_INFO_SATA_HOST ) +- karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |= +- CSMI_SAS_PROTOCOL_SATA; +- +- /* Fill in Phy Target Port Protocol. Bits 10:7 +- * More than one bit can be set, fall through cases. +- */ +- protocol = le32_to_cpu( +- sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo) & 0x780; +- karg.Information.Phy[ii].Identify.bTargetPortProtocol = 0; +- if( protocol & MPI_SAS_DEVICE_INFO_SSP_TARGET ) +- karg.Information.Phy[ii].Identify.bTargetPortProtocol |= +- CSMI_SAS_PROTOCOL_SSP; +- if( protocol & MPI_SAS_DEVICE_INFO_STP_TARGET ) +- karg.Information.Phy[ii].Identify.bTargetPortProtocol |= +- CSMI_SAS_PROTOCOL_STP; +- if( protocol & MPI_SAS_DEVICE_INFO_SMP_TARGET ) +- karg.Information.Phy[ii].Identify.bTargetPortProtocol |= +- CSMI_SAS_PROTOCOL_SMP; +- if( protocol & MPI_SAS_DEVICE_INFO_SATA_DEVICE ) +- karg.Information.Phy[ii].Identify.bTargetPortProtocol |= +- CSMI_SAS_PROTOCOL_SATA; +- +- /* Setup SAS Address for the attached device */ +- if (sasPhyPg0->AttachedDevHandle) { +- sas_address = reverse_byte_order64(sas_address); +- memcpy(karg.Information.Phy[ii].Attached.bSASAddress, +- &sas_address, sizeof(u64)); +- karg.Information.Phy[ii].Attached.bPhyIdentifier = +- sasPhyPg0->AttachedPhyIdentifier; +- } +- +- /* Setup SAS Address for the parent device */ +- csmisas_sas_device_pg0(ioc, &device_info, +- (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << +- MPI_SAS_DEVICE_PGAD_FORM_SHIFT), +- sasIoUnitPg0->PhyData[ii].ControllerDevHandle); +- sas_address = reverse_byte_order64(device_info.sas_address); +- memcpy(karg.Information.Phy[ii].Identify.bSASAddress, +- &sas_address, sizeof(u64)); +- karg.Information.Phy[ii].Identify.bPhyIdentifier = ii; +- +- pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz, +- (u8 *) sasPhyPg0, sasPhyPg0_dma); +- } +- +-sas_get_phy_info_exit: +- +- if (sasIoUnitPg0) +- pci_free_consistent(ioc->pcidev, sasIoUnitPg0_data_sz, +- (u8 *) sasIoUnitPg0, sasIoUnitPg0_dma); +- +- /* Copy the data from kernel memory to user memory +- */ +- if (copy_to_user((char *)arg, &karg, +- sizeof(CSMI_SAS_PHY_INFO_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s - " +- "Unable to write out csmisas_get_phy_info_buffer @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- dcsmisasprintk(("%s exit.\n",__FUNCTION__)); +- return 0; +-} +- +-/** +- * Prototype Routine for the CSMI SAS Set PHY Info command. +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- * -ENODEV if no such device/adapter +- **/ +-static int +-csmisas_set_phy_info(unsigned long arg) +-{ +- CSMI_SAS_SET_PHY_INFO_BUFFER __user *uarg = (void __user *) arg; +- CSMI_SAS_SET_PHY_INFO_BUFFER karg; +- MPT_ADAPTER *ioc = NULL; +- int iocnum; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- +- if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SET_PHY_INFO_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in csmi_sas_set_phy_info struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, +- &ioc)) < 0) || (ioc == NULL)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not found!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- if (!csmisas_is_this_sas_cntr(ioc)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not SAS controller!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +-/* TODO - implement IOCTL here */ +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_BAD_CNTL_CODE; +- dcsmisasprintk((": not implemented\n")); +- +-// cim_set_phy_info_exit: +- +- /* Copy the data from kernel memory to user memory +- */ +- if (copy_to_user((char *)arg, &karg, +- sizeof(CSMI_SAS_SET_PHY_INFO_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to write out csmi_sas_set_phy_info @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- dcsmisasprintk(("%s exit.\n",__FUNCTION__)); +- return 0; +- +-} +- +-/** +- * Prototype Routine for the CSMI Sas Get SCSI Address command. +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- * -ENODEV if no such device/adapter +- **/ +-static int +-csmisas_get_scsi_address(unsigned long arg) +-{ +- CSMI_SAS_GET_SCSI_ADDRESS_BUFFER __user *uarg = (void __user *) arg; +- CSMI_SAS_GET_SCSI_ADDRESS_BUFFER karg; +- MPT_ADAPTER *ioc = NULL; +- int iocnum; +- u64 sas_address; +- struct sas_device_info *sas_info; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- +- if (copy_from_user(&karg, uarg, +- sizeof(CSMI_SAS_GET_SCSI_ADDRESS_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in csmi_sas_get_scsi_address struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, +- &ioc)) < 0) || (ioc == NULL)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not found!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- if (!csmisas_is_this_sas_cntr(ioc)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not SAS controller!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- /* reverse byte order the sas address */ +- memcpy(&sas_address, karg.bSASAddress, sizeof(u64)); +- sas_address = reverse_byte_order64(sas_address); +- +- /* Search the list for the matching SAS address. */ +- karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_SCSI_ADDRESS; +- karg.bPathId = 0; +- karg.bTargetId = 0; +- karg.bLun = 0; +- +- sas_info = csmisas_get_device_component_by_sas_addr(ioc, sas_address); +- if (!sas_info || sas_info->is_cached || sas_info->is_logical_volume) +- goto csmisas_get_scsi_address_exit; +- +- karg.bPathId = sas_info->os.channel; +- karg.bTargetId = sas_info->os.id; +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; +- +- csmisas_get_scsi_address_exit: +- +- /* Copy the data from kernel memory to user memory +- */ +- if (copy_to_user((char *)arg, &karg, +- sizeof(CSMI_SAS_GET_SCSI_ADDRESS_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to write out csmi_sas_get_scsi_address @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- dcsmisasprintk(("%s exit.\n",__FUNCTION__)); +- return 0; +-} +- +-/** +- * Prototype Routine for the CSMI Sas Get SCSI Address command. +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- * -ENODEV if no such device/adapter +- **/ +-static int +-csmisas_get_sata_signature(unsigned long arg) +-{ +- CSMI_SAS_SATA_SIGNATURE_BUFFER __user *uarg = (void __user *) arg; +- CSMI_SAS_SATA_SIGNATURE_BUFFER karg; +- MPT_ADAPTER *ioc = NULL; +- int iocnum; +- int rc, jj; +- ConfigExtendedPageHeader_t hdr; +- CONFIGPARMS cfg; +- SasPhyPage0_t *sasPhyPg0; +- dma_addr_t sasPhyPg0_dma; +- int sasPhyPg0_data_sz; +- SasDevicePage1_t *sasDevicePg1; +- dma_addr_t sasDevicePg1_dma; +- int sasDevicePg1_data_sz; +- u8 phyId; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- sasPhyPg0=NULL; +- sasPhyPg0_data_sz=0; +- sasDevicePg1=NULL; +- sasDevicePg1_data_sz=0; +- +- if (copy_from_user(&karg, uarg, +- sizeof(CSMI_SAS_SATA_SIGNATURE_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in csmi_sas_sata_signature struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, +- &ioc)) < 0) || (ioc == NULL)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not found!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- if (!csmisas_is_this_sas_cntr(ioc)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not SAS controller!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- phyId = karg.Signature.bPhyIdentifier; +- if (phyId >= ioc->num_ports) { +- karg.IoctlHeader.ReturnCode = CSMI_SAS_PHY_DOES_NOT_EXIST; +- dcsmisasprintk((": phyId >= ioc->num_ports\n")); +- goto cim_sata_signature_exit; +- } +- +- /* Default to success.*/ +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; +- +- /* Issue a config request to get the devHandle of the attached device +- */ +- +- /* Issue a config request to get phy information. */ +- hdr.PageVersion = MPI_SASPHY0_PAGEVERSION; +- hdr.ExtPageLength = 0; +- hdr.PageNumber = 0; +- hdr.Reserved1 = 0; +- hdr.Reserved2 = 0; +- hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; +- hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY; +- +- cfg.cfghdr.ehdr = &hdr; +- cfg.physAddr = -1; +- cfg.pageAddr = phyId; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.dir = 0; /* read */ +- cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) { +- /* Don't check if this failed. Already in a +- * failure case. +- */ +- dcsmisasprintk((": FAILED: MPI_SASPHY0_PAGEVERSION: HEADER\n")); +- dcsmisasprintk((": rc=%x\n",rc)); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_sata_signature_exit; +- } +- +- if (hdr.ExtPageLength == 0) { +- /* Don't check if this failed. Already in a +- * failure case. +- */ +- dcsmisasprintk((": hdr.ExtPageLength == 0\n")); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_sata_signature_exit; +- } +- +- +- sasPhyPg0_data_sz = hdr.ExtPageLength * 4; +- rc = -ENOMEM; +- +- sasPhyPg0 = (SasPhyPage0_t *) pci_alloc_consistent(ioc->pcidev, +- sasPhyPg0_data_sz, &sasPhyPg0_dma); +- +- if (! sasPhyPg0) { +- dcsmisasprintk((": pci_alloc_consistent: FAILED\n")); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_sata_signature_exit; +- } +- +- memset((u8 *)sasPhyPg0, 0, sasPhyPg0_data_sz); +- cfg.physAddr = sasPhyPg0_dma; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) { +- /* Don't check if this failed. Already in a +- * failure case. +- */ +- dcsmisasprintk((": FAILED: MPI_SASPHY0_PAGEVERSION: PAGE\n")); +- dcsmisasprintk((": rc=%x\n",rc)); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_sata_signature_exit; +- } +- +- /* Make sure a SATA device is attached. */ +- if ((le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) & +- MPI_SAS_DEVICE_INFO_SATA_DEVICE) == 0) { +- dcsmisasprintk((": NOT A SATA DEVICE\n")); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_SATA_DEVICE; +- goto cim_sata_signature_exit; +- } +- +- /* Get device page 1 for FIS signature. */ +- hdr.PageVersion = MPI_SASDEVICE1_PAGEVERSION; +- hdr.ExtPageLength = 0; +- hdr.PageNumber = 1 /* page number 1 */; +- hdr.Reserved1 = 0; +- hdr.Reserved2 = 0; +- hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; +- hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE; +- +- cfg.cfghdr.ehdr = &hdr; +- cfg.physAddr = -1; +- +- cfg.pageAddr = ((MPI_SAS_DEVICE_PGAD_FORM_HANDLE << +- MPI_SAS_DEVICE_PGAD_FORM_SHIFT) | +- le16_to_cpu(sasPhyPg0->AttachedDevHandle)); +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.dir = 0; /* read */ +- cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) { +- dcsmisasprintk((": FAILED: MPI_SASDEVICE1_PAGEVERSION: HEADER\n")); +- dcsmisasprintk((": rc=%x\n",rc)); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_sata_signature_exit; +- } +- +- if (hdr.ExtPageLength == 0) { +- dcsmisasprintk((": hdr.ExtPageLength == 0\n")); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_sata_signature_exit; +- } +- +- sasDevicePg1_data_sz = hdr.ExtPageLength * 4; +- rc = -ENOMEM; +- +- sasDevicePg1 = (SasDevicePage1_t *) pci_alloc_consistent +- (ioc->pcidev, sasDevicePg1_data_sz, &sasDevicePg1_dma); +- +- if (! sasDevicePg1) { +- dcsmisasprintk((": pci_alloc_consistent: FAILED\n")); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_sata_signature_exit; +- } +- +- memset((u8 *)sasDevicePg1, 0, sasDevicePg1_data_sz); +- cfg.physAddr = sasDevicePg1_dma; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) { +- dcsmisasprintk((": FAILED: MPI_SASDEVICE1_PAGEVERSION: PAGE\n")); +- dcsmisasprintk((": rc=%x\n",rc)); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_sata_signature_exit; +- } +- +-/* EDM : dump Device Page 1 data*/ +- dcsmisasprintk(("---- SAS DEVICE PAGE 1 ---------\n")); +- dcsmisasprintk(("Handle=0x%x\n",sasDevicePg1->DevHandle)); +- dcsmisasprintk(("SAS Address=")); +- for(jj=0;jj<8;jj++) +- dcsmisasprintk(("%02x ", +- ((u8 *)&sasDevicePg1->SASAddress)[jj])); +- dcsmisasprintk(("\n")); +- dcsmisasprintk(("Target ID=0x%x\n",sasDevicePg1->TargetID)); +- dcsmisasprintk(("Bus=0x%x\n",sasDevicePg1->Bus)); +- dcsmisasprintk(("Initial Reg Device FIS=")); +- for(jj=0;jj<20;jj++) +- dcsmisasprintk(("%02x ", +- ((u8 *)&sasDevicePg1->InitialRegDeviceFIS)[jj])); +- dcsmisasprintk(("\n\n")); +-/* EDM : debug data */ +- +- memcpy(karg.Signature.bSignatureFIS, +- sasDevicePg1->InitialRegDeviceFIS,20); +- +- cim_sata_signature_exit: +- +- if (sasPhyPg0) +- pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz, +- (u8 *) sasPhyPg0, sasPhyPg0_dma); +- +- if (sasDevicePg1) +- pci_free_consistent(ioc->pcidev, sasDevicePg1_data_sz, +- (u8 *) sasDevicePg1, sasDevicePg1_dma); +- +- /* Copy the data from kernel memory to user memory +- */ +- if (copy_to_user((char *)arg, &karg, +- sizeof(CSMI_SAS_SATA_SIGNATURE_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to write out csmi_sas_sata_signature @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- dcsmisasprintk(("%s exit.\n",__FUNCTION__)); +- return 0; +-} +- +-/** +- * Prototype Routine for the CSMI Sas Get SCSI Address command. +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- * -ENODEV if no such device/adapter +- **/ +-static int +-csmisas_get_device_address(unsigned long arg) +-{ +- CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER __user *uarg = (void __user *) arg; +- CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER karg; +- MPT_ADAPTER *ioc = NULL; +- int iocnum; +- struct sas_device_info *sas_info; +- u64 sas_address; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- +- if (copy_from_user(&karg, uarg, +- sizeof(CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in csmi_sas_get_device_address_buffer struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, +- &ioc)) < 0) || (ioc == NULL)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not found!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- if (!csmisas_is_this_sas_cntr(ioc)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not SAS controller!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_DEVICE_ADDRESS; +- memset(karg.bSASAddress, 0, sizeof(u64)); +- memset(karg.bSASLun, 0, sizeof(karg.bSASLun)); +- +- /* Search the list for the matching SAS address. */ +- sas_info = csmisas_get_device_component_by_os(ioc, karg.bPathId, +- karg.bTargetId); +- if (!sas_info || sas_info->is_cached || sas_info->is_logical_volume) +- goto csmisas_get_device_address_exit; +- +- sas_address = reverse_byte_order64(sas_info->sas_address); +- memcpy(karg.bSASAddress, &sas_address, sizeof(u64)); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; +- +- csmisas_get_device_address_exit: +- +- /* Copy the data from kernel memory to user memory +- */ +- if (copy_to_user((char *)arg, &karg, +- sizeof(CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to write out csmi_sas_get_device_address_buffer @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- dcsmisasprintk(("%s exit.\n",__FUNCTION__)); +- return 0; +-} +- +-/** +- * Prototype Routine for the CSMI Sas Get Link Errors command. +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- * -ENODEV if no such device/adapter +- **/ +-static int +-csmisas_get_link_errors(unsigned long arg) +-{ +- CSMI_SAS_LINK_ERRORS_BUFFER __user *uarg = (void __user *) arg; +- CSMI_SAS_LINK_ERRORS_BUFFER karg; +- MPT_ADAPTER *ioc = NULL; +- MPT_FRAME_HDR *mf = NULL; +- MPIHeader_t *mpi_hdr; +- int iocnum; +- int rc; +- ConfigExtendedPageHeader_t hdr; +- CONFIGPARMS cfg; +- SasPhyPage1_t *sasPhyPage1; +- dma_addr_t sasPhyPage1_dma; +- int sasPhyPage1_data_sz; +- SasIoUnitControlRequest_t *sasIoUnitCntrReq; +- SasIoUnitControlReply_t *sasIoUnitCntrReply; +- u8 phyId; +- u16 ioc_status; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- sasPhyPage1=NULL; +- sasPhyPage1_data_sz=0; +- +- if (copy_from_user(&karg, uarg, +- sizeof(CSMI_SAS_LINK_ERRORS_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in csmisas_get_link_errors struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, +- &ioc)) < 0) || (ioc == NULL)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not found!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- if (!csmisas_is_this_sas_cntr(ioc)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not SAS controller!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- phyId = karg.Information.bPhyIdentifier; +- if (phyId >= ioc->num_ports) { +- karg.IoctlHeader.ReturnCode = CSMI_SAS_PHY_DOES_NOT_EXIST; +- dcsmisasprintk((": phyId >= ioc->num_ports\n")); +- goto cim_get_link_errors_exit; +- } +- +- /* Default to success.*/ +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; +- +- /* Issue a config request to get the devHandle of the attached device +- */ +- +- /* Issue a config request to get phy information. */ +- hdr.PageVersion = MPI_SASPHY1_PAGEVERSION; +- hdr.ExtPageLength = 0; +- hdr.PageNumber = 1 /* page number 1*/; +- hdr.Reserved1 = 0; +- hdr.Reserved2 = 0; +- hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; +- hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY; +- +- cfg.cfghdr.ehdr = &hdr; +- cfg.physAddr = -1; +- cfg.pageAddr = phyId; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.dir = 0; /* read */ +- cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) { +- /* Don't check if this failed. Already in a +- * failure case. +- */ +- dcsmisasprintk((": FAILED: MPI_SASPHY1_PAGEVERSION: HEADER\n")); +- dcsmisasprintk((": rc=%x\n",rc)); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_get_link_errors_exit; +- } +- +- if (hdr.ExtPageLength == 0) { +- /* Don't check if this failed. Already in a +- * failure case. +- */ +- dcsmisasprintk((": hdr.ExtPageLength == 0\n")); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_get_link_errors_exit; +- } +- +- +- sasPhyPage1_data_sz = hdr.ExtPageLength * 4; +- rc = -ENOMEM; +- +- sasPhyPage1 = (SasPhyPage1_t *) pci_alloc_consistent(ioc->pcidev, +- sasPhyPage1_data_sz, &sasPhyPage1_dma); +- +- if (! sasPhyPage1) { +- dcsmisasprintk((": pci_alloc_consistent: FAILED\n")); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_get_link_errors_exit; +- } +- +- memset((u8 *)sasPhyPage1, 0, sasPhyPage1_data_sz); +- cfg.physAddr = sasPhyPage1_dma; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) { +- /* Don't check if this failed. Already in a +- * failure case. +- */ +- dcsmisasprintk((": FAILED: MPI_SASPHY1_PAGEVERSION: PAGE\n")); +- dcsmisasprintk((": rc=%x\n",rc)); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_get_link_errors_exit; +- } +- +-/* EDM : dump PHY Page 1 data*/ +- dcsmisasprintk(("---- SAS PHY PAGE 1 ------------\n")); +- dcsmisasprintk(("Invalid Dword Count=0x%x\n", +- sasPhyPage1->InvalidDwordCount)); +- dcsmisasprintk(("Running Disparity Error Count=0x%x\n", +- sasPhyPage1->RunningDisparityErrorCount)); +- dcsmisasprintk(("Loss Dword Synch Count=0x%x\n", +- sasPhyPage1->LossDwordSynchCount)); +- dcsmisasprintk(("PHY Reset Problem Count=0x%x\n", +- sasPhyPage1->PhyResetProblemCount)); +- dcsmisasprintk(("\n\n")); +-/* EDM : debug data */ +- +- karg.Information.uInvalidDwordCount = +- le32_to_cpu(sasPhyPage1->InvalidDwordCount); +- karg.Information.uRunningDisparityErrorCount = +- le32_to_cpu(sasPhyPage1->RunningDisparityErrorCount); +- karg.Information.uLossOfDwordSyncCount = +- le32_to_cpu(sasPhyPage1->LossDwordSynchCount); +- karg.Information.uPhyResetProblemCount = +- le32_to_cpu(sasPhyPage1->PhyResetProblemCount); +- +- if (karg.Information.bResetCounts == +- CSMI_SAS_LINK_ERROR_DONT_RESET_COUNTS ) { +- goto cim_get_link_errors_exit; +- } +- +- /* Clear Error log +- * +- * Issue IOUNIT Control Reqeust Message +- */ +- +- /* Get a MF for this command. +- */ +- if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) { +- dcsmisasprintk((": no msg frames!\n")); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_get_link_errors_exit; +- } +- +- mpi_hdr = (MPIHeader_t *) mf; +- sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf; +- memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t)); +- sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL; +- sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext; +- sasIoUnitCntrReq->PhyNum = phyId; +- sasIoUnitCntrReq->Operation = MPI_SAS_OP_PHY_CLEAR_ERROR_LOG; +- +- if (csmisas_send_command_wait(ioc, mf, karg.IoctlHeader.Timeout) != 0) { +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_get_link_errors_exit; +- } +- +- /* process the completed Reply Message Frame */ +- if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) { +- +- sasIoUnitCntrReply = +- (SasIoUnitControlReply_t *)ioc->ioctl->ReplyFrame; +- ioc_status = le16_to_cpu(sasIoUnitCntrReply->IOCStatus) +- & MPI_IOCSTATUS_MASK; +- +- if (ioc_status != MPI_IOCSTATUS_SUCCESS) { +- dcsmisasprintk((": SAS IO Unit Control: ")); +- dcsmisasprintk(("IOCStatus=0x%X IOCLogInfo=0x%X\n", +- sasIoUnitCntrReply->IOCStatus, +- sasIoUnitCntrReply->IOCLogInfo)); +- } +- } +- +- cim_get_link_errors_exit: +- +- if (sasPhyPage1) +- pci_free_consistent(ioc->pcidev, sasPhyPage1_data_sz, +- (u8 *) sasPhyPage1, sasPhyPage1_dma); +- +- /* Copy the data from kernel memory to user memory +- */ +- if (copy_to_user((char *)arg, &karg, +- sizeof(CSMI_SAS_LINK_ERRORS_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to write out csmisas_get_link_errors @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- dcsmisasprintk(("%s exit.\n",__FUNCTION__)); +- return 0; +- +-} +- +-/** +- * Prototype Routine for the CSMI SAS SMP Passthru command. +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- * -ENODEV if no such device/adapter +- **/ +-static int +-csmisas_smp_passthru(unsigned long arg) +-{ +- CSMI_SAS_SMP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg; +- MPT_ADAPTER *ioc; +- CSMI_SAS_SMP_PASSTHRU_BUFFER karg; +- pSmpPassthroughRequest_t smpReq; +- pSmpPassthroughReply_t smpReply; +- MPT_FRAME_HDR *mf = NULL; +- MPIHeader_t *mpi_hdr; +- char *psge; +- int iocnum, flagsLength; +- void * request_data; +- dma_addr_t request_data_dma; +- u32 request_data_sz; +- void * response_data; +- dma_addr_t response_data_dma; +- u32 response_data_sz; +- u16 ioc_status; +- u64 sas_address; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- +- if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SMP_PASSTHRU_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in csmi_sas_smp_passthru struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- request_data = NULL; +- response_data = NULL; +- response_data_sz = sizeof(CSMI_SAS_SMP_RESPONSE); +- request_data_sz = karg.Parameters.uRequestLength; +- +- if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, +- &ioc)) < 0) || (ioc == NULL)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not found!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- if (!csmisas_is_this_sas_cntr(ioc)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not SAS controller!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- /* Make sure the adapter is not being reset. */ +- if (!ioc->ioctl) { +- printk(KERN_ERR "%s@%d::%s - " +- "No memory available during driver init.\n", +- __FILE__, __LINE__,__FUNCTION__); +- return -ENOMEM; +- } else if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) { +- printk(KERN_ERR "%s@%d::%s - " +- "Busy with IOC Reset \n", +- __FILE__, __LINE__,__FUNCTION__); +- return -EBUSY; +- } +- +- /* Default to success.*/ +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; +- +- /* Do some error checking on the request. */ +- if (karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) { +- karg.IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT; +- goto cim_smp_passthru_exit; +- } +- +- if ((request_data_sz > 0xFFFF) || (!request_data_sz)) { +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_smp_passthru_exit; +- } +- +- /* Get a free request frame and save the message context. +- */ +- if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) { +- dcsmisasprintk((": no msg frames!\n")); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_smp_passthru_exit; +- } +- +- mpi_hdr = (MPIHeader_t *) mf; +- smpReq = (pSmpPassthroughRequest_t ) mf; +- +- memset(smpReq,0,ioc->req_sz); +- +- memcpy(&sas_address, karg.Parameters.bDestinationSASAddress, +- sizeof(u64)); +- sas_address = cpu_to_le64(reverse_byte_order64(sas_address)); +- memcpy(&smpReq->SASAddress, &sas_address, sizeof(u64)); +- +- /* Fill in smp request. */ +- smpReq->PhysicalPort = karg.Parameters.bPortIdentifier; +- smpReq->Function = MPI_FUNCTION_SMP_PASSTHROUGH; +- smpReq->RequestDataLength = cpu_to_le16(request_data_sz); +- smpReq->ConnectionRate = karg.Parameters.bConnectionRate; +- smpReq->MsgContext = mpi_hdr->MsgContext; +- smpReq->Reserved2 = 0; +- smpReq->Reserved3 = 0; +- +- /* +- * Prepare the necessary pointers to run +- * through the SGL generation +- */ +- +- psge = (char *)&smpReq->SGL; +- +- /* setup the *Request* payload SGE */ +- flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT | +- MPI_SGE_FLAGS_SYSTEM_ADDRESS | +- MPI_SGE_FLAGS_32_BIT_ADDRESSING | +- MPI_SGE_FLAGS_HOST_TO_IOC | +- MPI_SGE_FLAGS_END_OF_BUFFER; +- +- if (sizeof(dma_addr_t) == sizeof(u64)) { +- flagsLength |= MPI_SGE_FLAGS_64_BIT_ADDRESSING; +- } +- flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT; +- flagsLength |= request_data_sz; +- +- request_data = pci_alloc_consistent( +- ioc->pcidev, request_data_sz, &request_data_dma); +- +- if (!request_data) { +- dcsmisasprintk((": pci_alloc_consistent: FAILED\n")); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- mpt_free_msg_frame(ioc, mf); +- goto cim_smp_passthru_exit; +- } +- +- mpt_add_sge(psge, flagsLength, request_data_dma); +- psge += (sizeof(u32) + sizeof(dma_addr_t)); +- +- memcpy(request_data,&karg.Parameters.Request,request_data_sz); +- +- /* setup the *Response* payload SGE */ +- response_data = pci_alloc_consistent( +- ioc->pcidev, response_data_sz, &response_data_dma); +- +- if (!response_data) { +- dcsmisasprintk((": pci_alloc_consistent: FAILED\n")); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- mpt_free_msg_frame(ioc, mf); +- goto cim_smp_passthru_exit; +- } +- +- flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT | +- MPI_SGE_FLAGS_SYSTEM_ADDRESS | +- MPI_SGE_FLAGS_32_BIT_ADDRESSING | +- MPI_SGE_FLAGS_IOC_TO_HOST | +- MPI_SGE_FLAGS_END_OF_BUFFER; +- +- if (sizeof(dma_addr_t) == sizeof(u64)) { +- flagsLength |= MPI_SGE_FLAGS_64_BIT_ADDRESSING; +- } +- +- flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT; +- flagsLength |= response_data_sz; +- +- mpt_add_sge(psge, flagsLength, response_data_dma); +- +- if (csmisas_send_command_wait(ioc, mf, karg.IoctlHeader.Timeout) != 0) { +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_smp_passthru_exit; +- } +- +- if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) == 0) { +- dcsmisasprintk((": SMP Passthru: oh no, there is no reply!!")); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_smp_passthru_exit; +- } +- +- /* process the completed Reply Message Frame */ +- smpReply = (pSmpPassthroughReply_t )ioc->ioctl->ReplyFrame; +- ioc_status = le16_to_cpu(smpReply->IOCStatus) & MPI_IOCSTATUS_MASK; +- +- if ((ioc_status != MPI_IOCSTATUS_SUCCESS) && +- (ioc_status != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN)) { +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- dcsmisasprintk((": SMP Passthru: ")); +- dcsmisasprintk(("IOCStatus=0x%X IOCLogInfo=0x%X SASStatus=0x%X\n", +- le16_to_cpu(smpReply->IOCStatus), +- le32_to_cpu(smpReply->IOCLogInfo), +- smpReply->SASStatus)); +- goto cim_smp_passthru_exit; +- } +- +- karg.Parameters.bConnectionStatus = +- map_sas_status_to_csmi(smpReply->SASStatus); +- +- +- if (le16_to_cpu(smpReply->ResponseDataLength)) { +- karg.Parameters.uResponseBytes = le16_to_cpu(smpReply->ResponseDataLength); +- memcpy(&karg.Parameters.Response, +- response_data, le16_to_cpu(smpReply->ResponseDataLength)); +- } +- +- cim_smp_passthru_exit: +- +- if (request_data) +- pci_free_consistent(ioc->pcidev, request_data_sz, +- (u8 *)request_data, request_data_dma); +- +- if (response_data) +- pci_free_consistent(ioc->pcidev, response_data_sz, +- (u8 *)response_data, response_data_dma); +- +- +- /* Copy the data from kernel memory to user memory +- */ +- if (copy_to_user((char *)arg, &karg, +- sizeof(CSMI_SAS_SMP_PASSTHRU_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to write out csmi_sas_smp_passthru @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- dcsmisasprintk((": %s exit.\n",__FUNCTION__)); +- return 0; +-} +- +-/** +- * Prototype Routine for the CSMI SAS SSP Passthru command. +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- * -ENODEV if no such device/adapter +- **/ +-static int csmisas_ssp_passthru(unsigned long arg) +-{ +- CSMI_SAS_SSP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg; +- CSMI_SAS_SSP_PASSTHRU_BUFFER karg_hdr, * karg; +- MPT_ADAPTER *ioc = NULL; +- pSCSIIORequest_t pScsiRequest; +- pSCSIIOReply_t pScsiReply; +- MPT_FRAME_HDR *mf = NULL; +- MPIHeader_t *mpi_hdr; +- int iocnum,ii; +- u64 sas_address; +- u16 req_idx; +- char *psge; +- int flagsLength; +- void * request_data; +- dma_addr_t request_data_dma; +- u32 request_data_sz; +- int malloc_data_sz; +- int memory_pages; +- u16 ioc_status; +- u8 volume_id; +- u8 volume_bus; +- u8 is_hidden_raid_component; +- u8 channel; +- u8 id; +- struct sas_device_info *sas_info; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- +- if (copy_from_user(&karg_hdr, uarg, sizeof(CSMI_SAS_SSP_PASSTHRU_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in csmi_sas_ssp_passthru struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- request_data = NULL; +- request_data_sz = karg_hdr.Parameters.uDataLength; +- channel = 0; +- id = 0; +- volume_id = 0; +- volume_bus = 0; +- is_hidden_raid_component = 0; +- +- malloc_data_sz = (request_data_sz + +- offsetof(CSMI_SAS_SSP_PASSTHRU_BUFFER,bDataBuffer)); +- memory_pages = get_order(malloc_data_sz); +- karg = (CSMI_SAS_SSP_PASSTHRU_BUFFER *)__get_free_pages( +- GFP_KERNEL, memory_pages); +- if (!karg){ +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to malloc SAS_SSP_PASSTHRU_BUFFER " +- "malloc_data_sz=%d memory_pages=%d\n", +- __FILE__, __LINE__, __FUNCTION__, +- malloc_data_sz, memory_pages); +- return -ENOMEM; +- } +- +- dcsmisasprintk((KERN_ERR "%s@%d::%s() - " +- "malloc'ed SAS_SSP_PASSTHRU_BUFFER " +- "malloc_data_sz=%d memory_pages=%d\n", +- __FILE__, __LINE__, __FUNCTION__, +- malloc_data_sz, memory_pages)); +- +- memset(karg, 0, sizeof(*karg)); +- +- if (copy_from_user(karg, uarg, request_data_sz + +- offsetof(CSMI_SAS_SSP_PASSTHRU_BUFFER,bDataBuffer))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in csmi_sas_ssp_passthru struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- free_pages((unsigned long)karg, memory_pages); +- return -EFAULT; +- } +- +- /* +- * some checks of the incoming frame +- */ +- if ( offsetof(CSMI_SAS_SSP_PASSTHRU_BUFFER,bDataBuffer) + +- request_data_sz - sizeof(IOCTL_HEADER) > +- karg->IoctlHeader.Length ) { +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER; +- dcsmisasprintk((KERN_ERR +- "%s::%s()" +- " @%d - expected datalen incorrect!\n", +- __FILE__, __FUNCTION__, __LINE__)); +- goto cim_ssp_passthru_exit; +- } +- +- if (((iocnum = mpt_verify_adapter(karg->IoctlHeader.IOControllerNumber, +- &ioc)) < 0) || (ioc == NULL)) { +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER; +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not found!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- goto cim_ssp_passthru_exit; +- } +- +- if (!csmisas_is_this_sas_cntr(ioc)) { +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER; +- dcsmisasprintk((KERN_ERR +- "%s::%s()" +- " @%d - ioc%d not SAS controller!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- goto cim_ssp_passthru_exit; +- } +- +- /* Default to success. +- */ +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; +- +- /* Neither a phy nor a port has been selected. +- */ +- if ((karg->Parameters.bPhyIdentifier == CSMI_SAS_USE_PORT_IDENTIFIER) && +- (karg->Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT)) { +- karg->IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT; +- dcsmisasprintk((KERN_ERR +- "%s::%s()" +- " @%d - incorrect bPhyIdentifier and bPortIdentifier!\n", +- __FILE__, __FUNCTION__, __LINE__)); +- goto cim_ssp_passthru_exit; +- } +- +- /* A phy has been selected. Verify that it's valid. +- */ +- if (karg->Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) { +- +- /* Is the phy in range? */ +- if (karg->Parameters.bPhyIdentifier >= ioc->num_ports) { +- dcsmisasprintk((": phyId >= ioc->num_ports (%d %d)\n", +- karg->Parameters.bPhyIdentifier, +- ioc->num_ports)); +- karg->IoctlHeader.ReturnCode = +- CSMI_SAS_PHY_DOES_NOT_EXIST; +- goto cim_ssp_passthru_exit; +- } +- } +- +- if(karg->Parameters.bAdditionalCDBLength) { +- /* TODO - SCSI IO (32) Request Message support +- */ +- dcsmisasprintk((": greater than 16-byte cdb is not supported!\n")); +- karg->IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_INVALID_PARAMETER; +- goto cim_ssp_passthru_exit; +- } +- +- /* we will use SAS address to resolve the scsi adddressing +- */ +- memcpy(&sas_address, karg->Parameters.bDestinationSASAddress, +- sizeof(u64)); +- sas_address = reverse_byte_order64(sas_address); +- +- /* Search the list for the matching SAS address. +- */ +- sas_info = csmisas_get_device_component_by_sas_addr(ioc, sas_address); +- if (!sas_info || sas_info->is_cached) { +- /* +- *Invalid SAS address +- */ +- karg->IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_INVALID_PARAMETER; +- dcsmisasprintk((KERN_ERR +- "%s::%s()" +- " @%d - couldn't find associated SASAddress=%llX!\n", +- __FILE__, __FUNCTION__, __LINE__, sas_address)); +- goto cim_ssp_passthru_exit; +- } +- +- id = sas_info->fw.id; +- channel = sas_info->fw.channel; +- +- if (csmisas_is_phys_disk(ioc, channel, id)) { +- id = csmisas_raid_id_to_num(ioc, channel, id); +- channel = 0; +- is_hidden_raid_component = 1; +- } +- +- /* Get a free request frame and save the message context. +- */ +- if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) { +- dcsmisasprintk((": no msg frames!\n")); +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_ssp_passthru_exit; +- } +- +- mpi_hdr = (MPIHeader_t *) mf; +- pScsiRequest = (pSCSIIORequest_t) mf; +- req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); +- +- memset(pScsiRequest,0,sizeof(SCSIIORequest_t)); +- +- /* Fill in SCSI IO (16) request. +- */ +- +- pScsiRequest->Function = (is_hidden_raid_component == 1) ? +- MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH : MPI_FUNCTION_SCSI_IO_REQUEST; +- pScsiRequest->TargetID = id; +- pScsiRequest->Bus = channel; +- memcpy(pScsiRequest->LUN, &karg->Parameters.bLun, 8); +- pScsiRequest->CDBLength = karg->Parameters.bCDBLength; +- pScsiRequest->DataLength = cpu_to_le32(request_data_sz); +- pScsiRequest->MsgContext = mpi_hdr->MsgContext; +- memcpy(pScsiRequest->CDB, karg->Parameters.bCDB, +- pScsiRequest->CDBLength); +- +- #if defined(MPT_DEBUG_CSMISAS) +- { +- int k; +- printk("\tchannel=%d id=%d ", sas_info->fw.channel, +- sas_info->fw.id); +- if (is_hidden_raid_component) +- printk("num_id=%d ", id); +- printk("\n"); +- printk("\tcdb_len = %d data_len=%d\n", +- pScsiRequest->CDBLength, request_data_sz); +- printk("\t"); +- for (k = 0; k < pScsiRequest->CDBLength; ++k) +- printk(" %02x", pScsiRequest->CDB[k]); +- printk("\n"); +- } +- #endif +- +- /* direction +- */ +- if (karg->Parameters.uFlags & CSMI_SAS_SSP_READ) { +- pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ); +- } else if (karg->Parameters.uFlags & CSMI_SAS_SSP_WRITE) { +- pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_WRITE); +- } else if ((karg->Parameters.uFlags & CSMI_SAS_SSP_UNSPECIFIED) && +- (!karg->Parameters.uDataLength)) { +- /* no data transfer +- */ +- pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_NODATATRANSFER); +- } else { +- /* no direction specified +- */ +- pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ); +- pScsiRequest->MsgFlags = +- MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR; +- } +- +- pScsiRequest->MsgFlags |= mpt_msg_flags(); +- /* task attributes +- */ +- if((karg->Parameters.uFlags && 0xFF) == 0) { +- pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_SIMPLEQ); +- } else if (karg->Parameters.uFlags & +- CSMI_SAS_SSP_TASK_ATTRIBUTE_HEAD_OF_QUEUE) { +- pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_HEADOFQ); +- } else if (karg->Parameters.uFlags & +- CSMI_SAS_SSP_TASK_ATTRIBUTE_ORDERED) { +- pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_ORDEREDQ); +- } else if (karg->Parameters.uFlags & +- CSMI_SAS_SSP_TASK_ATTRIBUTE_ACA) { +- pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_ACAQ); +- } else { +- pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_UNTAGGED); +- } +- +- /* setup sense +- */ +- pScsiRequest->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; +- pScsiRequest->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma + +- (req_idx * MPT_SENSE_BUFFER_ALLOC)); +- +- /* setup databuffer sg, assuming we fit everything one contiguous buffer +- */ +- psge = (char *)&pScsiRequest->SGL; +- +- if (karg->Parameters.uFlags & CSMI_SAS_SSP_WRITE) { +- flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE; +- } else if (karg->Parameters.uFlags & CSMI_SAS_SSP_READ) { +- flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ; +- }else { +- flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT | +- MPI_SGE_FLAGS_DIRECTION | +- mpt_addr_size() ) +- << MPI_SGE_FLAGS_SHIFT; +- } +- flagsLength |= request_data_sz; +- +- if ( request_data_sz > 0) { +- request_data = pci_alloc_consistent( +- ioc->pcidev, request_data_sz, &request_data_dma); +- +- if (request_data == NULL) { +- dcsmisasprintk((": pci_alloc_consistent: FAILED " +- "request_data_sz=%d\n", request_data_sz)); +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- mpt_free_msg_frame(ioc, mf); +- goto cim_ssp_passthru_exit; +- } +- +- mpt_add_sge(psge, flagsLength, request_data_dma); +- if (karg->Parameters.uFlags & CSMI_SAS_SSP_WRITE) +- memcpy(request_data, karg->bDataBuffer, request_data_sz); +- } else { +- mpt_add_sge(psge, flagsLength, (dma_addr_t) -1); +- } +- +- if (csmisas_send_command_wait(ioc, mf, karg->IoctlHeader.Timeout) != 0) { +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_ssp_passthru_exit; +- } +- +- memset(&karg->Status,0,sizeof(CSMI_SAS_SSP_PASSTHRU_STATUS)); +- karg->Status.bConnectionStatus = CSMI_SAS_OPEN_ACCEPT; +- karg->Status.bDataPresent = CSMI_SAS_SSP_NO_DATA_PRESENT; +- karg->Status.bStatus = GOOD; +- karg->Status.bResponseLength[0] = 0; +- karg->Status.bResponseLength[1] = 0; +- karg->Status.uDataBytes = request_data_sz; +- +- /* process the completed Reply Message Frame */ +- if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) { +- +- pScsiReply = (pSCSIIOReply_t ) ioc->ioctl->ReplyFrame; +- karg->Status.bStatus = pScsiReply->SCSIStatus; +- karg->Status.uDataBytes = min(le32_to_cpu(pScsiReply->TransferCount), +- request_data_sz); +- ioc_status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK; +- +- if (pScsiReply->SCSIState == +- MPI_SCSI_STATE_AUTOSENSE_VALID) { +- karg->Status.bConnectionStatus = +- CSMI_SAS_SSP_SENSE_DATA_PRESENT; +- karg->Status.bResponseLength[0] = +- (u8)le32_to_cpu(pScsiReply->SenseCount) & 0xFF; +- memcpy(karg->Status.bResponse, +- ioc->ioctl->sense, le32_to_cpu(pScsiReply->SenseCount)); +- } else if(pScsiReply->SCSIState == +- MPI_SCSI_STATE_RESPONSE_INFO_VALID) { +- karg->Status.bDataPresent = +- CSMI_SAS_SSP_RESPONSE_DATA_PRESENT; +- karg->Status.bResponseLength[0] = +- sizeof(pScsiReply->ResponseInfo); +- for (ii=0;ii<sizeof(pScsiReply->ResponseInfo);ii++) { +- karg->Status.bResponse[ii] = +- ((u8*)&pScsiReply->ResponseInfo)[ +- (sizeof(pScsiReply->ResponseInfo)-1)-ii]; +- } +- } else if ((ioc_status != MPI_IOCSTATUS_SUCCESS) && +- (ioc_status != MPI_IOCSTATUS_SCSI_RECOVERED_ERROR) && +- (ioc_status != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN)) { +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- dcsmisasprintk((": SCSI IO : ")); +- dcsmisasprintk(("IOCStatus=0x%X IOCLogInfo=0x%X\n", +- pScsiReply->IOCStatus, +- pScsiReply->IOCLogInfo)); +- } +- } +- +- if ((karg->Status.uDataBytes) && (request_data) && +- (karg->Parameters.uFlags & CSMI_SAS_SSP_READ)) { +- if (copy_to_user((char *)uarg->bDataBuffer, +- request_data, karg->Status.uDataBytes)) { +- printk(KERN_ERR "%s@%d::%s - " +- "Unable to write data to user %p\n", +- __FILE__, __LINE__,__FUNCTION__, +- (void*)karg->bDataBuffer); +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- } +- } +- +- cim_ssp_passthru_exit: +- +- +- if (request_data) +- pci_free_consistent(ioc->pcidev, request_data_sz, +- (u8 *)request_data, request_data_dma); +- +- /* Copy the data from kernel memory to user memory +- */ +- if (copy_to_user((char *)arg, karg, +- offsetof(CSMI_SAS_SSP_PASSTHRU_BUFFER, bDataBuffer))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to write out csmi_sas_ssp_passthru @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- free_pages((unsigned long)karg, memory_pages); +- return -EFAULT; +- } +- +- dcsmisasprintk(("%s exit.\n",__FUNCTION__)); +- free_pages((unsigned long)karg, memory_pages); +- return 0; +-} +- +-/** +- * Prototype Routine for the CSMI SAS STP Passthru command. +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- * -ENODEV if no such device/adapter +- **/ +-static int +-csmisas_stp_passthru(unsigned long arg) +-{ +- CSMI_SAS_STP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg; +- CSMI_SAS_STP_PASSTHRU_BUFFER karg; +- MPT_ADAPTER *ioc = NULL; +- pSataPassthroughRequest_t pSataRequest; +- pSataPassthroughReply_t pSataReply; +- MPT_FRAME_HDR *mf = NULL; +- MPIHeader_t *mpi_hdr; +- int iocnum; +- u32 data_sz; +- u64 sas_address; +- u16 req_idx; +- char *psge; +- int flagsLength; +- void * request_data; +- dma_addr_t request_data_dma; +- u32 request_data_sz; +- u8 channel; +- u8 id; +- u8 volume_id; +- u8 volume_bus; +- struct sas_device_info *sas_info; +- u16 ioc_status; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- +- if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_STP_PASSTHRU_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- request_data=NULL; +- request_data_sz = karg.Parameters.uDataLength; +- volume_id = 0; +- volume_bus = 0; +- channel = 0; +- id = 0; +- +- if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, +- &ioc)) < 0) || (ioc == NULL)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s @%d - ioc%d not found!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- if (!csmisas_is_this_sas_cntr(ioc)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not SAS controller!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- /* Default to success. +- */ +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; +- +- /* Neither a phy nor a port has been selected. +- */ +- if ((karg.Parameters.bPhyIdentifier == CSMI_SAS_USE_PORT_IDENTIFIER) && +- (karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT)) { +- karg.IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT; +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - incorrect bPhyIdentifier and bPortIdentifier!\n", +- __FILE__,__FUNCTION__, __LINE__)); +- goto cim_stp_passthru_exit; +- } +- +- /* A phy has been selected. Verify that it's valid. +- */ +- if (karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) { +- +- /* Is the phy in range? */ +- if (karg.Parameters.bPhyIdentifier >= ioc->num_ports) { +- karg.IoctlHeader.ReturnCode = +- CSMI_SAS_PHY_DOES_NOT_EXIST; +- goto cim_stp_passthru_exit; +- } +- } +- +- /* some checks of the incoming frame +- */ +- if (request_data_sz > 0xFFFF) { +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - uDataLength > 0xFFFF!\n", +- __FILE__, __FUNCTION__, __LINE__)); +- goto cim_stp_passthru_exit; +- } +- +- data_sz = sizeof(CSMI_SAS_STP_PASSTHRU_BUFFER) - +- sizeof(IOCTL_HEADER) - sizeof(u8*) + +- request_data_sz; +- +- if ( data_sz > karg.IoctlHeader.Length ) { +- karg.IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_INVALID_PARAMETER; +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - expected datalen incorrect!\n", +- __FILE__, __FUNCTION__,__LINE__)); +- goto cim_stp_passthru_exit; +- } +- +- +- /* we will use SAS address to resolve the scsi adddressing +- */ +- memcpy(&sas_address, karg.Parameters.bDestinationSASAddress, +- sizeof(u64)); +- sas_address = reverse_byte_order64(sas_address); +- +- /* Search the list for the matching SAS address. +- */ +- sas_info = csmisas_get_device_component_by_sas_addr(ioc, sas_address); +- if (!sas_info || sas_info->is_cached || sas_info->is_logical_volume) { +- /* +- *Invalid SAS address +- */ +- karg.IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_INVALID_PARAMETER; +- dcsmisasprintk((KERN_ERR +- "%s::%s()" +- " @%d - couldn't find associated SASAddress=%llX!\n", +- __FILE__, __FUNCTION__, __LINE__, sas_address)); +- goto cim_stp_passthru_exit; +- } +- +- id = sas_info->fw.id; +- channel = sas_info->fw.channel; +- +- /* check that this is an STP or SATA target device +- */ +- if ( !(sas_info->device_info & MPI_SAS_DEVICE_INFO_STP_TARGET ) && +- !(sas_info->device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE )) { +- karg.IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_INVALID_PARAMETER; +- goto cim_stp_passthru_exit; +- } +- +- /* Get a free request frame and save the message context. +- */ +- if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) { +- dcsmisasprintk((": no msg frames!\n")); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_stp_passthru_exit; +- } +- +- mpi_hdr = (MPIHeader_t *) mf; +- pSataRequest = (pSataPassthroughRequest_t) mf; +- req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); +- +- memset(pSataRequest,0,sizeof(pSataPassthroughRequest_t)); +- +- pSataRequest->TargetID = id; +- pSataRequest->Bus = channel; +- pSataRequest->Function = MPI_FUNCTION_SATA_PASSTHROUGH; +- pSataRequest->PassthroughFlags = cpu_to_le16(karg.Parameters.uFlags); +- pSataRequest->ConnectionRate = karg.Parameters.bConnectionRate; +- pSataRequest->MsgContext = mpi_hdr->MsgContext; +- pSataRequest->DataLength = cpu_to_le32(request_data_sz); +- pSataRequest->MsgFlags = 0; +- memcpy( pSataRequest->CommandFIS,karg.Parameters.bCommandFIS, 20); +- +- psge = (char *)&pSataRequest->SGL; +- if (karg.Parameters.uFlags & CSMI_SAS_STP_WRITE) { +- flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE; +- } else if (karg.Parameters.uFlags & CSMI_SAS_STP_READ) { +- flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ; +- }else { +- flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT | +- MPI_SGE_FLAGS_DIRECTION | +- mpt_addr_size() ) +- << MPI_SGE_FLAGS_SHIFT; +- } +- +- flagsLength |= request_data_sz; +- if (request_data_sz > 0) { +- request_data = pci_alloc_consistent( +- ioc->pcidev, request_data_sz, &request_data_dma); +- +- if (request_data == NULL) { +- dcsmisasprintk((": pci_alloc_consistent: FAILED\n")); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- mpt_free_msg_frame(ioc, mf); +- goto cim_stp_passthru_exit; +- } +- +- mpt_add_sge(psge, flagsLength, request_data_dma); +- if (karg.Parameters.uFlags & CSMI_SAS_STP_WRITE) { +- if (copy_from_user(request_data, +- karg.bDataBuffer, +- request_data_sz)) { +- printk(KERN_ERR +- "%s::%s() @%d - Unable to read user data " +- "struct @ %p\n", +- __FILE__, __FUNCTION__, __LINE__, +- (void*)karg.bDataBuffer); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- mpt_free_msg_frame(ioc, mf); +- goto cim_stp_passthru_exit; +- } +- } +- } else { +- mpt_add_sge(psge, flagsLength, (dma_addr_t) -1); +- } +- +- if (csmisas_send_command_wait(ioc, mf, karg.IoctlHeader.Timeout) != 0) { +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_stp_passthru_exit; +- } +- +- memset(&karg.Status,0,sizeof(CSMI_SAS_STP_PASSTHRU_STATUS)); +- +- if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) == 0) { +- dcsmisasprintk((": STP Passthru: oh no, there is no reply!!")); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_stp_passthru_exit; +- } +- +- /* process the completed Reply Message Frame */ +- pSataReply = (pSataPassthroughReply_t ) ioc->ioctl->ReplyFrame; +- ioc_status = le16_to_cpu(pSataReply->IOCStatus) & MPI_IOCSTATUS_MASK; +- +- if (ioc_status != MPI_IOCSTATUS_SUCCESS && +- ioc_status != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) { +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- dcsmisasprintk((": STP Passthru: ")); +- dcsmisasprintk(("IOCStatus=0x%X IOCLogInfo=0x%X SASStatus=0x%X\n", +- le16_to_cpu(pSataReply->IOCStatus), +- le32_to_cpu(pSataReply->IOCLogInfo), +- pSataReply->SASStatus)); +- } +- +- karg.Status.bConnectionStatus = +- map_sas_status_to_csmi(pSataReply->SASStatus); +- +- memcpy(karg.Status.bStatusFIS,pSataReply->StatusFIS, 20); +- +- /* +- * for now, just zero out uSCR array, +- * then copy the one dword returned +- * in the reply frame into uSCR[0] +- */ +- memset( karg.Status.uSCR, 0, 64); +- karg.Status.uSCR[0] = le32_to_cpu(pSataReply->StatusControlRegisters); +- +- if((le32_to_cpu(pSataReply->TransferCount)) && (request_data) && +- (karg.Parameters.uFlags & CSMI_SAS_STP_READ)) { +- karg.Status.uDataBytes = +- min(le32_to_cpu(pSataReply->TransferCount),request_data_sz); +- if (copy_to_user((char *)uarg->bDataBuffer, +- request_data, karg.Status.uDataBytes)) { +- printk(KERN_ERR "%s::%s() @%d - " +- "Unable to write data to user %p\n", +- __FILE__, __FUNCTION__, __LINE__, +- (void*)karg.bDataBuffer); +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- } +- } +- +- cim_stp_passthru_exit: +- +- if (request_data) +- pci_free_consistent(ioc->pcidev, request_data_sz, +- (u8 *)request_data, request_data_dma); +- +- /* Copy th data from kernel memory to user memory +- */ +- if (copy_to_user((char *)arg, &karg, +- offsetof(CSMI_SAS_STP_PASSTHRU_BUFFER,bDataBuffer))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to write out csmi_sas_ssp_passthru @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- dcsmisasprintk((": %s exit.\n",__FUNCTION__)); +- return 0; +-} +- +-/** +- * Prototype Routine for the CSMI SAS Firmware Download command. +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- * -ENODEV if no such device/adapter +- **/ +-static int +-csmisas_firmware_download(unsigned long arg) +-{ +- CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER __user *uarg = (void __user *) arg; +- CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER karg; +- MPT_ADAPTER *ioc = NULL; +- int iocnum; +- pMpiFwHeader_t pFwHeader=NULL; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- +- if (copy_from_user(&karg, uarg, +- sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in csmi_sas_firmware_download struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, +- &ioc)) < 0) || (ioc == NULL)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not found!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- if (!csmisas_is_this_sas_cntr(ioc)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not SAS controller!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- /* Default to success.*/ +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; +- karg.Information.usStatus = CSMI_SAS_FWD_SUCCESS; +- karg.Information.usSeverity = CSMI_SAS_FWD_INFORMATION; +- +- /* some checks of the incoming frame */ +- if ((karg.Information.uBufferLength + +- sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD)) > +- karg.IoctlHeader.Length) { +- karg.IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_INVALID_PARAMETER; +- karg.Information.usStatus = CSMI_SAS_FWD_FAILED; +- goto cim_firmware_download_exit; +- } +- +- if ( karg.Information.uDownloadFlags & +- (CSMI_SAS_FWD_SOFT_RESET | CSMI_SAS_FWD_VALIDATE)) { +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- karg.Information.usStatus = CSMI_SAS_FWD_REJECT; +- karg.Information.usSeverity = CSMI_SAS_FWD_ERROR; +- goto cim_firmware_download_exit; +- } +- +- /* now we need to alloc memory so we can pull in the +- * fw image attached to end of incoming packet. +- */ +- pFwHeader = kmalloc(karg.Information.uBufferLength, GFP_KERNEL); +- if (!pFwHeader){ +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- karg.Information.usStatus = CSMI_SAS_FWD_REJECT; +- karg.Information.usSeverity = CSMI_SAS_FWD_ERROR; +- goto cim_firmware_download_exit; +- } +- memset(pFwHeader, 0, sizeof(*pFwHeader)); +- +- if (copy_from_user(pFwHeader, uarg->bDataBuffer, +- karg.Information.uBufferLength)) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in pFwHeader @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- if ( !((pFwHeader->Signature0 == MPI_FW_HEADER_SIGNATURE_0) && +- (pFwHeader->Signature1 == MPI_FW_HEADER_SIGNATURE_1) && +- (pFwHeader->Signature2 == MPI_FW_HEADER_SIGNATURE_2))) { +- // the signature check failed +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- karg.Information.usStatus = CSMI_SAS_FWD_REJECT; +- karg.Information.usSeverity = CSMI_SAS_FWD_ERROR; +- goto cim_firmware_download_exit; +- } +- +- if ( mptctl_do_fw_download(karg.IoctlHeader.IOControllerNumber, +- uarg->bDataBuffer, karg.Information.uBufferLength) +- != 0) { +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- karg.Information.usStatus = CSMI_SAS_FWD_FAILED; +- karg.Information.usSeverity = CSMI_SAS_FWD_FATAL; +- goto cim_firmware_download_exit; +- } +- +- if((karg.Information.uDownloadFlags & CSMI_SAS_FWD_SOFT_RESET) || +- (karg.Information.uDownloadFlags & CSMI_SAS_FWD_HARD_RESET)) { +- if (mpt_HardResetHandler(ioc, CAN_SLEEP) != 0) { +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- karg.Information.usStatus = CSMI_SAS_FWD_FAILED; +- karg.Information.usSeverity = CSMI_SAS_FWD_FATAL; +- } +- } +- +- cim_firmware_download_exit: +- +- if(pFwHeader) +- kfree(pFwHeader); +- +- /* Copy the data from kernel memory to user memory +- */ +- if (copy_to_user((char *)arg, &karg, +- sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to write out csmi_sas_firmware_download @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- dcsmisasprintk(("%s exit.\n",__FUNCTION__)); +- return 0; +-} +- +-/** +- * Prototype Routine for the CSMI SAS Get RAID Info command. +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- * -ENODEV if no such device/adapter +- **/ +-static int +-csmisas_get_raid_info(unsigned long arg) +-{ +- CSMI_SAS_RAID_INFO_BUFFER __user *uarg = (void __user *) arg; +- CSMI_SAS_RAID_INFO_BUFFER karg; +- MPT_ADAPTER *ioc = NULL; +- int iocnum; +- u32 raidFlags; +- u8 maxRaidTypes; +- u8 maxDrivesPerSet; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- +- if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_RAID_INFO_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in csmi_sas_get_raid_info struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, +- &ioc)) < 0) || (ioc == NULL)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not found!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- if (!csmisas_is_this_sas_cntr(ioc)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not SAS controller!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- if (!ioc->raid_data.pIocPg2) +- goto csmisas_get_raid_info_out; +- karg.Information.uNumRaidSets = +- ioc->raid_data.pIocPg2->NumActiveVolumes; +- karg.Information.uMaxRaidSets = ioc->raid_data.pIocPg2->MaxVolumes; +- if( ioc->raid_data.pIocPg6 ) { +- // get absolute maximum for all RAID sets +- maxDrivesPerSet = ioc->raid_data.pIocPg6->MaxDrivesIS; +- maxDrivesPerSet = max(ioc->raid_data.pIocPg6->MaxDrivesIM, +- maxDrivesPerSet); +- maxDrivesPerSet = max(ioc->raid_data.pIocPg6->MaxDrivesIME, +- maxDrivesPerSet); +- karg.Information.uMaxDrivesPerSet = maxDrivesPerSet; +- } +- else +- karg.Information.uMaxDrivesPerSet = 8; +- // For bMaxRaidSets, count bits set in bits 0-6 of CapabilitiesFlags +- raidFlags = ioc->raid_data.pIocPg2->CapabilitiesFlags & 0x0000007F; +- for( maxRaidTypes=0; raidFlags; maxRaidTypes++ ) +- raidFlags &= raidFlags - 1; +- karg.Information.bMaxRaidTypes = maxRaidTypes; +- // ulMinRaidSetBlocks hard coded to 1MB until available from config page +- karg.Information.ulMinRaidSetBlocks.uLowPart = 2048; +- karg.Information.ulMinRaidSetBlocks.uHighPart = 0; +- karg.Information.ulMaxRaidSetBlocks.uLowPart = 0xffffffff; +- if( ioc->raid_data.pIocPg2->CapabilitiesFlags & +- MPI_IOCPAGE2_CAP_FLAGS_RAID_64_BIT_ADDRESSING ) +- karg.Information.ulMaxRaidSetBlocks.uHighPart = 0xffffffff; +- else +- karg.Information.ulMaxRaidSetBlocks.uHighPart = 0; +- karg.Information.uMaxPhysicalDrives = +- ioc->raid_data.pIocPg2->MaxPhysDisks; +- karg.Information.uMaxExtents = 1; +- karg.Information.uMaxModules = 0; +- karg.Information.uMaxTransformationMemory = 0; +- karg.Information.uChangeCount = ioc->csmi_change_count; +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; +- +-csmisas_get_raid_info_out: +- +- /* Copy the data from kernel memory to user memory +- */ +- if (copy_to_user((char *)arg, &karg, +- sizeof(CSMI_SAS_RAID_INFO_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to write out csmi_sas_get_raid_info @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- dcsmisasprintk(("%s exit.\n",__FUNCTION__)); +- return 0; +-} +- +-/** +- * csmisas_do_raid - Format and Issue a RAID volume request message. +- * @ioc: Pointer to MPT_ADAPTER structure +- * @action: What do be done. +- * @PhysDiskNum: Logical target id. +- * @VolumeBus: Target locations bus. +- * @VolumeId: Volume id +- * +- * Returns: < 0 on a fatal error +- * 0 on success +- * +- * Remark: Wait to return until reply processed by the ISR. +- **/ +-static int +-csmisas_do_raid(MPT_ADAPTER *ioc, u8 action, u8 PhysDiskNum, u8 VolumeBus, u8 VolumeId, pMpiRaidActionReply_t reply) +-{ +- MpiRaidActionRequest_t *pReq; +- MpiRaidActionReply_t *pReply; +- MPT_FRAME_HDR *mf; +- +- /* Get and Populate a free Frame +- */ +- if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) { +- dcsmisasprintk((": no msg frames!\n")); +- return -EAGAIN; +- } +- pReq = (MpiRaidActionRequest_t *)mf; +- pReq->Action = action; +- pReq->Reserved1 = 0; +- pReq->ChainOffset = 0; +- pReq->Function = MPI_FUNCTION_RAID_ACTION; +- pReq->VolumeID = VolumeId; +- pReq->VolumeBus = VolumeBus; +- pReq->PhysDiskNum = PhysDiskNum; +- pReq->MsgFlags = 0; +- pReq->Reserved2 = 0; +- pReq->ActionDataWord = 0; /* Reserved for this action */ +- //pReq->ActionDataSGE = 0; +- +- mpt_add_sge((char *)&pReq->ActionDataSGE, +- MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); +- +- if (csmisas_send_command_wait(ioc, mf, MPT_IOCTL_DEFAULT_TIMEOUT) != 0) +- return -ENODATA; +- +- if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) && +- (reply != NULL)){ +- pReply = (MpiRaidActionReply_t *)&(ioc->ioctl->ReplyFrame); +- memcpy(reply, pReply, +- min(ioc->reply_sz, +- 4*pReply->MsgLength)); +- } +- +- return 0; +-} +- +-/** +- * csmisas_raid_inq +- * @ioc = per host instance +- * @opcode = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH or +- * MPI_FUNCTION_SCSI_IO_REQUEST +- * @id = target id +- * @bus = target bus +- * @inq_vpd = inquiry data, returned +- * @inq_vpd_sz = maximum size of inquiry data +- * +- * Return = 0(sucess), non-zero(failure) +- **/ +-static int +-csmisas_raid_inq(MPT_ADAPTER *ioc, u8 opcode, u8 bus, u8 id, u8 inq_vpd_page, +- u8 * inq_vpd, u32 inq_vpd_sz) +-{ +- MPT_FRAME_HDR *mf = NULL; +- MPIHeader_t *mpi_hdr; +- pSCSIIORequest_t pScsiRequest; +- u16 req_idx; +- char *psge; +- u8 inq_vpd_cdb[6]; +- u8 *request_data=NULL; +- dma_addr_t request_data_dma; +- u32 request_data_sz; +- int rc = 0; +- +- request_data_sz = inq_vpd_sz; +- +- /* fill-in cdb */ +- memset(inq_vpd_cdb, 0, sizeof(inq_vpd_cdb)); +- inq_vpd_cdb[0] = 0x12; +- if (inq_vpd_page) { +- inq_vpd_cdb[1] = 0x01; /* evpd bit */ +- inq_vpd_cdb[2] = inq_vpd_page; +- } +- inq_vpd_cdb[3] = (u8)(request_data_sz >> 8); +- inq_vpd_cdb[4] = (u8)request_data_sz; +- +- /* Get a free request frame and save the message context. +- */ +- if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) { +- dcsmisasprintk((": no msg frames!\n")); +- goto csmisas_raid_inq_exit; +- } +- +- mpi_hdr = (MPIHeader_t *) mf; +- pScsiRequest = (pSCSIIORequest_t) mf; +- req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); +- +- memset(pScsiRequest,0,sizeof(SCSIIORequest_t)); +- pScsiRequest->Function = opcode; +- pScsiRequest->TargetID = id; +- pScsiRequest->Bus = bus; +- pScsiRequest->CDBLength = 6; +- pScsiRequest->DataLength = cpu_to_le32(request_data_sz); +- pScsiRequest->MsgContext = mpi_hdr->MsgContext; +- memcpy(pScsiRequest->CDB,inq_vpd_cdb,pScsiRequest->CDBLength); +- pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ); +- pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_SIMPLEQ); +- pScsiRequest->MsgFlags = mpt_msg_flags(); +- +- /* setup sense +- */ +- pScsiRequest->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; +- pScsiRequest->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma + +- (req_idx * MPT_SENSE_BUFFER_ALLOC)); +- +- request_data = pci_alloc_consistent( +- ioc->pcidev, request_data_sz, &request_data_dma); +- +- if (request_data == NULL) { +- mpt_free_msg_frame(ioc, mf); +- rc=-1; +- goto csmisas_raid_inq_exit; +- } +- +- memset(request_data,0,request_data_sz); +- psge = (char *)&pScsiRequest->SGL; +- mpt_add_sge(psge, (MPT_SGE_FLAGS_SSIMPLE_READ | 0xFC) , +- request_data_dma); +- +- if (csmisas_send_command_wait(ioc, mf, MPT_IOCTL_DEFAULT_TIMEOUT) != 0) { +- rc=-1; +- goto csmisas_raid_inq_exit; +- } +- +- /* copy the request_data */ +- memcpy(inq_vpd, request_data, request_data_sz); +- +- csmisas_raid_inq_exit: +- +- if (request_data) +- pci_free_consistent(ioc->pcidev, request_data_sz, +- request_data, request_data_dma); +- +- return rc; +-} +- +-/** +- * Prototype Routine for the CSMI SAS Get RAID Config command. +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- * -ENODEV if no such device/adapter +- **/ +-static int +-csmisas_get_raid_config(unsigned long arg) +-{ +- CSMI_SAS_RAID_CONFIG_BUFFER __user *uarg = (void __user *) arg; +- CSMI_SAS_RAID_CONFIG_BUFFER karg,*pKarg=NULL; +- CONFIGPARMS cfg; +- ConfigPageHeader_t header; +- MPT_ADAPTER *ioc = NULL; +- int iocnum; +- u8 volumeID, VolumeBus; +- u8 physDiskNum, physDiskNumMax; +- int volumepage0sz = 0; +- int physdiskpage0sz = 0, ioc_page5_sz = 0; +- dma_addr_t volume0_dma, physdisk0_dma; +- dma_addr_t ioc_page5_dma = 0; +- pRaidVolumePage0_t pVolume0 = NULL; +- pRaidPhysDiskPage0_t pPhysDisk0 = NULL; +- pMpiRaidActionReply_t pRaidActionReply = NULL; +- u32 device_info = 0; +- pIOCPage5_t pIocPage5 = NULL; +- int i, idx, csmi_sas_raid_config_buffer_sz; +- int memory_pages; +- int copy_buffer_sz = 0; +- u64 totalMaxLBA, tmpTotalMaxLBA; +- u64 sas_address; +- struct sas_device_info *sas_info; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- +- if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in csmisas_get_raid_config struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- csmi_sas_raid_config_buffer_sz = karg.IoctlHeader.Length; +- memory_pages = get_order(csmi_sas_raid_config_buffer_sz); +- pKarg = (CSMI_SAS_RAID_CONFIG_BUFFER *)__get_free_pages( +- GFP_KERNEL, memory_pages); +- if (!pKarg){ +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to malloc RAID_CONFIG_BUFFER " +- "csmi_sas_raid_config_buffer_sz=%d memory_pages=%d\n", +- __FILE__, __LINE__, __FUNCTION__, +- csmi_sas_raid_config_buffer_sz, memory_pages); +- return -ENOMEM; +- } +- memset(pKarg, 0, sizeof(*pKarg)); +- +- if (copy_from_user(pKarg, uarg, csmi_sas_raid_config_buffer_sz)) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in csmisas_get_raid_config struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- free_pages((unsigned long)pKarg, memory_pages); +- return -EFAULT; +- } +- +- if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber, +- &ioc)) < 0) || (ioc == NULL)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not found!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- free_pages((unsigned long)pKarg, memory_pages); +- return -ENODEV; +- } +- +- if (!csmisas_is_this_sas_cntr(ioc)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not SAS controller!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- free_pages((unsigned long)pKarg, memory_pages); +- return -ENODEV; +- } +- +- if (pKarg->Configuration.uChangeCount != 0 && +- pKarg->Configuration.uChangeCount != ioc->csmi_change_count ) { +- pKarg->IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_INVALID_PARAMETER; +- pKarg->Configuration.uFailureCode = +- CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID; +- goto cim_get_raid_config_exit; +- } +- +- if (!ioc->raid_data.pIocPg2) { +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_get_raid_config_exit; +- } +- +- /* +- * Check to see if the input uRaidSetIndex is +- * greater than the number of RAID sets +- */ +- if (pKarg->Configuration.uRaidSetIndex >= +- ioc->raid_data.pIocPg2->NumActiveVolumes) { +- pKarg->IoctlHeader.ReturnCode = CSMI_SAS_RAID_SET_OUT_OF_RANGE; +- goto cim_get_raid_config_exit; +- } +- +- /* +- * get RAID Volume Page 0 +- */ +- volumeID = ioc->raid_data.pIocPg2->RaidVolume[pKarg->Configuration.uRaidSetIndex].VolumeID; +- VolumeBus = ioc->raid_data.pIocPg2->RaidVolume[pKarg->Configuration.uRaidSetIndex].VolumeBus; +- +- header.PageVersion = 0; +- header.PageLength = 0; +- header.PageNumber = 0; +- header.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME; +- cfg.cfghdr.hdr = &header; +- cfg.physAddr = -1; +- cfg.pageAddr = (VolumeBus << 8) + volumeID; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.dir = 0; +- cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; +- if (mpt_config(ioc, &cfg) != 0) { +- pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_get_raid_config_exit; +- } +- +- if (header.PageLength == 0) { +- pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_get_raid_config_exit; +- } +- +- volumepage0sz = header.PageLength * 4; +- pVolume0 = pci_alloc_consistent(ioc->pcidev, volumepage0sz, +- &volume0_dma); +- if (!pVolume0) { +- pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_get_raid_config_exit; +- } +- +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- cfg.physAddr = volume0_dma; +- if (mpt_config(ioc, &cfg) != 0) { +- pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_get_raid_config_exit; +- } +- +- totalMaxLBA = (u64)le32_to_cpu(pVolume0->MaxLBA) | +- ((u64)le32_to_cpu(pVolume0->MaxLBAHigh)) << 32; +- tmpTotalMaxLBA = totalMaxLBA + 1; +- do_div(tmpTotalMaxLBA, 2048); +- pKarg->Configuration.uCapacity = tmpTotalMaxLBA; +- pKarg->Configuration.uStripeSize = +- le32_to_cpu(pVolume0->StripeSize)/2; +- +- switch(pVolume0->VolumeType) { +- case MPI_RAID_VOL_TYPE_IS: +- pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_0; +- break; +- case MPI_RAID_VOL_TYPE_IME: +- pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_10; +- break; +- case MPI_RAID_VOL_TYPE_IM: +- pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_1; +- break; +- default: +- pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_OTHER; +- break; +- } +- +- switch (pVolume0->VolumeStatus.State) { +- case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL: +- pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_OK; +- break; +- case MPI_RAIDVOL0_STATUS_STATE_DEGRADED: +- /* Volume is degraded, check if Resyncing or Inactive */ +- pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_DEGRADED; +- break; +- case MPI_RAIDVOL0_STATUS_STATE_FAILED: +- pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_FAILED; +- break; +- } +- +- /* check flags */ +- if (pVolume0->VolumeStatus.Flags & +- MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE) +- pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_OFFLINE; +- else if (pVolume0->VolumeStatus.Flags & +- MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) +- pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_REBUILDING; +- +- pKarg->Configuration.bInformation = 0; /* default */ +- if(pVolume0->VolumeStatus.Flags & +- MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS ) { +- +- uint64_t * ptrUint64; +- uint64_t totalBlocks64, blocksRemaining64; +- uint32_t totalBlocks32, blocksRemaining32; +- +- /* get percentage complete */ +- pRaidActionReply = kmalloc( sizeof(MPI_RAID_VOL_INDICATOR) + +- offsetof(MSG_RAID_ACTION_REPLY,ActionData), +- GFP_KERNEL); +- +- if (!pRaidActionReply){ +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to malloc @ %p\n", +- __FILE__, __LINE__, __FUNCTION__,pKarg); +- goto cim_get_raid_config_exit; +- } +- memset(pRaidActionReply, 0, sizeof(*pRaidActionReply)); +- +- csmisas_do_raid(ioc, +- MPI_RAID_ACTION_INDICATOR_STRUCT, +- 0, VolumeBus, volumeID, pRaidActionReply); +- +- ptrUint64 = (uint64_t *)&pRaidActionReply->ActionData; +- totalBlocks64 = *ptrUint64; +- ptrUint64++; +- blocksRemaining64 = *ptrUint64; +- while(totalBlocks64 > 0xFFFFFFFFUL){ +- totalBlocks64 = totalBlocks64 >> 1; +- blocksRemaining64 = blocksRemaining64 >> 1; +- } +- totalBlocks32 = (uint32_t)totalBlocks64; +- blocksRemaining32 = (uint32_t)blocksRemaining64; +- +- if(totalBlocks32) +- pKarg->Configuration.bInformation = +- (totalBlocks32 - blocksRemaining32) / +- (totalBlocks32 / 100); +- +- kfree(pRaidActionReply); +- } +- +- /* fill-in more information depending on data type */ +- if (pKarg->Configuration.bDataType == +- CSMI_SAS_RAID_DATA_ADDITIONAL_DATA) { +- pKarg->Configuration.Data->bLabel[0] = '\0'; +- pKarg->Configuration.Data->bRaidSetLun[1] = 0; +- pKarg->Configuration.Data->bWriteProtection = +- CSMI_SAS_RAID_SET_WRITE_PROTECT_UNKNOWN; +- pKarg->Configuration.Data->bCacheSetting = +- CSMI_SAS_RAID_SET_CACHE_UNKNOWN; +- pKarg->Configuration.Data->bCacheRatio = 0; +- pKarg->Configuration.Data->usBlockSize = 512; +- pKarg->Configuration.Data->ulRaidSetExtentOffset.uLowPart = 0; +- pKarg->Configuration.Data->ulRaidSetExtentOffset.uHighPart = 0; +- pKarg->Configuration.Data->ulRaidSetBlocks.uLowPart = +- le32_to_cpu(pVolume0->MaxLBA); +- pKarg->Configuration.Data->ulRaidSetBlocks.uHighPart = +- le32_to_cpu(pVolume0->MaxLBAHigh); +- if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IS || +- pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IME ) { +- pKarg->Configuration.Data->uStripeSizeInBlocks = +- le32_to_cpu(pVolume0->StripeSize); +- } else { +- pKarg->Configuration.Data->uStripeSizeInBlocks = 0; +- } +- pKarg->Configuration.Data->uSectorsPerTrack = 128; +- for (i=0; i<16; i++) { +- // unsupported +- pKarg->Configuration.Data->bApplicationScratchPad[i] = +- 0xFF; +- } +- pKarg->Configuration.Data->uNumberOfHeads = 16; +- +- tmpTotalMaxLBA = totalMaxLBA; +- do_div(tmpTotalMaxLBA, +- (pKarg->Configuration.Data->uNumberOfHeads * +- pKarg->Configuration.Data->uSectorsPerTrack)); +- pKarg->Configuration.Data->uNumberOfTracks = tmpTotalMaxLBA; +- pKarg->Configuration.bDriveCount = 1; +- } else if ( pKarg->Configuration.bDataType == +- CSMI_SAS_RAID_DATA_DEVICE_ID ) { +- /* Send inquiry to get VPD Page 0x83 */ +- u32 vpd_page_sz; +- vpd_page_sz = csmi_sas_raid_config_buffer_sz - +- offsetof(CSMI_SAS_RAID_CONFIG,DeviceId); +- if (csmisas_raid_inq(ioc, MPI_FUNCTION_SCSI_IO_REQUEST, +- VolumeBus, volumeID, 0x83, +- (u8*)&pKarg->Configuration.DeviceId->bDeviceIdentificationVPDPage, +- vpd_page_sz) != 0) { +- pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_get_raid_config_exit; +- } +- pKarg->Configuration.bDriveCount = 1; +- } +- +- if (pKarg->Configuration.bDataType != CSMI_SAS_RAID_DATA_DRIVES) { +- pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; +- goto cim_get_raid_config_exit; +- } +- +- /* suppress drive information */ +- if (pKarg->Configuration.bDriveCount == +- CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED) { +- pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; +- goto cim_get_raid_config_exit; +- } +- +- /* get hotspare info, used later in this function */ +- if (pVolume0->VolumeSettings.HotSparePool) { +- /* Read and save IOC Page 5 +- */ +- header.PageVersion = 0; +- header.PageLength = 0; +- header.PageNumber = 5; +- header.PageType = MPI_CONFIG_PAGETYPE_IOC; +- cfg.cfghdr.hdr = &header; +- cfg.physAddr = -1; +- cfg.pageAddr = 0; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.dir = 0; +- cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; +- if ((mpt_config(ioc, &cfg) == 0) && (header.PageLength)) { +- ioc_page5_sz = header.PageLength * 4; +- pIocPage5 = pci_alloc_consistent(ioc->pcidev, +- ioc_page5_sz, +- &ioc_page5_dma); +- memset(pIocPage5,0,ioc_page5_sz); +- if (ioc_page5_dma) { +- cfg.physAddr = ioc_page5_dma; +- cfg.action = +- MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- mpt_config(ioc, &cfg); +- } +- } +- } +- +- /* +- * get RAID Physical Disk Page 0 +- */ +- header.PageVersion = 0; +- header.PageLength = 0; +- header.PageNumber = 0; +- header.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK; +- cfg.cfghdr.hdr = &header; +- cfg.physAddr = -1; +- cfg.pageAddr = 0; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.dir = 0; +- cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; +- if (mpt_config(ioc, &cfg) != 0) { +- pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_get_raid_config_exit; +- } +- +- if (header.PageLength == 0) { +- pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_get_raid_config_exit; +- } +- +- physdiskpage0sz = header.PageLength * 4; +- pPhysDisk0 = pci_alloc_consistent(ioc->pcidev, physdiskpage0sz, +- &physdisk0_dma); +- if (!pPhysDisk0) { +- pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_get_raid_config_exit; +- } +- cfg.physAddr = physdisk0_dma; +- +- physDiskNumMax = (csmi_sas_raid_config_buffer_sz - +- offsetof(CSMI_SAS_RAID_CONFIG,Drives)) +- / sizeof(CSMI_SAS_RAID_DRIVES); +- +- pKarg->Configuration.bDriveCount=0; +- +- tmpTotalMaxLBA = totalMaxLBA; +- if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IS) { +- do_div(tmpTotalMaxLBA, pVolume0->NumPhysDisks); +- dcsmisasprintk(("IS Volume tmpTotalMaxLBA=%llX\n", +- (unsigned long long)tmpTotalMaxLBA)); +- } +- else if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IME) { +- do_div(tmpTotalMaxLBA, pVolume0->NumPhysDisks * 2); +- dcsmisasprintk(("IME Volume tmpTotalMaxLBA=%llX\n", +- (unsigned long long)tmpTotalMaxLBA)); +- } else { +- dcsmisasprintk(("IM Volume tmpTotalMaxLBA=%llX\n", +- (unsigned long long)tmpTotalMaxLBA)); +- } +- +- for (i=0; i< min(pVolume0->NumPhysDisks, physDiskNumMax); i++) { +- +- physDiskNum = pVolume0->PhysDisk[i].PhysDiskNum; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- cfg.pageAddr = physDiskNum; +- if (mpt_config(ioc, &cfg) != 0){ +- pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_get_raid_config_exit; +- } +- +- /* Search the list for the matching SAS address. */ +- sas_info = csmisas_get_device_component_by_fw(ioc, pPhysDisk0->PhysDiskBus, +- pPhysDisk0->PhysDiskID); +- +- if (!sas_info) +- continue; +- +- sas_address = reverse_byte_order64(sas_info->sas_address); +- memcpy(pKarg->Configuration.Drives[i].bSASAddress, +- &sas_address,sizeof(u64)); +- if (!device_info) +- device_info = sas_info->device_info; +- +- memcpy(pKarg->Configuration.Drives[i].bModel, +- pPhysDisk0->InquiryData.VendorID, +- offsetof(RAID_PHYS_DISK0_INQUIRY_DATA,ProductRevLevel)); +- memcpy(pKarg->Configuration.Drives[i].bFirmware, +- pPhysDisk0->InquiryData.ProductRevLevel, +- sizeof(pPhysDisk0->InquiryData.ProductRevLevel)); +- if (csmisas_is_sata(pPhysDisk0)) { +- memcpy(&pKarg->Configuration.Drives[i].bSerialNumber, +- &pPhysDisk0->ExtDiskIdentifier[4], +- 4); +- memcpy(&pKarg->Configuration.Drives[i].bSerialNumber[4], +- &pPhysDisk0->DiskIdentifier, +- sizeof(pPhysDisk0->DiskIdentifier)); +- } else { +- memcpy(pKarg->Configuration.Drives[i].bSerialNumber, +- pPhysDisk0->DiskIdentifier, +- sizeof(pPhysDisk0->DiskIdentifier)); +- } +- +- pKarg->Configuration.Drives[i].bDriveUsage = +- (pPhysDisk0->PhysDiskStatus.Flags & +- MPI_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME) ? +- CSMI_SAS_DRIVE_CONFIG_NOT_USED : +- CSMI_SAS_DRIVE_CONFIG_MEMBER; +- +- pKarg->Configuration.Drives[i].bDriveStatus = +- CSMI_SAS_DRIVE_STATUS_OK; +- if (pPhysDisk0->PhysDiskStatus.State == +- MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED) { +- pKarg->Configuration.Drives[i].bDriveStatus = +- CSMI_SAS_DRIVE_STATUS_OFFLINE; +- } else if(pPhysDisk0->PhysDiskStatus.State) { +- pKarg->Configuration.Drives[i].bDriveStatus = +- CSMI_SAS_DRIVE_STATUS_FAILED; +- if(pKarg->Configuration.bStatus == +- CSMI_SAS_RAID_SET_STATUS_DEGRADED) +- pKarg->Configuration.bInformation = i; +- } else if((pVolume0->VolumeStatus.Flags & +- MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) && +- (pPhysDisk0->PhysDiskStatus.Flags & +- MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC)) +- pKarg->Configuration.Drives[i].bDriveStatus = +- CSMI_SAS_DRIVE_STATUS_REBUILDING; +- else if(pPhysDisk0->ErrorData.SmartCount || +- (pPhysDisk0->PhysDiskStatus.Flags & +- MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC)) +- pKarg->Configuration.Drives[i].bDriveStatus = +- CSMI_SAS_DRIVE_STATUS_DEGRADED; +- +- memset(pKarg->Configuration.Drives[i].bSASLun, +- 0, sizeof(pKarg->Configuration.Drives[i].bSASLun)); +- if (csmisas_is_sata(pPhysDisk0)) { +- pKarg->Configuration.Drives[i].bDriveType = +- CSMI_SAS_DRIVE_TYPE_SATA; +- } else { /* drive in a volume can only be SAS/SATA */ +- pKarg->Configuration.Drives[i].bDriveType = +- CSMI_SAS_DRIVE_TYPE_SINGLE_PORT_SAS; +- } +- +- pKarg->Configuration.Drives[i].usBlockSize = 512; +- pKarg->Configuration.Drives[i].uDriveIndex = +- pPhysDisk0->PhysDiskNum; +- pKarg->Configuration.Drives[i].ulTotalUserBlocks.uLowPart = +- (u32)tmpTotalMaxLBA; +- pKarg->Configuration.Drives[i].ulTotalUserBlocks.uHighPart = +- (u32)(tmpTotalMaxLBA >> 32); +- pKarg->Configuration.bDriveCount++; +- } +- +- /* adding hot spare info at the end */ +- if ((pVolume0->VolumeSettings.HotSparePool) && (pIocPage5) && +- (pVolume0->VolumeType != MPI_RAID_VOL_TYPE_IS)) { +- for (idx = 0, i = pVolume0->NumPhysDisks ; +- idx < pIocPage5->NumHotSpares ; idx++) { +- if (i >= physDiskNumMax) +- break; +- if ((pVolume0->VolumeSettings.HotSparePool & +- pIocPage5->HotSpare[idx].HotSparePool) == 0) +- continue; +- if(pIocPage5->HotSpare[idx].Flags != +- MPI_IOC_PAGE_5_HOT_SPARE_ACTIVE) +- continue; +- physDiskNum = pIocPage5->HotSpare[idx].PhysDiskNum; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- cfg.pageAddr = physDiskNum; +- if (mpt_config(ioc, &cfg) != 0) +- continue; +- +- /* Search the list for the matching SAS address. */ +- sas_info = csmisas_get_device_component_by_fw(ioc, +- pPhysDisk0->PhysDiskBus, pPhysDisk0->PhysDiskID); +- +- if (!sas_info) +- continue; +- +- sas_address = reverse_byte_order64(sas_info->sas_address); +- memcpy(pKarg->Configuration.Drives[i].bSASAddress, +- &sas_address,sizeof(u64)); +- +- /* don't mix SSP hot spare +- * in SATA volume +- */ +- if (!csmisas_is_sata(pPhysDisk0) && +- (device_info & +- MPI_SAS_DEVICE_INFO_SATA_DEVICE)) +- continue; +- +- /* don't mix SATA hot spare +- * in SSP volume +- */ +- if (csmisas_is_sata(pPhysDisk0) && +- (device_info & +- MPI_SAS_DEVICE_INFO_SSP_TARGET)) +- continue; +- +- /* capacity check for IM volumes*/ +- if ((pVolume0->VolumeType == +- MPI_RAID_VOL_TYPE_IM) && +- (totalMaxLBA + +- (64*2*1024) /* metadata = 64MB*/ > +- le32_to_cpu(pPhysDisk0->MaxLBA))) +- continue; +- +- tmpTotalMaxLBA = totalMaxLBA; +- do_div(tmpTotalMaxLBA, pVolume0->NumPhysDisks); +- /* capacity check for IME volumes*/ +- if ((pVolume0->VolumeType == +- MPI_RAID_VOL_TYPE_IME) && +- ((tmpTotalMaxLBA * 2) + +- (64*2*1024 ) /*metadata = 64MB*/ > +- le32_to_cpu(pPhysDisk0->MaxLBA))) +- break; +- +- /* capacity check for IME volumes*/ +- if ((pVolume0->VolumeType == +- MPI_RAID_VOL_TYPE_IME) && +- (((totalMaxLBA + +- pVolume0->NumPhysDisks) * 2) + +- (64*2*1024 ) /*metadata = 64MB*/ > +- le32_to_cpu(pPhysDisk0->MaxLBA))) +- continue; +- +- memcpy(pKarg->Configuration.Drives[i].bModel, +- pPhysDisk0->InquiryData.VendorID, +- offsetof(RAID_PHYS_DISK0_INQUIRY_DATA,ProductRevLevel)); +- memcpy(pKarg->Configuration.Drives[i].bFirmware, +- pPhysDisk0->InquiryData.ProductRevLevel, +- sizeof(pPhysDisk0->InquiryData.ProductRevLevel)); +- if (csmisas_is_sata(pPhysDisk0)) { +- memcpy(&pKarg->Configuration.Drives[i].bSerialNumber, +- &pPhysDisk0->ExtDiskIdentifier[4], +- 4); +- memcpy(&pKarg->Configuration.Drives[i].bSerialNumber[4], +- &pPhysDisk0->DiskIdentifier, +- sizeof(pPhysDisk0->DiskIdentifier)); +- } else { +- memcpy(pKarg->Configuration.Drives[i].bSerialNumber, +- pPhysDisk0->DiskIdentifier, +- sizeof(pPhysDisk0->DiskIdentifier)); +- } +- pKarg->Configuration.Drives[i].bDriveStatus = +- CSMI_SAS_DRIVE_STATUS_OK; +- if(pPhysDisk0->PhysDiskStatus.State) +- pKarg->Configuration.Drives[i].bDriveStatus = +- CSMI_SAS_DRIVE_STATUS_FAILED; +- else if(pPhysDisk0->ErrorData.SmartCount) +- pKarg->Configuration.Drives[i].bDriveStatus = +- CSMI_SAS_DRIVE_STATUS_DEGRADED; +- pKarg->Configuration.Drives[i].bDriveUsage = +- CSMI_SAS_DRIVE_CONFIG_SPARE; +- pKarg->Configuration.Drives[i].usBlockSize = 512; +- pKarg->Configuration.Drives[i].uDriveIndex = +- pPhysDisk0->PhysDiskNum; +- if (csmisas_is_sata(pPhysDisk0)) { +- pKarg->Configuration.Drives[i].bDriveType = +- CSMI_SAS_DRIVE_TYPE_SATA; +- } else { /* drive in a volume can only be SAS/SATA */ +- pKarg->Configuration.Drives[i].bDriveType = +- CSMI_SAS_DRIVE_TYPE_SINGLE_PORT_SAS; +- } +- +- i++; +- pKarg->Configuration.bDriveCount++; +- } +- } +- +- // Only return data on the first 240 drives +- if( pKarg->Configuration.bDriveCount > 0xF0 ) +- pKarg->Configuration.bDriveCount = +- CSMI_SAS_RAID_DRIVE_COUNT_TOO_BIG; +- +- pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; +- +- cim_get_raid_config_exit: +- +- if (pVolume0 != NULL) +- pci_free_consistent(ioc->pcidev, volumepage0sz, pVolume0, +- volume0_dma); +- +- if(pPhysDisk0 != NULL) +- pci_free_consistent(ioc->pcidev, physdiskpage0sz, pPhysDisk0, +- physdisk0_dma); +- +- if(pIocPage5 != NULL) +- pci_free_consistent(ioc->pcidev, ioc_page5_sz, pIocPage5, +- ioc_page5_dma); +- +- /* Copy the data from kernel memory to user memory +- */ +- +- /* find the buffer size to copy depending on how much is filled-in */ +- switch (pKarg->Configuration.bDataType) { +- case CSMI_SAS_RAID_DATA_ADDITIONAL_DATA: +- copy_buffer_sz = sizeof(IOCTL_HEADER) + +- offsetof(CSMI_SAS_RAID_CONFIG,Data) + +- sizeof(CSMI_SAS_RAID_SET_ADDITIONAL_DATA); +- break; +- case CSMI_SAS_RAID_DATA_DRIVES: +- if (pKarg->Configuration.bDriveCount == +- CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED) +- copy_buffer_sz = sizeof(IOCTL_HEADER) + +- offsetof(CSMI_SAS_RAID_CONFIG,Drives); +- else +- copy_buffer_sz = sizeof(IOCTL_HEADER) + +- offsetof(CSMI_SAS_RAID_CONFIG,Drives) + +- (pKarg->Configuration.bDriveCount * +- sizeof(CSMI_SAS_RAID_DRIVES)); +- break; +- case CSMI_SAS_RAID_DATA_DEVICE_ID: +- copy_buffer_sz = csmi_sas_raid_config_buffer_sz; +- break; +- } +- +- if (copy_to_user((char *)arg, pKarg, copy_buffer_sz)) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to write out csmi_sas_get_raid_config @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- free_pages((unsigned long)pKarg, memory_pages); +- return -EFAULT; +- } +- +- dcsmisasprintk(("%s exit.\n",__FUNCTION__)); +- free_pages((unsigned long)pKarg, memory_pages); +- return 0; +-} +- +-/** +- * Prototype Routine for the CSMI SAS Get RAID Features command. +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- * -ENODEV if no such device/adapter +- **/ +-static int +-csmisas_get_raid_features(unsigned long arg) +-{ +- CSMI_SAS_RAID_FEATURES_BUFFER __user *uarg = (void __user *) arg; +- CSMI_SAS_RAID_FEATURES_BUFFER karg, *pKarg=NULL; +- int csmi_sas_raid_features_buffer_sz, iocnum; +- int memory_pages; +- MPT_ADAPTER *ioc = NULL; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- +- if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in csmi_sas_get_raid_features struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- csmi_sas_raid_features_buffer_sz = karg.IoctlHeader.Length; +- memory_pages = get_order(csmi_sas_raid_features_buffer_sz); +- pKarg = (CSMI_SAS_RAID_FEATURES_BUFFER *)__get_free_pages( +- GFP_KERNEL, memory_pages); +- if (!pKarg){ +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to malloc RAID_FEATURES_BUFFER " +- "csmi_sas_raid_features_buffer_sz=%d memory_pages=%d\n", +- __FILE__, __LINE__, __FUNCTION__, +- csmi_sas_raid_features_buffer_sz, memory_pages); +- return -ENOMEM; +- } +- memset(pKarg, 0, sizeof(*pKarg)); +- +- if (copy_from_user(pKarg, uarg, csmi_sas_raid_features_buffer_sz)) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in csmi_sas_get_raid_features struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- free_pages((unsigned long)pKarg, memory_pages); +- return -EFAULT; +- } +- +- if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber, +- &ioc)) < 0) || (ioc == NULL)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not found!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- free_pages((unsigned long)pKarg, memory_pages); +- return -ENODEV; +- } +- +- if (!csmisas_is_this_sas_cntr(ioc)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not SAS controller!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- free_pages((unsigned long)pKarg, memory_pages); +- return -ENODEV; +- } +- +- if (pKarg->Information.uChangeCount != 0 && +- pKarg->Information.uChangeCount != ioc->csmi_change_count ) { +- pKarg->IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_INVALID_PARAMETER; +- pKarg->Information.uFailureCode = +- CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID; +- goto cim_get_raid_features_exit; +- } +- +- pKarg->Information.uFeatures = CSMI_SAS_RAID_FEATURE_REBUILD | +- CSMI_SAS_RAID_FEATURE_SURFACE_SCAN | +- CSMI_SAS_RAID_FEATURE_SPARES_SHARED; +- pKarg->Information.bDefaultTransformPriority = +- CSMI_SAS_PRIORITY_UNKNOWN; +- pKarg->Information.bTransformPriority = CSMI_SAS_PRIORITY_UNKNOWN; +- pKarg->Information.bDefaultRebuildPriority = CSMI_SAS_PRIORITY_UNKNOWN; +- pKarg->Information.bRebuildPriority = +- pKarg->Information.bDefaultRebuildPriority; +- pKarg->Information.bDefaultSurfaceScanPriority = +- CSMI_SAS_PRIORITY_UNKNOWN; +- pKarg->Information.bSurfaceScanPriority = CSMI_SAS_PRIORITY_UNKNOWN; +- pKarg->Information.uRaidSetTransformationRules = 0; +- +- /* IS */ +- pKarg->Information.RaidType[0].bRaidType = CSMI_SAS_RAID_TYPE_0; +- pKarg->Information.RaidType[0].uSupportedStripeSizeMap = 0x80; +- +- /* IM */ +- pKarg->Information.RaidType[1].bRaidType = CSMI_SAS_RAID_TYPE_1; +- pKarg->Information.RaidType[1].uSupportedStripeSizeMap = 0; +- +- /* IME */ +- pKarg->Information.RaidType[2].bRaidType = CSMI_SAS_RAID_TYPE_1E; +- pKarg->Information.RaidType[2].uSupportedStripeSizeMap = 0x80; +- +- pKarg->Information.RaidType[3].bRaidType = CSMI_SAS_RAID_TYPE_END; +- pKarg->Information.bCacheRatiosSupported[0] = +- CSMI_SAS_RAID_CACHE_RATIO_END; +- +- cim_get_raid_features_exit: +- +- /* +- * Copy the data from kernel memory to user memory +- */ +- if (copy_to_user((char *)arg, pKarg, +- sizeof(CSMI_SAS_RAID_FEATURES_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to write out csmi_sas_get_raid_features @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- free_pages((unsigned long)pKarg, memory_pages); +- return -EFAULT; +- } +- +- dcsmisasprintk(("%s exit.\n",__FUNCTION__)); +- free_pages((unsigned long)pKarg, memory_pages); +- return 0; +-} +- +-/** +- * Prototype Routine for the CSMI SAS Set RAID Control command. +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- * -ENODEV if no such device/adapter +- **/ +-static int +-csmisas_set_raid_control(unsigned long arg) +-{ +- CSMI_SAS_RAID_CONTROL_BUFFER __user *uarg = (void __user *) arg; +- CSMI_SAS_RAID_CONTROL_BUFFER karg, *pKarg=NULL; +- int csmi_sas_raid_control_buffer_sz, iocnum; +- int memory_pages; +- MPT_ADAPTER *ioc = NULL; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- +- if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in csmi_sas_set_raid_control struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- csmi_sas_raid_control_buffer_sz = karg.IoctlHeader.Length; +- memory_pages = get_order(csmi_sas_raid_control_buffer_sz); +- pKarg = (CSMI_SAS_RAID_CONTROL_BUFFER *)__get_free_pages( +- GFP_KERNEL, memory_pages); +- if (!pKarg){ +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to malloc RAID_CONTROL_BUFFER " +- "csmi_sas_raid_control_buffer_sz=%d memory_pages=%d\n", +- __FILE__, __LINE__, __FUNCTION__, +- csmi_sas_raid_control_buffer_sz, memory_pages); +- return -ENOMEM; +- } +- memset(pKarg, 0, sizeof(*pKarg)); +- +- if (copy_from_user(pKarg, uarg, csmi_sas_raid_control_buffer_sz)) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in csmi_sas_set_raid_control struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- free_pages((unsigned long)pKarg, memory_pages); +- return -EFAULT; +- } +- +- if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber, +- &ioc)) < 0) || (ioc == NULL)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not found!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- free_pages((unsigned long)pKarg, memory_pages); +- return -ENODEV; +- } +- +- if (!csmisas_is_this_sas_cntr(ioc)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not SAS controller!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- free_pages((unsigned long)pKarg, memory_pages); +- return -ENODEV; +- } +- +- if (pKarg->Information.uChangeCount != 0 && +- pKarg->Information.uChangeCount != ioc->csmi_change_count ) { +- pKarg->IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_INVALID_PARAMETER; +- pKarg->Information.uFailureCode = +- CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID; +- goto cim_set_raid_control_exit; +- } +- +- if (pKarg->Information.bTransformPriority != +- CSMI_SAS_PRIORITY_UNCHANGED) { +- pKarg->IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_INVALID_PARAMETER; +- pKarg->Information.uFailureCode = +- CSMI_SAS_FAIL_CODE_TRANSFORM_PRIORITY_INVALID; +- goto cim_set_raid_control_exit; +- } +- +- if (pKarg->Information.bRebuildPriority != +- CSMI_SAS_PRIORITY_AUTO && +- pKarg->Information.bRebuildPriority != +- CSMI_SAS_PRIORITY_UNCHANGED) { +- pKarg->IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_INVALID_PARAMETER; +- pKarg->Information.uFailureCode = +- CSMI_SAS_FAIL_CODE_REBUILD_PRIORITY_INVALID; +- goto cim_set_raid_control_exit; +- } +- +- if (pKarg->Information.bCacheRatioFlag == +- CSMI_SAS_RAID_CACHE_RATIO_DISABLE) { +- pKarg->IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_INVALID_PARAMETER; +- pKarg->Information.uFailureCode = +- CSMI_SAS_FAIL_CODE_CACHE_RATIO_INVALID; +- goto cim_set_raid_control_exit; +- } +- +- if( !strcmp(pKarg->Information.bClearConfiguration, +- CSMI_SAS_RAID_CLEAR_CONFIGURATION_SIGNATURE) ) { +- pKarg->IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_INVALID_PARAMETER; +- pKarg->Information.uFailureCode = +- CSMI_SAS_FAIL_CODE_CLEAR_CONFIGURATION_INVALID; +- goto cim_set_raid_control_exit; +- } +- +- pKarg->Information.bFailureDescription[0] = '\0'; +- +- cim_set_raid_control_exit: +- +- /* +- * Copy the data from kernel memory to user memory +- */ +- if (copy_to_user((char *)arg, pKarg, +- sizeof(CSMI_SAS_RAID_CONTROL_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to write out csmi_sas_set_raid_control @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- free_pages((unsigned long)pKarg, memory_pages); +- return -EFAULT; +- } +- +- dcsmisasprintk(("%s exit.\n",__FUNCTION__)); +- free_pages((unsigned long)pKarg, memory_pages); +- return 0; +-} +- +-/** +- * Prototype Routine for the CSMI SAS Get Raid Element. +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- * -ENODEV if no such device/adapter +- **/ +-static int +-csmisas_get_raid_element(unsigned long arg) +-{ +- CSMI_SAS_RAID_ELEMENT_BUFFER __user *uarg = (void __user *) arg; +- CSMI_SAS_RAID_ELEMENT_BUFFER karg; +- MPT_ADAPTER *ioc = NULL; +- int iocnum; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- +- if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_RAID_ELEMENT_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in csmisas_get_raid_element struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, +- &ioc)) < 0) || (ioc == NULL)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not found!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- if (!csmisas_is_this_sas_cntr(ioc)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not SAS controller!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +-/* TODO - implement IOCTL here */ +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_BAD_CNTL_CODE; +- dcsmisasprintk((": not implemented\n")); +- +-// csmisas_get_raid_element_exit: +- +- /* Copy the data from kernel memory to user memory +- */ +- if (copy_to_user((char *)arg, &karg, +- sizeof(CSMI_SAS_RAID_ELEMENT_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to write out csmisas_get_raid_element @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- dcsmisasprintk(("%s exit.\n",__FUNCTION__)); +- return 0; +- +-} +- +-/** +- * Prototype Routine for the CSMI SAS Set Raid Operation +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- * -ENODEV if no such device/adapter +- **/ +-static int +-csmisas_set_raid_operation(unsigned long arg) +-{ +- CSMI_SAS_RAID_SET_OPERATION_BUFFER __user *uarg = (void __user *) arg; +- CSMI_SAS_RAID_SET_OPERATION_BUFFER karg; +- MPT_ADAPTER *ioc = NULL; +- int iocnum; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- +- if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_RAID_SET_OPERATION_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in csmi_set_raid_operation struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, +- &ioc)) < 0) || (ioc == NULL)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not found!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- if (!csmisas_is_this_sas_cntr(ioc)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not SAS controller!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +-/* TODO - implement IOCTL here */ +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_BAD_CNTL_CODE; +- dcsmisasprintk((": not implemented\n")); +- +-// cim_set_raid_operation: +- +- /* Copy the data from kernel memory to user memory +- */ +- if (copy_to_user((char *)arg, &karg, +- sizeof(CSMI_SAS_RAID_SET_OPERATION_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to write out csmi_set_raid_operation @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- dcsmisasprintk(("%s exit.\n",__FUNCTION__)); +- return 0; +- +-} +- +- +-/** +- * Prototype Routine for the CSMI SAS Task Managment Config command. +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- * -ENODEV if no such device/adapter +- **/ +-static int +-csmisas_task_managment(unsigned long arg) +-{ +- CSMI_SAS_SSP_TASK_IU_BUFFER __user *uarg = (void __user *) arg; +- CSMI_SAS_SSP_TASK_IU_BUFFER karg; +- pSCSITaskMgmt_t pScsiTm; +- pSCSITaskMgmtReply_t pScsiTmReply; +- MPT_ADAPTER *ioc = NULL; +- MPT_SCSI_HOST *hd; +- MPT_FRAME_HDR *mf = NULL; +- MPIHeader_t *mpi_hdr; +- int iocnum; +- u8 taskType; +- u8 channel; +- u8 id; +- u8 queueTag; +- u32 msgContext = 0; +- int i; +- u8 found_qtag; +- struct sas_device_info *sas_info; +- u16 ioc_status; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- +- if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SSP_TASK_IU_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in csmi_sas_task_managment struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, +- &ioc)) < 0) || (ioc == NULL)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not found!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- if (!csmisas_is_this_sas_cntr(ioc)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not SAS controller!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER; +- +- sas_info = csmisas_get_device_component_by_os(ioc, +- karg.Parameters.bPathId, karg.Parameters.bTargetId); +- if (!sas_info || sas_info->is_cached || sas_info->is_logical_volume) +- goto cim_get_task_managment_exit; +- +- channel = sas_info->fw.channel; +- id = sas_info->fw.id; +- queueTag = (u8)karg.Parameters.uQueueTag & 0xFF; +- hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; +- +- /* try to catch an error +- */ +- if ((karg.Parameters.uFlags & CSMI_SAS_TASK_IU) && +- (karg.Parameters.uFlags & CSMI_SAS_HARD_RESET_SEQUENCE)) +- goto cim_get_task_managment_exit; +- +- if (karg.Parameters.uFlags & CSMI_SAS_TASK_IU) { +- switch (karg.Parameters.bTaskManagementFunction) { +- +- case CSMI_SAS_SSP_ABORT_TASK: +- taskType = MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK; +- break; +- case CSMI_SAS_SSP_ABORT_TASK_SET: +- taskType = MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET; +- break; +- case CSMI_SAS_SSP_CLEAR_TASK_SET: +- taskType = MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET; +- break; +- case CSMI_SAS_SSP_LOGICAL_UNIT_RESET: +- taskType = MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET; +- break; +- case CSMI_SAS_SSP_CLEAR_ACA: +- case CSMI_SAS_SSP_QUERY_TASK: +- default: +- goto cim_get_task_managment_exit; +- } +- } else if (karg.Parameters.uFlags & CSMI_SAS_HARD_RESET_SEQUENCE) +- taskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET; +- else +- goto cim_get_task_managment_exit; +- +- switch (karg.Parameters.uInformation) { +- case CSMI_SAS_SSP_TEST: +- dcsmisasprintk(("TM request for test purposes\n")); +- break; +- case CSMI_SAS_SSP_EXCEEDED: +- dcsmisasprintk(("TM request due to timeout\n")); +- break; +- case CSMI_SAS_SSP_DEMAND: +- dcsmisasprintk(("TM request demanded by app\n")); +- break; +- case CSMI_SAS_SSP_TRIGGER: +- dcsmisasprintk(("TM request sent to trigger event\n")); +- break; +- } +- +- switch (taskType) { +- +- case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK: +- /* +- * look up qtag in the ScsiLookup[] table +- */ +- for (i = 0, found_qtag = 0; i < hd->ioc->req_depth; i++) { +-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)) +- if ((hd->ScsiLookup[i]) && +- (hd->ScsiLookup[i]->tag == queueTag)) { +-#else +- if ((ioc->ScsiLookup[i]) && +- (ioc->ScsiLookup[i]->tag == queueTag)) { +-#endif +- mf = MPT_INDEX_2_MFPTR(hd->ioc, i); +- msgContext = +- mf->u.frame.hwhdr.msgctxu.MsgContext; +- found_qtag=1; +- break; +- } +- } +- +- if(!found_qtag) +- goto cim_get_task_managment_exit; +- +- case MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET: +- case MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET: +- case MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET: +- /* for now, this should work +- */ +- case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET: +- +- /* Single threading .... +- */ +-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)) +- if (mptctl_set_tm_flags(hd) != 0) { +- karg.IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_FAILED; +- goto cim_get_task_managment_exit; +- } +-#endif +- +- /* Send request +- */ +- if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) { +- dcsmisasprintk((": no msg frames!\n")); +-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)) +- mptctl_free_tm_flags(ioc); +-#endif +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_get_task_managment_exit; +- } +- +- mpi_hdr = (MPIHeader_t *) mf; +- pScsiTm = (pSCSITaskMgmt_t ) mf; +- +- memset(pScsiTm,0,sizeof(SCSITaskMgmt_t)); +- pScsiTm->TaskType = taskType; +- pScsiTm->Bus = channel; +- pScsiTm->TargetID = id; +-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)) +- int_to_scsilun(karg.Parameters.bLun, +- (struct scsi_lun *)pScsiTm->LUN); +-#else +- pScsiTm->LUN[1] = karg.Parameters.bLun; +-#endif +- pScsiTm->MsgContext = mpi_hdr->MsgContext; +- pScsiTm->TaskMsgContext = msgContext; +- pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; +- +- if (csmisas_send_handshake_wait(ioc, mf, +- karg.IoctlHeader.Timeout) != 0) { +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_get_task_managment_exit; +- } +- +- if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) { +- +- pScsiTmReply = +- (pSCSITaskMgmtReply_t ) ioc->ioctl->ReplyFrame; +- +- ioc_status = le16_to_cpu(pScsiTmReply->IOCStatus) +- & MPI_IOCSTATUS_MASK; +- +- memset(&karg.Status,0, +- sizeof(CSMI_SAS_SSP_PASSTHRU_STATUS)); +- +- if(ioc_status == MPI_IOCSTATUS_SUCCESS) { +- karg.IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_SUCCESS; +- karg.Status.bSSPStatus = +- CSMI_SAS_SSP_STATUS_COMPLETED; +- }else if(ioc_status == MPI_IOCSTATUS_INSUFFICIENT_RESOURCES) { +- karg.IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_SUCCESS; +- karg.Status.bSSPStatus = +- CSMI_SAS_SSP_STATUS_RETRY; +- }else { +- karg.IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_FAILED; +- karg.Status.bSSPStatus = +- CSMI_SAS_SSP_STATUS_FATAL_ERROR; +- } +- } else +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- +- break; +- +- default: +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER; +- break; +- } +- +- +- cim_get_task_managment_exit: +- +- /* Copy the data from kernel memory to user memory +- */ +- if (copy_to_user((char *)arg, &karg, +- sizeof(CSMI_SAS_SSP_TASK_IU_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to write out csmi_sas_task_managment @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- dcsmisasprintk(("%s exit.\n",__FUNCTION__)); +- return 0; +-} +- +-/** +- * map_sas_status_to_csmi - Conversion for Connection Status +- * @mpi_sas_status: Sas status returned by the firmware +- * +- * Returns converted connection status +- * +- **/ +-static u8 +-map_sas_status_to_csmi(u8 mpi_sas_status) +-{ +- u8 csmi_connect_status; +- +- switch (mpi_sas_status) { +- +- case MPI_SASSTATUS_SUCCESS: +- csmi_connect_status = CSMI_SAS_OPEN_ACCEPT; +- break; +- +- case MPI_SASSTATUS_UTC_BAD_DEST: +- csmi_connect_status = CSMI_SAS_OPEN_REJECT_BAD_DESTINATION; +- break; +- +- case MPI_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED: +- csmi_connect_status = CSMI_SAS_OPEN_REJECT_RATE_NOT_SUPPORTED; +- break; +- +- case MPI_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED: +- csmi_connect_status = +- CSMI_SAS_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED; +- break; +- +- case MPI_SASSTATUS_UTC_STP_RESOURCES_BUSY: +- csmi_connect_status = CSMI_SAS_OPEN_REJECT_STP_RESOURCES_BUSY; +- break; +- +- case MPI_SASSTATUS_UTC_WRONG_DESTINATION: +- csmi_connect_status = CSMI_SAS_OPEN_REJECT_WRONG_DESTINATION; +- break; +- +- case MPI_SASSTATUS_SDSF_NAK_RECEIVED: +- csmi_connect_status = CSMI_SAS_OPEN_REJECT_RETRY; +- break; +- +- case MPI_SASSTATUS_SDSF_CONNECTION_FAILED: +- csmi_connect_status = CSMI_SAS_OPEN_REJECT_PATHWAY_BLOCKED; +- break; +- +- case MPI_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT: +- csmi_connect_status = CSMI_SAS_OPEN_REJECT_NO_DESTINATION; +- break; +- +- case MPI_SASSTATUS_UNKNOWN_ERROR: +- case MPI_SASSTATUS_INVALID_FRAME: +- case MPI_SASSTATUS_UTC_BREAK_RECEIVED: +- case MPI_SASSTATUS_UTC_PORT_LAYER_REQUEST: +- case MPI_SASSTATUS_SHORT_INFORMATION_UNIT: +- case MPI_SASSTATUS_LONG_INFORMATION_UNIT: +- case MPI_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA: +- case MPI_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR: +- case MPI_SASSTATUS_XFER_RDY_NOT_EXPECTED: +- case MPI_SASSTATUS_DATA_INCORRECT_DATA_LENGTH: +- case MPI_SASSTATUS_DATA_TOO_MUCH_READ_DATA: +- case MPI_SASSTATUS_DATA_OFFSET_ERROR: +- csmi_connect_status = CSMI_SAS_OPEN_REJECT_RESERVE_STOP; +- break; +- +- default: +- csmi_connect_status = CSMI_SAS_OPEN_REJECT_RESERVE_STOP; +- break; +- } +- +- return csmi_connect_status; +-} +- +-/** +- * csmisas_phy_reset +- * Issues a phy link reset or phy hard reset +- * +- * @ioc - Pointer to MPT_ADAPTER structure +- * @PhyNum - phy number +- * @opcode - {MPI_SAS_OP_PHY_LINK_RESET,MPI_SAS_OP_PHY_HARD_RESET} +- * +- * Returns: 0 for success, non-zero error +- **/ +-static int +-csmisas_phy_reset(MPT_ADAPTER *ioc, u8 PhyNum, u8 opcode) +-{ +- SasIoUnitControlRequest_t *sasIoUnitCntrReq; +- SasIoUnitControlReply_t *sasIoUnitCntrReply; +- MPT_FRAME_HDR *mf = NULL; +- MPIHeader_t *mpi_hdr; +- u16 ioc_status; +- +- if ((opcode != MPI_SAS_OP_PHY_LINK_RESET) && +- (opcode != MPI_SAS_OP_PHY_HARD_RESET)) +- return -1; +- +- /* Get a MF for this command. +- */ +- if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) { +- dcsmisasprintk((": no msg frames!\n")); +- return -1; +- } +- +- mpi_hdr = (MPIHeader_t *) mf; +- sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf; +- memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t)); +- sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL; +- sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext; +- sasIoUnitCntrReq->Operation = opcode; +- sasIoUnitCntrReq->PhyNum = PhyNum; +- +- if (csmisas_send_command_wait(ioc, mf, MPT_IOCTL_DEFAULT_TIMEOUT) != 0) +- return -1; +- +- if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) == 0) +- return -1; +- +- /* process the completed Reply Message Frame */ +- sasIoUnitCntrReply = (SasIoUnitControlReply_t *)ioc->ioctl->ReplyFrame; +- ioc_status = le16_to_cpu(sasIoUnitCntrReply->IOCStatus) +- & MPI_IOCSTATUS_MASK; +- if (ioc_status != MPI_IOCSTATUS_SUCCESS) { +- printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n", +- __FUNCTION__, +- sasIoUnitCntrReply->IOCStatus, +- sasIoUnitCntrReply->IOCLogInfo); +- return -1; +- } +- return 0; +-} +- +-/** Prototype Routine for the CSMI SAS Phy Control command. +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- * -ENODEV if no such device/adapter +- **/ +-static int +-csmisas_phy_control(unsigned long arg) +-{ +- CSMI_SAS_PHY_CONTROL_BUFFER __user *uarg = (void __user *) arg; +- IOCTL_HEADER ioctl_header; +- PCSMI_SAS_PHY_CONTROL_BUFFER karg; +- SasIOUnitPage0_t *sasIoUnitPg0=NULL; +- dma_addr_t sasIoUnitPg0_dma; +- int sasIoUnitPg0_data_sz=0; +- SasIOUnitPage1_t *sasIoUnitPg1=NULL; +- dma_addr_t sasIoUnitPg1_dma; +- int sasIoUnitPg1_data_sz=0; +- ConfigExtendedPageHeader_t hdr; +- CONFIGPARMS cfg; +- MPT_ADAPTER *ioc = NULL; +- int iocnum; +- int csmi_sas_phy_control_buffer_sz; +- int memory_pages; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- +- if (copy_from_user(&ioctl_header, uarg, sizeof(IOCTL_HEADER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in IOCTL_HEADER" +- "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- csmi_sas_phy_control_buffer_sz = ioctl_header.Length; +- memory_pages = get_order(csmi_sas_phy_control_buffer_sz); +- karg = (PCSMI_SAS_PHY_CONTROL_BUFFER)__get_free_pages( +- GFP_KERNEL, memory_pages); +- if (!karg){ +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to malloc SAS_PHY_CONTROL_BUFFER " +- "csmi_sas_phy_control_buffer_sz=%d memory_pages=%d\n", +- __FILE__, __LINE__, __FUNCTION__, +- csmi_sas_phy_control_buffer_sz, memory_pages); +- return -ENOMEM; +- } +- memset(karg, 0, sizeof(*karg)); +- +- if (copy_from_user(karg, uarg, csmi_sas_phy_control_buffer_sz)) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in csmi_sas_phy_control_buffer " +- "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg); +- free_pages((unsigned long)karg, memory_pages); +- return -EFAULT; +- } +- +- if (((iocnum = mpt_verify_adapter(ioctl_header.IOControllerNumber, +- &ioc)) < 0) || (ioc == NULL)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not found!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- free_pages((unsigned long)karg, memory_pages); +- return -ENODEV; +- } +- +- if (!csmisas_is_this_sas_cntr(ioc)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not SAS controller!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- free_pages((unsigned long)karg, memory_pages); +- return -ENODEV; +- } +- +- if (karg->bPhyIdentifier >= ioc->num_ports) { +- karg->IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_INVALID_PARAMETER; +- goto cim_sas_phy_control_exit; +- } +- +- /* +- * Retreive SAS IOUNIT PAGE 0 +- */ +- +- hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION; +- hdr.ExtPageLength = 0; +- hdr.PageNumber = 0; +- hdr.Reserved1 = 0; +- hdr.Reserved2 = 0; +- hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; +- hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; +- +- cfg.cfghdr.ehdr = &hdr; +- cfg.physAddr = -1; +- cfg.pageAddr = 0; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.dir = 0; /* read */ +- cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; +- +- if (mpt_config(ioc, &cfg) != 0) { +- dcsmisasprintk(( +- ": FAILED: READ MPI_SASIOUNITPAGE0: HEADER\n")); +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_sas_phy_control_exit; +- } +- +- if (hdr.ExtPageLength == 0) { +- dcsmisasprintk((": hdr.ExtPageLength == 0\n")); +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_sas_phy_control_exit; +- } +- +- sasIoUnitPg0_data_sz = hdr.ExtPageLength * 4; +- sasIoUnitPg0 = (SasIOUnitPage0_t *) pci_alloc_consistent(ioc->pcidev, +- sasIoUnitPg0_data_sz, &sasIoUnitPg0_dma); +- +- if (!sasIoUnitPg0) { +- dcsmisasprintk((": pci_alloc_consistent: FAILED\n")); +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_sas_phy_control_exit; +- } +- +- memset((u8 *)sasIoUnitPg0, 0, sasIoUnitPg0_data_sz); +- cfg.physAddr = sasIoUnitPg0_dma; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- +- if (mpt_config(ioc, &cfg) != 0) { +- dcsmisasprintk(( +- ": FAILED: READ MPI_SASIOUNITPAGE0: CURRENT\n")); +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_sas_phy_control_exit; +- } +- +- /* +- * Retreive SAS IOUNIT PAGE 1 +- */ +- +- hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION; +- hdr.ExtPageLength = 0; +- hdr.PageNumber = 1; +- hdr.Reserved1 = 0; +- hdr.Reserved2 = 0; +- hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; +- hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; +- +- cfg.cfghdr.ehdr = &hdr; +- cfg.physAddr = -1; +- cfg.pageAddr = 0; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.dir = 0; /* read */ +- cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; +- +- if (mpt_config(ioc, &cfg) != 0) { +- dcsmisasprintk(( +- ": FAILED: READ MPI_SASIOUNITPAGE1: HEADER\n")); +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_sas_phy_control_exit; +- } +- +- if (hdr.ExtPageLength == 0) { +- dcsmisasprintk((": hdr.ExtPageLength == 0\n")); +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_sas_phy_control_exit; +- } +- +- sasIoUnitPg1_data_sz = hdr.ExtPageLength * 4; +- sasIoUnitPg1 = (SasIOUnitPage1_t *) pci_alloc_consistent(ioc->pcidev, +- sasIoUnitPg1_data_sz, &sasIoUnitPg1_dma); +- +- if (!sasIoUnitPg1) { +- dcsmisasprintk((": pci_alloc_consistent: FAILED\n")); +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_sas_phy_control_exit; +- } +- +- memset((u8 *)sasIoUnitPg1, 0, sasIoUnitPg1_data_sz); +- cfg.physAddr = sasIoUnitPg1_dma; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- +- if (mpt_config(ioc, &cfg) != 0) { +- dcsmisasprintk(( +- ": FAILED: READ MPI_SASIOUNITPAGE1: CURRENT\n")); +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_sas_phy_control_exit; +- } +- +- switch (karg->uFunction) { +- +- case CSMI_SAS_PC_LINK_RESET: +- case CSMI_SAS_PC_HARD_RESET: +- { +- u8 opcode = (karg->uFunction==CSMI_SAS_PC_LINK_RESET) ? +- MPI_SAS_OP_PHY_LINK_RESET : MPI_SAS_OP_PHY_HARD_RESET; +- +- if((karg->uLinkFlags & CSMI_SAS_PHY_ACTIVATE_CONTROL) && +- (karg->usLengthOfControl >= sizeof(CSMI_SAS_PHY_CONTROL)) && +- (karg->bNumberOfControls > 0)){ +- if(karg->Control[0].bRate == +- CSMI_SAS_LINK_RATE_1_5_GBPS) { +- sasIoUnitPg1->PhyData[karg->bPhyIdentifier].MaxMinLinkRate = +- MPI_SAS_IOUNIT1_MAX_RATE_1_5 | +- MPI_SAS_IOUNIT1_MIN_RATE_1_5; +- } +- else if(karg->Control[0].bRate == +- CSMI_SAS_LINK_RATE_3_0_GBPS) { +- sasIoUnitPg1->PhyData[karg->bPhyIdentifier].MaxMinLinkRate = +- MPI_SAS_IOUNIT1_MAX_RATE_3_0 | +- MPI_SAS_IOUNIT1_MIN_RATE_3_0; +- } +- sasIoUnitPg1->PhyData[karg->bPhyIdentifier].PhyFlags &= +- ~MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE; +- cfg.dir = 1; +- cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM; +- if (mpt_config(ioc, &cfg) != 0) { +- dcsmisasprintk(( +- ": FAILED: WRITE MPI_SASIOUNITPAGE1 NVRAM\n")); +- karg->IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_FAILED; +- goto cim_sas_phy_control_exit; +- } +- cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; +- if (mpt_config(ioc, &cfg) != 0) { +- dcsmisasprintk(( +- ": FAILED: WRITE MPI_SASIOUNITPAGE1 CURRENT\n")); +- karg->IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_FAILED; +- goto cim_sas_phy_control_exit; +- } +- } +- if (csmisas_phy_reset(ioc, +- karg->bPhyIdentifier, opcode) != 0) { +- dcsmisasprintk(( +- ": FAILED: csmisas_phy_reset\n")); +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_sas_phy_control_exit; +- } +- break; +- +- } +- case CSMI_SAS_PC_PHY_DISABLE: +- if(karg->usLengthOfControl || karg->bNumberOfControls) { +- karg->IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_INVALID_PARAMETER; +- break; +- } +- sasIoUnitPg1->PhyData[karg->bPhyIdentifier].PhyFlags |= +- MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE; +- cfg.dir = 1; +- cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM; +- if (mpt_config(ioc, &cfg) != 0) { +- dcsmisasprintk(( +- ": FAILED: WRITE MPI_SASIOUNITPAGE1 NVRAM\n")); +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_sas_phy_control_exit; +- } +- cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; +- if (mpt_config(ioc, &cfg) != 0) { +- dcsmisasprintk(( +- ": FAILED: WRITE MPI_SASIOUNITPAGE1 CURRENT\n")); +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_sas_phy_control_exit; +- } +- if (csmisas_phy_reset(ioc, +- karg->bPhyIdentifier, MPI_SAS_OP_PHY_HARD_RESET) != 0) { +- dcsmisasprintk(( +- ": FAILED: csmisas_phy_reset\n")); +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- goto cim_sas_phy_control_exit; +- } +- break; +- +- case CSMI_SAS_PC_GET_PHY_SETTINGS: +- if(karg->usLengthOfControl || karg->bNumberOfControls) { +- karg->IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_INVALID_PARAMETER; +- break; +- } +- if(csmi_sas_phy_control_buffer_sz < +- offsetof(CSMI_SAS_PHY_CONTROL_BUFFER,Control) + +- (4* sizeof(CSMI_SAS_PHY_CONTROL))) { +- karg->IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_INVALID_PARAMETER; +- break; +- } +- karg->usLengthOfControl = sizeof(CSMI_SAS_PHY_CONTROL); +- karg->bNumberOfControls = 4; +- karg->Control[0].bType = CSMI_SAS_SAS; +- karg->Control[0].bRate = CSMI_SAS_LINK_RATE_1_5_GBPS; +- karg->Control[1].bType = CSMI_SAS_SAS; +- karg->Control[1].bRate = CSMI_SAS_LINK_RATE_3_0_GBPS; +- karg->Control[2].bType = CSMI_SAS_SATA; +- karg->Control[2].bRate = CSMI_SAS_LINK_RATE_1_5_GBPS; +- karg->Control[3].bType = CSMI_SAS_SATA; +- karg->Control[3].bRate = CSMI_SAS_LINK_RATE_3_0_GBPS; +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; +- break; +- default: +- break; +- } +- +- cim_sas_phy_control_exit: +- +- if (sasIoUnitPg0) +- pci_free_consistent(ioc->pcidev, sasIoUnitPg0_data_sz, +- (u8 *) sasIoUnitPg0, sasIoUnitPg0_dma); +- +- if (sasIoUnitPg1) +- pci_free_consistent(ioc->pcidev, sasIoUnitPg1_data_sz, +- (u8 *) sasIoUnitPg1, sasIoUnitPg1_dma); +- +- /* Copy the data from kernel memory to user memory +- */ +- if (copy_to_user((char *)arg,karg,csmi_sas_phy_control_buffer_sz)) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to write out csmi_sas_phy_control_buffer @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- free_pages((unsigned long)karg, memory_pages); +- return -EFAULT; +- } +- +- dcsmisasprintk(("%s exit.\n",__FUNCTION__)); +- free_pages((unsigned long)karg, memory_pages); +- return 0; +-} +- +-/** +- * csmisas_get_manuf_pg_7 - Fetch Manufacturing config Page7. +- * @ioc: Pointer to MPT_ADAPTER structure +- * @mfgpage7_buffer: pointer to ManufacturingPage7_t that returns config +- * page data +- * @mfg_size - max size of buffer +- * +- * Return: 0 for success +- * -ENOMEM if no memory available +- * -EPERM if not allowed due to ISR context +- * -EAGAIN if no msg frames currently available +- * -EFAULT for non-successful reply or no reply (timeout) +- **/ +-static int +-csmisas_get_manuf_pg_7(MPT_ADAPTER *ioc, ManufacturingPage7_t *mfgpage7_buffer, int mfg_size) +-{ +- ConfigPageHeader_t hdr; +- CONFIGPARMS cfg; +- ManufacturingPage7_t *mfgPage7 = NULL; +- dma_addr_t mfgPage7_dma; +- int data_sz = 0; +- int rc; +- +- /* Get Manufacturing Page 7 header */ +- hdr.PageVersion = MPI_MANUFACTURING0_PAGEVERSION; +- hdr.PageLength = 0; +- hdr.PageNumber = 7; +- hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING; +- cfg.cfghdr.hdr = &hdr; +- cfg.physAddr = -1; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.dir = 0; +- cfg.pageAddr = 0; +- cfg.timeout = 0; +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) +- goto csmisas_get_manuf_pg_7_exit; +- +- if (hdr.PageLength == 0) { +- rc = -EFAULT; +- goto csmisas_get_manuf_pg_7_exit; +- } +- +- data_sz = hdr.PageLength * 4; +- mfgPage7 = pci_alloc_consistent(ioc->pcidev, data_sz, &mfgPage7_dma); +- if (!mfgPage7) { +- rc = -ENOMEM; +- goto csmisas_get_manuf_pg_7_exit; +- } +- +- memset((u8 *)mfgPage7, 0, data_sz); +- cfg.physAddr = mfgPage7_dma; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) +- goto csmisas_get_manuf_pg_7_exit; +- +- /* copy buffer back to user */ +- memcpy(mfgpage7_buffer, mfgPage7, min(data_sz, mfg_size)); +- +- csmisas_get_manuf_pg_7_exit: +- +- if (mfgPage7) +- pci_free_consistent(ioc->pcidev, data_sz, (u8 *)mfgPage7, +- mfgPage7_dma); +- +- return rc; +-} +- +-/** +- * Prototype Routine for the CSMI SAS Get Connector info command. +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- * -ENODEV if no such device/adapter +- **/ +-static int +-csmisas_get_connector_info(unsigned long arg) +-{ +- CSMI_SAS_CONNECTOR_INFO_BUFFER __user *uarg = (void __user *) arg; +- CSMI_SAS_CONNECTOR_INFO_BUFFER karg; +- MPT_ADAPTER *ioc = NULL; +- ManufacturingPage7_t *mfgPg7 = NULL; +- int mfgPg7_sz; +- int iocnum; +- int i; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- +- if (copy_from_user(&karg, uarg, +- sizeof(CSMI_SAS_CONNECTOR_INFO_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in csmi_sas_connector_info_buffer" +- " struct @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, +- &ioc)) < 0) || (ioc == NULL)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not found!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- if (!csmisas_is_this_sas_cntr(ioc)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not SAS controller!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- return -ENODEV; +- } +- +- karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; +- +- /* `32` is the sizeof MPI_MANPAGE7_CONNECTOR_INFO */ +- for (i = 0; i < 32; i++) { +- karg.Reference[i].uPinout = CSMI_SAS_CON_UNKNOWN; +- strcpy(karg.Reference[i].bConnector,""); +- karg.Reference[i].bLocation = CSMI_SAS_CON_UNKNOWN; +- } +- +- mfgPg7_sz = offsetof(CONFIG_PAGE_MANUFACTURING_7,ConnectorInfo) + +- (ioc->num_ports * sizeof(MPI_MANPAGE7_CONNECTOR_INFO)); +- mfgPg7 = kmalloc(mfgPg7_sz, GFP_KERNEL); +- if (!mfgPg7){ +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to malloc @ %p\n", +- __FILE__, __LINE__, __FUNCTION__, mfgPg7); +- return -EFAULT; +- } +- memset(mfgPg7, 0, mfgPg7_sz); +- +- if (!csmisas_get_manuf_pg_7(ioc, mfgPg7, mfgPg7_sz)) { +- for (i = 0; i < ioc->num_ports; i++) { +- karg.Reference[i].uPinout = +- le32_to_cpu(mfgPg7->ConnectorInfo[i].Pinout); +- /*endian conversion , this is u8 * 16 ?? */ +- strncpy(karg.Reference[i].bConnector, +- mfgPg7->ConnectorInfo[i].Connector, 16); +- karg.Reference[i].bLocation = +- mfgPg7->ConnectorInfo[i].Location; +- } +- } +- +- kfree(mfgPg7); +- +- /* Copy the data from kernel memory to user memory +- */ +- if (copy_to_user((char *)arg, &karg, +- sizeof(CSMI_SAS_CONNECTOR_INFO_BUFFER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to write out csmi_sas_connector_info_buffer @" +- "%p\n", +- __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- dcsmisasprintk(("%s exit.\n",__FUNCTION__)); +- return 0; +-} +- +-/** +- * csmisas_fill_location_data +- * +- * Outputs: None. +- * Return: 0 if successful +- **/ +-static int +-csmisas_fill_location_data(MPT_ADAPTER *ioc, u8 bus, u8 id, u8 opcode, +- CSMI_SAS_LOCATION_IDENTIFIER * location_ident) +-{ +- +- ConfigExtendedPageHeader_t hdr; +- CONFIGPARMS cfg; +- int rc; +- SasDevicePage0_t *sasDevicePg0=NULL; +- SasEnclosurePage0_t *sasEnclosurePg0=NULL; +- dma_addr_t sasDevicePg0_dma,sasEnclosurePg0_dma; +- int sasDevicePg0_data_sz=0; +- int sasEnclosurePg0_data_sz=0; +- u64 sas_address; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- memset (location_ident, 0, sizeof(*location_ident)); +- +- /* SAS Device Page 0 */ +- hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION; +- hdr.ExtPageLength = 0; +- hdr.PageNumber = 0; +- hdr.Reserved1 = 0; +- hdr.Reserved2 = 0; +- hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; +- hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE; +- +- cfg.cfghdr.ehdr = &hdr; +- cfg.physAddr = -1; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.dir = 0; /* read */ +- cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) { +- rc=-1; +- goto fill_location_data_exit; +- } +- +- if (hdr.ExtPageLength == 0) { +- rc=-1; +- goto fill_location_data_exit; +- } +- +- sasDevicePg0_data_sz = hdr.ExtPageLength * 4; +- sasDevicePg0 = (SasDevicePage0_t *) pci_alloc_consistent( +- ioc->pcidev, sasDevicePg0_data_sz, &sasDevicePg0_dma); +- if (!sasDevicePg0) { +- rc=-1; +- goto fill_location_data_exit; +- } +- +- memset((u8 *)sasDevicePg0, 0, sasDevicePg0_data_sz); +- cfg.physAddr = sasDevicePg0_dma; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- cfg.pageAddr = (bus << 8) + id +- + (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << +- MPI_SAS_DEVICE_PGAD_FORM_SHIFT); +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) { +- rc=-1; +- goto fill_location_data_exit; +- } +- +- location_ident->bLocationFlags |= CSMI_SAS_LOCATE_SAS_ADDRESS_VALID; +- memcpy(&sas_address, &sasDevicePg0->SASAddress, sizeof(u64)); +- sas_address = reverse_byte_order64(sas_address); +- memcpy(location_ident->bSASAddress, &sas_address, sizeof(u64)); +- +- location_ident->bLocationFlags |= CSMI_SAS_LOCATE_SAS_LUN_VALID; +- memset(location_ident->bSASLun, 0, sizeof(location_ident->bSASLun)); +- +- /* SAS Enclosure Page 0 */ +- hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION; +- hdr.ExtPageLength = 0; +- hdr.PageNumber = 0; +- hdr.Reserved1 = 0; +- hdr.Reserved2 = 0; +- hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; +- hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE; +- +- cfg.cfghdr.ehdr = &hdr; +- cfg.physAddr = -1; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.dir = 0; /* read */ +- cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) { +- rc=0; +- goto fill_location_data_exit; +- } +- +- if (hdr.ExtPageLength == 0) { +- rc=0; +- goto fill_location_data_exit; +- } +- +- sasEnclosurePg0_data_sz = hdr.ExtPageLength * 4; +- sasEnclosurePg0 = (SasEnclosurePage0_t *) pci_alloc_consistent( +- ioc->pcidev, sasEnclosurePg0_data_sz, &sasEnclosurePg0_dma); +- if (!sasEnclosurePg0) { +- rc=0; +- goto fill_location_data_exit; +- } +- cfg.physAddr = sasEnclosurePg0_dma; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- cfg.pageAddr = sasDevicePg0->EnclosureHandle +- + (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE << MPI_SAS_ENCLOS_PGAD_FORM_SHIFT); +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) { +- rc=0; +- goto fill_location_data_exit; +- } +- +- location_ident->bLocationFlags |= CSMI_SAS_LOCATE_ENCLOSURE_IDENTIFIER_VALID; +- memcpy(&sas_address, &sasEnclosurePg0->EnclosureLogicalID, sizeof(u64)); +- sas_address = reverse_byte_order64(sas_address); +- if (sas_address) +- memcpy(location_ident->bEnclosureIdentifier, &sas_address, sizeof(u64)); +- else +- strcpy(location_ident->bEnclosureIdentifier,"Internal"); +- +-// bBayPrefix - not supported +- +-// TODO - We need to look at sasEnclosurePg0-.Flags , to determine +-// whether SEP BUS/TargetID is valid. Ifs its a SES device, then +-// issue internal inquiry to (bus/id) to gather the Enclosure name. +-// If the device is SMP, then issue SMP_MANUFACTURING to get enclosure name +-// If its direct attached, there is no enclosure name +- location_ident->bLocationFlags |= CSMI_SAS_LOCATE_ENCLOSURE_NAME_VALID; +- strcpy(location_ident->bEnclosureName,"Not Supported"); +- +- location_ident->bLocationFlags |= CSMI_SAS_LOCATE_LOCATION_STATE_VALID; +- location_ident->bLocationState = CSMI_SAS_LOCATE_UNKNOWN; +- +- location_ident->bLocationFlags |= CSMI_SAS_LOCATE_BAY_IDENTIFIER_VALID; +- location_ident->bBayIdentifier = le16_to_cpu(sasDevicePg0->Slot); +- +- +-// TODO - illuminating LEDs, +-// karg->bIdentify = CSMI_SAS_LOCATE_FORCE_OFF, CSMI_SAS_LOCATE_FORCE_ON +-// We can enable/disable LEDs by SCSI Enclosure Processor MPI request message +-// printk("Flags=0x%x\n",sasEnclosurePg0->Flags); +- +-/* check sasEnclosurePg0->Flags - +- * to validate whether we need to send the SEPRequest +- * bit:5 should be set +- * bit:3-0 any bit should be set. If zero, then SEPRequest will fail +-*/ +- +-/* MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR +- * Look in mpi_init.h +- * SEPRequest_t = structure +- * +- * SEPRequest_t->Action should be set to MPI_SEP_REQ_ACTION_WRITE_STATUS +- * +- * SEPRequest_t->Flags should be set to +- * MPI_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS, to pass along enclosure/slot ids +- * +- * SEPRequest_t->SlotStatus |= MPI_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST - this +- * will illuminate the LEDs +- */ +- +-fill_location_data_exit: +- +- if (sasDevicePg0 != NULL) +- pci_free_consistent(ioc->pcidev, sasDevicePg0_data_sz, +- sasDevicePg0, sasDevicePg0_dma); +- +- if (sasEnclosurePg0 != NULL) +- pci_free_consistent(ioc->pcidev, sasEnclosurePg0_data_sz, +- sasEnclosurePg0, sasEnclosurePg0_dma); +- +- dcsmisasprintk(("%s exit.\n",__FUNCTION__)); +- return rc; +-} +- +-static int +-csmisas_fill_location_data_raid(MPT_ADAPTER *ioc, PCSMI_SAS_GET_LOCATION_BUFFER karg, u8 VolumeBus, +- u8 volumeID) +-{ +- pRaidVolumePage0_t pVolume0 = NULL; +- pRaidPhysDiskPage0_t pPhysDisk0 = NULL; +- CONFIGPARMS cfg; +- ConfigPageHeader_t header; +- u8 physDiskNumMax; +- int volumepage0sz = 0, physdiskpage0sz = 0; +- dma_addr_t volume0_dma, physdisk0_dma; +- int csmi_sas_get_location_sz; +- int rc = 0, i, idx; +- int num_hotpares; +- u64 totalMaxLBA, tmpTotalMaxLBA; +- IOCPage5_t *iocPage5 = NULL; +- u32 device_info = 0; +- struct sas_device_info *sas_info; +- +- int sz; +- +- csmi_sas_get_location_sz = karg->IoctlHeader.Length; +- physDiskNumMax = (csmi_sas_get_location_sz - +- offsetof(CSMI_SAS_GET_LOCATION_BUFFER,Location)) +- / sizeof(CSMI_SAS_LOCATION_IDENTIFIER); +- karg->bNumberOfLocationIdentifiers=0; +- +- /* +- * get RAID Volume Page 0 +- */ +- +- header.PageVersion = 0; +- header.PageLength = 0; +- header.PageNumber = 0; +- header.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME; +- cfg.cfghdr.hdr = &header; +- cfg.physAddr = -1; +- cfg.pageAddr = (VolumeBus << 8) + volumeID; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.dir = 0; +- cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; +- if (mpt_config(ioc, &cfg) != 0) { +- rc = -1; +- goto sas_fill_location_data_raid_exit; +- } +- +- if (header.PageLength == 0) { +- rc = -1; +- goto sas_fill_location_data_raid_exit; +- } +- +- volumepage0sz = header.PageLength * 4; +- pVolume0 = pci_alloc_consistent(ioc->pcidev, volumepage0sz, +- &volume0_dma); +- if (!pVolume0) { +- rc = -1; +- goto sas_fill_location_data_raid_exit; +- } +- +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- cfg.physAddr = volume0_dma; +- if (mpt_config(ioc, &cfg) != 0){ +- rc = -1; +- goto sas_fill_location_data_raid_exit; +- } +- +- totalMaxLBA = (u64)le32_to_cpu(pVolume0->MaxLBA) | +- ((u64)le32_to_cpu(pVolume0->MaxLBAHigh)) << 32; +- +- /* +- * get RAID Physical Disk Page 0 +- */ +- header.PageVersion = 0; +- header.PageLength = 0; +- header.PageNumber = 0; +- header.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK; +- cfg.cfghdr.hdr = &header; +- cfg.physAddr = -1; +- cfg.pageAddr = 0; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.dir = 0; +- cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; +- if (mpt_config(ioc, &cfg) != 0) { +- rc = -1; +- goto sas_fill_location_data_raid_exit; +- } +- +- if (header.PageLength == 0) { +- rc = -1; +- goto sas_fill_location_data_raid_exit; +- } +- +- physdiskpage0sz = header.PageLength * 4; +- pPhysDisk0 = pci_alloc_consistent(ioc->pcidev, physdiskpage0sz, +- &physdisk0_dma); +- if (!pPhysDisk0) { +- rc = -1; +- goto sas_fill_location_data_raid_exit; +- } +- cfg.physAddr = physdisk0_dma; +- +- for (i=0; i < min(pVolume0->NumPhysDisks, physDiskNumMax); i++) { +- +- /* obtain a refresh of pPhysDisk0 */ +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- cfg.pageAddr = pVolume0->PhysDisk[i].PhysDiskNum; +- if (mpt_config(ioc, &cfg) != 0){ +- rc = -1; +- goto sas_fill_location_data_raid_exit; +- } +- +- if((csmisas_fill_location_data(ioc, pPhysDisk0->PhysDiskBus, +- pPhysDisk0->PhysDiskID, karg->bIdentify, +- &karg->Location[karg->bNumberOfLocationIdentifiers])) == 0) +- karg->bNumberOfLocationIdentifiers++; +- +- if (device_info) +- continue; +- sas_info = csmisas_get_device_component_by_fw(ioc, +- pPhysDisk0->PhysDiskBus, pPhysDisk0->PhysDiskID); +- if (!sas_info || sas_info->is_cached) +- continue; +- device_info = sas_info->device_info; +- } +- +- if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IS) +- goto sas_fill_location_data_raid_exit; +- +- /* +- * hot spare support +- * +- */ +- +- num_hotpares = csmisas_get_number_hotspares(ioc); +- +- if (num_hotpares) { +- +- sz = offsetof(IOCPage5_t, HotSpare) + +- num_hotpares * sizeof(IOC_5_HOT_SPARE); +- iocPage5 = kmalloc(sz, GFP_KERNEL); +- +- if (!iocPage5) +- goto sas_fill_location_data_raid_exit; +- memset(iocPage5, 0, sizeof(*iocPage5)); +- +- if (csmisas_get_ioc_pg5(ioc, iocPage5, sz) != 0) +- goto sas_fill_location_data_raid_exit; +- +- for(i = 0, idx = pVolume0->NumPhysDisks ; i < num_hotpares; +- i++, idx++) { +- +- if (idx >= physDiskNumMax) +- break; +- +- /* obtain a refresh of pPhysDisk0 */ +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- cfg.pageAddr = iocPage5->HotSpare[i].PhysDiskNum; +- if (mpt_config(ioc, &cfg) != 0) +- goto sas_fill_location_data_raid_exit; +- +- /* Search the list for the matching SAS address. */ +- sas_info = csmisas_get_device_component_by_fw(ioc, +- pPhysDisk0->PhysDiskBus, pPhysDisk0->PhysDiskID); +- +- if (!sas_info || sas_info->is_cached) +- continue; +- +- /* don't mix SSP hot spare +- * in SATA volume +- */ +- if (!csmisas_is_sata(pPhysDisk0) && +- (device_info & +- MPI_SAS_DEVICE_INFO_SATA_DEVICE)) +- continue; +- +- /* don't mix SATA hot spare +- * in SSP volume +- */ +- if (csmisas_is_sata(pPhysDisk0) && +- (device_info & +- MPI_SAS_DEVICE_INFO_SSP_TARGET)) +- continue; +- +- /* capacity check for IM volumes*/ +- if ((pVolume0->VolumeType == +- MPI_RAID_VOL_TYPE_IM) && +- (totalMaxLBA + +- (64*2*1024) /* metadata = 64MB*/ > +- le32_to_cpu(pPhysDisk0->MaxLBA))) +- continue; +- +- tmpTotalMaxLBA = totalMaxLBA; +- do_div(tmpTotalMaxLBA, pVolume0->NumPhysDisks); +- /* capacity check for IME volumes*/ +- if ((pVolume0->VolumeType == +- MPI_RAID_VOL_TYPE_IME) && +- ((tmpTotalMaxLBA * 2) + +- (64*2*1024 ) /*metadata = 64MB*/ > +- le32_to_cpu(pPhysDisk0->MaxLBA))) +- continue; +- +- if((csmisas_fill_location_data(ioc, +- pPhysDisk0->PhysDiskBus, pPhysDisk0->PhysDiskID, +- karg->bIdentify, +- &karg->Location[karg->bNumberOfLocationIdentifiers])) == 0) +- karg->bNumberOfLocationIdentifiers++; +- } +- } +- +- +- sas_fill_location_data_raid_exit: +- +- kfree(iocPage5); +- +- if (pVolume0) +- pci_free_consistent(ioc->pcidev, volumepage0sz, pVolume0, +- volume0_dma); +- +- if(pPhysDisk0) +- pci_free_consistent(ioc->pcidev, physdiskpage0sz, pPhysDisk0, +- physdisk0_dma); +- +- return rc; +-} +- +-/** +- * Prototype Routine for the CSMI SAS Get location command. +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- * -ENODEV if no such device/adapter +- */ +-static int +-csmisas_get_location(unsigned long arg) +-{ +- CSMI_SAS_GET_LOCATION_BUFFER __user *uarg = (void __user *) arg; +- PCSMI_SAS_GET_LOCATION_BUFFER karg; +- IOCTL_HEADER ioctl_header; +- MPT_ADAPTER *ioc = NULL; +- int iocnum,i; +- int csmi_sas_get_location_sz; +- int memory_pages; +- struct sas_device_info *sas_info; +- +- dcsmisasprintk(("%s enter.\n",__FUNCTION__)); +- +- if (copy_from_user(&ioctl_header, uarg, sizeof(IOCTL_HEADER))) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in IOCTL_HEADER" +- "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg); +- return -EFAULT; +- } +- +- csmi_sas_get_location_sz = ioctl_header.Length; +- memory_pages = get_order(csmi_sas_get_location_sz); +- karg = (PCSMI_SAS_GET_LOCATION_BUFFER)__get_free_pages( +- GFP_KERNEL, memory_pages); +- if (!karg){ +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to malloc GET_LOCATION_BUFFER " +- "csmi_sas_get_location_sz=%d memory_pages=%d\n", +- __FILE__, __LINE__, __FUNCTION__, +- csmi_sas_get_location_sz, memory_pages); +- return -ENOMEM; +- } +- memset(karg, 0, sizeof(*karg)); +- +- if (copy_from_user(karg, uarg, csmi_sas_get_location_sz)) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to read in csmi_sas_phy_control_buffer " +- "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg); +- free_pages((unsigned long)karg, memory_pages); +- return -EFAULT; +- } +- +- if (((iocnum = mpt_verify_adapter(karg->IoctlHeader.IOControllerNumber, +- &ioc)) < 0) || (ioc == NULL)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not found!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- free_pages((unsigned long)karg, memory_pages); +- return -ENODEV; +- } +- +- if (!csmisas_is_this_sas_cntr(ioc)) { +- dcsmisasprintk((KERN_ERR +- "%s::%s() @%d - ioc%d not SAS controller!\n", +- __FILE__, __FUNCTION__, __LINE__, iocnum)); +- free_pages((unsigned long)karg, memory_pages); +- return -ENODEV; +- } +- +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER; +- if(karg->bLengthOfLocationIdentifier != +- sizeof(CSMI_SAS_LOCATION_IDENTIFIER)) +- goto cim_sas_get_location_exit; +- +- sas_info = csmisas_get_device_component_by_os(ioc, karg->bPathId, +- karg->bTargetId); +- if (!sas_info) +- goto cim_sas_get_location_exit; +- +- /* RAID SUPPORT */ +- if (ioc->raid_data.pIocPg2 && sas_info->is_logical_volume) { +- for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++){ +- if (sas_info->fw.id == +- ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID && +- sas_info->fw.channel == +- ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus) { +- if(csmisas_fill_location_data_raid(ioc, karg, +- ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus, +- ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID) == 0) +- karg->IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_SUCCESS; +- else +- karg->IoctlHeader.ReturnCode = +- CSMI_SAS_STATUS_FAILED; +- goto cim_sas_get_location_exit; +- } +- } +- } +- +- /* NON-RAID SUPPORT */ +- if (sas_info->is_cached || sas_info->is_logical_volume) +- goto cim_sas_get_location_exit; +- +- /* make sure there's enough room to populate the Location[] struct */ +- if ((csmi_sas_get_location_sz - +- offsetof(CSMI_SAS_GET_LOCATION_BUFFER,Location)) < +- sizeof(CSMI_SAS_LOCATION_IDENTIFIER)) +- goto cim_sas_get_location_exit; +- +- karg->bNumberOfLocationIdentifiers=1; +- karg->Location[0].bLocationFlags=0; +- if((csmisas_fill_location_data(ioc, sas_info->fw.channel, +- sas_info->fw.id, karg->bIdentify, &karg->Location[0])) == 0) +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; +- else +- karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; +- +- cim_sas_get_location_exit: +- +- /* Copy the data from kernel memory to user memory +- */ +- if (copy_to_user((char *)arg, karg, csmi_sas_get_location_sz)) { +- printk(KERN_ERR "%s@%d::%s() - " +- "Unable to write out csmi_sas_get_location_buffer " +- "@ %p\n",__FILE__, __LINE__, __FUNCTION__, uarg); +- free_pages((unsigned long)karg, memory_pages); +- return -EFAULT; +- } +- +- dcsmisasprintk(("%s exit.\n",__FUNCTION__)); +- free_pages((unsigned long)karg, memory_pages); +- return 0; +-} +diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/csmi/csmisas.h linux-2.6.9-55.0.12/drivers/message/fusion/csmi/csmisas.h +--- linux-2.6.9-67.0.1/drivers/message/fusion/csmi/csmisas.h 2007-12-21 11:40:54.000000000 +0100 ++++ linux-2.6.9-55.0.12/drivers/message/fusion/csmi/csmisas.h 1970-01-01 01:00:00.000000000 +0100 +@@ -1,1854 +0,0 @@ +-/************************************************************************** +- +-Module Name: +- +- CSMISAS.H +- +- +-Abstract: +- +- This file contains constants and data structure definitions used by drivers +- that support the Common Storage Management Interface specification for +- SAS or SATA in either the Windows or Linux. +- +- This should be considered as a reference implementation only. Changes may +- be necessary to accommodate a specific build environment or target OS. +- +-Revision History: +- +- 001 SEF 8/12/03 Initial release. +- 002 SEF 8/20/03 Cleanup to match documentation. +- 003 SEF 9/12/03 Additional cleanup, created combined header +- 004 SEF 9/23/03 Changed base types to match linux defaults +- Added RAID signature +- Added bControllerFlags to CSMI_SAS_CNTLR_CONFIG +- Changed CSMI_SAS_BEGIN_PACK to 8 for common structures +- Fixed other typos identified in first compilation test +- 005 SEF 10/03/03 Additions to match first version of CSMI document +- 006 SEF 10/14/03 Fixed typedef struct _CSMI_SAS_SMP_PASSTHRU_BUFFER +- Added defines for bConnectionRate +- 007 SEF 10/15/03 Added Firmware Download Control Code and support +- Added CSMI revision support +- 008 SEF 10/30/03 No functional change, just updated version to track +- spec changes +- 009 SEF 12/09/03 No functional change, just updated version to track +- spec changes +- 010 SEF 3/11/04 Fixed typedef struct CSMI_SAS_RAID_DRIVES to include the +- bFirmware member that is defined in the spec, but +- was missing in this file, +- added CC_CSMI_SAS_TASK_MANAGEMENT +- 011 SEF 4/02/04 No functional change, added comment line before +- CC_CSMI_SAS_TASK_MANAGEMENT +- 012 SEF 4/16/04 Added IOControllerNumber to linux header, +- Modified linux control codes to have upper word of +- 0xCC77.... to indicate CSMI version 77 +- Added bSignalClass to CC_CSMI_SET_PHY_INFO +- Added CC_CSMI_SAS_PHY_CONTROL support +- 013 SEF 5/14/04 Added CC_CSMI_SAS_GET_CONNECTOR_INFO support +- 014 SEF 5/24/04 No functional change, just updated version to track spec +- changes +- 015 SEF 6/16/04 changed bPinout to uPinout to reflect proper size, +- changed width of bLocation defines to reflect size +- 016 SEF 6/17/04 changed bLengthOfControls in CSMI_SAS_PHY_CONTROL +- to be proper size +- 017 SEF 9/17/04 added CSMI_SAS_SATA_PORT_SELECTOR, +- CSMI_SAS_LINK_VIRTUAL, CSMI_SAS_CON_NOT_PRESENT, and +- CSMI_SAS_CON_NOT_CONNECTED +- 018 SEF 9/20/04 added CSMI_SAS_PHY_USER_PATTERN, +- changed definition of CSMI_SAS_PHY_FIXED_PATTERN to not +- conflict with activate definition +- 019 SEF 12/06/04 added CSMI_SAS_GET_LOCATION +- added bSSPStatus to CSMI_SAS_SSP_PASSTHRU_STATUS +- structure +- 020 SEF 5/25/05 added CSMI_SAS_PHY_VIRTUAL_SMP, and changes to +- CSMI_SAS_GET_LOCATION +- 021 SEF 11/03/05 added new RAID creation functionality +- 022 SEF 2/01/06 corrected typo bNegotitiatedLInkRate +- Added two more RAID_TYPES, 7 and 8 +- 023 SEF 4/04/06 added CSMI_RAID_TYPE_1E +- changed structures that contained surface scan +- to priority approach rather than time, causes +- 0.89 to incompatible with 0.87, so a version +- check is necessary when interpreting the +- raid structures +- Added netware section +- 024 DRG 5/22/06 Added uFailureCode to CSMI_SAS_RAID_CONFIG and +- CSMI_SAS_RAID_FEATURES +- Changed __u64 fields to high and low __u32 fields in +- order to avoid backward compatibility issues with +- packing and alignment. +- Fixed alignment problem in CSMI_SAS_RAID_DRIVES. +- Added CSMI_SAS_CNTLR_SMART_ARRAY to uControllerFlags +- Reassigned the value of CSMI_SAS_CNTLR_RAID_CFG_SUPPORT +- to avoid a conflict. +- +-**************************************************************************/ +- +-#ifndef _CSMI_SAS_H_ +-#define _CSMI_SAS_H_ +- +-// CSMI Specification Revision, the intent is that all versions of the +-// specification will be backward compatible after the 1.00 release. +-// Major revision number, corresponds to xxxx. of CSMI specification +-// Minor revision number, corresponds to .xxxx of CSMI specification +-#define CSMI_MAJOR_REVISION 0 +-#define CSMI_MINOR_REVISION 90 +- +-/*************************************************************************/ +-/* PATCHES FOR TYPOS */ +-/*************************************************************************/ +- +-#define bNegotitiatedLInkRate bNegotiatedLinkRate +- +-/*************************************************************************/ +-/* TARGET OS LINUX SPECIFIC CODE */ +-/*************************************************************************/ +- +-// EDM #ifdef _linux +-#ifdef __KERNEL__ +- +-// Linux base types +- +-#include <linux/types.h> +- +-#define __i8 char +- +-// pack definition +- +-// EDM #define CSMI_SAS_BEGIN_PACK(x) pack(x) +-// EDM #define CSMI_SAS_END_PACK pack() +- +-// IOCTL Control Codes +-// (IoctlHeader.ControlCode) +- +-// Control Codes prior to 0.77 +- +-// Control Codes requiring CSMI_ALL_SIGNATURE +- +-// #define CC_CSMI_SAS_GET_DRIVER_INFO 0x12345678 +-// #define CC_CSMI_SAS_GET_CNTLR_CONFIG 0x23456781 +-// #define CC_CSMI_SAS_GET_CNTLR_STATUS 0x34567812 +-// #define CC_CSMI_SAS_FIRMWARE_DOWNLOAD 0x92345678 +- +-// Control Codes requiring CSMI_RAID_SIGNATURE +- +-// #define CC_CSMI_SAS_GET_RAID_INFO 0x45678123 +-// #define CC_CSMI_SAS_GET_RAID_CONFIG 0x56781234 +- +-// Control Codes requiring CSMI_SAS_SIGNATURE +- +-// #define CC_CSMI_SAS_GET_PHY_INFO 0x67812345 +-// #define CC_CSMI_SAS_SET_PHY_INFO 0x78123456 +-// #define CC_CSMI_SAS_GET_LINK_ERRORS 0x81234567 +-// #define CC_CSMI_SAS_SMP_PASSTHRU 0xA1234567 +-// #define CC_CSMI_SAS_SSP_PASSTHRU 0xB1234567 +-// #define CC_CSMI_SAS_STP_PASSTHRU 0xC1234567 +-// #define CC_CSMI_SAS_GET_SATA_SIGNATURE 0xD1234567 +-// #define CC_CSMI_SAS_GET_SCSI_ADDRESS 0xE1234567 +-// #define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0xF1234567 +-// #define CC_CSMI_SAS_TASK_MANAGEMENT 0xA2345678 +- +-// Control Codes for 0.77 and later +- +-// Control Codes requiring CSMI_ALL_SIGNATURE +- +-#define CC_CSMI_SAS_GET_DRIVER_INFO 0xCC770001 +-#define CC_CSMI_SAS_GET_CNTLR_CONFIG 0xCC770002 +-#define CC_CSMI_SAS_GET_CNTLR_STATUS 0xCC770003 +-#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD 0xCC770004 +- +-// Control Codes requiring CSMI_RAID_SIGNATURE +- +-#define CC_CSMI_SAS_GET_RAID_INFO 0xCC77000A +-#define CC_CSMI_SAS_GET_RAID_CONFIG 0xCC77000B +-#define CC_CSMI_SAS_GET_RAID_FEATURES 0xCC77000C +-#define CC_CSMI_SAS_SET_RAID_CONTROL 0xCC77000D +-#define CC_CSMI_SAS_GET_RAID_ELEMENT 0xCC77000E +-#define CC_CSMI_SAS_SET_RAID_OPERATION 0xCC77000F +- +-// Control Codes requiring CSMI_SAS_SIGNATURE +- +-#define CC_CSMI_SAS_GET_PHY_INFO 0xCC770014 +-#define CC_CSMI_SAS_SET_PHY_INFO 0xCC770015 +-#define CC_CSMI_SAS_GET_LINK_ERRORS 0xCC770016 +-#define CC_CSMI_SAS_SMP_PASSTHRU 0xCC770017 +-#define CC_CSMI_SAS_SSP_PASSTHRU 0xCC770018 +-#define CC_CSMI_SAS_STP_PASSTHRU 0xCC770019 +-#define CC_CSMI_SAS_GET_SATA_SIGNATURE 0xCC770020 +-#define CC_CSMI_SAS_GET_SCSI_ADDRESS 0xCC770021 +-#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0xCC770022 +-#define CC_CSMI_SAS_TASK_MANAGEMENT 0xCC770023 +-#define CC_CSMI_SAS_GET_CONNECTOR_INFO 0xCC770024 +-#define CC_CSMI_SAS_GET_LOCATION 0xCC770025 +- +- +-// Control Codes requiring CSMI_PHY_SIGNATURE +- +-#define CC_CSMI_SAS_PHY_CONTROL 0xCC77003C +- +-// EDM #pragma CSMI_SAS_BEGIN_PACK(8) +-#pragma pack(8) +- +-// IOCTL_HEADER +-typedef struct _IOCTL_HEADER { +- __u32 IOControllerNumber; +- __u32 Length; +- __u32 ReturnCode; +- __u32 Timeout; +- __u16 Direction; +-} IOCTL_HEADER, +- *PIOCTL_HEADER; +- +-// EDM #pragma CSMI_SAS_END_PACK +-#pragma pack() +- +-#endif +- +-/*************************************************************************/ +-/* TARGET OS WINDOWS SPECIFIC CODE */ +-/*************************************************************************/ +- +-#ifdef _WIN32 +- +-// windows IOCTL definitions +- +-#ifndef _NTDDSCSIH_ +-#include <ntddscsi.h> +-#endif +- +-// pack definition +- +-#if defined _MSC_VER +- #define CSMI_SAS_BEGIN_PACK(x) pack(push,x) +- #define CSMI_SAS_END_PACK pack(pop) +-#elif defined __BORLANDC__ +- #define CSMI_SAS_BEGIN_PACK(x) option -a##x +- #define CSMI_SAS_END_PACK option -a. +-#else +- #error "CSMISAS.H - Must externally define a pack compiler designator." +-#endif +- +-// base types +- +-#define __u8 unsigned char +-#define __u16 unsigned short +-#define __u32 unsigned long +-#define __u64 unsigned __int64 +- +-#define __i8 char +- +-// IOCTL Control Codes +-// (IoctlHeader.ControlCode) +- +-// Control Codes requiring CSMI_ALL_SIGNATURE +- +-#define CC_CSMI_SAS_GET_DRIVER_INFO 1 +-#define CC_CSMI_SAS_GET_CNTLR_CONFIG 2 +-#define CC_CSMI_SAS_GET_CNTLR_STATUS 3 +-#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD 4 +- +-// Control Codes requiring CSMI_RAID_SIGNATURE +- +-#define CC_CSMI_SAS_GET_RAID_INFO 10 +-#define CC_CSMI_SAS_GET_RAID_CONFIG 11 +-#define CC_CSMI_SAS_GET_RAID_FEATURES 12 +-#define CC_CSMI_SAS_SET_RAID_CONTROL 13 +-#define CC_CSMI_SAS_GET_RAID_ELEMENT 14 +-#define CC_CSMI_SAS_SET_RAID_OPERATION 15 +- +-// Control Codes requiring CSMI_SAS_SIGNATURE +- +-#define CC_CSMI_SAS_GET_PHY_INFO 20 +-#define CC_CSMI_SAS_SET_PHY_INFO 21 +-#define CC_CSMI_SAS_GET_LINK_ERRORS 22 +-#define CC_CSMI_SAS_SMP_PASSTHRU 23 +-#define CC_CSMI_SAS_SSP_PASSTHRU 24 +-#define CC_CSMI_SAS_STP_PASSTHRU 25 +-#define CC_CSMI_SAS_GET_SATA_SIGNATURE 26 +-#define CC_CSMI_SAS_GET_SCSI_ADDRESS 27 +-#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 28 +-#define CC_CSMI_SAS_TASK_MANAGEMENT 29 +-#define CC_CSMI_SAS_GET_CONNECTOR_INFO 30 +-#define CC_CSMI_SAS_GET_LOCATION 31 +- +-// Control Codes requiring CSMI_PHY_SIGNATURE +- +-#define CC_CSMI_SAS_PHY_CONTROL 60 +- +-#define IOCTL_HEADER SRB_IO_CONTROL +-#define PIOCTL_HEADER PSRB_IO_CONTROL +- +-#endif +- +-/*************************************************************************/ +-/* TARGET OS NETWARE SPECIFIC CODE */ +-/*************************************************************************/ +- +-#ifdef _NETWARE +- +-// NetWare IOCTL definitions +- +-#define CSMI_SAS_BEGIN_PACK(x) pack(x) +-#define CSMI_SAS_END_PACK pack() +- +-#ifndef LONG +-typedef unsigned long LONG; +-#endif +- +-#ifndef WORD +-typedef unsigned short WORD; +-#endif +- +-#ifndef BYTE +-typedef unsigned char BYTE; +-#endif +- +-/* Need to have these definitions for Netware */ +-#define __u8 unsigned char +-#define __u16 unsigned short +-#define __u32 unsigned long +-#define __u64 unsigned __int64 +- +-#define __i8 char +- +- +-// EDM #pragma CSMI_SAS_BEGIN_PACK(8) +-#pragma pack(8) +- +-// IOCTL_HEADER +-typedef struct _IOCTL_HEADER { +- __u32 Length; +- __u32 ReturnCode; +-} IOCTL_HEADER, +- *PIOCTL_HEADER; +- +-// EDM #pragma CSMI_SAS_END_PACK +-#pragma pack() +- +-// IOCTL Control Codes +-// (IoctlHeader.ControlCode) +- +-// Control Codes requiring CSMI_ALL_SIGNATURE +- +-#define CC_CSMI_SAS_GET_DRIVER_INFO 0x01FF0001 +-#define CC_CSMI_SAS_GET_CNTLR_CONFIG 0x01FF0002 +-#define CC_CSMI_SAS_GET_CNTLR_STATUS 0x01FF0003 +-#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD 0x01FF0004 +- +-// Control Codes requiring CSMI_RAID_SIGNATURE +- +-#define CC_CSMI_SAS_GET_RAID_INFO 0x01FF000A +-#define CC_CSMI_SAS_GET_RAID_CONFIG 0x01FF000B +-#define CC_CSMI_SAS_GET_RAID_FEATURES 0x01FF000C +-#define CC_CSMI_SAS_SET_RAID_CONTROL 0x01FF000D +-#define CC_CSMI_SAS_GET_RAID_ELEMENT 0x01FF000E +-#define CC_CSMI_SAS_SET_RAID_OPERATION 0x01FF000F +- +-// Control Codes requiring CSMI_SAS_SIGNATURE +- +-#define CC_CSMI_SAS_GET_PHY_INFO 0x01FF0014 +-#define CC_CSMI_SAS_SET_PHY_INFO 0x01FF0015 +-#define CC_CSMI_SAS_GET_LINK_ERRORS 0x01FF0016 +-#define CC_CSMI_SAS_SMP_PASSTHRU 0x01FF0017 +-#define CC_CSMI_SAS_SSP_PASSTHRU 0x01FF0018 +-#define CC_CSMI_SAS_STP_PASSTHRU 0x01FF0019 +-#define CC_CSMI_SAS_GET_SATA_SIGNATURE 0x01FF001A +-#define CC_CSMI_SAS_GET_SCSI_ADDRESS 0x01FF001B +-#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0x01FF001C +-#define CC_CSMI_SAS_TASK_MANAGEMENT 0x01FF001D +-#define CC_CSMI_SAS_GET_CONNECTOR_INFO 0x01FF001E +-#define CC_CSMI_SAS_GET_LOCATION 0x01FF001F +- +-// Control Codes requiring CSMI_PHY_SIGNATURE +- +-#define CC_CSMI_SAS_PHY_CONTROL 60 +- +-#endif +- +-/*************************************************************************/ +-/* TARGET OS NOT DEFINED ERROR */ +-/*************************************************************************/ +- +-// EDM +-//#if (!_WIN32 && !_linux && !_NETWARE) +-// #error "Unknown target OS." +-//#endif +- +-/*************************************************************************/ +-/* OS INDEPENDENT CODE */ +-/*************************************************************************/ +- +-/* * * * * * * * * * Class Independent IOCTL Constants * * * * * * * * * */ +- +-// Return codes for all IOCTL's regardless of class +-// (IoctlHeader.ReturnCode) +- +-#define CSMI_SAS_STATUS_SUCCESS 0 +-#define CSMI_SAS_STATUS_FAILED 1 +-#define CSMI_SAS_STATUS_BAD_CNTL_CODE 2 +-#define CSMI_SAS_STATUS_INVALID_PARAMETER 3 +-#define CSMI_SAS_STATUS_WRITE_ATTEMPTED 4 +- +-// Signature value +-// (IoctlHeader.Signature) +- +-#define CSMI_ALL_SIGNATURE "CSMIALL" +- +-// Timeout value default of 60 seconds +-// (IoctlHeader.Timeout) +- +-#define CSMI_ALL_TIMEOUT 60 +- +-// Direction values for data flow on this IOCTL +-// (IoctlHeader.Direction, Linux only) +-#define CSMI_SAS_DATA_READ 0 +-#define CSMI_SAS_DATA_WRITE 1 +- +-// I/O Bus Types +-// ISA and EISA bus types are not supported +-// (bIoBusType) +- +-#define CSMI_SAS_BUS_TYPE_PCI 3 +-#define CSMI_SAS_BUS_TYPE_PCMCIA 4 +- +-// Controller Status +-// (uStatus) +- +-#define CSMI_SAS_CNTLR_STATUS_GOOD 1 +-#define CSMI_SAS_CNTLR_STATUS_FAILED 2 +-#define CSMI_SAS_CNTLR_STATUS_OFFLINE 3 +-#define CSMI_SAS_CNTLR_STATUS_POWEROFF 4 +- +-// Offline Status Reason +-// (uOfflineReason) +- +-#define CSMI_SAS_OFFLINE_REASON_NO_REASON 0 +-#define CSMI_SAS_OFFLINE_REASON_INITIALIZING 1 +-#define CSMI_SAS_OFFLINE_REASON_BACKSIDE_BUS_DEGRADED 2 +-#define CSMI_SAS_OFFLINE_REASON_BACKSIDE_BUS_FAILURE 3 +- +-// Controller Class +-// (bControllerClass) +- +-#define CSMI_SAS_CNTLR_CLASS_HBA 5 +- +-// Controller Flag bits +-// (uControllerFlags) +- +-#define CSMI_SAS_CNTLR_SAS_HBA 0x00000001 +-#define CSMI_SAS_CNTLR_SAS_RAID 0x00000002 +-#define CSMI_SAS_CNTLR_SATA_HBA 0x00000004 +-#define CSMI_SAS_CNTLR_SATA_RAID 0x00000008 +-#define CSMI_SAS_CNTLR_SMART_ARRAY 0x00000010 +- +-// for firmware download +-#define CSMI_SAS_CNTLR_FWD_SUPPORT 0x00010000 +-#define CSMI_SAS_CNTLR_FWD_ONLINE 0x00020000 +-#define CSMI_SAS_CNTLR_FWD_SRESET 0x00040000 +-#define CSMI_SAS_CNTLR_FWD_HRESET 0x00080000 +-#define CSMI_SAS_CNTLR_FWD_RROM 0x00100000 +- +-// for RAID configuration supported +-#define CSMI_SAS_CNTLR_RAID_CFG_SUPPORT 0x01000000 +- +-// Download Flag bits +-// (uDownloadFlags) +-#define CSMI_SAS_FWD_VALIDATE 0x00000001 +-#define CSMI_SAS_FWD_SOFT_RESET 0x00000002 +-#define CSMI_SAS_FWD_HARD_RESET 0x00000004 +- +-// Firmware Download Status +-// (usStatus) +-#define CSMI_SAS_FWD_SUCCESS 0 +-#define CSMI_SAS_FWD_FAILED 1 +-#define CSMI_SAS_FWD_USING_RROM 2 +-#define CSMI_SAS_FWD_REJECT 3 +-#define CSMI_SAS_FWD_DOWNREV 4 +- +-// Firmware Download Severity +-// (usSeverity> +-#define CSMI_SAS_FWD_INFORMATION 0 +-#define CSMI_SAS_FWD_WARNING 1 +-#define CSMI_SAS_FWD_ERROR 2 +-#define CSMI_SAS_FWD_FATAL 3 +- +-/* * * * * * * * * * SAS RAID Class IOCTL Constants * * * * * * * * */ +- +-// Return codes for the RAID IOCTL's regardless of class +-// (IoctlHeader.ReturnCode) +- +-#define CSMI_SAS_RAID_SET_OUT_OF_RANGE 1000 +-#define CSMI_SAS_RAID_SET_BUFFER_TOO_SMALL 1001 +-#define CSMI_SAS_RAID_SET_DATA_CHANGED 1002 +- +-// Signature value +-// (IoctlHeader.Signature) +- +-#define CSMI_RAID_SIGNATURE "CSMIARY" +- +-// Timeout value default of 60 seconds +-// (IoctlHeader.Timeout) +- +-#define CSMI_RAID_TIMEOUT 60 +- +-// RAID Types +-// (bRaidType) +-#define CSMI_SAS_RAID_TYPE_NONE 0 +-#define CSMI_SAS_RAID_TYPE_0 1 +-#define CSMI_SAS_RAID_TYPE_1 2 +-#define CSMI_SAS_RAID_TYPE_10 3 +-#define CSMI_SAS_RAID_TYPE_5 4 +-#define CSMI_SAS_RAID_TYPE_15 5 +-#define CSMI_SAS_RAID_TYPE_6 6 +-#define CSMI_SAS_RAID_TYPE_50 7 +-#define CSMI_SAS_RAID_TYPE_VOLUME 8 +-#define CSMI_SAS_RAID_TYPE_1E 9 +-#define CSMI_SAS_RAID_TYPE_OTHER 255 +-// the last value 255 was already defined for other +-// so end is defined as 254 +-#define CSMI_SAS_RAID_TYPE_END 254 +- +-// RAID Status +-// (bStatus) +-#define CSMI_SAS_RAID_SET_STATUS_OK 0 +-#define CSMI_SAS_RAID_SET_STATUS_DEGRADED 1 +-#define CSMI_SAS_RAID_SET_STATUS_REBUILDING 2 +-#define CSMI_SAS_RAID_SET_STATUS_FAILED 3 +-#define CSMI_SAS_RAID_SET_STATUS_OFFLINE 4 +-#define CSMI_SAS_RAID_SET_STATUS_TRANSFORMING 5 +-#define CSMI_SAS_RAID_SET_STATUS_QUEUED_FOR_REBUILD 6 +-#define CSMI_SAS_RAID_SET_STATUS_QUEUED_FOR_TRANSFORMATION 7 +- +-// RAID Drive Count +-// (bDriveCount, 0xF1 to 0xFF are reserved) +-#define CSMI_SAS_RAID_DRIVE_COUNT_TOO_BIG 0xF1 +-#define CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED 0xF2 +- +-// RAID Data Type +-// (bDataType) +-#define CSMI_SAS_RAID_DATA_DRIVES 0 +-#define CSMI_SAS_RAID_DATA_DEVICE_ID 1 +-#define CSMI_SAS_RAID_DATA_ADDITIONAL_DATA 2 +- +-// RAID Drive Status +-// (bDriveStatus) +-#define CSMI_SAS_DRIVE_STATUS_OK 0 +-#define CSMI_SAS_DRIVE_STATUS_REBUILDING 1 +-#define CSMI_SAS_DRIVE_STATUS_FAILED 2 +-#define CSMI_SAS_DRIVE_STATUS_DEGRADED 3 +-#define CSMI_SAS_DRIVE_STATUS_OFFLINE 4 +-#define CSMI_SAS_DRIVE_STATUS_QUEUED_FOR_REBUILD 5 +- +-// RAID Drive Usage +-// (bDriveUsage) +-#define CSMI_SAS_DRIVE_CONFIG_NOT_USED 0 +-#define CSMI_SAS_DRIVE_CONFIG_MEMBER 1 +-#define CSMI_SAS_DRIVE_CONFIG_SPARE 2 +-#define CSMI_SAS_DRIVE_CONFIG_SPARE_ACTIVE 3 +- +-// RAID Drive Type +-// (bDriveType) +-#define CSMI_SAS_DRIVE_TYPE_UNKNOWN 0 +-#define CSMI_SAS_DRIVE_TYPE_SINGLE_PORT_SAS 1 +-#define CSMI_SAS_DRIVE_TYPE_DUAL_PORT_SAS 2 +-#define CSMI_SAS_DRIVE_TYPE_SATA 3 +-#define CSMI_SAS_DRIVE_TYPE_SATA_PS 4 +-#define CSMI_SAS_DRIVE_TYPE_OTHER 255 +- +-// RAID Write Protect +-// (bWriteProtect) +-#define CSMI_SAS_RAID_SET_WRITE_PROTECT_UNKNOWN 0 +-#define CSMI_SAS_RAID_SET_WRITE_PROTECT_UNCHANGED 0 +-#define CSMI_SAS_RAID_SET_WRITE_PROTECT_ENABLED 1 +-#define CSMI_SAS_RAID_SET_WRITE_PROTECT_DISABLED 2 +- +-// RAID Cache Setting +-// (bCacheSetting) +-#define CSMI_SAS_RAID_SET_CACHE_UNKNOWN 0 +-#define CSMI_SAS_RAID_SET_CACHE_UNCHANGED 0 +-#define CSMI_SAS_RAID_SET_CACHE_ENABLED 1 +-#define CSMI_SAS_RAID_SET_CACHE_DISABLED 2 +-#define CSMI_SAS_RAID_SET_CACHE_CORRUPT 3 +- +-// RAID Features +-// (uFeatures) +-#define CSMI_SAS_RAID_FEATURE_TRANSFORMATION 0x00000001 +-#define CSMI_SAS_RAID_FEATURE_REBUILD 0x00000002 +-#define CSMI_SAS_RAID_FEATURE_SPLIT_MIRROR 0x00000004 +-#define CSMI_SAS_RAID_FEATURE_MERGE_MIRROR 0x00000008 +-#define CSMI_SAS_RAID_FEATURE_LUN_RENUMBER 0x00000010 +-#define CSMI_SAS_RAID_FEATURE_SURFACE_SCAN 0x00000020 +-#define CSMI_SAS_RAID_FEATURE_SPARES_SHARED 0x00000040 +- +-// RAID Priority +-// (bDefaultTransformPriority, etc.) +-#define CSMI_SAS_PRIORITY_UNKNOWN 0 +-#define CSMI_SAS_PRIORITY_UNCHANGED 0 +-#define CSMI_SAS_PRIORITY_AUTO 1 +-#define CSMI_SAS_PRIORITY_OFF 2 +-#define CSMI_SAS_PRIORITY_LOW 3 +-#define CSMI_SAS_PRIORITY_MEDIUM 4 +-#define CSMI_SAS_PRIORITY_HIGH 5 +- +-// RAID Transformation Rules +-// (uRaidSetTransformationRules) +-#define CSMI_SAS_RAID_RULE_AVAILABLE_MEMORY 0x00000001 +-#define CSMI_SAS_RAID_RULE_OVERLAPPED_EXTENTS 0x00000002 +- +-// RAID Cache Ratios Supported +-// (bCacheRatiosSupported) +-// from 0 to 100 defines the write to read ratio, 0 is 100% write +-#define CSMI_SAS_RAID_CACHE_RATIO_RANGE 101 +-#define CSMI_SAS_RAID_CACHE_RATIO_FIXED 102 +-#define CSMI_SAS_RAID_CACHE_RATIO_AUTO 103 +-#define CSMI_SAS_RAID_CACHE_RATIO_END 255 +- +-// RAID Cache Ratio Flag +-// (bCacheRatioFlag) +-#define CSMI_SAS_RAID_CACHE_RATIO_DISABLE 0 +-#define CSMI_SAS_RAID_CACHE_RATIO_ENABLE 1 +- +-// RAID Clear Configuration Signature +-// (bClearConfiguration) +-#define CSMI_SAS_RAID_CLEAR_CONFIGURATION_SIGNATURE "RAIDCLR" +- +-// RAID Failure Codes +-// (uFailureCode) +-#define CSMI_SAS_FAIL_CODE_OK 0 +-#define CSMI_SAS_FAIL_CODE_PARAMETER_INVALID 1000 +-#define CSMI_SAS_FAIL_CODE_TRANSFORM_PRIORITY_INVALID 1001 +-#define CSMI_SAS_FAIL_CODE_REBUILD_PRIORITY_INVALID 1002 +-#define CSMI_SAS_FAIL_CODE_CACHE_RATIO_INVALID 1003 +-#define CSMI_SAS_FAIL_CODE_SURFACE_SCAN_INVALID 1004 +-#define CSMI_SAS_FAIL_CODE_CLEAR_CONFIGURATION_INVALID 1005 +-#define CSMI_SAS_FAIL_CODE_ELEMENT_INDEX_INVALID 1006 +-#define CSMI_SAS_FAIL_CODE_SUBELEMENT_INDEX_INVALID 1007 +-#define CSMI_SAS_FAIL_CODE_EXTENT_INVALID 1008 +-#define CSMI_SAS_FAIL_CODE_BLOCK_COUNT_INVALID 1009 +-#define CSMI_SAS_FAIL_CODE_DRIVE_INDEX_INVALID 1010 +-#define CSMI_SAS_FAIL_CODE_EXISTING_LUN_INVALID 1011 +-#define CSMI_SAS_FAIL_CODE_RAID_TYPE_INVALID 1012 +-#define CSMI_SAS_FAIL_CODE_STRIPE_SIZE_INVALID 1013 +-#define CSMI_SAS_FAIL_CODE_TRANSFORMATION_INVALID 1014 +-#define CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID 1015 +-#define CSMI_SAS_FAIL_CODE_ENUMERATION_TYPE_INVALID 1016 +- +-#define CSMI_SAS_FAIL_CODE_EXCEEDED_RAID_SET_COUNT 2000 +-#define CSMI_SAS_FAIL_CODE_DUPLICATE_LUN 2001 +- +-#define CSMI_SAS_FAIL_CODE_WAIT_FOR_OPERATION 3000 +- +-// RAID Enumeration Types +-// (uEnumerationType) +-#define CSMI_SAS_RAID_ELEMENT_TYPE_DRIVE 0 +-#define CSMI_SAS_RAID_ELEMENT_TYPE_MODULE 1 +-#define CSMI_SAS_RAID_ELEMENT_TYPE_DRIVE_RAID_SET 2 +-#define CSMI_SAS_RAID_ELEMENT_TYPE_EXTENT_DRIVE 3 +- +-// RAID Extent Types +-// (bExtentType) +-#define CSMI_SAS_RAID_EXTENT_RESERVED 0 +-#define CSMI_SAS_RAID_EXTENT_METADATA 1 +-#define CSMI_SAS_RAID_EXTENT_ALLOCATED 2 +-#define CSMI_SAS_RAID_EXTENT_UNALLOCATED 3 +- +-// RAID Operation Types +-// (uOperationType) +-#define CSMI_SAS_RAID_SET_CREATE 0 +-#define CSMI_SAS_RAID_SET_LABEL 1 +-#define CSMI_SAS_RAID_SET_TRANSFORM 2 +-#define CSMI_SAS_RAID_SET_DELETE 3 +-#define CSMI_SAS_RAID_SET_WRITE_PROTECT 4 +-#define CSMI_SAS_RAID_SET_CACHE 5 +-#define CSMI_SAS_RAID_SET_ONLINE_STATE 6 +-#define CSMI_SAS_RAID_SET_SPARE 7 +- +-// RAID Transform Types +-// (bTransformType) +-#define CSMI_SAS_RAID_SET_TRANSFORM_SPLIT_MIRROR 0 +-#define CSMI_SAS_RAID_SET_TRANSFORM_MERGE_RAID_0 1 +-#define CSMI_SAS_RAID_SET_TRANSFORM_LUN_RENUMBER 2 +-#define CSMI_SAS_RAID_SET_TRANSFORM_RAID_SET 3 +- +-// RAID Online State +-// (bOnlineState) +-#define CSMI_SAS_RAID_SET_STATE_UNKNOWN 0 +-#define CSMI_SAS_RAID_SET_STATE_ONLINE 1 +-#define CSMI_SAS_RAID_SET_STATE_OFFLINE 2 +- +-/* * * * * * * * * * SAS HBA Class IOCTL Constants * * * * * * * * * */ +- +-// Return codes for SAS IOCTL's +-// (IoctlHeader.ReturnCode) +- +-#define CSMI_SAS_PHY_INFO_CHANGED CSMI_SAS_STATUS_SUCCESS +-#define CSMI_SAS_PHY_INFO_NOT_CHANGEABLE 2000 +-#define CSMI_SAS_LINK_RATE_OUT_OF_RANGE 2001 +- +-#define CSMI_SAS_PHY_DOES_NOT_EXIST 2002 +-#define CSMI_SAS_PHY_DOES_NOT_MATCH_PORT 2003 +-#define CSMI_SAS_PHY_CANNOT_BE_SELECTED 2004 +-#define CSMI_SAS_SELECT_PHY_OR_PORT 2005 +-#define CSMI_SAS_PORT_DOES_NOT_EXIST 2006 +-#define CSMI_SAS_PORT_CANNOT_BE_SELECTED 2007 +-#define CSMI_SAS_CONNECTION_FAILED 2008 +- +-#define CSMI_SAS_NO_SATA_DEVICE 2009 +-#define CSMI_SAS_NO_SATA_SIGNATURE 2010 +-#define CSMI_SAS_SCSI_EMULATION 2011 +-#define CSMI_SAS_NOT_AN_END_DEVICE 2012 +-#define CSMI_SAS_NO_SCSI_ADDRESS 2013 +-#define CSMI_SAS_NO_DEVICE_ADDRESS 2014 +- +-// Signature value +-// (IoctlHeader.Signature) +- +-#define CSMI_SAS_SIGNATURE "CSMISAS" +- +-// Timeout value default of 60 seconds +-// (IoctlHeader.Timeout) +- +-#define CSMI_SAS_TIMEOUT 60 +- +-// Device types +-// (bDeviceType) +- +-#define CSMI_SAS_PHY_UNUSED 0x00 +-#define CSMI_SAS_NO_DEVICE_ATTACHED 0x00 +-#define CSMI_SAS_END_DEVICE 0x10 +-#define CSMI_SAS_EDGE_EXPANDER_DEVICE 0x20 +-#define CSMI_SAS_FANOUT_EXPANDER_DEVICE 0x30 +- +-// Protocol options +-// (bInitiatorPortProtocol, bTargetPortProtocol) +- +-#define CSMI_SAS_PROTOCOL_SATA 0x01 +-#define CSMI_SAS_PROTOCOL_SMP 0x02 +-#define CSMI_SAS_PROTOCOL_STP 0x04 +-#define CSMI_SAS_PROTOCOL_SSP 0x08 +- +-// Negotiated and hardware link rates +-// (bNegotiatedLinkRate, bMinimumLinkRate, bMaximumLinkRate) +- +-#define CSMI_SAS_LINK_RATE_UNKNOWN 0x00 +-#define CSMI_SAS_PHY_DISABLED 0x01 +-#define CSMI_SAS_LINK_RATE_FAILED 0x02 +-#define CSMI_SAS_SATA_SPINUP_HOLD 0x03 +-#define CSMI_SAS_SATA_PORT_SELECTOR 0x04 +-#define CSMI_SAS_LINK_RATE_1_5_GBPS 0x08 +-#define CSMI_SAS_LINK_RATE_3_0_GBPS 0x09 +-#define CSMI_SAS_LINK_VIRTUAL 0x10 +- +-// Discover state +-// (bAutoDiscover) +- +-#define CSMI_SAS_DISCOVER_NOT_SUPPORTED 0x00 +-#define CSMI_SAS_DISCOVER_NOT_STARTED 0x01 +-#define CSMI_SAS_DISCOVER_IN_PROGRESS 0x02 +-#define CSMI_SAS_DISCOVER_COMPLETE 0x03 +-#define CSMI_SAS_DISCOVER_ERROR 0x04 +- +-// Phy features +- +-#define CSMI_SAS_PHY_VIRTUAL_SMP 0x01 +- +-// Programmed link rates +-// (bMinimumLinkRate, bMaximumLinkRate) +-// (bProgrammedMinimumLinkRate, bProgrammedMaximumLinkRate) +- +-#define CSMI_SAS_PROGRAMMED_LINK_RATE_UNCHANGED 0x00 +-#define CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS 0x08 +-#define CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS 0x09 +- +-// Link rate +-// (bNegotiatedLinkRate in CSMI_SAS_SET_PHY_INFO) +- +-#define CSMI_SAS_LINK_RATE_NEGOTIATE 0x00 +-#define CSMI_SAS_LINK_RATE_PHY_DISABLED 0x01 +- +-// Signal class +-// (bSignalClass in CSMI_SAS_SET_PHY_INFO) +- +-#define CSMI_SAS_SIGNAL_CLASS_UNKNOWN 0x00 +-#define CSMI_SAS_SIGNAL_CLASS_DIRECT 0x01 +-#define CSMI_SAS_SIGNAL_CLASS_SERVER 0x02 +-#define CSMI_SAS_SIGNAL_CLASS_ENCLOSURE 0x03 +- +-// Link error reset +-// (bResetCounts) +- +-#define CSMI_SAS_LINK_ERROR_DONT_RESET_COUNTS 0x00 +-#define CSMI_SAS_LINK_ERROR_RESET_COUNTS 0x01 +- +-// Phy identifier +-// (bPhyIdentifier) +- +-#define CSMI_SAS_USE_PORT_IDENTIFIER 0xFF +- +-// Port identifier +-// (bPortIdentifier) +- +-#define CSMI_SAS_IGNORE_PORT 0xFF +- +-// Programmed link rates +-// (bConnectionRate) +- +-#define CSMI_SAS_LINK_RATE_NEGOTIATED 0x00 +-#define CSMI_SAS_LINK_RATE_1_5_GBPS 0x08 +-#define CSMI_SAS_LINK_RATE_3_0_GBPS 0x09 +- +-// Connection status +-// (bConnectionStatus) +- +-#define CSMI_SAS_OPEN_ACCEPT 0 +-#define CSMI_SAS_OPEN_REJECT_BAD_DESTINATION 1 +-#define CSMI_SAS_OPEN_REJECT_RATE_NOT_SUPPORTED 2 +-#define CSMI_SAS_OPEN_REJECT_NO_DESTINATION 3 +-#define CSMI_SAS_OPEN_REJECT_PATHWAY_BLOCKED 4 +-#define CSMI_SAS_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED 5 +-#define CSMI_SAS_OPEN_REJECT_RESERVE_ABANDON 6 +-#define CSMI_SAS_OPEN_REJECT_RESERVE_CONTINUE 7 +-#define CSMI_SAS_OPEN_REJECT_RESERVE_INITIALIZE 8 +-#define CSMI_SAS_OPEN_REJECT_RESERVE_STOP 9 +-#define CSMI_SAS_OPEN_REJECT_RETRY 10 +-#define CSMI_SAS_OPEN_REJECT_STP_RESOURCES_BUSY 11 +-#define CSMI_SAS_OPEN_REJECT_WRONG_DESTINATION 12 +- +-// SSP Status +-// (bSSPStatus) +- +-#define CSMI_SAS_SSP_STATUS_UNKNOWN 0x00 +-#define CSMI_SAS_SSP_STATUS_WAITING 0x01 +-#define CSMI_SAS_SSP_STATUS_COMPLETED 0x02 +-#define CSMI_SAS_SSP_STATUS_FATAL_ERROR 0x03 +-#define CSMI_SAS_SSP_STATUS_RETRY 0x04 +-#define CSMI_SAS_SSP_STATUS_NO_TAG 0x05 +- +-// SSP Flags +-// (uFlags) +- +-#define CSMI_SAS_SSP_READ 0x00000001 +-#define CSMI_SAS_SSP_WRITE 0x00000002 +-#define CSMI_SAS_SSP_UNSPECIFIED 0x00000004 +- +-#define CSMI_SAS_SSP_TASK_ATTRIBUTE_SIMPLE 0x00000000 +-#define CSMI_SAS_SSP_TASK_ATTRIBUTE_HEAD_OF_QUEUE 0x00000010 +-#define CSMI_SAS_SSP_TASK_ATTRIBUTE_ORDERED 0x00000020 +-#define CSMI_SAS_SSP_TASK_ATTRIBUTE_ACA 0x00000040 +- +-// SSP Data present +-// (bDataPresent) +- +-#define CSMI_SAS_SSP_NO_DATA_PRESENT 0x00 +-#define CSMI_SAS_SSP_RESPONSE_DATA_PRESENT 0x01 +-#define CSMI_SAS_SSP_SENSE_DATA_PRESENT 0x02 +- +-// STP Flags +-// (uFlags) +- +-#define CSMI_SAS_STP_READ 0x00000001 +-#define CSMI_SAS_STP_WRITE 0x00000002 +-#define CSMI_SAS_STP_UNSPECIFIED 0x00000004 +-#define CSMI_SAS_STP_PIO 0x00000010 +-#define CSMI_SAS_STP_DMA 0x00000020 +-#define CSMI_SAS_STP_PACKET 0x00000040 +-#define CSMI_SAS_STP_DMA_QUEUED 0x00000080 +-#define CSMI_SAS_STP_EXECUTE_DIAG 0x00000100 +-#define CSMI_SAS_STP_RESET_DEVICE 0x00000200 +- +-// Task Management Flags +-// (uFlags) +- +-#define CSMI_SAS_TASK_IU 0x00000001 +-#define CSMI_SAS_HARD_RESET_SEQUENCE 0x00000002 +-#define CSMI_SAS_SUPPRESS_RESULT 0x00000004 +- +-// Task Management Functions +-// (bTaskManagement) +- +-#define CSMI_SAS_SSP_ABORT_TASK 0x01 +-#define CSMI_SAS_SSP_ABORT_TASK_SET 0x02 +-#define CSMI_SAS_SSP_CLEAR_TASK_SET 0x04 +-#define CSMI_SAS_SSP_LOGICAL_UNIT_RESET 0x08 +-#define CSMI_SAS_SSP_CLEAR_ACA 0x40 +-#define CSMI_SAS_SSP_QUERY_TASK 0x80 +- +-// Task Management Information +-// (uInformation) +- +-#define CSMI_SAS_SSP_TEST 1 +-#define CSMI_SAS_SSP_EXCEEDED 2 +-#define CSMI_SAS_SSP_DEMAND 3 +-#define CSMI_SAS_SSP_TRIGGER 4 +- +-// Connector Pinout Information +-// (uPinout) +- +-#define CSMI_SAS_CON_UNKNOWN 0x00000001 +-#define CSMI_SAS_CON_SFF_8482 0x00000002 +-#define CSMI_SAS_CON_SFF_8470_LANE_1 0x00000100 +-#define CSMI_SAS_CON_SFF_8470_LANE_2 0x00000200 +-#define CSMI_SAS_CON_SFF_8470_LANE_3 0x00000400 +-#define CSMI_SAS_CON_SFF_8470_LANE_4 0x00000800 +-#define CSMI_SAS_CON_SFF_8484_LANE_1 0x00010000 +-#define CSMI_SAS_CON_SFF_8484_LANE_2 0x00020000 +-#define CSMI_SAS_CON_SFF_8484_LANE_3 0x00040000 +-#define CSMI_SAS_CON_SFF_8484_LANE_4 0x00080000 +- +-// Connector Location Information +-// (bLocation) +- +-// same as uPinout above... +-// #define CSMI_SAS_CON_UNKNOWN 0x01 +-#define CSMI_SAS_CON_INTERNAL 0x02 +-#define CSMI_SAS_CON_EXTERNAL 0x04 +-#define CSMI_SAS_CON_SWITCHABLE 0x08 +-#define CSMI_SAS_CON_AUTO 0x10 +-#define CSMI_SAS_CON_NOT_PRESENT 0x20 +-#define CSMI_SAS_CON_NOT_CONNECTED 0x80 +- +-// Device location identification +-// (bIdentify) +- +-#define CSMI_SAS_LOCATE_UNKNOWN 0x00 +-#define CSMI_SAS_LOCATE_FORCE_OFF 0x01 +-#define CSMI_SAS_LOCATE_FORCE_ON 0x02 +- +-// Location Valid flags +-// (uLocationFlags) +- +-#define CSMI_SAS_LOCATE_SAS_ADDRESS_VALID 0x00000001 +-#define CSMI_SAS_LOCATE_SAS_LUN_VALID 0x00000002 +-#define CSMI_SAS_LOCATE_ENCLOSURE_IDENTIFIER_VALID 0x00000004 +-#define CSMI_SAS_LOCATE_ENCLOSURE_NAME_VALID 0x00000008 +-#define CSMI_SAS_LOCATE_BAY_PREFIX_VALID 0x00000010 +-#define CSMI_SAS_LOCATE_BAY_IDENTIFIER_VALID 0x00000020 +-#define CSMI_SAS_LOCATE_LOCATION_STATE_VALID 0x00000040 +- +-/* * * * * * * * SAS Phy Control Class IOCTL Constants * * * * * * * * */ +- +-// Return codes for SAS Phy Control IOCTL's +-// (IoctlHeader.ReturnCode) +- +-// Signature value +-// (IoctlHeader.Signature) +- +-#define CSMI_PHY_SIGNATURE "CSMIPHY" +- +-// Phy Control Functions +-// (bFunction) +- +-// values 0x00 to 0xFF are consistent in definition with the SMP PHY CONTROL +-// function defined in the SAS spec +-#define CSMI_SAS_PC_NOP 0x00000000 +-#define CSMI_SAS_PC_LINK_RESET 0x00000001 +-#define CSMI_SAS_PC_HARD_RESET 0x00000002 +-#define CSMI_SAS_PC_PHY_DISABLE 0x00000003 +-// 0x04 to 0xFF reserved... +-#define CSMI_SAS_PC_GET_PHY_SETTINGS 0x00000100 +- +-// Link Flags +-#define CSMI_SAS_PHY_ACTIVATE_CONTROL 0x00000001 +-#define CSMI_SAS_PHY_UPDATE_SPINUP_RATE 0x00000002 +-#define CSMI_SAS_PHY_AUTO_COMWAKE 0x00000004 +- +-// Device Types for Phy Settings +-// (bType) +-#define CSMI_SAS_UNDEFINED 0x00 +-#define CSMI_SAS_SATA 0x01 +-#define CSMI_SAS_SAS 0x02 +- +-// Transmitter Flags +-// (uTransmitterFlags) +-#define CSMI_SAS_PHY_PREEMPHASIS_DISABLED 0x00000001 +- +-// Receiver Flags +-// (uReceiverFlags) +-#define CSMI_SAS_PHY_EQUALIZATION_DISABLED 0x00000001 +- +-// Pattern Flags +-// (uPatternFlags) +-// #define CSMI_SAS_PHY_ACTIVATE_CONTROL 0x00000001 +-#define CSMI_SAS_PHY_DISABLE_SCRAMBLING 0x00000002 +-#define CSMI_SAS_PHY_DISABLE_ALIGN 0x00000004 +-#define CSMI_SAS_PHY_DISABLE_SSC 0x00000008 +- +-#define CSMI_SAS_PHY_FIXED_PATTERN 0x00000010 +-#define CSMI_SAS_PHY_USER_PATTERN 0x00000020 +- +-// Fixed Patterns +-// (bFixedPattern) +-#define CSMI_SAS_PHY_CJPAT 0x00000001 +-#define CSMI_SAS_PHY_ALIGN 0x00000002 +- +-// Type Flags +-// (bTypeFlags) +-#define CSMI_SAS_PHY_POSITIVE_DISPARITY 0x01 +-#define CSMI_SAS_PHY_NEGATIVE_DISPARITY 0x02 +-#define CSMI_SAS_PHY_CONTROL_CHARACTER 0x04 +- +-// Miscellaneous +-#define SLOT_NUMBER_UNKNOWN 0xFFFF +- +-/*************************************************************************/ +-/* DATA STRUCTURES */ +-/*************************************************************************/ +- +-/* * * * * * * * * * Class Independent Structures * * * * * * * * * */ +- +-// EDM #pragma CSMI_SAS_BEGIN_PACK(8) +-#pragma pack(8) +- +-// CC_CSMI_SAS_DRIVER_INFO +- +-typedef struct _CSMI_SAS_DRIVER_INFO { +- __u8 szName[81]; +- __u8 szDescription[81]; +- __u16 usMajorRevision; +- __u16 usMinorRevision; +- __u16 usBuildRevision; +- __u16 usReleaseRevision; +- __u16 usCSMIMajorRevision; +- __u16 usCSMIMinorRevision; +-} CSMI_SAS_DRIVER_INFO, +- *PCSMI_SAS_DRIVER_INFO; +- +-typedef struct _CSMI_SAS_DRIVER_INFO_BUFFER { +- IOCTL_HEADER IoctlHeader; +- CSMI_SAS_DRIVER_INFO Information; +-} CSMI_SAS_DRIVER_INFO_BUFFER, +- *PCSMI_SAS_DRIVER_INFO_BUFFER; +- +-// CC_CSMI_SAS_CNTLR_CONFIGURATION +- +-typedef struct _CSMI_SAS_PCI_BUS_ADDRESS { +- __u8 bBusNumber; +- __u8 bDeviceNumber; +- __u8 bFunctionNumber; +- __u8 bReserved; +-} CSMI_SAS_PCI_BUS_ADDRESS, +- *PCSMI_SAS_PCI_BUS_ADDRESS; +- +-typedef union _CSMI_SAS_IO_BUS_ADDRESS { +- CSMI_SAS_PCI_BUS_ADDRESS PciAddress; +- __u8 bReserved[32]; +-} CSMI_SAS_IO_BUS_ADDRESS, +- *PCSMI_SAS_IO_BUS_ADDRESS; +- +-typedef struct _CSMI_SAS_CNTLR_CONFIG { +- __u32 uBaseIoAddress; +- struct { +- __u32 uLowPart; +- __u32 uHighPart; +- } BaseMemoryAddress; +- __u32 uBoardID; +- __u16 usSlotNumber; +- __u8 bControllerClass; +- __u8 bIoBusType; +- CSMI_SAS_IO_BUS_ADDRESS BusAddress; +- __u8 szSerialNumber[81]; +- __u16 usMajorRevision; +- __u16 usMinorRevision; +- __u16 usBuildRevision; +- __u16 usReleaseRevision; +- __u16 usBIOSMajorRevision; +- __u16 usBIOSMinorRevision; +- __u16 usBIOSBuildRevision; +- __u16 usBIOSReleaseRevision; +- __u32 uControllerFlags; +- __u16 usRromMajorRevision; +- __u16 usRromMinorRevision; +- __u16 usRromBuildRevision; +- __u16 usRromReleaseRevision; +- __u16 usRromBIOSMajorRevision; +- __u16 usRromBIOSMinorRevision; +- __u16 usRromBIOSBuildRevision; +- __u16 usRromBIOSReleaseRevision; +- __u8 bReserved[7]; +-} CSMI_SAS_CNTLR_CONFIG, +- *PCSMI_SAS_CNTLR_CONFIG; +- +-typedef struct _CSMI_SAS_CNTLR_CONFIG_BUFFER { +- IOCTL_HEADER IoctlHeader; +- CSMI_SAS_CNTLR_CONFIG Configuration; +-} CSMI_SAS_CNTLR_CONFIG_BUFFER, +- *PCSMI_SAS_CNTLR_CONFIG_BUFFER; +- +-// CC_CSMI_SAS_CNTLR_STATUS +- +-typedef struct _CSMI_SAS_CNTLR_STATUS { +- __u32 uStatus; +- __u32 uOfflineReason; +- __u8 bReserved[28]; +-} CSMI_SAS_CNTLR_STATUS, +- *PCSMI_SAS_CNTLR_STATUS; +- +-typedef struct _CSMI_SAS_CNTLR_STATUS_BUFFER { +- IOCTL_HEADER IoctlHeader; +- CSMI_SAS_CNTLR_STATUS Status; +-} CSMI_SAS_CNTLR_STATUS_BUFFER, +- *PCSMI_SAS_CNTLR_STATUS_BUFFER; +- +-// CC_CSMI_SAS_FIRMWARE_DOWNLOAD +- +-typedef struct _CSMI_SAS_FIRMWARE_DOWNLOAD { +- __u32 uBufferLength; +- __u32 uDownloadFlags; +- __u8 bReserved[32]; +- __u16 usStatus; +- __u16 usSeverity; +-} CSMI_SAS_FIRMWARE_DOWNLOAD, +- *PCSMI_SAS_FIRMWARE_DOWNLOAD; +- +-typedef struct _CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER { +- IOCTL_HEADER IoctlHeader; +- CSMI_SAS_FIRMWARE_DOWNLOAD Information; +- __u8 bDataBuffer[1]; +-} CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER, +- *PCSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER; +- +-// CC_CSMI_SAS_RAID_INFO +- +-typedef struct _CSMI_SAS_RAID_INFO { +- __u32 uNumRaidSets; +- __u32 uMaxDrivesPerSet; +- __u32 uMaxRaidSets; +- __u8 bMaxRaidTypes; +- __u8 bReservedByteFields[7]; +- struct +- { +- __u32 uLowPart; +- __u32 uHighPart; +- } ulMinRaidSetBlocks; +- struct +- { +- __u32 uLowPart; +- __u32 uHighPart; +- } ulMaxRaidSetBlocks; +- __u32 uMaxPhysicalDrives; +- __u32 uMaxExtents; +- __u32 uMaxModules; +- __u32 uMaxTransformationMemory; +- __u32 uChangeCount; +- __u8 bReserved[44]; +-} CSMI_SAS_RAID_INFO, +- *PCSMI_SAS_RAID_INFO; +- +-typedef struct _CSMI_SAS_RAID_INFO_BUFFER { +- IOCTL_HEADER IoctlHeader; +- CSMI_SAS_RAID_INFO Information; +-} CSMI_SAS_RAID_INFO_BUFFER, +- *PCSMI_SAS_RAID_INFO_BUFFER; +- +-// CC_CSMI_SAS_GET_RAID_CONFIG +- +-typedef struct _CSMI_SAS_RAID_DRIVES { +- __u8 bModel[40]; +- __u8 bFirmware[8]; +- __u8 bSerialNumber[40]; +- __u8 bSASAddress[8]; +- __u8 bSASLun[8]; +- __u8 bDriveStatus; +- __u8 bDriveUsage; +- __u16 usBlockSize; +- __u8 bDriveType; +- __u8 bReserved[15]; +- __u32 uDriveIndex; +- struct +- { +- __u32 uLowPart; +- __u32 uHighPart; +- } ulTotalUserBlocks; +-} CSMI_SAS_RAID_DRIVES, +- *PCSMI_SAS_RAID_DRIVES; +- +-typedef struct _CSMI_SAS_RAID_DEVICE_ID { +- __u8 bDeviceIdentificationVPDPage[1]; +-} CSMI_SAS_RAID_DEVICE_ID, +- *PCSMI_SAS_RAID_DEVICE_ID; +- +-typedef struct _CSMI_SAS_RAID_SET_ADDITIONAL_DATA { +- __u8 bLabel[16]; +- __u8 bRaidSetLun[8]; +- __u8 bWriteProtection; +- __u8 bCacheSetting; +- __u8 bCacheRatio; +- __u16 usBlockSize; +- __u8 bReservedBytes[11]; +- struct +- { +- __u32 uLowPart; +- __u32 uHighPart; +- } ulRaidSetExtentOffset; +- struct +- { +- __u32 uLowPart; +- __u32 uHighPart; +- } ulRaidSetBlocks; +- __u32 uStripeSizeInBlocks; +- __u32 uSectorsPerTrack; +- __u8 bApplicationScratchPad[16]; +- __u32 uNumberOfHeads; +- __u32 uNumberOfTracks; +- __u8 bReserved[24]; +-} CSMI_SAS_RAID_SET_ADDITIONAL_DATA, +- *PCSMI_SAS_RAID_SET_ADDITIONAL_DATA; +- +-typedef struct _CSMI_SAS_RAID_CONFIG { +- __u32 uRaidSetIndex; +- __u32 uCapacity; +- __u32 uStripeSize; +- __u8 bRaidType; +- __u8 bStatus; +- __u8 bInformation; +- __u8 bDriveCount; +- __u8 bDataType; +- __u8 bReserved[11]; +- __u32 uFailureCode; +- __u32 uChangeCount; +- union { +- CSMI_SAS_RAID_DRIVES Drives[1]; +- CSMI_SAS_RAID_DEVICE_ID DeviceId[1]; +- CSMI_SAS_RAID_SET_ADDITIONAL_DATA Data[1]; +- }; +-} CSMI_SAS_RAID_CONFIG, +- *PCSMI_SAS_RAID_CONFIG; +- +-typedef struct _CSMI_SAS_RAID_CONFIG_BUFFER { +- IOCTL_HEADER IoctlHeader; +- CSMI_SAS_RAID_CONFIG Configuration; +-} CSMI_SAS_RAID_CONFIG_BUFFER, +- *PCSMI_SAS_RAID_CONFIG_BUFFER; +- +-// CC_CSMI_SAS_GET_RAID_FEATURES +- +-typedef struct _CSMI_SAS_RAID_TYPE_DESCRIPTION { +- __u8 bRaidType; +- __u8 bReservedBytes[7]; +- __u32 uSupportedStripeSizeMap; +- __u8 bReserved[24]; +-} CSMI_SAS_RAID_TYPE_DESCRIPTION, +- *PCSMI_SAS_RAID_TYPE_DESCRIPTION; +- +-typedef struct _CSMI_SAS_RAID_FEATURES { +- __u32 uFeatures; +- __u8 bReservedFeatures[32]; +- __u8 bDefaultTransformPriority; +- __u8 bTransformPriority; +- __u8 bDefaultRebuildPriority; +- __u8 bRebuildPriority; +- __u8 bDefaultSurfaceScanPriority; +- __u8 bSurfaceScanPriority; +- __u16 usReserved; +- __u32 uRaidSetTransformationRules; +- __u32 uReserved[11]; +- CSMI_SAS_RAID_TYPE_DESCRIPTION RaidType[24]; +- __u8 bCacheRatiosSupported[104]; +- __u32 uChangeCount; +- __u32 uFailureCode; +- __u8 bReserved[120]; +-} CSMI_SAS_RAID_FEATURES, +- *PCSMI_SAS_RAID_FEATURES; +- +-typedef struct _CSMI_SAS_RAID_FEATURES_BUFFER { +- IOCTL_HEADER IoctlHeader; +- CSMI_SAS_RAID_FEATURES Information; +-} CSMI_SAS_RAID_FEATURES_BUFFER, +- *PCSMI_SAS_RAID_FEATURES_BUFFER; +- +-// CC_CSMI_SAS_SET_RAID_CONTROL +- +-typedef struct _CSMI_SAS_RAID_CONTROL { +- __u8 bTransformPriority; +- __u8 bRebuildPriority; +- __u8 bCacheRatioFlag; +- __u8 bCacheRatio; +- __u8 bSurfaceScanPriority; +- __u8 bReservedBytes[15]; +- __u8 bClearConfiguration[8]; +- __u32 uChangeCount; +- __u8 bReserved[88]; +- __u32 uFailureCode; +- __u8 bFailureDescription[80]; +-} CSMI_SAS_RAID_CONTROL, +- *PCSMI_SAS_RAID_CONTROL; +- +-typedef struct _CSMI_SAS_RAID_CONTROL_BUFFER { +- IOCTL_HEADER IoctlHeader; +- CSMI_SAS_RAID_CONTROL Information; +-} CSMI_SAS_RAID_CONTROL_BUFFER, +- *PCSMI_SAS_RAID_CONTROL_BUFFER; +- +-// CC_CSMI_SAS_GET_RAID_ELEMENT +- +-typedef struct _CSMI_SAS_DRIVE_EXTENT_INFO { +- __u32 uDriveIndex; +- __u8 bExtentType; +- __u8 bReservedBytes[7]; +- struct +- { +- __u32 uLowPart; +- __u32 uHighPart; +- } ulExtentOffset; +- struct +- { +- __u32 uLowPart; +- __u32 uHighPart; +- } ulExtentBlocks; +- __u32 uRaidSetIndex; +- __u8 bReserved[96]; +-} CSMI_SAS_DRIVE_EXTENT_INFO, +- *PCSMI_SAS_DRIVE_EXTENT_INFO; +- +-typedef struct _CSMI_SAS_RAID_MODULE_INFO { +- __u8 bReserved[128]; +-} CSMI_SAS_RAID_MODULE_INFO, +- *PCSMI_SAS_RAID_MODULE_INFO; +- +-typedef struct _CSMI_SAS_DRIVE_LOCATION { +- __u8 bConnector[16]; +- __u8 bBoxName[16]; +- __u32 uBay; +- __u8 bReservedBytes[4]; +- __u8 bAttachedSASAddress[8]; +- __u8 bAttachedPhyIdentifier; +- __u8 bReserved[79]; +-} CSMI_SAS_DRIVE_LOCATION, +- *PCSMI_SAS_DRIVE_LOCATION; +- +-typedef struct _CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA { +- __u8 bNegotiatedLinkRate[2]; +- __u8 bReserved[126]; +-} CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA, +- *PCSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA; +- +-typedef struct _CSMI_SAS_DRIVE_INFO { +- CSMI_SAS_RAID_DRIVES Device; +- CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA Data; +- CSMI_SAS_DRIVE_LOCATION Location; +- __u8 bReserved[16]; +-} CSMI_SAS_DRIVE_INFO, +- *PCSMI_SAS_DRIVE_INFO; +- +-typedef struct _CSMI_SAS_RAID_ELEMENT { +- __u32 uEnumerationType; +- __u32 uElementIndex; +- __u32 uNumElements; +- __u32 uChangeCount; +- __u32 uSubElementIndex; +- __u8 bReserved[32]; +- __u32 uFailureCode; +- __u8 bFailureDescription[80]; +- union { +- CSMI_SAS_DRIVE_INFO Drive; +- CSMI_SAS_RAID_MODULE_INFO Module; +- CSMI_SAS_DRIVE_EXTENT_INFO Extent; +- } Element; +-} CSMI_SAS_RAID_ELEMENT, +- *PCSMI_SAS_RAID_ELEMENT; +- +-typedef struct _CSMI_SAS_RAID_ELEMENT_BUFFER { +- IOCTL_HEADER IoctlHeader; +- CSMI_SAS_RAID_ELEMENT Information; +-} CSMI_SAS_RAID_ELEMENT_BUFFER, +- *PCSMI_SAS_RAID_ELEMENT_BUFFER; +- +-// CC_CSMI_SAS_SET_RAID_OPERATION +- +-typedef struct _CSMI_SAS_RAID_SET_LIST { +- __u32 uRaidSetIndex; +- __u8 bExistingLun[8]; +- __u8 bNewLun[8]; +- __u8 bReserved[12]; +-} CSMI_SAS_RAID_SET_LIST, +- *PCSMI_SAS_RAID_SET_LIST; +- +-typedef struct _CSMI_SAS_RAID_SET_DRIVE_LIST { +- __u32 uDriveIndex; +- __u8 bDriveUsage; +- __u8 bReserved[27]; +-} CSMI_SAS_RAID_SET_DRIVE_LIST, +- *PCSMI_SAS_RAID_SET_DRIVE_LIST; +- +-typedef struct _CSMI_SAS_RAID_SET_SPARE_INFO { +- __u32 uRaidSetIndex; +- __u32 uDriveCount; +- __u8 bApplicationScratchPad[16]; +- __u8 bReserved[104]; +-} CSMI_SAS_RAID_SET_SPARE_INFO, +- *PCSMI_SAS_RAID_SET_SPARE_INFO; +- +-typedef struct _CSMI_SAS_RAID_SET_ONLINE_STATE_INFO { +- __u32 uRaidSetIndex; +- __u8 bOnlineState; +- __u8 bReserved[123]; +-} CSMI_SAS_RAID_SET_ONLINE_STATE_INFO, +- *PCSMI_SAS_RAID_SET_ONLINE_STATE_INFO; +- +-typedef struct _CSMI_SAS_RAID_SET_CACHE_INFO { +- __u32 uRaidSetIndex; +- __u8 bCacheSetting; +- __u8 bCacheRatioFlag; +- __u8 bCacheRatio; +- __u8 bReserved[121]; +-} CSMI_SAS_RAID_SET_CACHE_INFO, +- *PCSMI_SAS_RAID_SET_CACHE_INFO; +- +-typedef struct _CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO { +- __u32 uRaidSetIndex; +- __u8 bWriteProtectSetting; +- __u8 bReserved[123]; +-} CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO, +- *PCSMI_SAS_RAID_SET_WRITE_PROTECT_INFO; +- +-typedef struct _CSMI_SAS_RAID_SET_DELETE_INFO { +- __u32 uRaidSetIndex; +- __u8 bReserved[124]; +-} CSMI_SAS_RAID_SET_DELETE_INFO, +- *PCSMI_SAS_RAID_SET_DELETE_INFO; +- +-typedef struct _CSMI_SAS_RAID_SET_MODIFY_INFO { +- __u8 bRaidType; +- __u8 bReservedBytes[7]; +- __u32 uStripeSize; +- struct +- { +- __u32 uLowPart; +- __u32 uHighPart; +- } ulRaidSetBlocks; +- struct +- { +- __u32 uLowPart; +- __u32 uHighPart; +- } ulRaidSetExtentOffset; +- __u32 uDriveCount; +- __u8 bReserved[96]; +-} CSMI_SAS_RAID_SET_MODIFY_INFO, +- *PCSMI_SAS_RAID_SET_MODIFY_INFO; +- +-typedef struct _CSMI_SAS_RAID_SET_TRANSFORM_INFO { +- __u8 bTransformType; +- __u8 bReservedBytes[3]; +- __u32 uRaidSetIndex; +- __u8 bRaidType; +- __u8 bReservedBytes2[11]; +- __u32 uAdditionalRaidSetIndex; +- __u32 uRaidSetCount; +- __u8 bApplicationScratchPad[16]; +- CSMI_SAS_RAID_SET_MODIFY_INFO Modify; +- __u8 bReserved[80]; +-} CSMI_SAS_RAID_SET_TRANSFORM_INFO, +- *PCSMI_SAS_RAID_SET_TRANSFORM_INFO; +- +-typedef struct _CSMI_SAS_RAID_SET_LABEL_INFO { +- __u32 uRaidSetIndex; +- __u8 bLabel[16]; +- __u8 bReserved[108]; +-} CSMI_SAS_RAID_SET_LABEL_INFO, +- *PCSMI_SAS_RAID_SET_LABEL_INFO; +- +-typedef struct _CSMI_SAS_RAID_SET_CREATE_INFO { +- __u8 bRaidType; +- __u8 bReservedBytes[7]; +- __u32 uStripeSize; +- __u32 uTrackSectorCount; +- struct +- { +- __u32 uLowPart; +- __u32 uHighPart; +- } ulRaidSetBlocks; +- struct +- { +- __u32 uLowPart; +- __u32 uHighPart; +- } ulRaidSetExtentOffset; +- __u32 uDriveCount; +- __u8 bLabel[16]; +- __u32 uRaidSetIndex; +- __u8 bApplicationScratchPad[16]; +- __u32 uNumberOfHeads; +- __u32 uNumberOfTracks; +- __u8 bReserved[48]; +-} CSMI_SAS_RAID_SET_CREATE_INFO, +- *PCSMI_SAS_RAID_SET_CREATE_INFO; +- +-typedef struct _CSMI_SAS_RAID_SET_OPERATION { +- __u32 uOperationType; +- __u32 uChangeCount; +- __u32 uFailureCode; +- __u8 bFailureDescription[80]; +- __u8 bReserved[28]; +- union { +- CSMI_SAS_RAID_SET_CREATE_INFO Create; +- CSMI_SAS_RAID_SET_LABEL_INFO Label; +- CSMI_SAS_RAID_SET_TRANSFORM_INFO Transform; +- CSMI_SAS_RAID_SET_DELETE_INFO Delete; +- CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO Protect; +- CSMI_SAS_RAID_SET_CACHE_INFO Cache; +- CSMI_SAS_RAID_SET_ONLINE_STATE_INFO State; +- CSMI_SAS_RAID_SET_SPARE_INFO Spare; +- } Operation; +- union { +- CSMI_SAS_RAID_SET_DRIVE_LIST DriveList[1]; +- CSMI_SAS_RAID_SET_LIST RaidSetList[1]; +- } Parameters; +-} CSMI_SAS_RAID_SET_OPERATION, +- *PCSMI_SAS_RAID_SET_OPERATION; +- +-typedef struct _CSMI_SAS_RAID_SET_OPERATION_BUFFER { +- IOCTL_HEADER IoctlHeader; +- CSMI_SAS_RAID_SET_OPERATION Information; +-} CSMI_SAS_RAID_SET_OPERATION_BUFFER, +- *PCSMI_SAS_RAID_SET_OPERATION_BUFFER; +- +-/* * * * * * * * * * SAS HBA Class Structures * * * * * * * * * */ +- +-// CC_CSMI_SAS_GET_PHY_INFO +- +-typedef struct _CSMI_SAS_IDENTIFY { +- __u8 bDeviceType; +- __u8 bRestricted; +- __u8 bInitiatorPortProtocol; +- __u8 bTargetPortProtocol; +- __u8 bRestricted2[8]; +- __u8 bSASAddress[8]; +- __u8 bPhyIdentifier; +- __u8 bSignalClass; +- __u8 bReserved[6]; +-} CSMI_SAS_IDENTIFY, +- *PCSMI_SAS_IDENTIFY; +- +-typedef struct _CSMI_SAS_PHY_ENTITY { +- CSMI_SAS_IDENTIFY Identify; +- __u8 bPortIdentifier; +- __u8 bNegotiatedLinkRate; +- __u8 bMinimumLinkRate; +- __u8 bMaximumLinkRate; +- __u8 bPhyChangeCount; +- __u8 bAutoDiscover; +- __u8 bPhyFeatures; +- __u8 bReserved; +- CSMI_SAS_IDENTIFY Attached; +-} CSMI_SAS_PHY_ENTITY, +- *PCSMI_SAS_PHY_ENTITY; +- +-typedef struct _CSMI_SAS_PHY_INFO { +- __u8 bNumberOfPhys; +- __u8 bReserved[3]; +- CSMI_SAS_PHY_ENTITY Phy[32]; +-} CSMI_SAS_PHY_INFO, +- *PCSMI_SAS_PHY_INFO; +- +-typedef struct _CSMI_SAS_PHY_INFO_BUFFER { +- IOCTL_HEADER IoctlHeader; +- CSMI_SAS_PHY_INFO Information; +-} CSMI_SAS_PHY_INFO_BUFFER, +- *PCSMI_SAS_PHY_INFO_BUFFER; +- +-// CC_CSMI_SAS_SET_PHY_INFO +- +-typedef struct _CSMI_SAS_SET_PHY_INFO { +- __u8 bPhyIdentifier; +- __u8 bNegotiatedLinkRate; +- __u8 bProgrammedMinimumLinkRate; +- __u8 bProgrammedMaximumLinkRate; +- __u8 bSignalClass; +- __u8 bReserved[3]; +-} CSMI_SAS_SET_PHY_INFO, +- *PCSMI_SAS_SET_PHY_INFO; +- +-typedef struct _CSMI_SAS_SET_PHY_INFO_BUFFER { +- IOCTL_HEADER IoctlHeader; +- CSMI_SAS_SET_PHY_INFO Information; +-} CSMI_SAS_SET_PHY_INFO_BUFFER, +- *PCSMI_SAS_SET_PHY_INFO_BUFFER; +- +-// CC_CSMI_SAS_GET_LINK_ERRORS +- +-typedef struct _CSMI_SAS_LINK_ERRORS { +- __u8 bPhyIdentifier; +- __u8 bResetCounts; +- __u8 bReserved[2]; +- __u32 uInvalidDwordCount; +- __u32 uRunningDisparityErrorCount; +- __u32 uLossOfDwordSyncCount; +- __u32 uPhyResetProblemCount; +-} CSMI_SAS_LINK_ERRORS, +- *PCSMI_SAS_LINK_ERRORS; +- +-typedef struct _CSMI_SAS_LINK_ERRORS_BUFFER { +- IOCTL_HEADER IoctlHeader; +- CSMI_SAS_LINK_ERRORS Information; +-} CSMI_SAS_LINK_ERRORS_BUFFER, +- *PCSMI_SAS_LINK_ERRORS_BUFFER; +- +-// CC_CSMI_SAS_SMP_PASSTHRU +- +-typedef struct _CSMI_SAS_SMP_REQUEST { +- __u8 bFrameType; +- __u8 bFunction; +- __u8 bReserved[2]; +- __u8 bAdditionalRequestBytes[1016]; +-} CSMI_SAS_SMP_REQUEST, +- *PCSMI_SAS_SMP_REQUEST; +- +-typedef struct _CSMI_SAS_SMP_RESPONSE { +- __u8 bFrameType; +- __u8 bFunction; +- __u8 bFunctionResult; +- __u8 bReserved; +- __u8 bAdditionalResponseBytes[1016]; +-} CSMI_SAS_SMP_RESPONSE, +- *PCSMI_SAS_SMP_RESPONSE; +- +-typedef struct _CSMI_SAS_SMP_PASSTHRU { +- __u8 bPhyIdentifier; +- __u8 bPortIdentifier; +- __u8 bConnectionRate; +- __u8 bReserved; +- __u8 bDestinationSASAddress[8]; +- __u32 uRequestLength; +- CSMI_SAS_SMP_REQUEST Request; +- __u8 bConnectionStatus; +- __u8 bReserved2[3]; +- __u32 uResponseBytes; +- CSMI_SAS_SMP_RESPONSE Response; +-} CSMI_SAS_SMP_PASSTHRU, +- *PCSMI_SAS_SMP_PASSTHRU; +- +-typedef struct _CSMI_SAS_SMP_PASSTHRU_BUFFER { +- IOCTL_HEADER IoctlHeader; +- CSMI_SAS_SMP_PASSTHRU Parameters; +-} CSMI_SAS_SMP_PASSTHRU_BUFFER, +- *PCSMI_SAS_SMP_PASSTHRU_BUFFER; +- +-// CC_CSMI_SAS_SSP_PASSTHRU +- +-typedef struct _CSMI_SAS_SSP_PASSTHRU { +- __u8 bPhyIdentifier; +- __u8 bPortIdentifier; +- __u8 bConnectionRate; +- __u8 bReserved; +- __u8 bDestinationSASAddress[8]; +- __u8 bLun[8]; +- __u8 bCDBLength; +- __u8 bAdditionalCDBLength; +- __u8 bReserved2[2]; +- __u8 bCDB[16]; +- __u32 uFlags; +- __u8 bAdditionalCDB[24]; +- __u32 uDataLength; +-} CSMI_SAS_SSP_PASSTHRU, +- *PCSMI_SAS_SSP_PASSTHRU; +- +-typedef struct _CSMI_SAS_SSP_PASSTHRU_STATUS { +- __u8 bConnectionStatus; +- __u8 bSSPStatus; +- __u8 bReserved[2]; +- __u8 bDataPresent; +- __u8 bStatus; +- __u8 bResponseLength[2]; +- __u8 bResponse[256]; +- __u32 uDataBytes; +-} CSMI_SAS_SSP_PASSTHRU_STATUS, +- *PCSMI_SAS_SSP_PASSTHRU_STATUS; +- +-typedef struct _CSMI_SAS_SSP_PASSTHRU_BUFFER { +- IOCTL_HEADER IoctlHeader; +- CSMI_SAS_SSP_PASSTHRU Parameters; +- CSMI_SAS_SSP_PASSTHRU_STATUS Status; +- __u8 bDataBuffer[1]; +-} CSMI_SAS_SSP_PASSTHRU_BUFFER, +- *PCSMI_SAS_SSP_PASSTHRU_BUFFER; +- +-// CC_CSMI_SAS_STP_PASSTHRU +- +-typedef struct _CSMI_SAS_STP_PASSTHRU { +- __u8 bPhyIdentifier; +- __u8 bPortIdentifier; +- __u8 bConnectionRate; +- __u8 bReserved; +- __u8 bDestinationSASAddress[8]; +- __u8 bReserved2[4]; +- __u8 bCommandFIS[20]; +- __u32 uFlags; +- __u32 uDataLength; +-} CSMI_SAS_STP_PASSTHRU, +- *PCSMI_SAS_STP_PASSTHRU; +- +-typedef struct _CSMI_SAS_STP_PASSTHRU_STATUS { +- __u8 bConnectionStatus; +- __u8 bReserved[3]; +- __u8 bStatusFIS[20]; +- __u32 uSCR[16]; +- __u32 uDataBytes; +-} CSMI_SAS_STP_PASSTHRU_STATUS, +- *PCSMI_SAS_STP_PASSTHRU_STATUS; +- +-typedef struct _CSMI_SAS_STP_PASSTHRU_BUFFER { +- IOCTL_HEADER IoctlHeader; +- CSMI_SAS_STP_PASSTHRU Parameters; +- CSMI_SAS_STP_PASSTHRU_STATUS Status; +- __u8 bDataBuffer[1]; +-} CSMI_SAS_STP_PASSTHRU_BUFFER, +- *PCSMI_SAS_STP_PASSTHRU_BUFFER; +- +-// CC_CSMI_SAS_GET_SATA_SIGNATURE +- +-typedef struct _CSMI_SAS_SATA_SIGNATURE { +- __u8 bPhyIdentifier; +- __u8 bReserved[3]; +- __u8 bSignatureFIS[20]; +-} CSMI_SAS_SATA_SIGNATURE, +- *PCSMI_SAS_SATA_SIGNATURE; +- +-typedef struct _CSMI_SAS_SATA_SIGNATURE_BUFFER { +- IOCTL_HEADER IoctlHeader; +- CSMI_SAS_SATA_SIGNATURE Signature; +-} CSMI_SAS_SATA_SIGNATURE_BUFFER, +- *PCSMI_SAS_SATA_SIGNATURE_BUFFER; +- +-// CC_CSMI_SAS_GET_SCSI_ADDRESS +- +-typedef struct _CSMI_SAS_GET_SCSI_ADDRESS_BUFFER { +- IOCTL_HEADER IoctlHeader; +- __u8 bSASAddress[8]; +- __u8 bSASLun[8]; +- __u8 bHostIndex; +- __u8 bPathId; +- __u8 bTargetId; +- __u8 bLun; +-} CSMI_SAS_GET_SCSI_ADDRESS_BUFFER, +- *PCSMI_SAS_GET_SCSI_ADDRESS_BUFFER; +- +-// CC_CSMI_SAS_GET_DEVICE_ADDRESS +- +-typedef struct _CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER { +- IOCTL_HEADER IoctlHeader; +- __u8 bHostIndex; +- __u8 bPathId; +- __u8 bTargetId; +- __u8 bLun; +- __u8 bSASAddress[8]; +- __u8 bSASLun[8]; +-} CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER, +- *PCSMI_SAS_GET_DEVICE_ADDRESS_BUFFER; +- +-// CC_CSMI_SAS_TASK_MANAGEMENT +- +-typedef struct _CSMI_SAS_SSP_TASK_IU { +- __u8 bHostIndex; +- __u8 bPathId; +- __u8 bTargetId; +- __u8 bLun; +- __u32 uFlags; +- __u32 uQueueTag; +- __u32 uReserved; +- __u8 bTaskManagementFunction; +- __u8 bReserved[7]; +- __u32 uInformation; +-} CSMI_SAS_SSP_TASK_IU, +- *PCSMI_SAS_SSP_TASK_IU; +- +-typedef struct _CSMI_SAS_SSP_TASK_IU_BUFFER { +- IOCTL_HEADER IoctlHeader; +- CSMI_SAS_SSP_TASK_IU Parameters; +- CSMI_SAS_SSP_PASSTHRU_STATUS Status; +-} CSMI_SAS_SSP_TASK_IU_BUFFER, +- *PCSMI_SAS_SSP_TASK_IU_BUFFER; +- +-// CC_CSMI_SAS_GET_CONNECTOR_INFO +- +-typedef struct _CSMI_SAS_GET_CONNECTOR_INFO { +- __u32 uPinout; +- __u8 bConnector[16]; +- __u8 bLocation; +- __u8 bReserved[15]; +-} CSMI_SAS_CONNECTOR_INFO, +- *PCSMI_SAS_CONNECTOR_INFO; +- +-typedef struct _CSMI_SAS_CONNECTOR_INFO_BUFFER { +- IOCTL_HEADER IoctlHeader; +- CSMI_SAS_CONNECTOR_INFO Reference[32]; +-} CSMI_SAS_CONNECTOR_INFO_BUFFER, +- *PCSMI_SAS_CONNECTOR_INFO_BUFFER; +- +-// CC_CSMI_SAS_GET_LOCATION +- +-typedef struct _CSMI_SAS_LOCATION_IDENTIFIER { +- __u32 bLocationFlags; +- __u8 bSASAddress[8]; +- __u8 bSASLun[8]; +- __u8 bEnclosureIdentifier[8]; +- __u8 bEnclosureName[32]; +- __u8 bBayPrefix[32]; +- __u8 bBayIdentifier; +- __u8 bLocationState; +- __u8 bReserved[2]; +-} CSMI_SAS_LOCATION_IDENTIFIER, +- *PCSMI_SAS_LOCATION_IDENTIFIER; +- +-typedef struct _CSMI_SAS_GET_LOCATION_BUFFER { +- IOCTL_HEADER IoctlHeader; +- __u8 bHostIndex; +- __u8 bPathId; +- __u8 bTargetId; +- __u8 bLun; +- __u8 bIdentify; +- __u8 bNumberOfLocationIdentifiers; +- __u8 bLengthOfLocationIdentifier; +- CSMI_SAS_LOCATION_IDENTIFIER Location[1]; +-} CSMI_SAS_GET_LOCATION_BUFFER, +- *PCSMI_SAS_GET_LOCATION_BUFFER; +- +-// CC_CSMI_SAS_PHY_CONTROL +- +-typedef struct _CSMI_SAS_CHARACTER { +- __u8 bTypeFlags; +- __u8 bValue; +-} CSMI_SAS_CHARACTER, +- *PCSMI_SAS_CHARACTER; +- +-typedef struct _CSMI_SAS_PHY_CONTROL { +- __u8 bType; +- __u8 bRate; +- __u8 bReserved[6]; +- __u32 uVendorUnique[8]; +- __u32 uTransmitterFlags; +- __i8 bTransmitAmplitude; +- __i8 bTransmitterPreemphasis; +- __i8 bTransmitterSlewRate; +- __i8 bTransmitterReserved[13]; +- __u8 bTransmitterVendorUnique[64]; +- __u32 uReceiverFlags; +- __i8 bReceiverThreshold; +- __i8 bReceiverEqualizationGain; +- __i8 bReceiverReserved[14]; +- __u8 bReceiverVendorUnique[64]; +- __u32 uPatternFlags; +- __u8 bFixedPattern; +- __u8 bUserPatternLength; +- __u8 bPatternReserved[6]; +- CSMI_SAS_CHARACTER UserPatternBuffer[16]; +-} CSMI_SAS_PHY_CONTROL, +- *PCSMI_SAS_PHY_CONTROL; +- +-typedef struct _CSMI_SAS_PHY_CONTROL_BUFFER { +- IOCTL_HEADER IoctlHeader; +- __u32 uFunction; +- __u8 bPhyIdentifier; +- __u16 usLengthOfControl; +- __u8 bNumberOfControls; +- __u8 bReserved[4]; +- __u32 uLinkFlags; +- __u8 bSpinupRate; +- __u8 bLinkReserved[7]; +- __u32 uVendorUnique[8]; +- CSMI_SAS_PHY_CONTROL Control[1]; +-} CSMI_SAS_PHY_CONTROL_BUFFER, +- *PCSMI_SAS_PHY_CONTROL_BUFFER; +- +-//EDM #pragma CSMI_SAS_END_PACK +-#pragma pack() +- +-#endif // _CSMI_SAS_H_ +diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/csmisas.c linux-2.6.9-55.0.12/drivers/message/fusion/csmisas.c +--- linux-2.6.9-67.0.1/drivers/message/fusion/csmisas.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.9-55.0.12/drivers/message/fusion/csmisas.c 2007-11-02 09:10:23.000000000 +0100 +@@ -0,0 +1,5095 @@ ++#define mptctl_is_this_sas_cntr(ioc) (ioc->bus_type == SAS) ? 1 : 0 ++ ++#ifndef TRUE ++#define TRUE (1) ++#endif ++#ifndef FALSE ++#define FALSE (0) ++#endif ++ ++#ifdef QUIESE_IO ++static int mptctl_raid_get_volume_id(MPT_ADAPTER *ioc, u8 PhysDiskNum, u8 *VolumeID, ++ u8 *VolumeBus); ++#endif ++static int mptctl_do_raid(MPT_ADAPTER *ioc, u8 action, u8 PhysDiskNum, u8 VolumeBus, ++ u8 VolumeId, pMpiRaidActionReply_t reply); ++static u8 map_sas_status_to_csmi(u8 mpi_sas_status); ++ ++static u64 reverse_byte_order64(u64 * data64) ++{ ++ int i; ++ u64 rc; ++ u8 * inWord = (u8 *)data64, * outWord = (u8 *)&rc; ++ ++ for (i=0;i<8;i++) outWord[i] = inWord[7-i]; ++ ++ return rc; ++} ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* Routine for the CSMI Sas Get Driver Info command. ++ * ++ * Outputs: None. ++ * Return: 0 if successful ++ * -EFAULT if data unavailable ++ * -ENODEV if no such device/adapter ++ */ ++static int ++mptctl_csmi_sas_get_driver_info(unsigned long arg) ++{ ++ ++ CSMI_SAS_DRIVER_INFO_BUFFER __user *uarg = (void __user *) arg; ++ CSMI_SAS_DRIVER_INFO_BUFFER karg; ++ MPT_ADAPTER *ioc = NULL; ++ int iocnum; ++ ++ dctlprintk((": %s called.\n",__FUNCTION__)); ++ ++ if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s - " ++ "Unable to read in csmi_sas_get_driver_info_buffer struct @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, ++ &ioc)) < 0) || (ioc == NULL)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not found!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ if (!mptctl_is_this_sas_cntr(ioc)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not SAS controller!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ /* Fill in the data and return the structure to the calling ++ * program ++ */ ++ memcpy( karg.Information.szName, MPT_MISCDEV_BASENAME, ++ sizeof(MPT_MISCDEV_BASENAME)); ++ memcpy( karg.Information.szDescription, MPT_CSMI_DESCRIPTION, ++ sizeof(MPT_CSMI_DESCRIPTION)); ++ ++ karg.Information.usMajorRevision = MPT_LINUX_MAJOR_VERSION; ++ karg.Information.usMinorRevision = MPT_LINUX_MINOR_VERSION; ++ karg.Information.usBuildRevision = MPT_LINUX_BUILD_VERSION; ++ karg.Information.usReleaseRevision = MPT_LINUX_RELEASE_VERSION; ++ ++ karg.Information.usCSMIMajorRevision = CSMI_MAJOR_REVISION; ++ karg.Information.usCSMIMinorRevision = CSMI_MINOR_REVISION; ++ ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; ++ ++ /* Copy the data from kernel memory to user memory ++ */ ++ if (copy_to_user((char *)arg, &karg, ++ sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s - " ++ "Unable to write out csmi_sas_get_driver_info_buffer @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* Prototype Routine for the CSMI_SAS_GET_CNTLR_CONFIG command. ++ * ++ * Outputs: None. ++ * Return: 0 if successful ++ * -EFAULT if data unavailable ++ * -ENODEV if no such device/adapter ++ */ ++static int ++mptctl_csmi_sas_get_cntlr_config(unsigned long arg) ++{ ++ ++ CSMI_SAS_CNTLR_CONFIG_BUFFER __user *uarg = (void __user *) arg; ++ CSMI_SAS_CNTLR_CONFIG_BUFFER karg; ++ MPT_ADAPTER *ioc = NULL; ++ int iocnum; ++ int ii; ++ unsigned int reg; ++ u32 l; ++ ++ dctlprintk((": %s called.\n",__FUNCTION__)); ++ ++ if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_CNTLR_CONFIG_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s - " ++ "Unable to read in csmi_sas_get_cntlr_config_buffer struct @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, ++ &ioc)) < 0) || (ioc == NULL)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not found!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER; ++ return -ENODEV; ++ } ++ ++ if (!mptctl_is_this_sas_cntr(ioc)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not SAS controller!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ /* Clear the struct before filling in data. */ ++ memset( &karg.Configuration, 0, sizeof(CSMI_SAS_CNTLR_CONFIG)); ++ ++ /* Fill in the data and return the structure to the calling ++ * program ++ */ ++ ++ /* Get Base IO and Mem Mapped Addresses. */ ++ for(ii=0; ii < DEVICE_COUNT_RESOURCE; ii++) { ++ reg = PCI_BASE_ADDRESS_0 + (ii << 2); ++ pci_read_config_dword(ioc->pcidev, reg, &l); ++ ++ if ((l & PCI_BASE_ADDRESS_SPACE) == ++ PCI_BASE_ADDRESS_SPACE_MEMORY) { ++ karg.Configuration.BaseMemoryAddress.uLowPart = ++ l & PCI_BASE_ADDRESS_MEM_MASK; ++ } ++ else { ++ karg.Configuration.uBaseIoAddress = ++ l & PCI_BASE_ADDRESS_IO_MASK; ++ } ++ ++ if ((l & (PCI_BASE_ADDRESS_SPACE | ++ PCI_BASE_ADDRESS_MEM_TYPE_MASK)) ++ == (PCI_BASE_ADDRESS_SPACE_MEMORY | ++ PCI_BASE_ADDRESS_MEM_TYPE_64)) { ++ pci_read_config_dword(ioc->pcidev, reg+4, &l); ++ karg.Configuration.BaseMemoryAddress.uHighPart = l; ++ } ++ if ((l & PCI_BASE_ADDRESS_SPACE) == ++ PCI_BASE_ADDRESS_SPACE_MEMORY) { ++ break; ++ } ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) ++ karg.Configuration.uBoardID = (ioc->pcidev->subsystem_device << 16) | ++ (ioc->pcidev->subsystem_vendor); ++#endif ++ ++ karg.Configuration.usSlotNumber = ++ (ioc->pci_slot_number = 0xff) ? ++ SLOT_NUMBER_UNKNOWN : ioc->pci_slot_number; ++ karg.Configuration.bControllerClass = CSMI_SAS_CNTLR_CLASS_HBA; ++ karg.Configuration.bIoBusType = CSMI_SAS_BUS_TYPE_PCI; ++ karg.Configuration.BusAddress.PciAddress.bBusNumber = ++ ioc->pcidev->bus->number; ++ karg.Configuration.BusAddress.PciAddress.bDeviceNumber = ++ PCI_SLOT(ioc->pcidev->devfn); ++ karg.Configuration.BusAddress.PciAddress.bFunctionNumber = ++ PCI_FUNC(ioc->pcidev->devfn); ++ karg.Configuration.BusAddress.PciAddress.bReserved = 0; ++ memcpy( &karg.Configuration.szSerialNumber,ioc->BoardTracerNumber, 16 ); ++ karg.Configuration.usMajorRevision = ioc->facts.FWVersion.Struct.Major; ++ karg.Configuration.usMinorRevision = ioc->facts.FWVersion.Struct.Minor; ++ karg.Configuration.usBuildRevision = ioc->facts.FWVersion.Struct.Unit; ++ karg.Configuration.usReleaseRevision = ioc->facts.FWVersion.Struct.Dev; ++ karg.Configuration.usBIOSMajorRevision = ++ (ioc->biosVersion & 0xFF000000) >> 24; ++ karg.Configuration.usBIOSMinorRevision = ++ (ioc->biosVersion & 0x00FF0000) >> 16; ++ karg.Configuration.usBIOSBuildRevision = ++ (ioc->biosVersion & 0x0000FF00) >> 8; ++ karg.Configuration.usBIOSReleaseRevision = ++ (ioc->biosVersion & 0x000000FF); ++ karg.Configuration.uControllerFlags = ++ CSMI_SAS_CNTLR_SAS_HBA | CSMI_SAS_CNTLR_SAS_RAID | ++ CSMI_SAS_CNTLR_FWD_SUPPORT | CSMI_SAS_CNTLR_FWD_ONLINE | ++ CSMI_SAS_CNTLR_FWD_SRESET ; ++ ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; ++ ++ /* All Rrom entries will be zero. Skip them. */ ++ /* bReserved will also be zeros. */ ++ /* Copy the data from kernel memory to user memory ++ */ ++ if (copy_to_user((char *)arg, &karg, ++ sizeof(CSMI_SAS_DRIVER_INFO_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s - " ++ "Unable to write out csmi_sas_get_driver_info_buffer @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* Prototype Routine for the CSMI Sas Get Controller Status command. ++ * ++ * Outputs: None. ++ * Return: 0 if successful ++ * -EFAULT if data unavailable ++ * -ENODEV if no such device/adapter ++ */ ++static int ++mptctl_csmi_sas_get_cntlr_status(unsigned long arg) ++{ ++ ++ CSMI_SAS_CNTLR_STATUS_BUFFER __user *uarg = (void __user *) arg; ++ MPT_ADAPTER *ioc = NULL; ++ CSMI_SAS_CNTLR_STATUS_BUFFER karg; ++ int iocnum; ++ int rc; ++ ++ dctlprintk((": %s called.\n",__FUNCTION__)); ++ ++ if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_CNTLR_STATUS_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s - " ++ "Unable to read in csmi_sas_get_cntlr_status_buffer struct @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, ++ &ioc)) < 0) || (ioc == NULL)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not found!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ if (!mptctl_is_this_sas_cntr(ioc)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not SAS controller!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ /* Fill in the data and return the structure to the calling ++ * program ++ */ ++ ++ rc = mpt_GetIocState(ioc, 1); ++ switch (rc) { ++ case MPI_IOC_STATE_OPERATIONAL: ++ karg.Status.uStatus = CSMI_SAS_CNTLR_STATUS_GOOD; ++ karg.Status.uOfflineReason = 0; ++ break; ++ ++ case MPI_IOC_STATE_FAULT: ++ karg.Status.uStatus = CSMI_SAS_CNTLR_STATUS_FAILED; ++ karg.Status.uOfflineReason = 0; ++ break; ++ ++ case MPI_IOC_STATE_RESET: ++ case MPI_IOC_STATE_READY: ++ default: ++ karg.Status.uStatus = CSMI_SAS_CNTLR_STATUS_OFFLINE; ++ karg.Status.uOfflineReason = ++ CSMI_SAS_OFFLINE_REASON_INITIALIZING; ++ break; ++ } ++ ++ memset(&karg.Status.bReserved, 0, 28); ++ ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; ++ ++ /* Copy the data from kernel memory to user memory ++ */ ++ if (copy_to_user((char *)arg, &karg, ++ sizeof(CSMI_SAS_CNTLR_STATUS_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s - " ++ "Unable to write out csmi_sas_get_cntlr_status @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* Prototype Routine for the CSMI Sas Get Phy Info command. ++ * ++ * Outputs: None. ++ * Return: 0 if successful ++ * -EFAULT if data unavailable ++ * -ENODEV if no such device/adapter ++ */ ++static int ++mptctl_csmi_sas_get_phy_info(unsigned long arg) ++{ ++ CSMI_SAS_PHY_INFO_BUFFER __user *uarg = (void __user *) arg; ++ CSMI_SAS_PHY_INFO_BUFFER karg; ++ MPT_ADAPTER *ioc = NULL; ++ ConfigExtendedPageHeader_t hdr; ++ CONFIGPARMS cfg; ++ SasIOUnitPage0_t *sasIoUnitPg0; ++ dma_addr_t sasIoUnitPg0_dma; ++ int sasIoUnitPg0_data_sz; ++ SasPhyPage0_t *sasPhyPg0; ++ dma_addr_t sasPhyPg0_dma; ++ int sasPhyPg0_data_sz; ++ u16 protocol; ++ int iocnum; ++ int rc; ++ int ii; ++ u64 SASAddress64; ++ ++ dctlprintk((": %s called.\n",__FUNCTION__)); ++ sasIoUnitPg0=NULL; ++ sasPhyPg0=NULL; ++ sasIoUnitPg0_data_sz=0; ++ sasPhyPg0_data_sz=0; ++ ++ if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_PHY_INFO_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s - " ++ "Unable to read in csmi_sas_get_phy_info_buffer struct @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, ++ &ioc)) < 0) || (ioc == NULL)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not found!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ if (!mptctl_is_this_sas_cntr(ioc)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not SAS controller!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ /* Fill in the data and return the structure to the calling ++ * program ++ */ ++ memset( &karg.Information, 0, sizeof(CSMI_SAS_PHY_INFO)); ++ ++ /* Issue a config request to get the number of phys ++ */ ++ hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION; ++ hdr.ExtPageLength = 0; ++ hdr.PageNumber = 0; ++ hdr.Reserved1 = 0; ++ hdr.Reserved2 = 0; ++ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; ++ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; ++ ++ cfg.cfghdr.ehdr = &hdr; ++ cfg.physAddr = -1; ++ cfg.pageAddr = 0; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; ++ cfg.dir = 0; /* read */ ++ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; ++ ++ if ((rc = mpt_config(ioc, &cfg)) != 0) { ++ /* Don't check if this failed. Already in a ++ * failure case. ++ */ ++ dctlprintk(( ++ ": FAILED: MPI_SASIOUNITPAGE0_PAGEVERSION: HEADER\n")); ++ dctlprintk((": rc=%x\n",rc)); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto sas_get_phy_info_exit; ++ } ++ ++ if (hdr.ExtPageLength == 0) { ++ /* Don't check if this failed. Already in a ++ * failure case. ++ */ ++ dctlprintk((": hdr.ExtPageLength == 0\n")); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto sas_get_phy_info_exit; ++ } ++ ++ sasIoUnitPg0_data_sz = hdr.ExtPageLength * 4; ++ rc = -ENOMEM; ++ ++ sasIoUnitPg0 = (SasIOUnitPage0_t *) pci_alloc_consistent(ioc->pcidev, ++ sasIoUnitPg0_data_sz, &sasIoUnitPg0_dma); ++ ++ if (!sasIoUnitPg0) { ++ dctlprintk((": pci_alloc_consistent: FAILED\n")); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto sas_get_phy_info_exit; ++ } ++ ++ memset((u8 *)sasIoUnitPg0, 0, sasIoUnitPg0_data_sz); ++ cfg.physAddr = sasIoUnitPg0_dma; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; ++ ++ if ((rc = mpt_config(ioc, &cfg)) != 0) { ++ ++ /* Don't check if this failed. Already in a ++ * failure case. ++ */ ++ dctlprintk(( ++ ": FAILED: MPI_SASIOUNITPAGE0_PAGEVERSION: PAGE\n")); ++ dctlprintk((": rc=%x\n",rc)); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto sas_get_phy_info_exit; ++ } ++ ++ ++ /* Number of Phys. */ ++ karg.Information.bNumberOfPhys = sasIoUnitPg0->NumPhys; ++ ++ /* Fill in information for each phy. */ ++ for (ii = 0; ii < karg.Information.bNumberOfPhys; ii++) { ++ ++/* EDM : dump IO Unit Page 0 data*/ ++ dsasprintk(("---- IO UNIT PAGE 0 ------------\n")); ++ dsasprintk(("Handle=0x%X\n", ++ le16_to_cpu(sasIoUnitPg0->PhyData[ii].AttachedDeviceHandle))); ++ dsasprintk(("Controller Handle=0x%X\n", ++ le16_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerDevHandle))); ++ dsasprintk(("Port=0x%X\n", ++ sasIoUnitPg0->PhyData[ii].Port)); ++ dsasprintk(("Port Flags=0x%X\n", ++ sasIoUnitPg0->PhyData[ii].PortFlags)); ++ dsasprintk(("PHY Flags=0x%X\n", ++ sasIoUnitPg0->PhyData[ii].PhyFlags)); ++ dsasprintk(("Negotiated Link Rate=0x%X\n", ++ sasIoUnitPg0->PhyData[ii].NegotiatedLinkRate)); ++ dsasprintk(("Controller PHY Device Info=0x%X\n", ++ le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo))); ++ dsasprintk(("DiscoveryStatus=0x%X\n", ++ le32_to_cpu(sasIoUnitPg0->PhyData[ii].DiscoveryStatus))); ++ dsasprintk(("\n")); ++/* EDM : debug data */ ++ ++ /* PHY stuff. */ ++ karg.Information.Phy[ii].bPortIdentifier = ++ sasIoUnitPg0->PhyData[ii].Port; ++ ++ /* Get the negotiated link rate for the phy. */ ++ switch (sasIoUnitPg0->PhyData[ii].NegotiatedLinkRate) { ++ ++ case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED: ++ karg.Information.Phy[ii].bNegotiatedLinkRate = ++ CSMI_SAS_PHY_DISABLED; ++ break; ++ ++ case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION: ++ karg.Information.Phy[ii].bNegotiatedLinkRate = ++ CSMI_SAS_LINK_RATE_FAILED; ++ break; ++ ++ case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE: ++ break; ++ ++ case MPI_SAS_IOUNIT0_RATE_1_5: ++ karg.Information.Phy[ii].bNegotiatedLinkRate = ++ CSMI_SAS_LINK_RATE_1_5_GBPS; ++ break; ++ ++ case MPI_SAS_IOUNIT0_RATE_3_0: ++ karg.Information.Phy[ii].bNegotiatedLinkRate = ++ CSMI_SAS_LINK_RATE_3_0_GBPS; ++ break; ++ ++ case MPI_SAS_IOUNIT0_RATE_UNKNOWN: ++ default: ++ karg.Information.Phy[ii].bNegotiatedLinkRate = ++ CSMI_SAS_LINK_RATE_UNKNOWN; ++ break; ++ } ++ ++ if (sasIoUnitPg0->PhyData[ii].PortFlags & ++ MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS) { ++ karg.Information.Phy[ii].bAutoDiscover = ++ CSMI_SAS_DISCOVER_IN_PROGRESS; ++ } else { ++ karg.Information.Phy[ii].bAutoDiscover = ++ CSMI_SAS_DISCOVER_COMPLETE; ++ } ++ ++ /* Issue a config request to get ++ * phy information. ++ */ ++ hdr.PageVersion = MPI_SASPHY0_PAGEVERSION; ++ hdr.ExtPageLength = 0; ++ hdr.PageNumber = 0; ++ hdr.Reserved1 = 0; ++ hdr.Reserved2 = 0; ++ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; ++ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY; ++ ++ cfg.cfghdr.ehdr = &hdr; ++ cfg.physAddr = -1; ++ cfg.pageAddr = ii; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; ++ cfg.dir = 0; /* read */ ++ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; ++ ++ if ((rc = mpt_config(ioc, &cfg)) != 0) { ++ dctlprintk(( ++ ": FAILED: MPI_SASPHY0_PAGEVERSION: HEADER\n")); ++ dctlprintk((": rc=%x\n",rc)); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto sas_get_phy_info_exit; ++ } ++ ++ if (hdr.ExtPageLength == 0) { ++ dctlprintk((": pci_alloc_consistent: FAILED\n")); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto sas_get_phy_info_exit; ++ } ++ ++ sasPhyPg0_data_sz = hdr.ExtPageLength * 4; ++ rc = -ENOMEM; ++ ++ sasPhyPg0 = (SasPhyPage0_t *) pci_alloc_consistent( ++ ioc->pcidev, sasPhyPg0_data_sz, &sasPhyPg0_dma); ++ ++ if (! sasPhyPg0) { ++ dctlprintk((": pci_alloc_consistent: FAILED\n")); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto sas_get_phy_info_exit; ++ } ++ ++ memset((u8 *)sasPhyPg0, 0, sasPhyPg0_data_sz); ++ cfg.physAddr = sasPhyPg0_dma; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; ++ ++ if ((rc = mpt_config(ioc, &cfg)) != 0) { ++ dctlprintk(( ++ ": FAILED: MPI_SASPHY0_PAGEVERSION: PAGE\n")); ++ dctlprintk((": rc=%x\n",rc)); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz, ++ (u8 *) sasPhyPg0, sasPhyPg0_dma); ++ goto sas_get_phy_info_exit; ++ } ++ ++ le64_to_cpus((u64 *)&sasPhyPg0->SASAddress); ++ memcpy(&SASAddress64, &sasPhyPg0->SASAddress, sizeof(u64)); ++ ++/* EDM : dump PHY Page 0 data*/ ++ dsasprintk(("---- SAS PHY PAGE 0 ------------\n")); ++ dsasprintk(("Handle=0x%X\n", ++ le16_to_cpu(sasPhyPg0->AttachedDevHandle))); ++ dsasprintk(("SAS Address=0x%llX\n",SASAddress64)); ++ dsasprintk(("Attached PHY Identifier=0x%X\n", ++ sasPhyPg0->AttachedPhyIdentifier)); ++ dsasprintk(("Attached Device Info=0x%X\n", ++ le32_to_cpu(sasPhyPg0->AttachedDeviceInfo))); ++ dsasprintk(("Programmed Link Rate=0x%X\n", ++ sasPhyPg0->ProgrammedLinkRate)); ++ dsasprintk(("Hardware Link Rate=0x%X\n", ++ ioc->sasPhyInfo[ii].hwLinkRate)); ++ dsasprintk(("Change Count=0x%X\n", ++ sasPhyPg0->ChangeCount)); ++ dsasprintk(("PHY Info=0x%X\n", ++ le32_to_cpu(sasPhyPg0->PhyInfo))); ++ dsasprintk(("\n")); ++/* EDM : debug data */ ++ ++ /* save the data */ ++ ++ /* Set Max hardware link rate. ++ * This value is hard coded ++ * because the HW link rate ++ * is currently being ++ * overwritten in FW. ++ */ ++ ++ /* Set Max hardware link rate. */ ++ switch (sasPhyPg0->HwLinkRate & ++ MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) { ++ ++ case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5: ++ karg.Information.Phy[ii].bMaximumLinkRate = ++ CSMI_SAS_LINK_RATE_1_5_GBPS; ++ break; ++ ++ case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0: ++ karg.Information.Phy[ii].bMaximumLinkRate = ++ CSMI_SAS_LINK_RATE_3_0_GBPS; ++ break; ++ default: ++ break; ++ } ++ ++ /* Set Max programmed link rate. */ ++ switch (sasPhyPg0->ProgrammedLinkRate & ++ MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) { ++ ++ case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5: ++ karg.Information.Phy[ii].bMaximumLinkRate |= ++ (CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS << 4); ++ break; ++ ++ case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0: ++ karg.Information.Phy[ii].bMaximumLinkRate |= ++ (CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS << 4); ++ break; ++ default: ++ break; ++ } ++ ++ /* Set Min hardware link rate. */ ++ switch (sasPhyPg0->HwLinkRate & ++ MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) { ++ ++ case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5: ++ karg.Information.Phy[ii].bMinimumLinkRate = ++ CSMI_SAS_LINK_RATE_1_5_GBPS; ++ break; ++ ++ case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0: ++ karg.Information.Phy[ii].bMinimumLinkRate = ++ CSMI_SAS_LINK_RATE_3_0_GBPS; ++ break; ++ default: ++ break; ++ } ++ ++ /* Set Min programmed link rate. */ ++ switch (sasPhyPg0->ProgrammedLinkRate & ++ MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) { ++ ++ case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5: ++ karg.Information.Phy[ii].bMinimumLinkRate |= ++ (CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS << 4); ++ break; ++ ++ case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0: ++ karg.Information.Phy[ii].bMinimumLinkRate |= ++ (CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS << 4); ++ break; ++ default: ++ break; ++ } ++ ++ /* Fill in Attached Device ++ * Initiator Port Protocol. ++ * Bits 6:3 ++ * More than one bit can be set. ++ */ ++ protocol = le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) & 0x78; ++ karg.Information.Phy[ii].Attached.bInitiatorPortProtocol = 0; ++ if (protocol & MPI_SAS_DEVICE_INFO_SSP_INITIATOR) ++ karg.Information.Phy[ii].Attached.bInitiatorPortProtocol = ++ CSMI_SAS_PROTOCOL_SSP; ++ if (protocol & MPI_SAS_DEVICE_INFO_STP_INITIATOR) ++ karg.Information.Phy[ii].Attached.bInitiatorPortProtocol |= ++ CSMI_SAS_PROTOCOL_STP; ++ if (protocol & MPI_SAS_DEVICE_INFO_SMP_INITIATOR) ++ karg.Information.Phy[ii].Attached.bInitiatorPortProtocol |= ++ CSMI_SAS_PROTOCOL_SMP; ++ if (protocol & MPI_SAS_DEVICE_INFO_SATA_HOST) ++ karg.Information.Phy[ii].Attached.bInitiatorPortProtocol |= ++ CSMI_SAS_PROTOCOL_SATA; ++ ++ ++ /* Fill in Phy Target Port ++ * Protocol. Bits 10:7 ++ * More than one bit can be set. ++ */ ++ protocol = le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) & 0x780; ++ karg.Information.Phy[ii].Attached.bTargetPortProtocol = 0; ++ if (protocol & MPI_SAS_DEVICE_INFO_SSP_TARGET) ++ karg.Information.Phy[ii].Attached.bTargetPortProtocol |= ++ CSMI_SAS_PROTOCOL_SSP; ++ if (protocol & MPI_SAS_DEVICE_INFO_STP_TARGET) ++ karg.Information.Phy[ii].Attached.bTargetPortProtocol |= ++ CSMI_SAS_PROTOCOL_STP; ++ if (protocol & MPI_SAS_DEVICE_INFO_SMP_TARGET) ++ karg.Information.Phy[ii].Attached.bTargetPortProtocol |= ++ CSMI_SAS_PROTOCOL_SMP; ++ if (protocol & MPI_SAS_DEVICE_INFO_SATA_DEVICE) ++ karg.Information.Phy[ii].Attached.bTargetPortProtocol |= ++ CSMI_SAS_PROTOCOL_SATA; ++ ++ ++ /* Fill in Attached device type */ ++ switch (le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) & ++ MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) { ++ ++ case MPI_SAS_DEVICE_INFO_NO_DEVICE: ++ karg.Information.Phy[ii].Attached.bDeviceType = ++ CSMI_SAS_NO_DEVICE_ATTACHED; ++ break; ++ ++ case MPI_SAS_DEVICE_INFO_END_DEVICE: ++ karg.Information.Phy[ii].Attached.bDeviceType = ++ CSMI_SAS_END_DEVICE; ++ break; ++ ++ case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER: ++ karg.Information.Phy[ii].Attached.bDeviceType = ++ CSMI_SAS_EDGE_EXPANDER_DEVICE; ++ break; ++ ++ case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER: ++ karg.Information.Phy[ii].Attached.bDeviceType = ++ CSMI_SAS_FANOUT_EXPANDER_DEVICE; ++ break; ++ } ++ ++ /* Identify Info. */ ++ switch (le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo) & ++ MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) { ++ ++ case MPI_SAS_DEVICE_INFO_NO_DEVICE: ++ karg.Information.Phy[ii].Identify.bDeviceType = ++ CSMI_SAS_NO_DEVICE_ATTACHED; ++ break; ++ ++ case MPI_SAS_DEVICE_INFO_END_DEVICE: ++ karg.Information.Phy[ii].Identify.bDeviceType = ++ CSMI_SAS_END_DEVICE; ++ break; ++ ++ case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER: ++ karg.Information.Phy[ii].Identify.bDeviceType = ++ CSMI_SAS_EDGE_EXPANDER_DEVICE; ++ break; ++ ++ case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER: ++ karg.Information.Phy[ii].Identify.bDeviceType = ++ CSMI_SAS_FANOUT_EXPANDER_DEVICE; ++ break; ++ } ++ ++ /* Fill in Phy Initiator Port Protocol. Bits 6:3 ++ * More than one bit can be set, fall through cases. ++ */ ++ protocol = le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo) ++ & 0x78; ++ karg.Information.Phy[ii].Identify.bInitiatorPortProtocol = 0; ++ if( protocol & MPI_SAS_DEVICE_INFO_SSP_INITIATOR ) ++ karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |= ++ CSMI_SAS_PROTOCOL_SSP; ++ if( protocol & MPI_SAS_DEVICE_INFO_STP_INITIATOR ) ++ karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |= ++ CSMI_SAS_PROTOCOL_STP; ++ if( protocol & MPI_SAS_DEVICE_INFO_SMP_INITIATOR ) ++ karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |= ++ CSMI_SAS_PROTOCOL_SMP; ++ if( protocol & MPI_SAS_DEVICE_INFO_SATA_HOST ) ++ karg.Information.Phy[ii].Identify.bInitiatorPortProtocol |= ++ CSMI_SAS_PROTOCOL_SATA; ++ ++ /* Fill in Phy Target Port Protocol. Bits 10:7 ++ * More than one bit can be set, fall through cases. ++ */ ++ protocol = le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo) ++ & 0x780; ++ karg.Information.Phy[ii].Identify.bTargetPortProtocol = 0; ++ if( protocol & MPI_SAS_DEVICE_INFO_SSP_TARGET ) ++ karg.Information.Phy[ii].Identify.bTargetPortProtocol |= ++ CSMI_SAS_PROTOCOL_SSP; ++ if( protocol & MPI_SAS_DEVICE_INFO_STP_TARGET ) ++ karg.Information.Phy[ii].Identify.bTargetPortProtocol |= ++ CSMI_SAS_PROTOCOL_STP; ++ if( protocol & MPI_SAS_DEVICE_INFO_SMP_TARGET ) ++ karg.Information.Phy[ii].Identify.bTargetPortProtocol |= ++ CSMI_SAS_PROTOCOL_SMP; ++ if( protocol & MPI_SAS_DEVICE_INFO_SATA_DEVICE ) ++ karg.Information.Phy[ii].Identify.bTargetPortProtocol |= ++ CSMI_SAS_PROTOCOL_SATA; ++ ++ ++ /* Setup Identify SAS Address and Phy Identifier ++ * ++ * Get phy Sas address from device list. ++ * Search the list for the matching ++ * devHandle. ++ */ ++ ++ /* Setup SAS Address for the Phy */ ++ SASAddress64 = reverse_byte_order64((u64 *)&ioc->sasPhyInfo[ii].SASAddress); ++ memcpy(karg.Information.Phy[ii].Identify.bSASAddress,&SASAddress64, ++ sizeof(u64)); ++ ++ karg.Information.Phy[ii].Identify.bPhyIdentifier = ii; ++ ++ /* Setup SAS Address for the attached device */ ++ SASAddress64 = reverse_byte_order64((u64 *)&sasPhyPg0->SASAddress); ++ memcpy(karg.Information.Phy[ii].Attached.bSASAddress,&SASAddress64, ++ sizeof(u64)); ++ ++ karg.Information.Phy[ii].Attached.bPhyIdentifier = ++ sasPhyPg0->AttachedPhyIdentifier; ++ ++ pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz, ++ (u8 *) sasPhyPg0, sasPhyPg0_dma); ++ } ++ ++sas_get_phy_info_exit: ++ ++ if (sasIoUnitPg0) ++ pci_free_consistent(ioc->pcidev, sasIoUnitPg0_data_sz, ++ (u8 *) sasIoUnitPg0, sasIoUnitPg0_dma); ++ ++ /* Copy the data from kernel memory to user memory ++ */ ++ if (copy_to_user((char *)arg, &karg, ++ sizeof(CSMI_SAS_PHY_INFO_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s - " ++ "Unable to write out csmi_sas_get_phy_info_buffer @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* Prototype Routine for the CSMI SAS Set PHY Info command. ++ * ++ * Outputs: None. ++ * Return: 0 if successful ++ * -EFAULT if data unavailable ++ * -ENODEV if no such device/adapter ++ */ ++static int ++mptctl_csmi_sas_set_phy_info(unsigned long arg) ++{ ++ CSMI_SAS_SET_PHY_INFO_BUFFER __user *uarg = (void __user *) arg; ++ CSMI_SAS_SET_PHY_INFO_BUFFER karg; ++ MPT_ADAPTER *ioc = NULL; ++ int iocnum; ++ ++ dctlprintk((": %s called.\n",__FUNCTION__)); ++ ++ if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SET_PHY_INFO_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to read in csmi_sas_set_phy_info struct @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, ++ &ioc)) < 0) || (ioc == NULL)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not found!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ if (!mptctl_is_this_sas_cntr(ioc)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not SAS controller!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++/* TODO - implement IOCTL here */ ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ dctlprintk((": not implemented\n")); ++ ++// cim_set_phy_info_exit: ++ ++ /* Copy the data from kernel memory to user memory ++ */ ++ if (copy_to_user((char *)arg, &karg, ++ sizeof(CSMI_SAS_SET_PHY_INFO_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to write out csmi_sas_set_phy_info @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ return 0; ++ ++} ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* Prototype Routine for the CSMI Sas Get SCSI Address command. ++ * ++ * Outputs: None. ++ * Return: 0 if successful ++ * -EFAULT if data unavailable ++ * -ENODEV if no such device/adapter ++ */ ++static int ++mptctl_csmi_sas_get_scsi_address(unsigned long arg) ++{ ++ CSMI_SAS_GET_SCSI_ADDRESS_BUFFER __user *uarg = (void __user *) arg; ++ CSMI_SAS_GET_SCSI_ADDRESS_BUFFER karg; ++ MPT_ADAPTER *ioc = NULL; ++ int iocnum; ++ sas_device_info_t *sasDevice; ++ u64 SASAddress64; ++ ++ dctlprintk((": %s called.\n",__FUNCTION__)); ++ ++ if (copy_from_user(&karg, uarg, ++ sizeof(CSMI_SAS_GET_SCSI_ADDRESS_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to read in csmi_sas_get_scsi_address struct @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, ++ &ioc)) < 0) || (ioc == NULL)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not found!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ if (!mptctl_is_this_sas_cntr(ioc)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not SAS controller!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ /* Fill in the data and return the structure to the calling ++ * program ++ */ ++ ++ /* Copy the SAS address in reverse byte order. */ ++ SASAddress64 = reverse_byte_order64((u64 *)&karg.bSASAddress); ++ ++ /* Search the list for the matching SAS address. */ ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_SCSI_ADDRESS; ++ list_for_each_entry(sasDevice, &ioc->sasDeviceList, list) { ++ ++ /* Found the matching device. */ ++ if ((memcmp(&sasDevice->SASAddress, ++ &SASAddress64, sizeof(u64)) != 0)) ++ continue; ++ ++ karg.bPathId = sasDevice->Bus; ++ karg.bTargetId = sasDevice->TargetId; ++ karg.bLun = karg.bSASLun[0]; ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; ++ ++ if (((sasDevice->DeviceInfo & 0x00000003) == ++ MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER) || ++ ((sasDevice->DeviceInfo & 0x00000003) == ++ MPI_SAS_DEVICE_INFO_EDGE_EXPANDER)) ++ karg.IoctlHeader.ReturnCode = ++ CSMI_SAS_NOT_AN_END_DEVICE; ++ break; ++ } ++ ++ /* Copy the data from kernel memory to user memory ++ */ ++ if (copy_to_user((char *)arg, &karg, ++ sizeof(CSMI_SAS_GET_SCSI_ADDRESS_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to write out csmi_sas_get_scsi_address @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ return 0; ++ ++} ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* Prototype Routine for the CSMI Sas Get SCSI Address command. ++ * ++ * Outputs: None. ++ * Return: 0 if successful ++ * -EFAULT if data unavailable ++ * -ENODEV if no such device/adapter ++ */ ++static int ++mptctl_csmi_sas_get_sata_signature(unsigned long arg) ++{ ++ CSMI_SAS_SATA_SIGNATURE_BUFFER __user *uarg = (void __user *) arg; ++ CSMI_SAS_SATA_SIGNATURE_BUFFER karg; ++ MPT_ADAPTER *ioc = NULL; ++ int iocnum; ++ int rc, jj; ++ ConfigExtendedPageHeader_t hdr; ++ CONFIGPARMS cfg; ++ SasPhyPage0_t *sasPhyPg0; ++ dma_addr_t sasPhyPg0_dma; ++ int sasPhyPg0_data_sz; ++ SasDevicePage1_t *sasDevicePg1; ++ dma_addr_t sasDevicePg1_dma; ++ int sasDevicePg1_data_sz; ++ u8 phyId; ++ ++ dctlprintk((": %s called.\n",__FUNCTION__)); ++ sasPhyPg0=NULL; ++ sasPhyPg0_data_sz=0; ++ sasDevicePg1=NULL; ++ sasDevicePg1_data_sz=0; ++ ++ if (copy_from_user(&karg, uarg, ++ sizeof(CSMI_SAS_SATA_SIGNATURE_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to read in csmi_sas_sata_signature struct @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, ++ &ioc)) < 0) || (ioc == NULL)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not found!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ if (!mptctl_is_this_sas_cntr(ioc)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not SAS controller!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ phyId = karg.Signature.bPhyIdentifier; ++ if (phyId >= ioc->numPhys) { ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_PHY_DOES_NOT_EXIST; ++ dctlprintk((": phyId >= ioc->numPhys\n")); ++ goto cim_sata_signature_exit; ++ } ++ ++ /* Default to success.*/ ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; ++ ++ /* Issue a config request to get the devHandle of the attached device ++ */ ++ ++ /* Issue a config request to get phy information. */ ++ hdr.PageVersion = MPI_SASPHY0_PAGEVERSION; ++ hdr.ExtPageLength = 0; ++ hdr.PageNumber = 0; ++ hdr.Reserved1 = 0; ++ hdr.Reserved2 = 0; ++ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; ++ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY; ++ ++ cfg.cfghdr.ehdr = &hdr; ++ cfg.physAddr = -1; ++ cfg.pageAddr = phyId; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; ++ cfg.dir = 0; /* read */ ++ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; ++ ++ if ((rc = mpt_config(ioc, &cfg)) != 0) { ++ /* Don't check if this failed. Already in a ++ * failure case. ++ */ ++ dctlprintk((": FAILED: MPI_SASPHY0_PAGEVERSION: HEADER\n")); ++ dctlprintk((": rc=%x\n",rc)); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_sata_signature_exit; ++ } ++ ++ if (hdr.ExtPageLength == 0) { ++ /* Don't check if this failed. Already in a ++ * failure case. ++ */ ++ dctlprintk((": hdr.ExtPageLength == 0\n")); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_sata_signature_exit; ++ } ++ ++ ++ sasPhyPg0_data_sz = hdr.ExtPageLength * 4; ++ rc = -ENOMEM; ++ ++ sasPhyPg0 = (SasPhyPage0_t *) pci_alloc_consistent(ioc->pcidev, ++ sasPhyPg0_data_sz, &sasPhyPg0_dma); ++ ++ if (! sasPhyPg0) { ++ dctlprintk((": pci_alloc_consistent: FAILED\n")); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_sata_signature_exit; ++ } ++ ++ memset((u8 *)sasPhyPg0, 0, sasPhyPg0_data_sz); ++ cfg.physAddr = sasPhyPg0_dma; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; ++ ++ if ((rc = mpt_config(ioc, &cfg)) != 0) { ++ /* Don't check if this failed. Already in a ++ * failure case. ++ */ ++ dctlprintk((": FAILED: MPI_SASPHY0_PAGEVERSION: PAGE\n")); ++ dctlprintk((": rc=%x\n",rc)); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_sata_signature_exit; ++ } ++ ++ /* Make sure a SATA device is attached. */ ++ if ((le32_to_cpu(sasPhyPg0->AttachedDeviceInfo) & ++ MPI_SAS_DEVICE_INFO_SATA_DEVICE) == 0) { ++ dctlprintk((": NOT A SATA DEVICE\n")); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_SATA_DEVICE; ++ goto cim_sata_signature_exit; ++ } ++ ++ /* Get device page 1 for FIS signature. */ ++ hdr.PageVersion = MPI_SASDEVICE1_PAGEVERSION; ++ hdr.ExtPageLength = 0; ++ hdr.PageNumber = 1 /* page number 1 */; ++ hdr.Reserved1 = 0; ++ hdr.Reserved2 = 0; ++ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; ++ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE; ++ ++ cfg.cfghdr.ehdr = &hdr; ++ cfg.physAddr = -1; ++ ++ cfg.pageAddr = ((MPI_SAS_DEVICE_PGAD_FORM_HANDLE << ++ MPI_SAS_DEVICE_PGAD_FORM_SHIFT) | ++ le16_to_cpu(sasPhyPg0->AttachedDevHandle)); ++ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; ++ cfg.dir = 0; /* read */ ++ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; ++ ++ if ((rc = mpt_config(ioc, &cfg)) != 0) { ++ dctlprintk((": FAILED: MPI_SASDEVICE1_PAGEVERSION: HEADER\n")); ++ dctlprintk((": rc=%x\n",rc)); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_sata_signature_exit; ++ } ++ ++ if (hdr.ExtPageLength == 0) { ++ dctlprintk((": hdr.ExtPageLength == 0\n")); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_sata_signature_exit; ++ } ++ ++ sasDevicePg1_data_sz = hdr.ExtPageLength * 4; ++ rc = -ENOMEM; ++ ++ sasDevicePg1 = (SasDevicePage1_t *) pci_alloc_consistent ++ (ioc->pcidev, sasDevicePg1_data_sz, &sasDevicePg1_dma); ++ ++ if (! sasDevicePg1) { ++ dctlprintk((": pci_alloc_consistent: FAILED\n")); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_sata_signature_exit; ++ } ++ ++ memset((u8 *)sasDevicePg1, 0, sasDevicePg1_data_sz); ++ cfg.physAddr = sasDevicePg1_dma; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; ++ ++ if ((rc = mpt_config(ioc, &cfg)) != 0) { ++ dctlprintk((": FAILED: MPI_SASDEVICE1_PAGEVERSION: PAGE\n")); ++ dctlprintk((": rc=%x\n",rc)); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_sata_signature_exit; ++ } ++ ++/* EDM : dump Device Page 1 data*/ ++ dsasprintk(("---- SAS DEVICE PAGE 1 ---------\n")); ++ dsasprintk(("Handle=0x%x\n",sasDevicePg1->DevHandle)); ++ dsasprintk(("SAS Address=")); ++ for(jj=0;jj<8;jj++) ++ dsasprintk(("%02x ", ++ ((u8 *)&sasDevicePg1->SASAddress)[jj])); ++ dsasprintk(("\n")); ++ dsasprintk(("Target ID=0x%x\n",sasDevicePg1->TargetID)); ++ dsasprintk(("Bus=0x%x\n",sasDevicePg1->Bus)); ++ dsasprintk(("Initial Reg Device FIS=")); ++ for(jj=0;jj<20;jj++) ++ dsasprintk(("%02x ", ++ ((u8 *)&sasDevicePg1->InitialRegDeviceFIS)[jj])); ++ dsasprintk(("\n\n")); ++/* EDM : debug data */ ++ ++ memcpy(karg.Signature.bSignatureFIS, ++ sasDevicePg1->InitialRegDeviceFIS,20); ++ ++cim_sata_signature_exit: ++ ++ if (sasPhyPg0) ++ pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz, ++ (u8 *) sasPhyPg0, sasPhyPg0_dma); ++ ++ if (sasDevicePg1) ++ pci_free_consistent(ioc->pcidev, sasDevicePg1_data_sz, ++ (u8 *) sasDevicePg1, sasDevicePg1_dma); ++ ++ /* Copy the data from kernel memory to user memory ++ */ ++ if (copy_to_user((char *)arg, &karg, ++ sizeof(CSMI_SAS_SATA_SIGNATURE_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to write out csmi_sas_sata_signature @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* Prototype Routine for the CSMI Sas Get SCSI Address command. ++ * ++ * Outputs: None. ++ * Return: 0 if successful ++ * -EFAULT if data unavailable ++ * -ENODEV if no such device/adapter ++ */ ++static int ++mptctl_csmi_sas_get_device_address(unsigned long arg) ++{ ++ CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER __user *uarg = (void __user *) arg; ++ CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER karg; ++ MPT_ADAPTER *ioc = NULL; ++ int iocnum; ++ sas_device_info_t *sasDevice; ++ u64 SASAddress64; ++ ++ dctlprintk((": %s called.\n",__FUNCTION__)); ++ ++ if (copy_from_user(&karg, uarg, ++ sizeof(CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to read in csmi_sas_get_device_address_buffer struct @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, ++ &ioc)) < 0) || (ioc == NULL)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not found!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ if (!mptctl_is_this_sas_cntr(ioc)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not SAS controller!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ /* Fill in the data and return the structure to the calling ++ * program ++ */ ++ ++ /* Search the list for the matching SAS address. */ ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_NO_DEVICE_ADDRESS; ++ list_for_each_entry(sasDevice, &ioc->sasDeviceList, list) { ++ ++ /* Find the matching device. */ ++ if ((karg.bPathId == sasDevice->Bus) && ++ (karg.bTargetId == sasDevice->TargetId)) { ++ ++ SASAddress64 = reverse_byte_order64(&sasDevice->SASAddress); ++ memcpy(&karg.bSASAddress,&SASAddress64,sizeof(u64)); ++ karg.bSASLun[0] = karg.bLun; ++ memset(karg.bSASLun, 0, sizeof(karg.bSASLun)); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; ++ break; ++ } else ++ /* Keep looking. */ ++ continue; ++ } ++ ++ /* Copy the data from kernel memory to user memory ++ */ ++ if (copy_to_user((char *)arg, &karg, ++ sizeof(CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to write out csmi_sas_get_device_address_buffer @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ return 0; ++ ++} ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* Prototype Routine for the CSMI Sas Get Link Errors command. ++ * ++ * Outputs: None. ++ * Return: 0 if successful ++ * -EFAULT if data unavailable ++ * -ENODEV if no such device/adapter ++ */ ++static int ++mptctl_csmi_sas_get_link_errors(unsigned long arg) ++{ ++ CSMI_SAS_LINK_ERRORS_BUFFER __user *uarg = (void __user *) arg; ++ CSMI_SAS_LINK_ERRORS_BUFFER karg; ++ MPT_ADAPTER *ioc = NULL; ++ MPT_FRAME_HDR *mf = NULL; ++ MPIHeader_t *mpi_hdr; ++ int iocnum; ++ int rc,ii; ++ ConfigExtendedPageHeader_t hdr; ++ CONFIGPARMS cfg; ++ SasPhyPage1_t *sasPhyPage1; ++ dma_addr_t sasPhyPage1_dma; ++ int sasPhyPage1_data_sz; ++ SasIoUnitControlRequest_t *sasIoUnitCntrReq; ++ SasIoUnitControlReply_t *sasIoUnitCntrReply; ++ u8 phyId; ++ int wait_timeout; ++ ++ dctlprintk((": %s called.\n",__FUNCTION__)); ++ sasPhyPage1=NULL; ++ sasPhyPage1_data_sz=0; ++ ++ if (copy_from_user(&karg, uarg, ++ sizeof(CSMI_SAS_LINK_ERRORS_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to read in mptctl_csmi_sas_get_link_errors struct @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, ++ &ioc)) < 0) || (ioc == NULL)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not found!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ if (!mptctl_is_this_sas_cntr(ioc)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not SAS controller!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ phyId = karg.Information.bPhyIdentifier; ++ if (phyId >= ioc->numPhys) { ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_PHY_DOES_NOT_EXIST; ++ dctlprintk((": phyId >= ioc->numPhys\n")); ++ goto cim_get_link_errors_exit; ++ } ++ ++ /* Default to success.*/ ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; ++ ++ /* Issue a config request to get the devHandle of the attached device ++ */ ++ ++ /* Issue a config request to get phy information. */ ++ hdr.PageVersion = MPI_SASPHY1_PAGEVERSION; ++ hdr.ExtPageLength = 0; ++ hdr.PageNumber = 1 /* page number 1*/; ++ hdr.Reserved1 = 0; ++ hdr.Reserved2 = 0; ++ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; ++ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY; ++ ++ cfg.cfghdr.ehdr = &hdr; ++ cfg.physAddr = -1; ++ cfg.pageAddr = phyId; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; ++ cfg.dir = 0; /* read */ ++ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; ++ ++ if ((rc = mpt_config(ioc, &cfg)) != 0) { ++ /* Don't check if this failed. Already in a ++ * failure case. ++ */ ++ dctlprintk((": FAILED: MPI_SASPHY1_PAGEVERSION: HEADER\n")); ++ dctlprintk((": rc=%x\n",rc)); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_get_link_errors_exit; ++ } ++ ++ if (hdr.ExtPageLength == 0) { ++ /* Don't check if this failed. Already in a ++ * failure case. ++ */ ++ dctlprintk((": hdr.ExtPageLength == 0\n")); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_get_link_errors_exit; ++ } ++ ++ ++ sasPhyPage1_data_sz = hdr.ExtPageLength * 4; ++ rc = -ENOMEM; ++ ++ sasPhyPage1 = (SasPhyPage1_t *) pci_alloc_consistent(ioc->pcidev, ++ sasPhyPage1_data_sz, &sasPhyPage1_dma); ++ ++ if (! sasPhyPage1) { ++ dctlprintk((": pci_alloc_consistent: FAILED\n")); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_get_link_errors_exit; ++ } ++ ++ memset((u8 *)sasPhyPage1, 0, sasPhyPage1_data_sz); ++ cfg.physAddr = sasPhyPage1_dma; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; ++ ++ if ((rc = mpt_config(ioc, &cfg)) != 0) { ++ /* Don't check if this failed. Already in a ++ * failure case. ++ */ ++ dctlprintk((": FAILED: MPI_SASPHY1_PAGEVERSION: PAGE\n")); ++ dctlprintk((": rc=%x\n",rc)); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_get_link_errors_exit; ++ } ++ ++/* EDM : dump PHY Page 1 data*/ ++ dsasprintk(("---- SAS PHY PAGE 1 ------------\n")); ++ dsasprintk(("Invalid Dword Count=0x%x\n", ++ sasPhyPage1->InvalidDwordCount)); ++ dsasprintk(("Running Disparity Error Count=0x%x\n", ++ sasPhyPage1->RunningDisparityErrorCount)); ++ dsasprintk(("Loss Dword Synch Count=0x%x\n", ++ sasPhyPage1->LossDwordSynchCount)); ++ dsasprintk(("PHY Reset Problem Count=0x%x\n", ++ sasPhyPage1->PhyResetProblemCount)); ++ dsasprintk(("\n\n")); ++/* EDM : debug data */ ++ ++ karg.Information.uInvalidDwordCount = ++ le32_to_cpu(sasPhyPage1->InvalidDwordCount); ++ karg.Information.uRunningDisparityErrorCount = ++ le32_to_cpu(sasPhyPage1->RunningDisparityErrorCount); ++ karg.Information.uLossOfDwordSyncCount = ++ le32_to_cpu(sasPhyPage1->LossDwordSynchCount); ++ karg.Information.uPhyResetProblemCount = ++ le32_to_cpu(sasPhyPage1->PhyResetProblemCount); ++ ++ if (karg.Information.bResetCounts == ++ CSMI_SAS_LINK_ERROR_DONT_RESET_COUNTS ) { ++ goto cim_get_link_errors_exit; ++ } ++ ++ /* Clear Error log ++ * ++ * Issue IOUNIT Control Reqeust Message ++ */ ++ ++ /* Get a MF for this command. ++ */ ++ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) { ++ dctlprintk((": no msg frames!\n")); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_get_link_errors_exit; ++ } ++ ++ mpi_hdr = (MPIHeader_t *) mf; ++ sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf; ++ memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t)); ++ sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL; ++ sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext; ++ sasIoUnitCntrReq->PhyNum = phyId; ++ sasIoUnitCntrReq->Operation = MPI_SAS_OP_PHY_CLEAR_ERROR_LOG; ++ ++ ioc->ioctl->wait_done = 0; ++ mpt_put_msg_frame(mptctl_id, ioc, mf); ++ ++ /* Now wait for the command to complete */ ++ wait_timeout=max_t(int,MPT_IOCTL_DEFAULT_TIMEOUT,karg.IoctlHeader.Timeout); ++ ii = wait_event_timeout(mptctl_wait, ++ ioc->ioctl->wait_done == 1, ++ HZ*wait_timeout); ++ ++ if(ii <=0 && (ioc->ioctl->wait_done != 1 )) { ++ /* Now we need to reset the board */ ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ mpt_free_msg_frame(ioc, mf); ++ mptctl_timeout_expired(ioc->ioctl); ++ goto cim_get_link_errors_exit; ++ } ++ ++ /* process the completed Reply Message Frame */ ++ if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) { ++ ++ sasIoUnitCntrReply = ++ (SasIoUnitControlReply_t *)ioc->ioctl->ReplyFrame; ++ ++ if ( le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) { ++ dctlprintk((": SAS IO Unit Control: ")); ++ dctlprintk(("IOCStatus=0x%X IOCLogInfo=0x%X\n", ++ sasIoUnitCntrReply->IOCStatus, ++ sasIoUnitCntrReply->IOCLogInfo)); ++ } ++ } ++ ++cim_get_link_errors_exit: ++ ++ ioc->ioctl->status &= ~(MPT_IOCTL_STATUS_TM_FAILED | ++ MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID | ++ MPT_IOCTL_STATUS_RF_VALID); ++ ++ if (sasPhyPage1) ++ pci_free_consistent(ioc->pcidev, sasPhyPage1_data_sz, ++ (u8 *) sasPhyPage1, sasPhyPage1_dma); ++ ++ /* Copy the data from kernel memory to user memory ++ */ ++ if (copy_to_user((char *)arg, &karg, ++ sizeof(CSMI_SAS_LINK_ERRORS_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to write out mptctl_csmi_sas_get_link_errors @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ return 0; ++ ++} ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* Prototype Routine for the CSMI SAS SMP Passthru command. ++ * ++ * Outputs: None. ++ * Return: 0 if successful ++ * -EFAULT if data unavailable ++ * -ENODEV if no such device/adapter ++ */ ++static int ++mptctl_csmi_sas_smp_passthru(unsigned long arg) ++{ ++ CSMI_SAS_SMP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg; ++ MPT_ADAPTER *ioc; ++ CSMI_SAS_SMP_PASSTHRU_BUFFER karg; ++ pSmpPassthroughRequest_t smpReq; ++ pSmpPassthroughReply_t smpReply; ++ MPT_FRAME_HDR *mf = NULL; ++ MPIHeader_t *mpi_hdr; ++ char *psge; ++ int iocnum, flagsLength,ii; ++ u8 index; ++ void * request_data; ++ dma_addr_t request_data_dma; ++ u32 request_data_sz; ++ void * response_data; ++ dma_addr_t response_data_dma; ++ u32 response_data_sz; ++ u16 ioc_stat; ++ int wait_timeout; ++ ++ dctlprintk((": %s called.\n",__FUNCTION__)); ++ ++ if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SMP_PASSTHRU_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to read in csmi_sas_smp_passthru struct @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ request_data = NULL; ++ response_data = NULL; ++ response_data_sz = sizeof(CSMI_SAS_SMP_RESPONSE); ++ request_data_sz = karg.Parameters.uRequestLength; ++ ++ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, ++ &ioc)) < 0) || (ioc == NULL)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not found!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ if (!mptctl_is_this_sas_cntr(ioc)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not SAS controller!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ /* Make sure the adapter is not being reset. */ ++ if (!ioc->ioctl) { ++ printk(KERN_ERR "%s@%d::%s - " ++ "No memory available during driver init.\n", ++ __FILE__, __LINE__,__FUNCTION__); ++ return -ENOMEM; ++ } else if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) { ++ printk(KERN_ERR "%s@%d::%s - " ++ "Busy with IOC Reset \n", ++ __FILE__, __LINE__,__FUNCTION__); ++ return -EBUSY; ++ } ++ ++ /* Default to success.*/ ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; ++ ++ /* Do some error checking on the request. */ ++ if (karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) { ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT; ++ goto cim_smp_passthru_exit; ++ } ++ ++ if ((request_data_sz > 0xFFFF) || (!request_data_sz)) { ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_smp_passthru_exit; ++ } ++ ++ /* Get a free request frame and save the message context. ++ */ ++ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) { ++ dctlprintk((": no msg frames!\n")); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_smp_passthru_exit; ++ } ++ ++ mpi_hdr = (MPIHeader_t *) mf; ++ smpReq = (pSmpPassthroughRequest_t ) mf; ++ ++ memset(smpReq,0,ioc->req_sz); ++ ++ /* Fill in smp request. */ ++ smpReq->PhysicalPort = karg.Parameters.bPortIdentifier; ++ smpReq->Function = MPI_FUNCTION_SMP_PASSTHROUGH; ++ smpReq->RequestDataLength = cpu_to_le16(request_data_sz); ++ smpReq->ConnectionRate = karg.Parameters.bConnectionRate; ++ smpReq->MsgContext = mpi_hdr->MsgContext; ++ for ( index = 0; index < 8; index++ ) { ++ ((u8*)&smpReq->SASAddress)[7 - index] = ++ karg.Parameters.bDestinationSASAddress[index]; ++ } ++ smpReq->Reserved2 = 0; ++ smpReq->Reserved3 = 0; ++ ++ /* ++ * Prepare the necessary pointers to run ++ * through the SGL generation ++ */ ++ ++ psge = (char *)&smpReq->SGL; ++ ++ /* setup the *Request* payload SGE */ ++ flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT | ++ MPI_SGE_FLAGS_SYSTEM_ADDRESS | ++ MPI_SGE_FLAGS_32_BIT_ADDRESSING | ++ MPI_SGE_FLAGS_HOST_TO_IOC | ++ MPI_SGE_FLAGS_END_OF_BUFFER; ++ ++ if (sizeof(dma_addr_t) == sizeof(u64)) { ++ flagsLength |= MPI_SGE_FLAGS_64_BIT_ADDRESSING; ++ } ++ flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT; ++ flagsLength |= request_data_sz; ++ ++ request_data = pci_alloc_consistent( ++ ioc->pcidev, request_data_sz, &request_data_dma); ++ ++ if (!request_data) { ++ dctlprintk((": pci_alloc_consistent: FAILED\n")); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ mpt_free_msg_frame(ioc, mf); ++ goto cim_smp_passthru_exit; ++ } ++ ++ mpt_add_sge(psge, flagsLength, request_data_dma); ++ psge += (sizeof(u32) + sizeof(dma_addr_t)); ++ ++ memcpy(request_data,&karg.Parameters.Request,request_data_sz); ++ ++ /* setup the *Response* payload SGE */ ++ response_data = pci_alloc_consistent( ++ ioc->pcidev, response_data_sz, &response_data_dma); ++ ++ if (!response_data) { ++ dctlprintk((": pci_alloc_consistent: FAILED\n")); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ mpt_free_msg_frame(ioc, mf); ++ goto cim_smp_passthru_exit; ++ } ++ ++ flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT | ++ MPI_SGE_FLAGS_SYSTEM_ADDRESS | ++ MPI_SGE_FLAGS_32_BIT_ADDRESSING | ++ MPI_SGE_FLAGS_IOC_TO_HOST | ++ MPI_SGE_FLAGS_END_OF_BUFFER; ++ ++ if (sizeof(dma_addr_t) == sizeof(u64)) { ++ flagsLength |= MPI_SGE_FLAGS_64_BIT_ADDRESSING; ++ } ++ ++ flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT; ++ flagsLength |= response_data_sz; ++ ++ mpt_add_sge(psge, flagsLength, response_data_dma); ++ ++ /* The request is complete. Set the timer parameters ++ * and issue the request. ++ */ ++ ioc->ioctl->wait_done = 0; ++ mpt_put_msg_frame(mptctl_id, ioc, mf); ++ ++ /* Now wait for the command to complete */ ++ wait_timeout=max_t(int,MPT_IOCTL_DEFAULT_TIMEOUT,karg.IoctlHeader.Timeout); ++ ii = wait_event_timeout(mptctl_wait, ++ ioc->ioctl->wait_done == 1, ++ HZ*wait_timeout); ++ ++ if(ii <=0 && (ioc->ioctl->wait_done != 1 )) { ++ /* Now we need to reset the board */ ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ mpt_free_msg_frame(ioc, mf); ++ mptctl_timeout_expired(ioc->ioctl); ++ goto cim_smp_passthru_exit; ++ } ++ ++ if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) == 0) { ++ dctlprintk((": SMP Passthru: oh no, there is no reply!!")); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_smp_passthru_exit; ++ } ++ ++ /* process the completed Reply Message Frame */ ++ smpReply = (pSmpPassthroughReply_t )ioc->ioctl->ReplyFrame; ++ ioc_stat = le16_to_cpu(smpReply->IOCStatus) & MPI_IOCSTATUS_MASK; ++ ++ if ((ioc_stat != MPI_IOCSTATUS_SUCCESS) && ++ (ioc_stat != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN)) { ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ dctlprintk((": SMP Passthru: ")); ++ dctlprintk(("IOCStatus=0x%X IOCLogInfo=0x%X SASStatus=0x%X\n", ++ smpReply->IOCStatus, ++ smpReply->IOCLogInfo, ++ smpReply->SASStatus)); ++ goto cim_smp_passthru_exit; ++ } ++ ++ karg.Parameters.bConnectionStatus = ++ map_sas_status_to_csmi(smpReply->SASStatus); ++ ++ ++ if (le16_to_cpu(smpReply->ResponseDataLength)) { ++ karg.Parameters.uResponseBytes = le16_to_cpu(smpReply->ResponseDataLength); ++ memcpy(&karg.Parameters.Response, ++ response_data, le16_to_cpu(smpReply->ResponseDataLength)); ++ } ++ ++cim_smp_passthru_exit: ++ ++ ioc->ioctl->status &= ~( MPT_IOCTL_STATUS_TM_FAILED | ++ MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID | ++ MPT_IOCTL_STATUS_RF_VALID); ++ ++ if (request_data) ++ pci_free_consistent(ioc->pcidev, request_data_sz, ++ (u8 *)request_data, request_data_dma); ++ ++ if (response_data) ++ pci_free_consistent(ioc->pcidev, response_data_sz, ++ (u8 *)response_data, response_data_dma); ++ ++ ++ /* Copy the data from kernel memory to user memory ++ */ ++ if (copy_to_user((char *)arg, &karg, ++ sizeof(CSMI_SAS_SMP_PASSTHRU_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to write out csmi_sas_smp_passthru @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ return 0; ++ ++} ++ ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* Prototype Routine for the CSMI SAS SSP Passthru command. ++ * ++ * Outputs: None. ++ * Return: 0 if successful ++ * -EFAULT if data unavailable ++ * -ENODEV if no such device/adapter ++ */ ++static int mptctl_csmi_sas_ssp_passthru(unsigned long arg) ++{ ++ CSMI_SAS_SSP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg; ++ CSMI_SAS_SSP_PASSTHRU_BUFFER karg; ++ MPT_ADAPTER *ioc = NULL; ++ pSCSIIORequest_t pScsiRequest; ++ pSCSIIOReply_t pScsiReply; ++ MPT_FRAME_HDR *mf = NULL; ++ MPIHeader_t *mpi_hdr; ++ int iocnum,ii; ++ u32 data_sz; ++ u64 SASAddress64; ++ sas_device_info_t *sasDevice; ++ u16 req_idx; ++ char *psge; ++ int flagsLength; ++ void * request_data; ++ dma_addr_t request_data_dma; ++ u32 request_data_sz; ++ u8 found; ++ u16 ioc_stat; ++ u8 volume_id; ++ u8 volume_bus; ++ u8 quiese_io_flag=0; ++ u8 bus; ++ u8 target; ++ int wait_timeout; ++ ++ dctlprintk((": %s called.\n",__FUNCTION__)); ++ ++ if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SSP_PASSTHRU_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to read in csmi_sas_ssp_passthru struct @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ request_data=NULL; ++ request_data_sz = karg.Parameters.uDataLength; ++ bus=0; ++ target=0; ++ volume_id=0; ++ volume_bus=0; ++ ++ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, ++ &ioc)) < 0) || (ioc == NULL)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not found!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ if (!mptctl_is_this_sas_cntr(ioc)) { ++ dctlprintk((KERN_ERR ++ "%s::%s()" ++ " @%d - ioc%d not SAS controller!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ /* Default to success. ++ */ ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; ++ ++ /* Neither a phy nor a port has been selected. ++ */ ++ if ((karg.Parameters.bPhyIdentifier == CSMI_SAS_USE_PORT_IDENTIFIER) && ++ (karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT)) { ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT; ++ dctlprintk((KERN_ERR ++ "%s::%s()" ++ " @%d - incorrect bPhyIdentifier and bPortIdentifier!\n", ++ __FILE__, __FUNCTION__, __LINE__)); ++ goto cim_ssp_passthru_exit; ++ } ++ ++ /* A phy has been selected. Verify that it's valid. ++ */ ++ if (karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) { ++ ++ /* Is the phy in range? */ ++ if (karg.Parameters.bPhyIdentifier >= ioc->numPhys) { ++ karg.IoctlHeader.ReturnCode = ++ CSMI_SAS_PHY_DOES_NOT_EXIST; ++ goto cim_ssp_passthru_exit; ++ } ++ } ++ ++ /* some checks of the incoming frame ++ */ ++ if (request_data_sz > 0xFFFF) { ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ dctlprintk((KERN_ERR ++ "%s::%s()" ++ " @%d - uDataLength > 0xFFFF!\n", ++ __FILE__, __FUNCTION__, __LINE__)); ++ goto cim_ssp_passthru_exit; ++ } ++ ++ data_sz = sizeof(CSMI_SAS_SSP_PASSTHRU_BUFFER) - ++ sizeof(IOCTL_HEADER) - sizeof(u8*) + ++ request_data_sz; ++ ++ if ( data_sz > karg.IoctlHeader.Length ) { ++ karg.IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_INVALID_PARAMETER; ++ dctlprintk((KERN_ERR ++ "%s::%s()" ++ " @%d - expected datalen incorrect!\n", ++ __FILE__, __FUNCTION__, __LINE__)); ++ goto cim_ssp_passthru_exit; ++ } ++ ++ /* we will use SAS address to resolve the scsi adddressing ++ */ ++ memcpy(&SASAddress64,karg.Parameters.bDestinationSASAddress, ++ sizeof(u64)); ++ SASAddress64 = reverse_byte_order64(&SASAddress64); ++ ++ /* Search the list for the matching SAS address. ++ */ ++ found = FALSE; ++ list_for_each_entry(sasDevice, &ioc->sasDeviceList, list) { ++ ++ /* Find the matching device. ++ */ ++ if (sasDevice->SASAddress != SASAddress64) ++ continue; ++ ++ found = TRUE; ++ bus = sasDevice->Bus; ++ target = sasDevice->TargetId; ++ break; ++ } ++ ++ /* Invalid SAS address ++ */ ++ if (found == FALSE) { ++ karg.IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_INVALID_PARAMETER; ++ dctlprintk((KERN_ERR ++ "%s::%s()" ++ " @%d - couldn't find associated SASAddress!\n", ++ __FILE__, __FUNCTION__, __LINE__)); ++ goto cim_ssp_passthru_exit; ++ } ++ ++ if(karg.Parameters.bAdditionalCDBLength) { ++ /* TODO - SCSI IO (32) Request Message support ++ */ ++ dctlprintk((": greater than 16-byte cdb is not supported!\n")); ++ karg.IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_INVALID_PARAMETER; ++ goto cim_ssp_passthru_exit; ++ } ++ ++ /* see if this is for raid phy disk */ ++ if (ioc->raid_data.isRaid && ioc->raid_data.pIocPg3) { ++ for (ii = 0; (ii<ioc->raid_data.pIocPg3->NumPhysDisks && ++ quiese_io_flag==0); ii++) { ++ if (target == ioc->raid_data.pIocPg3->PhysDisk[ii].PhysDiskID) { ++ target = ioc->raid_data.pIocPg3->PhysDisk[ii].PhysDiskNum; ++ quiese_io_flag=1; ++ } ++ } ++ } ++#ifdef QUIESE_IO ++ /* if RAID Volume, then quiesce io to phys disk*/ ++ if (quiese_io_flag==1) { ++ if (mptctl_raid_get_volume_id(ioc, target, ++ &volume_id, &volume_bus) != 0) { ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_ssp_passthru_exit; ++ } ++ mptctl_do_raid(ioc, ++ MPI_RAID_ACTION_QUIESCE_PHYS_IO, ++ target, volume_bus, volume_id, NULL); ++ } ++#endif ++ /* Get a free request frame and save the message context. ++ */ ++ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) { ++ dctlprintk((": no msg frames!\n")); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_ssp_passthru_exit; ++ } ++ ++ mpi_hdr = (MPIHeader_t *) mf; ++ pScsiRequest = (pSCSIIORequest_t) mf; ++ req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); ++ ++ memset(pScsiRequest,0,sizeof(SCSIIORequest_t)); ++ ++ /* Fill in SCSI IO (16) request. ++ */ ++ ++ pScsiRequest->Function = (quiese_io_flag==1) ? ++ MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH : MPI_FUNCTION_SCSI_IO_REQUEST; ++ pScsiRequest->TargetID = target; ++ pScsiRequest->Bus = bus; ++ memcpy(pScsiRequest->LUN,karg.Parameters.bLun,8); ++ pScsiRequest->CDBLength = karg.Parameters.bCDBLength; ++ pScsiRequest->DataLength = cpu_to_le16(request_data_sz); ++ pScsiRequest->MsgContext = mpi_hdr->MsgContext; ++ memcpy(pScsiRequest->CDB,karg.Parameters.bCDB, ++ pScsiRequest->CDBLength); ++ ++ /* direction ++ */ ++ if (karg.Parameters.uFlags & CSMI_SAS_SSP_READ) { ++ pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ); ++ } else if (karg.Parameters.uFlags & CSMI_SAS_SSP_WRITE) { ++ pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_WRITE); ++ } else if ((karg.Parameters.uFlags & CSMI_SAS_SSP_UNSPECIFIED) && ++ (!karg.Parameters.uDataLength)) { ++ /* no data transfer ++ */ ++ pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_NODATATRANSFER); ++ } else { ++ /* no direction specified ++ */ ++ pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ); ++ pScsiRequest->MsgFlags = ++ MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR; ++ } ++ ++ /* task attributes ++ */ ++ if((karg.Parameters.uFlags && 0xFF) == 0) { ++ pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_SIMPLEQ); ++ } else if (karg.Parameters.uFlags & ++ CSMI_SAS_SSP_TASK_ATTRIBUTE_HEAD_OF_QUEUE) { ++ pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_HEADOFQ); ++ } else if (karg.Parameters.uFlags & ++ CSMI_SAS_SSP_TASK_ATTRIBUTE_ORDERED) { ++ pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_ORDEREDQ); ++ } else if (karg.Parameters.uFlags & ++ CSMI_SAS_SSP_TASK_ATTRIBUTE_ACA) { ++ pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_ACAQ); ++ } else { ++ pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_UNTAGGED); ++ } ++ ++ /* setup sense ++ */ ++ pScsiRequest->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; ++ pScsiRequest->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma + ++ (req_idx * MPT_SENSE_BUFFER_ALLOC)); ++ ++ /* setup databuffer sg, assuming we fit everything one contiguous buffer ++ */ ++ psge = (char *)&pScsiRequest->SGL; ++ ++ if (karg.Parameters.uFlags & CSMI_SAS_SSP_WRITE) { ++ flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE; ++ } else if (karg.Parameters.uFlags & CSMI_SAS_SSP_READ) { ++ flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ; ++ }else { ++ flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT | ++ MPI_SGE_FLAGS_DIRECTION | ++ mpt_addr_size() ) ++ << MPI_SGE_FLAGS_SHIFT; ++ } ++ flagsLength |= request_data_sz; ++ ++ if ( request_data_sz > 0) { ++ request_data = pci_alloc_consistent( ++ ioc->pcidev, request_data_sz, &request_data_dma); ++ ++ if (request_data == NULL) { ++ dctlprintk((": pci_alloc_consistent: FAILED request_data_sz=%d\n", request_data_sz)); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ mpt_free_msg_frame(ioc, mf); ++ goto cim_ssp_passthru_exit; ++ } ++ ++ mpt_add_sge(psge, flagsLength, request_data_dma); ++ ++ if (karg.Parameters.uFlags & CSMI_SAS_SSP_WRITE) { ++ ++ if (copy_from_user(request_data, ++ karg.bDataBuffer, ++ request_data_sz)) { ++ printk(KERN_ERR ++ "%s@%d::%s - Unable " ++ "to read user data " ++ "struct @ %p\n", ++ __FILE__, __LINE__,__FUNCTION__, ++ (void*)karg.bDataBuffer); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ mpt_free_msg_frame(ioc, mf); ++ goto cim_ssp_passthru_exit; ++ } ++ } ++ } else { ++ mpt_add_sge(psge, flagsLength, (dma_addr_t) -1); ++ } ++ ++ /* The request is complete. Set the timer parameters ++ * and issue the request. ++ */ ++ ioc->ioctl->wait_done = 0; ++ mpt_put_msg_frame(mptctl_id, ioc, mf); ++ ++ /* Now wait for the command to complete */ ++ wait_timeout=max_t(int,MPT_IOCTL_DEFAULT_TIMEOUT,karg.IoctlHeader.Timeout); ++ ii = wait_event_timeout(mptctl_wait, ++ ioc->ioctl->wait_done == 1, ++ HZ*wait_timeout); ++ ++ if(ii <=0 && (ioc->ioctl->wait_done != 1 )) { ++ /* Now we need to reset the board */ ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ mpt_free_msg_frame(ioc, mf); ++ mptctl_timeout_expired(ioc->ioctl); ++ goto cim_ssp_passthru_exit; ++ } ++ ++ memset(&karg.Status,0,sizeof(CSMI_SAS_SSP_PASSTHRU_STATUS)); ++ karg.Status.bConnectionStatus = CSMI_SAS_OPEN_ACCEPT; ++ karg.Status.bDataPresent = CSMI_SAS_SSP_NO_DATA_PRESENT; ++ karg.Status.bStatus = GOOD; ++ karg.Status.bResponseLength[0] = 0; ++ karg.Status.bResponseLength[1] = 0; ++ karg.Status.uDataBytes = request_data_sz; ++ ++ /* process the completed Reply Message Frame */ ++ if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) { ++ ++ pScsiReply = (pSCSIIOReply_t ) ioc->ioctl->ReplyFrame; ++ karg.Status.bStatus = pScsiReply->SCSIStatus; ++ karg.Status.uDataBytes = min(le32_to_cpu(pScsiReply->TransferCount), ++ request_data_sz); ++ ioc_stat = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK; ++ ++ if (pScsiReply->SCSIState == ++ MPI_SCSI_STATE_AUTOSENSE_VALID) { ++ karg.Status.bConnectionStatus = ++ CSMI_SAS_SSP_SENSE_DATA_PRESENT; ++ karg.Status.bResponseLength[0] = ++ (u8)le32_to_cpu(pScsiReply->SenseCount) & 0xFF; ++ memcpy(karg.Status.bResponse, ++ ioc->ioctl->sense, le32_to_cpu(pScsiReply->SenseCount)); ++ } else if(pScsiReply->SCSIState == ++ MPI_SCSI_STATE_RESPONSE_INFO_VALID) { ++ karg.Status.bDataPresent = ++ CSMI_SAS_SSP_RESPONSE_DATA_PRESENT; ++ karg.Status.bResponseLength[0] = ++ sizeof(pScsiReply->ResponseInfo); ++ for (ii=0;ii<sizeof(pScsiReply->ResponseInfo);ii++) { ++ karg.Status.bResponse[ii] = ++ ((u8*)&pScsiReply->ResponseInfo)[ ++ (sizeof(pScsiReply->ResponseInfo)-1)-ii]; ++ } ++ } else if ((ioc_stat != MPI_IOCSTATUS_SUCCESS) && ++ (ioc_stat != MPI_IOCSTATUS_SCSI_RECOVERED_ERROR) && ++ (ioc_stat != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN)) { ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ dctlprintk((": SCSI IO : ")); ++ dctlprintk(("IOCStatus=0x%X IOCLogInfo=0x%X\n", ++ pScsiReply->IOCStatus, ++ pScsiReply->IOCLogInfo)); ++ } ++ } ++ ++ if ((karg.Status.uDataBytes) && (request_data) && ++ (karg.Parameters.uFlags & CSMI_SAS_SSP_READ)) { ++ if (copy_to_user((char *)uarg->bDataBuffer, ++ request_data, karg.Status.uDataBytes)) { ++ printk(KERN_ERR "%s@%d::%s - " ++ "Unable to write data to user %p\n", ++ __FILE__, __LINE__,__FUNCTION__, ++ (void*)karg.bDataBuffer); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ } ++ } ++ ++cim_ssp_passthru_exit: ++ ++ ioc->ioctl->status &= ~( MPT_IOCTL_STATUS_TM_FAILED | ++ MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID | ++ MPT_IOCTL_STATUS_RF_VALID); ++ ++ if (request_data) ++ pci_free_consistent(ioc->pcidev, request_data_sz, ++ (u8 *)request_data, request_data_dma); ++ ++#ifdef QUIESE_IO ++ if (quiese_io_flag) { ++ mptctl_do_raid(ioc, ++ MPI_RAID_ACTION_ENABLE_PHYS_IO, ++ target, volume_bus, volume_id, NULL); ++ } ++#endif ++ /* Copy the data from kernel memory to user memory ++ */ ++ if (copy_to_user((char *)arg, &karg, ++ offsetof(CSMI_SAS_SSP_PASSTHRU_BUFFER,bDataBuffer))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to write out csmi_sas_ssp_passthru @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* Prototype Routine for the CSMI SAS STP Passthru command. ++ * ++ * Outputs: None. ++ * Return: 0 if successful ++ * -EFAULT if data unavailable ++ * -ENODEV if no such device/adapter ++ */ ++static int ++mptctl_csmi_sas_stp_passthru(unsigned long arg) ++{ ++ CSMI_SAS_STP_PASSTHRU_BUFFER __user *uarg = (void __user *) arg; ++ CSMI_SAS_STP_PASSTHRU_BUFFER karg; ++ MPT_ADAPTER *ioc = NULL; ++ pSataPassthroughRequest_t pSataRequest; ++ pSataPassthroughReply_t pSataReply; ++ MPT_FRAME_HDR *mf = NULL; ++ MPIHeader_t *mpi_hdr; ++ int iocnum,ii; ++ u32 data_sz; ++ u64 SASAddress64; ++ sas_device_info_t *sasDevice=NULL; ++ u16 req_idx; ++ char *psge; ++ int flagsLength; ++ void * request_data; ++ dma_addr_t request_data_dma; ++ u32 request_data_sz; ++ u8 found; ++ u8 bus; ++ u8 target; ++ u8 volume_id; ++ u8 volume_bus; ++#ifdef QUIESE_IO ++ u8 quiese_io_flag=0; ++ u8 phys_disk_num=0; ++#endif ++ int wait_timeout; ++ ++ dctlprintk((": %s called.\n",__FUNCTION__)); ++ ++ if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_STP_PASSTHRU_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to read struct @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ request_data=NULL; ++ request_data_sz = karg.Parameters.uDataLength; ++ volume_id=0; ++ volume_bus=0; ++ bus=0; ++ target=0; ++ ++ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, ++ &ioc)) < 0) || (ioc == NULL)) { ++ dctlprintk((KERN_ERR ++ "%s::%s @%d - ioc%d not found!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ if (!mptctl_is_this_sas_cntr(ioc)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not SAS controller!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ /* Default to success. ++ */ ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; ++ ++ /* Neither a phy nor a port has been selected. ++ */ ++ if ((karg.Parameters.bPhyIdentifier == CSMI_SAS_USE_PORT_IDENTIFIER) && ++ (karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT)) { ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_SELECT_PHY_OR_PORT; ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - incorrect bPhyIdentifier and bPortIdentifier!\n", ++ __FILE__,__FUNCTION__, __LINE__)); ++ goto cim_stp_passthru_exit; ++ } ++ ++ /* A phy has been selected. Verify that it's valid. ++ */ ++ if (karg.Parameters.bPortIdentifier == CSMI_SAS_IGNORE_PORT) { ++ ++ /* Is the phy in range? */ ++ if (karg.Parameters.bPhyIdentifier >= ioc->numPhys) { ++ karg.IoctlHeader.ReturnCode = ++ CSMI_SAS_PHY_DOES_NOT_EXIST; ++ goto cim_stp_passthru_exit; ++ } ++ } ++ ++ /* some checks of the incoming frame ++ */ ++ if (request_data_sz > 0xFFFF) { ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - uDataLength > 0xFFFF!\n", ++ __FILE__, __FUNCTION__, __LINE__)); ++ goto cim_stp_passthru_exit; ++ } ++ ++ data_sz = sizeof(CSMI_SAS_STP_PASSTHRU_BUFFER) - ++ sizeof(IOCTL_HEADER) - sizeof(u8*) + ++ request_data_sz; ++ ++ if ( data_sz > karg.IoctlHeader.Length ) { ++ karg.IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_INVALID_PARAMETER; ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - expected datalen incorrect!\n", ++ __FILE__, __FUNCTION__,__LINE__)); ++ goto cim_stp_passthru_exit; ++ } ++ ++ /* we will use SAS address to resolve the scsi adddressing ++ */ ++ memcpy(&SASAddress64,karg.Parameters.bDestinationSASAddress, ++ sizeof(u64)); ++ SASAddress64 = reverse_byte_order64(&SASAddress64); ++ ++ /* Search the list for the matching SAS address. ++ */ ++ found = FALSE; ++ list_for_each_entry(sasDevice, &ioc->sasDeviceList, list) { ++ ++ /* Find the matching device. ++ */ ++ if (sasDevice->SASAddress != SASAddress64) ++ continue; ++ ++ found = TRUE; ++ bus = sasDevice->Bus; ++ target = sasDevice->TargetId;; ++ break; ++ } ++ ++ /* Invalid SAS address ++ */ ++ if (found == FALSE) { ++ karg.IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_INVALID_PARAMETER; ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - couldn't find associated SASAddress!\n", ++ __FILE__, __FUNCTION__, __LINE__)); ++ goto cim_stp_passthru_exit; ++ } ++ ++ /* check that this is an STP or SATA target device ++ */ ++ if ( !(sasDevice->DeviceInfo & MPI_SAS_DEVICE_INFO_STP_TARGET ) && ++ !(sasDevice->DeviceInfo & MPI_SAS_DEVICE_INFO_SATA_DEVICE )) { ++ karg.IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_INVALID_PARAMETER; ++ goto cim_stp_passthru_exit; ++ } ++ ++#ifdef QUIESE_IO ++ /* see if this is for raid phy disk */ ++ if (ioc->raid_data.isRaid && ioc->raid_data.pIocPg3) { ++ for (ii = 0; (ii<ioc->raid_data.pIocPg3->NumPhysDisks && ++ quiese_io_flag==0); ii++) ++ if (target == ioc->raid_data.pIocPg3->PhysDisk[ii].PhysDiskID) { ++ phys_disk_num = ioc->raid_data.pIocPg3->PhysDisk[ii].PhysDiskNum; ++ quiese_io_flag=1; ++ } ++ } ++ /* if RAID Volume, then quiesce io to phys disk*/ ++ if (quiese_io_flag==1) { ++ if (mptctl_raid_get_volume_id(ioc, phys_disk_num, ++ &volume_id, &volume_bus) != 0) { ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_stp_passthru_exit; ++ } ++ mptctl_do_raid(ioc, ++ MPI_RAID_ACTION_QUIESCE_PHYS_IO, ++ phys_disk_num, volume_bus, volume_id, NULL); ++ } ++#endif ++ /* Get a free request frame and save the message context. ++ */ ++ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) { ++ dctlprintk((": no msg frames!\n")); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_stp_passthru_exit; ++ } ++ ++ mpi_hdr = (MPIHeader_t *) mf; ++ pSataRequest = (pSataPassthroughRequest_t) mf; ++ req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); ++ ++ memset(pSataRequest,0,sizeof(pSataPassthroughRequest_t)); ++ ++ pSataRequest->TargetID = target; ++ pSataRequest->Bus = bus; ++ pSataRequest->Function = MPI_FUNCTION_SATA_PASSTHROUGH; ++ pSataRequest->PassthroughFlags = cpu_to_le16(karg.Parameters.uFlags); ++ pSataRequest->ConnectionRate = karg.Parameters.bConnectionRate; ++ pSataRequest->MsgContext = mpi_hdr->MsgContext; ++ pSataRequest->DataLength = cpu_to_le32(request_data_sz); ++ pSataRequest->MsgFlags = 0; ++ memcpy( pSataRequest->CommandFIS,karg.Parameters.bCommandFIS, 20); ++ ++ psge = (char *)&pSataRequest->SGL; ++ if (karg.Parameters.uFlags & CSMI_SAS_STP_WRITE) { ++ flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE; ++ } else if (karg.Parameters.uFlags & CSMI_SAS_STP_READ) { ++ flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ; ++ }else { ++ flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT | ++ MPI_SGE_FLAGS_DIRECTION | ++ mpt_addr_size() ) ++ << MPI_SGE_FLAGS_SHIFT; ++ } ++ ++ flagsLength |= request_data_sz; ++ if (request_data_sz > 0) { ++ request_data = pci_alloc_consistent( ++ ioc->pcidev, request_data_sz, &request_data_dma); ++ ++ if (request_data == NULL) { ++ dctlprintk((": pci_alloc_consistent: FAILED\n")); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ mpt_free_msg_frame(ioc, mf); ++ goto cim_stp_passthru_exit; ++ } ++ ++ mpt_add_sge(psge, flagsLength, request_data_dma); ++ if (karg.Parameters.uFlags & CSMI_SAS_STP_WRITE) { ++ if (copy_from_user(request_data, ++ karg.bDataBuffer, ++ request_data_sz)) { ++ printk(KERN_ERR ++ "%s::%s() @%d - Unable to read user data " ++ "struct @ %p\n", ++ __FILE__, __FUNCTION__, __LINE__, ++ (void*)karg.bDataBuffer); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ mpt_free_msg_frame(ioc, mf); ++ goto cim_stp_passthru_exit; ++ } ++ } ++ } else { ++ mpt_add_sge(psge, flagsLength, (dma_addr_t) -1); ++ } ++ ++ /* The request is complete. Set the timer parameters ++ * and issue the request. ++ */ ++ ioc->ioctl->wait_done = 0; ++ mpt_put_msg_frame(mptctl_id, ioc, mf); ++ ++ /* Now wait for the command to complete */ ++ wait_timeout=max_t(int,MPT_IOCTL_DEFAULT_TIMEOUT,karg.IoctlHeader.Timeout); ++ ii = wait_event_timeout(mptctl_wait, ++ ioc->ioctl->wait_done == 1, ++ HZ*wait_timeout); ++ ++ if(ii <=0 && (ioc->ioctl->wait_done != 1 )) { ++ /* Now we need to reset the board */ ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ mpt_free_msg_frame(ioc, mf); ++ mptctl_timeout_expired(ioc->ioctl); ++ goto cim_stp_passthru_exit; ++ } ++ ++ memset(&karg.Status,0,sizeof(CSMI_SAS_STP_PASSTHRU_STATUS)); ++ ++ if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) == 0) { ++ dctlprintk((": STP Passthru: oh no, there is no reply!!")); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_stp_passthru_exit; ++ } ++ ++ /* process the completed Reply Message Frame */ ++ pSataReply = (pSataPassthroughReply_t ) ioc->ioctl->ReplyFrame; ++ ++ if ((le16_to_cpu(pSataReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) && ++ (le16_to_cpu(pSataReply->IOCStatus) != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN )) { ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ dctlprintk((": STP Passthru: ")); ++ dctlprintk(("IOCStatus=0x%X IOCLogInfo=0x%X SASStatus=0x%X\n", ++ le16_to_cpu(pSataReply->IOCStatus), ++ le32_to_cpu(pSataReply->IOCLogInfo), ++ pSataReply->SASStatus)); ++ } ++ ++ karg.Status.bConnectionStatus = ++ map_sas_status_to_csmi(pSataReply->SASStatus); ++ ++ memcpy(karg.Status.bStatusFIS,pSataReply->StatusFIS, 20); ++ ++ /* ++ * for now, just zero out uSCR array, ++ * then copy the one dword returned ++ * in the reply frame into uSCR[0] ++ */ ++ memset( karg.Status.uSCR, 0, 64); ++ karg.Status.uSCR[0] = le32_to_cpu(pSataReply->StatusControlRegisters); ++ ++ if((le32_to_cpu(pSataReply->TransferCount)) && (request_data) && ++ (karg.Parameters.uFlags & CSMI_SAS_STP_READ)) { ++ karg.Status.uDataBytes = ++ min(le32_to_cpu(pSataReply->TransferCount),request_data_sz); ++ if (copy_to_user((char *)uarg->bDataBuffer, ++ request_data, karg.Status.uDataBytes)) { ++ printk(KERN_ERR "%s::%s() @%d - " ++ "Unable to write data to user %p\n", ++ __FILE__, __FUNCTION__, __LINE__, ++ (void*)karg.bDataBuffer); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ } ++ } ++ ++cim_stp_passthru_exit: ++ ++ ioc->ioctl->status &= ~( MPT_IOCTL_STATUS_TM_FAILED | ++ MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID | ++ MPT_IOCTL_STATUS_RF_VALID ); ++ ++ if (request_data) ++ pci_free_consistent(ioc->pcidev, request_data_sz, ++ (u8 *)request_data, request_data_dma); ++ ++#ifdef QUIESE_IO ++ if (quiese_io_flag) ++ mptctl_do_raid(ioc, ++ MPI_RAID_ACTION_ENABLE_PHYS_IO, ++ phys_disk_num, volume_bus, volume_id, NULL); ++#endif ++ ++ /* Copy th data from kernel memory to user memory ++ */ ++ if (copy_to_user((char *)arg, &karg, ++ offsetof(CSMI_SAS_STP_PASSTHRU_BUFFER,bDataBuffer))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to write out csmi_sas_ssp_passthru @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ return 0; ++ ++} ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* Prototype Routine for the CSMI SAS Firmware Download command. ++ * ++ * Outputs: None. ++ * Return: 0 if successful ++ * -EFAULT if data unavailable ++ * -ENODEV if no such device/adapter ++ */ ++static int ++mptctl_csmi_sas_firmware_download(unsigned long arg) ++{ ++ CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER __user *uarg = (void __user *) arg; ++ CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER karg; ++ MPT_ADAPTER *ioc = NULL; ++ int iocnum; ++ pMpiFwHeader_t pFwHeader=NULL; ++ ++ dctlprintk((": %s called.\n",__FUNCTION__)); ++ ++ if (copy_from_user(&karg, uarg, ++ sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to read in csmi_sas_firmware_download struct @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, ++ &ioc)) < 0) || (ioc == NULL)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not found!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ if (!mptctl_is_this_sas_cntr(ioc)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not SAS controller!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ /* Default to success.*/ ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; ++ karg.Information.usStatus = CSMI_SAS_FWD_SUCCESS; ++ karg.Information.usSeverity = CSMI_SAS_FWD_INFORMATION; ++ ++ /* some checks of the incoming frame */ ++ if ((karg.Information.uBufferLength + ++ sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD)) > ++ karg.IoctlHeader.Length) { ++ karg.IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_INVALID_PARAMETER; ++ karg.Information.usStatus = CSMI_SAS_FWD_FAILED; ++ goto cim_firmware_download_exit; ++ } ++ ++ if ( karg.Information.uDownloadFlags & ++ (CSMI_SAS_FWD_SOFT_RESET | CSMI_SAS_FWD_VALIDATE)) { ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ karg.Information.usStatus = CSMI_SAS_FWD_REJECT; ++ karg.Information.usSeverity = CSMI_SAS_FWD_ERROR; ++ goto cim_firmware_download_exit; ++ } ++ ++ /* now we need to alloc memory so we can pull in the ++ * fw image attached to end of incomming packet. ++ */ ++ pFwHeader = kmalloc(karg.Information.uBufferLength, GFP_KERNEL); ++ if(pFwHeader==NULL){ ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ karg.Information.usStatus = CSMI_SAS_FWD_REJECT; ++ karg.Information.usSeverity = CSMI_SAS_FWD_ERROR; ++ goto cim_firmware_download_exit; ++ } ++ ++ if (copy_from_user(pFwHeader, uarg->bDataBuffer, ++ karg.Information.uBufferLength)) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to read in pFwHeader @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ if ( !((pFwHeader->Signature0 == MPI_FW_HEADER_SIGNATURE_0) && ++ (pFwHeader->Signature1 == MPI_FW_HEADER_SIGNATURE_1) && ++ (pFwHeader->Signature2 == MPI_FW_HEADER_SIGNATURE_2))) { ++ // the signature check failed ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ karg.Information.usStatus = CSMI_SAS_FWD_REJECT; ++ karg.Information.usSeverity = CSMI_SAS_FWD_ERROR; ++ goto cim_firmware_download_exit; ++ } ++ ++ if ( mptctl_do_fw_download(karg.IoctlHeader.IOControllerNumber, ++ uarg->bDataBuffer, karg.Information.uBufferLength) ++ != 0) { ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ karg.Information.usStatus = CSMI_SAS_FWD_FAILED; ++ karg.Information.usSeverity = CSMI_SAS_FWD_FATAL; ++ goto cim_firmware_download_exit; ++ } ++ ++ if((karg.Information.uDownloadFlags & CSMI_SAS_FWD_SOFT_RESET) || ++ (karg.Information.uDownloadFlags & CSMI_SAS_FWD_HARD_RESET)) { ++ if (mpt_HardResetHandler(ioc, CAN_SLEEP) != 0) { ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ karg.Information.usStatus = CSMI_SAS_FWD_FAILED; ++ karg.Information.usSeverity = CSMI_SAS_FWD_FATAL; ++ } ++ } ++ ++cim_firmware_download_exit: ++ ++ if(pFwHeader) ++ kfree(pFwHeader); ++ ++ /* Copy the data from kernel memory to user memory ++ */ ++ if (copy_to_user((char *)arg, &karg, ++ sizeof(CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to write out csmi_sas_firmware_download @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* Prototype Routine for the CSMI SAS Get RAID Info command. ++ * ++ * Outputs: None. ++ * Return: 0 if successful ++ * -EFAULT if data unavailable ++ * -ENODEV if no such device/adapter ++ */ ++static int ++mptctl_csmi_sas_get_raid_info(unsigned long arg) ++{ ++ CSMI_SAS_RAID_INFO_BUFFER __user *uarg = (void __user *) arg; ++ CSMI_SAS_RAID_INFO_BUFFER karg; ++ MPT_ADAPTER *ioc = NULL; ++ int iocnum; ++ u32 raidFlags; ++ u8 maxRaidTypes; ++ ++ dctlprintk((": %s called.\n",__FUNCTION__)); ++ ++ if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_RAID_INFO_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to read in csmi_sas_get_raid_info struct @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, ++ &ioc)) < 0) || (ioc == NULL)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not found!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ if (!mptctl_is_this_sas_cntr(ioc)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not SAS controller!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ if( !mpt_findImVolumes(ioc)) { ++ if ( ioc->raid_data.pIocPg2 ) { ++ karg.Information.uNumRaidSets = ioc->raid_data.pIocPg2->NumActiveVolumes; ++ // uMaxDrivesPerSet hard coded until value is available through RAID config page ++ karg.Information.uMaxDrivesPerSet = 8; ++ karg.Information.uMaxRaidSets = ioc->raid_data.pIocPg2->MaxVolumes; ++ // For bMaxRaidSets, count bits set in bits 0-6 of CapabilitiesFlags ++ raidFlags = ioc->raid_data.pIocPg2->CapabilitiesFlags & 0x0000007F; ++ for( maxRaidTypes=0; raidFlags; maxRaidTypes++ ) ++ { ++ raidFlags &= raidFlags - 1; ++ } ++ karg.Information.bMaxRaidTypes = maxRaidTypes; ++ // ulMinRaidSetBlocks hard coded to 1MB until available from config page ++ karg.Information.ulMinRaidSetBlocks = 2048; ++ karg.Information.ulMaxRaidSetBlocks = ++ (ioc->raid_data.pIocPg2->CapabilitiesFlags & ++ MPI_IOCPAGE2_CAP_FLAGS_RAID_64_BIT_ADDRESSING) ++ ? 0xffffffffffffffffULL : 0x00000000ffffffffULL; ++ karg.Information.uMaxPhysicalDrives = ioc->raid_data.pIocPg2->MaxPhysDisks; ++ karg.Information.uMaxExtents = 1; ++ karg.Information.uMaxModules = 0; ++ karg.Information.uMaxTransformationMemory = 0; ++ karg.Information.uChangeCount = ioc->csmi_change_count; ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; ++ } ++ } ++ ++ /* Copy the data from kernel memory to user memory ++ */ ++ if (copy_to_user((char *)arg, &karg, ++ sizeof(CSMI_SAS_RAID_INFO_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to write out csmi_sas_get_raid_info @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ return 0; ++ ++} ++ ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* mptscsih_do_raid - Format and Issue a RAID volume request message. ++ * @ioc: Pointer to MPT_ADAPTER structure ++ * @action: What do be done. ++ * @PhysDiskNum: Logical target id. ++ * @VolumeBus: Target locations bus. ++ * @VolumeId: Volume id ++ * ++ * Returns: < 0 on a fatal error ++ * 0 on success ++ * ++ * Remark: Wait to return until reply processed by the ISR. ++ */ ++static int ++mptctl_do_raid(MPT_ADAPTER *ioc, u8 action, u8 PhysDiskNum, u8 VolumeBus, u8 VolumeId, pMpiRaidActionReply_t reply) ++{ ++ MpiRaidActionRequest_t *pReq; ++ MpiRaidActionReply_t *pReply; ++ MPT_FRAME_HDR *mf; ++ int ii; ++ ++ /* Get and Populate a free Frame ++ */ ++ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) { ++ dctlprintk((": no msg frames!\n")); ++ return -EAGAIN; ++ } ++ pReq = (MpiRaidActionRequest_t *)mf; ++ pReq->Action = action; ++ pReq->Reserved1 = 0; ++ pReq->ChainOffset = 0; ++ pReq->Function = MPI_FUNCTION_RAID_ACTION; ++ pReq->VolumeID = VolumeId; ++ pReq->VolumeBus = VolumeBus; ++ pReq->PhysDiskNum = PhysDiskNum; ++ pReq->MsgFlags = 0; ++ pReq->Reserved2 = 0; ++ pReq->ActionDataWord = 0; /* Reserved for this action */ ++ //pReq->ActionDataSGE = 0; ++ ++ mpt_add_sge((char *)&pReq->ActionDataSGE, ++ MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); ++ ++ ioc->ioctl->wait_done = 0; ++ mpt_put_msg_frame(mptctl_id, ioc, mf); ++ ++ /* Now wait for the command to complete */ ++ ii = wait_event_timeout(mptctl_wait, ++ ioc->ioctl->wait_done == 1, ++ HZ*MPT_IOCTL_DEFAULT_TIMEOUT /* 10 sec */); ++ ++ if(ii <=0 && (ioc->ioctl->wait_done != 1 )) { ++ /* Now we need to reset the board */ ++ mpt_free_msg_frame(ioc, mf); ++ mptctl_timeout_expired(ioc->ioctl); ++ return -ENODATA; ++ } ++ ++ if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) && ++ (reply != NULL)){ ++ pReply = (MpiRaidActionReply_t *)&(ioc->ioctl->ReplyFrame); ++ memcpy(reply, pReply, ++ min(ioc->reply_sz, ++ 4*pReply->MsgLength)); ++ } ++ ++ return 0; ++} ++ ++#ifdef QUIESE_IO ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* mptctl_raid_get_volume_id - figures out which Volume a PhysDisk belongs to. ++ * @ioc: Pointer to MPT_ADAPTER structure ++ * @PhysDiskNum: an unique number assigned by IOC to identify a specific IR phy disk ++ * ++ * Returns: < 0 on a fatal error ++ * 0 on success ++ * ++ * Following parameters are valid when successful return ++ * @VolumeID - target device identification number of the volume ++ * @VolumeBus - the SCSI bus number of the volume ++ * ++ */ ++static int ++mptctl_raid_get_volume_id(MPT_ADAPTER *ioc, u8 PhysDiskNum, u8 *VolumeID, u8 *VolumeBus) ++{ ++ CONFIGPARMS cfg; ++ ConfigPageHeader_t header; ++ dma_addr_t volume0_dma; ++ int i,j; ++ int rc=0; ++ int volumepage0sz = 0; ++ pRaidVolumePage0_t pVolume0 = NULL; ++ ++ /* ++ * get RAID Volume Page 0 ++ */ ++ header.PageVersion = 0; ++ header.PageLength = 0; ++ header.PageNumber = 0; ++ header.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME; ++ cfg.cfghdr.hdr = &header; ++ cfg.physAddr = -1; ++ cfg.pageAddr = 0; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; ++ cfg.dir = 0; ++ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; ++ if (mpt_config(ioc, &cfg) != 0) { ++ rc = -1; ++ goto mptctl_raid_get_volume_id_exit; ++ } ++ ++ if (header.PageLength == 0) { ++ rc = -1; ++ goto mptctl_raid_get_volume_id_exit; ++ } ++ ++ volumepage0sz = header.PageLength * 4; ++ pVolume0 = pci_alloc_consistent(ioc->pcidev, volumepage0sz, ++ &volume0_dma); ++ if (!pVolume0) { ++ rc = -1; ++ goto mptctl_raid_get_volume_id_exit; ++ } ++ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; ++ cfg.physAddr = volume0_dma; ++ ++ for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++){ ++ *VolumeID = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID; ++ *VolumeBus = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus; ++ cfg.pageAddr = (*VolumeBus << 8) + *VolumeID; ++ if (mpt_config(ioc, &cfg) != 0){ ++ rc = -1; ++ goto mptctl_raid_get_volume_id_exit; ++ } ++ for (j=0; j<pVolume0->NumPhysDisks; j++){ ++ if (PhysDiskNum == pVolume0->PhysDisk[i].PhysDiskNum) ++ goto mptctl_raid_get_volume_id_exit; ++ } ++ } ++ ++mptctl_raid_get_volume_id_exit: ++ ++ if (pVolume0 != NULL) ++ pci_free_consistent(ioc->pcidev, volumepage0sz, pVolume0, ++ volume0_dma); ++ ++ return rc; ++} ++#endif ++ ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* mptctl_raid_inq ++ * @ioc = per host instance ++ * @opcode = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH or MPI_FUNCTION_SCSI_IO_REQUEST ++ * @target = target id ++ * @inq_vpd = inquiry data, returned ++ * @inq_vpd_sz = maximum size of inquiry data ++ * ++ * Return = 0(sucess), non-zero(failure) ++ */ ++static int ++mptctl_raid_inq(MPT_ADAPTER *ioc, u8 opcode, u8 target, u8 inq_vpd_page, u8 * inq_vpd, u32 inq_vpd_sz) ++{ ++ MPT_FRAME_HDR *mf = NULL; ++ MPIHeader_t *mpi_hdr; ++ pSCSIIORequest_t pScsiRequest; ++ u16 req_idx; ++ char *psge; ++ u8 inq_vpd_cdb[6]; ++ u8 *request_data=NULL; ++ dma_addr_t request_data_dma; ++ u32 request_data_sz; ++ int rc=0,ii; ++ ++ request_data_sz = 0xFFFF; /* max data size */ ++ ++ /* fill-in cdb */ ++ inq_vpd_cdb[0] = 0x12; ++ if (inq_vpd_page) { ++ inq_vpd_cdb[1] = 0x01; /* evpd bit */ ++ inq_vpd_cdb[2] = inq_vpd_page; ++ } ++ inq_vpd_cdb[3] = (u8)(request_data_sz >> 8); ++ inq_vpd_cdb[4] = (u8)request_data_sz; ++ ++ /* Get a free request frame and save the message context. ++ */ ++ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) { ++ dctlprintk((": no msg frames!\n")); ++ goto mptctl_raid_inq_exit; ++ } ++ ++ mpi_hdr = (MPIHeader_t *) mf; ++ pScsiRequest = (pSCSIIORequest_t) mf; ++ req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); ++ ++ memset(pScsiRequest,0,sizeof(SCSIIORequest_t)); ++ pScsiRequest->Function = opcode; ++ pScsiRequest->TargetID = target; ++ pScsiRequest->Bus = 0; ++ pScsiRequest->CDBLength = 6; ++ pScsiRequest->DataLength = cpu_to_le16(request_data_sz); ++ pScsiRequest->MsgContext = mpi_hdr->MsgContext; ++ memcpy(pScsiRequest->CDB,inq_vpd_cdb,pScsiRequest->CDBLength); ++ pScsiRequest->Control = cpu_to_le32(MPI_SCSIIO_CONTROL_READ); ++ pScsiRequest->Control |= cpu_to_le32(MPI_SCSIIO_CONTROL_SIMPLEQ); ++ ++ /* setup sense ++ */ ++ pScsiRequest->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; ++ pScsiRequest->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma + ++ (req_idx * MPT_SENSE_BUFFER_ALLOC)); ++ ++ request_data = pci_alloc_consistent( ++ ioc->pcidev, request_data_sz, &request_data_dma); ++ ++ if (request_data == NULL) { ++ mpt_free_msg_frame(ioc, mf); ++ rc=-1; ++ goto mptctl_raid_inq_exit; ++ } ++ ++ memset(request_data,0,request_data_sz); ++ psge = (char *)&pScsiRequest->SGL; ++ mpt_add_sge(psge, (MPT_SGE_FLAGS_SSIMPLE_READ | 0xFC) , request_data_dma); ++ ++ /* The request is complete. Set the timer parameters ++ * and issue the request. ++ */ ++ ioc->ioctl->wait_done = 0; ++ mpt_put_msg_frame(mptctl_id, ioc, mf); ++ ++ /* Now wait for the command to complete */ ++ ii = wait_event_timeout(mptctl_wait, ++ ioc->ioctl->wait_done == 1, ++ HZ*MPT_IOCTL_DEFAULT_TIMEOUT /* 10 sec */); ++ ++ if(ii <=0 && (ioc->ioctl->wait_done != 1 )) { ++ /* Now we need to reset the board */ ++ rc=-1; ++ mpt_free_msg_frame(ioc, mf); ++ mptctl_timeout_expired(ioc->ioctl); ++ goto mptctl_raid_inq_exit; ++ } ++ ++ /* copy the request_data */ ++ memcpy(inq_vpd,request_data,min(request_data_sz,inq_vpd_sz)); ++ ++mptctl_raid_inq_exit: ++ ++ if (request_data) ++ pci_free_consistent(ioc->pcidev, request_data_sz, ++ request_data, request_data_dma); ++ ++ return rc; ++} ++ ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* Prototype Routine for the CSMI SAS Get RAID Config command. ++ * ++ * Outputs: None. ++ * Return: 0 if successful ++ * -EFAULT if data unavailable ++ * -ENODEV if no such device/adapter ++ */ ++static int ++mptctl_csmi_sas_get_raid_config(unsigned long arg) ++{ ++ CSMI_SAS_RAID_CONFIG_BUFFER __user *uarg = (void __user *) arg; ++ CSMI_SAS_RAID_CONFIG_BUFFER karg,*pKarg=NULL; ++ CONFIGPARMS cfg; ++ ConfigPageHeader_t header; ++ MPT_ADAPTER *ioc = NULL; ++ int iocnum; ++ u8 volumeID, VolumeBus, physDiskNum, physDiskNumMax, found; ++ int volumepage0sz = 0, physdiskpage0sz = 0, ioc_page5_sz = 0; ++ dma_addr_t volume0_dma, physdisk0_dma, ioc_page5_dma; ++ pRaidVolumePage0_t pVolume0 = NULL; ++ pRaidPhysDiskPage0_t pPhysDisk0 = NULL; ++ pMpiRaidActionReply_t pRaidActionReply = NULL; ++ pIOCPage5_t pIocPage5 = NULL; ++ int i, idx, csmi_sas_raid_config_buffer_sz; ++ int copy_buffer_sz=0; ++ sas_device_info_t *sasDevice; ++ u32 device_info=0; ++ ++ dctlprintk((": %s called.\n",__FUNCTION__)); ++ ++ if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to read in csmi_sas_get_raid_config struct @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ csmi_sas_raid_config_buffer_sz = karg.IoctlHeader.Length; ++ pKarg = kmalloc(csmi_sas_raid_config_buffer_sz, GFP_KERNEL); ++ if(!pKarg){ ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to malloc @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__,pKarg); ++ return -EFAULT; ++ } ++ ++ if (copy_from_user(pKarg, uarg, csmi_sas_raid_config_buffer_sz)) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to read in csmi_sas_get_raid_config struct @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ kfree(pKarg); ++ return -EFAULT; ++ } ++ ++ if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber, ++ &ioc)) < 0) || (ioc == NULL)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not found!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ kfree(pKarg); ++ return -ENODEV; ++ } ++ ++ if (!mptctl_is_this_sas_cntr(ioc)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not SAS controller!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ kfree(pKarg); ++ return -ENODEV; ++ } ++ ++ if (!ioc->raid_data.isRaid) { ++ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_get_raid_config_exit; ++ } ++ ++ if (pKarg->Configuration.uChangeCount != 0 && ++ pKarg->Configuration.uChangeCount != ioc->csmi_change_count ) { ++ pKarg->IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_INVALID_PARAMETER; ++ //pKarg->Configuration.uFailureCode = ++ // CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID; ++ goto cim_get_raid_config_exit; ++ } ++ ++ /* check to see if the input uRaidSetIndex is greater than the number of RAID sets */ ++ if(pKarg->Configuration.uRaidSetIndex >= ++ ioc->raid_data.pIocPg2->NumActiveVolumes) { ++ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_RAID_SET_OUT_OF_RANGE; ++ goto cim_get_raid_config_exit; ++ } ++ ++ /* ++ * get RAID Volume Page 0 ++ */ ++ volumeID = ioc->raid_data.pIocPg2->RaidVolume[pKarg->Configuration.uRaidSetIndex].VolumeID; ++ VolumeBus = ioc->raid_data.pIocPg2->RaidVolume[pKarg->Configuration.uRaidSetIndex].VolumeBus; ++ ++ header.PageVersion = 0; ++ header.PageLength = 0; ++ header.PageNumber = 0; ++ header.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME; ++ cfg.cfghdr.hdr = &header; ++ cfg.physAddr = -1; ++ cfg.pageAddr = (VolumeBus << 8) + volumeID; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; ++ cfg.dir = 0; ++ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; ++ if (mpt_config(ioc, &cfg) != 0) { ++ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_get_raid_config_exit; ++ } ++ ++ if (header.PageLength == 0) { ++ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_get_raid_config_exit; ++ } ++ ++ volumepage0sz = header.PageLength * 4; ++ pVolume0 = pci_alloc_consistent(ioc->pcidev, volumepage0sz, ++ &volume0_dma); ++ if (!pVolume0) { ++ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_get_raid_config_exit; ++ } ++ ++ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; ++ cfg.physAddr = volume0_dma; ++ if (mpt_config(ioc, &cfg) != 0){ ++ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_get_raid_config_exit; ++ } ++ ++ pKarg->Configuration.uCapacity = ++ (le32_to_cpu(pVolume0->MaxLBA)+1)/2048; ++ pKarg->Configuration.uStripeSize = ++ le32_to_cpu(pVolume0->StripeSize)/2; ++ ++ switch(pVolume0->VolumeType) { ++ case MPI_RAID_VOL_TYPE_IS: ++ pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_0; ++ break; ++ case MPI_RAID_VOL_TYPE_IME: ++ pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_10; ++ break; ++ case MPI_RAID_VOL_TYPE_IM: ++ pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_1; ++ break; ++ default: ++ pKarg->Configuration.bRaidType = CSMI_SAS_RAID_TYPE_OTHER; ++ break; ++ } ++ ++ switch (pVolume0->VolumeStatus.State) { ++ case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL: ++ pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_OK; ++ break; ++ case MPI_RAIDVOL0_STATUS_STATE_DEGRADED: ++ /* Volume is degraded, check if Resyncing or Inactive */ ++ if (pVolume0->VolumeStatus.State & ++ MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) { ++ pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_REBUILDING; ++ } ++ else if (pVolume0->VolumeStatus.State & ++ MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE) { ++ pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_OFFLINE; ++ } ++ else { ++ pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_DEGRADED; ++ } ++ break; ++ case MPI_RAIDVOL0_STATUS_STATE_FAILED: ++ pKarg->Configuration.bStatus = CSMI_SAS_RAID_SET_STATUS_FAILED; ++ break; ++ } ++ ++ pKarg->Configuration.bInformation = 0; /* default */ ++ if(pVolume0->VolumeStatus.Flags & ++ MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS ) { ++ ++ uint64_t * ptrUint64; ++ uint64_t totalBlocks64, blocksRemaining64; ++ uint32_t totalBlocks32, blocksRemaining32; ++ ++ /* get percentage complete */ ++ pRaidActionReply = kmalloc( sizeof(MPI_RAID_VOL_INDICATOR) + ++ offsetof(MSG_RAID_ACTION_REPLY,ActionData), ++ GFP_KERNEL); ++ ++ if(pRaidActionReply == NULL){ ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to malloc @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__,pKarg); ++ goto cim_get_raid_config_exit; ++ } ++ ++ mptctl_do_raid(ioc, ++ MPI_RAID_ACTION_INDICATOR_STRUCT, ++ 0, VolumeBus, volumeID, pRaidActionReply); ++ ++ ptrUint64 = (uint64_t *)&pRaidActionReply->ActionData; ++ totalBlocks64 = *ptrUint64; ++ ptrUint64++; ++ blocksRemaining64 = *ptrUint64; ++ while(totalBlocks64 > 0xFFFFFFFFUL){ ++ totalBlocks64 = totalBlocks64 >> 1; ++ blocksRemaining64 = blocksRemaining64 >> 1; ++ } ++ totalBlocks32 = (uint32_t)totalBlocks64; ++ blocksRemaining32 = (uint32_t)blocksRemaining64; ++ ++ if(totalBlocks32) ++ pKarg->Configuration.bInformation = ++ (totalBlocks32 - blocksRemaining32) / ++ (totalBlocks32 / 100); ++ ++ kfree(pRaidActionReply); ++ } ++ ++ /* fill-in more information depending on data type */ ++ if (pKarg->Configuration.bDataType == CSMI_SAS_RAID_DATA_ADDITIONAL_DATA) { ++ pKarg->Configuration.Data->bLabel[0] = '\0'; ++ pKarg->Configuration.Data->bRaidSetLun[1] = 0; ++ pKarg->Configuration.Data->bWriteProtection = ++ CSMI_SAS_RAID_SET_WRITE_PROTECT_UNKNOWN; ++ pKarg->Configuration.Data->bCacheSetting = ++ CSMI_SAS_RAID_SET_CACHE_UNKNOWN; ++ pKarg->Configuration.Data->bCacheRatio = 0; ++ pKarg->Configuration.Data->usBlockSize = 512; ++ pKarg->Configuration.Data->ulRaidSetExtentOffset = 0; ++ pKarg->Configuration.Data->ulRaidSetBlocks = le32_to_cpu(pVolume0->MaxLBA); ++ if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IS || ++ pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IME ) { ++ pKarg->Configuration.Data->uStripeSizeInBlocks = ++ le32_to_cpu(pVolume0->StripeSize); ++ } ++ else { ++ pKarg->Configuration.Data->uStripeSizeInBlocks = 0; ++ } ++ pKarg->Configuration.Data->uSectorsPerTrack = 128; ++ for (i=0; i<16; i++) { ++ // unsupported ++ pKarg->Configuration.Data->bApplicationScratchPad[i] = 0xFF; ++ } ++ } ++ else if( pKarg->Configuration.bDataType == CSMI_SAS_RAID_DATA_DEVICE_ID ) { ++ /* Send inquiry to get VPD Page 0x83 */ ++ u8 * vpd_page=NULL; ++ u32 vpd_page_sz; ++ vpd_page_sz = pKarg->IoctlHeader.Length - sizeof(CSMI_SAS_RAID_CONFIG); ++ vpd_page = kmalloc(vpd_page_sz, GFP_KERNEL); ++ if (mptctl_raid_inq(ioc, MPI_FUNCTION_SCSI_IO_REQUEST, volumeID, 0x83, vpd_page, vpd_page_sz) != 0) { ++ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ kfree(vpd_page); ++ goto cim_get_raid_config_exit; ++ } ++ memset(&pKarg->Configuration.DeviceId->bDeviceIdentificationVPDPage, ++ 0,vpd_page_sz); ++ memcpy(&pKarg->Configuration.DeviceId->bDeviceIdentificationVPDPage, ++ vpd_page,vpd_page_sz); ++ kfree(vpd_page); ++ } ++ ++ if (pKarg->Configuration.bDataType != CSMI_SAS_RAID_DATA_DRIVES) { ++ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; ++ goto cim_get_raid_config_exit; ++ } ++ ++ /* suppress drive information */ ++ if (pKarg->Configuration.bDriveCount == ++ CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED) { ++ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; ++ goto cim_get_raid_config_exit; ++ } ++ ++ /* get hotspare info, used later in this function */ ++ if (pVolume0->VolumeSettings.HotSparePool) { ++ /* Read and save IOC Page 5 ++ */ ++ header.PageVersion = 0; ++ header.PageLength = 0; ++ header.PageNumber = 5; ++ header.PageType = MPI_CONFIG_PAGETYPE_IOC; ++ cfg.cfghdr.hdr = &header; ++ cfg.physAddr = -1; ++ cfg.pageAddr = 0; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; ++ cfg.dir = 0; ++ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; ++ if ((mpt_config(ioc, &cfg)==0) && (header.PageLength)) { ++ ioc_page5_sz = header.PageLength * 4; ++ pIocPage5 = pci_alloc_consistent(ioc->pcidev, ++ ioc_page5_sz, ++ &ioc_page5_dma); ++ memset(pIocPage5,0,ioc_page5_sz); ++ if (ioc_page5_dma) { ++ cfg.physAddr = ioc_page5_dma; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; ++ mpt_config(ioc, &cfg); ++ } ++ } ++ } ++ ++ /* ++ * get RAID Physical Disk Page 0 ++ */ ++ header.PageVersion = 0; ++ header.PageLength = 0; ++ header.PageNumber = 0; ++ header.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK; ++ cfg.cfghdr.hdr = &header; ++ cfg.physAddr = -1; ++ cfg.pageAddr = 0; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; ++ cfg.dir = 0; ++ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; ++ if (mpt_config(ioc, &cfg) != 0) { ++ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_get_raid_config_exit; ++ } ++ ++ if (header.PageLength == 0) { ++ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_get_raid_config_exit; ++ } ++ ++ physdiskpage0sz = header.PageLength * 4; ++ pPhysDisk0 = pci_alloc_consistent(ioc->pcidev, physdiskpage0sz, ++ &physdisk0_dma); ++ if (!pPhysDisk0) { ++ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_get_raid_config_exit; ++ } ++ cfg.physAddr = physdisk0_dma; ++ ++ physDiskNumMax = (csmi_sas_raid_config_buffer_sz - ++ offsetof(CSMI_SAS_RAID_CONFIG,Drives)) ++ / sizeof(CSMI_SAS_RAID_DRIVES); ++ ++ pKarg->Configuration.bDriveCount=0; ++ ++ for (i=0; i< min(pVolume0->NumPhysDisks, physDiskNumMax); i++) { ++ ++ physDiskNum = pVolume0->PhysDisk[i].PhysDiskNum; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; ++ cfg.pageAddr = physDiskNum; ++ if (mpt_config(ioc, &cfg) != 0){ ++ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_get_raid_config_exit; ++ } ++ memset(&pKarg->Configuration.Drives[i],0, ++ sizeof(CSMI_SAS_RAID_DRIVES)); ++ memcpy(pKarg->Configuration.Drives[i].bModel, ++ pPhysDisk0->InquiryData.VendorID, ++ offsetof(RAID_PHYS_DISK0_INQUIRY_DATA,ProductRevLevel)); ++ memcpy(pKarg->Configuration.Drives[i].bFirmware, ++ pPhysDisk0->InquiryData.ProductRevLevel, ++ sizeof(pPhysDisk0->InquiryData.ProductRevLevel)); ++ if ((pPhysDisk0->ExtDiskIdentifier[0] == 'A') && ++ (pPhysDisk0->ExtDiskIdentifier[1] == 'T') && ++ (pPhysDisk0->ExtDiskIdentifier[2] == 'A')) { ++ memcpy(&pKarg->Configuration.Drives[i].bSerialNumber, ++ &pPhysDisk0->ExtDiskIdentifier[4], ++ 4); ++ memcpy(&pKarg->Configuration.Drives[i].bSerialNumber[4], ++ &pPhysDisk0->DiskIdentifier, ++ sizeof(pPhysDisk0->DiskIdentifier)); ++ } else { ++ memcpy(pKarg->Configuration.Drives[i].bSerialNumber, ++ pPhysDisk0->DiskIdentifier, ++ sizeof(pPhysDisk0->DiskIdentifier)); ++ } ++ ++ pKarg->Configuration.Drives[i].bDriveUsage = ++ (pPhysDisk0->PhysDiskStatus.Flags & ++ MPI_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME) ? ++ CSMI_SAS_DRIVE_CONFIG_NOT_USED : ++ CSMI_SAS_DRIVE_CONFIG_MEMBER; ++ ++ pKarg->Configuration.Drives[i].bDriveStatus = ++ CSMI_SAS_DRIVE_STATUS_OK; ++ if (pPhysDisk0->PhysDiskStatus.State == ++ MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED) { ++ pKarg->Configuration.Drives[i].bDriveStatus = ++ CSMI_SAS_DRIVE_STATUS_OFFLINE; ++ } ++ else if(pPhysDisk0->PhysDiskStatus.State) { ++ pKarg->Configuration.Drives[i].bDriveStatus = ++ CSMI_SAS_DRIVE_STATUS_FAILED; ++ if(pKarg->Configuration.bStatus == ++ CSMI_SAS_RAID_SET_STATUS_DEGRADED) ++ pKarg->Configuration.bInformation = i; ++ } ++ else if((pVolume0->VolumeStatus.Flags & ++ MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) && ++ (pPhysDisk0->PhysDiskStatus.Flags & ++ MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC)) ++ pKarg->Configuration.Drives[i].bDriveStatus = ++ CSMI_SAS_DRIVE_STATUS_REBUILDING; ++ else if(pPhysDisk0->ErrorData.SmartCount) ++ pKarg->Configuration.Drives[i].bDriveStatus = ++ CSMI_SAS_DRIVE_STATUS_DEGRADED; ++ ++ /* Search the list for the matching SAS address. */ ++ found = FALSE; ++ list_for_each_entry(sasDevice, &ioc->sasDeviceList, list) { ++ ++ /* Found the matching device. */ ++ if ((pPhysDisk0->PhysDiskIOC == sasDevice->Bus) && ++ (pPhysDisk0->PhysDiskID == ++ sasDevice->TargetId)) { ++ u64 SASAddress64; ++ found = TRUE; ++ ++ SASAddress64 = ++ reverse_byte_order64(&sasDevice->SASAddress); ++ memcpy(pKarg->Configuration.Drives[i].bSASAddress, ++ &SASAddress64,sizeof(u64)); ++ memset(pKarg->Configuration.Drives[i].bSASLun, ++ 0, sizeof(pKarg->Configuration.Drives[i].bSASLun)); ++ device_info = sasDevice->DeviceInfo; ++ if (device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE) { ++ pKarg->Configuration.Drives[i].bDriveType = ++ CSMI_SAS_DRIVE_TYPE_SATA; ++ } ++ else { /* drive in a volume can only be SAS/SATA */ ++ pKarg->Configuration.Drives[i].bDriveType = ++ CSMI_SAS_DRIVE_TYPE_SINGLE_PORT_SAS; ++ } ++ break; ++ } else ++ continue; /* Keep looking. */ ++ } ++ pKarg->Configuration.Drives[i].usBlockSize = 512; ++ pKarg->Configuration.Drives[i].uDriveIndex = pPhysDisk0->PhysDiskNum; ++ if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IM) { ++ pKarg->Configuration.Drives[i].ulTotalUserBlocks = ++ le32_to_cpu(pVolume0->MaxLBA) + 1; ++ } ++ else if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IS) { ++ pKarg->Configuration.Drives[i].ulTotalUserBlocks = ++ (le32_to_cpu(pVolume0->MaxLBA) + 1) / (pVolume0->NumPhysDisks); ++ } ++ else if (pVolume0->VolumeType == MPI_RAID_VOL_TYPE_IME) { ++ pKarg->Configuration.Drives[i].ulTotalUserBlocks = ++ ((le32_to_cpu(pVolume0->MaxLBA) + 1) / (pVolume0->NumPhysDisks)) * 2; ++ } ++ pKarg->Configuration.bDriveCount++; ++ } ++ ++ /* adding hot spare info at the end */ ++ if ((pVolume0->VolumeSettings.HotSparePool) && (pIocPage5 != NULL)) { ++ for (idx = 0, i = pVolume0->NumPhysDisks ; ++ idx < pIocPage5->NumHotSpares ; idx++) { ++ if (i >= physDiskNumMax) ++ break; ++ if ((pVolume0->VolumeSettings.HotSparePool & ++ pIocPage5->HotSpare[idx].HotSparePool) == 0) ++ continue; ++ if(pIocPage5->HotSpare[idx].Flags != ++ MPI_IOC_PAGE_5_HOT_SPARE_ACTIVE) ++ continue; ++ physDiskNum = pIocPage5->HotSpare[idx].PhysDiskNum; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; ++ cfg.pageAddr = physDiskNum; ++ if (mpt_config(ioc, &cfg) != 0) ++ continue; ++ /* Search the list for the matching SAS address. */ ++ found = FALSE; ++ list_for_each_entry(sasDevice, &ioc->sasDeviceList, ++ list) { ++ /* Found the matching device. */ ++ if ((pPhysDisk0->PhysDiskIOC == ++ sasDevice->Bus) && ++ (pPhysDisk0->PhysDiskID == ++ sasDevice->TargetId)) { ++ u64 SASAddress64; ++ ++ /* sanity checks */ ++ ++ /* don't mix SSP hot spare ++ * in SATA volume ++ */ ++ if ((sasDevice->DeviceInfo & ++ MPI_SAS_DEVICE_INFO_SSP_TARGET) && ++ (device_info & ++ MPI_SAS_DEVICE_INFO_SATA_DEVICE)) ++ break; ++ ++ /* don't mix SATA hot spare ++ * in SSP volume ++ */ ++ if ((sasDevice->DeviceInfo & ++ MPI_SAS_DEVICE_INFO_SATA_DEVICE) && ++ (device_info & ++ MPI_SAS_DEVICE_INFO_SSP_TARGET)) ++ break; ++ ++ /* capacity check for IM volumes*/ ++ if ((pVolume0->VolumeType == ++ MPI_RAID_VOL_TYPE_IM) && ++ (le32_to_cpu(pVolume0->MaxLBA) + ++ (64*2*1024) /* metadata = 64MB*/ > ++ le32_to_cpu(pPhysDisk0->MaxLBA))) ++ break; ++ ++ /* capacity check for IME volumes*/ ++ if ((pVolume0->VolumeType == ++ MPI_RAID_VOL_TYPE_IME) && ++ (((le32_to_cpu(pVolume0->MaxLBA)/ ++ pVolume0->NumPhysDisks) * 2) + ++ (64*2*1024 ) /*metadata = 64MB*/ > ++ le32_to_cpu(pPhysDisk0->MaxLBA))) ++ break; ++ ++ found = TRUE; ++ ++ SASAddress64 = ++ reverse_byte_order64(&sasDevice->SASAddress); ++ memcpy(pKarg->Configuration.Drives[i].bSASAddress, ++ &SASAddress64,sizeof(u64)); ++ memset(pKarg->Configuration.Drives[i].bSASLun, 0, ++ sizeof(pKarg->Configuration.Drives[i].bSASLun)); ++ break; ++ } else ++ continue; /* Keep looking. */ ++ } ++ if (found==FALSE) ++ continue; ++ memset(&pKarg->Configuration.Drives[i],0, ++ sizeof(CSMI_SAS_RAID_DRIVES)); ++ memcpy(pKarg->Configuration.Drives[i].bModel, ++ pPhysDisk0->InquiryData.VendorID, ++ offsetof(RAID_PHYS_DISK0_INQUIRY_DATA,ProductRevLevel)); ++ memcpy(pKarg->Configuration.Drives[i].bFirmware, ++ pPhysDisk0->InquiryData.ProductRevLevel, ++ sizeof(pPhysDisk0->InquiryData.ProductRevLevel)); ++ if ((pPhysDisk0->ExtDiskIdentifier[0] == 'A') && ++ (pPhysDisk0->ExtDiskIdentifier[1] == 'T') && ++ (pPhysDisk0->ExtDiskIdentifier[2] == 'A')) { ++ memcpy(&pKarg->Configuration.Drives[i].bSerialNumber, ++ &pPhysDisk0->ExtDiskIdentifier[4], ++ 4); ++ memcpy(&pKarg->Configuration.Drives[i].bSerialNumber[4], ++ &pPhysDisk0->DiskIdentifier, ++ sizeof(pPhysDisk0->DiskIdentifier)); ++ } else { ++ memcpy(pKarg->Configuration.Drives[i].bSerialNumber, ++ pPhysDisk0->DiskIdentifier, ++ sizeof(pPhysDisk0->DiskIdentifier)); ++ } ++ pKarg->Configuration.Drives[i].bDriveStatus = ++ CSMI_SAS_DRIVE_STATUS_OK; ++ if(pPhysDisk0->PhysDiskStatus.State) ++ pKarg->Configuration.Drives[i].bDriveStatus = ++ CSMI_SAS_DRIVE_STATUS_FAILED; ++ else if(pPhysDisk0->ErrorData.SmartCount) ++ pKarg->Configuration.Drives[i].bDriveStatus = ++ CSMI_SAS_DRIVE_STATUS_DEGRADED; ++ pKarg->Configuration.Drives[i].bDriveUsage = ++ CSMI_SAS_DRIVE_CONFIG_SPARE; ++ i++; ++ pKarg->Configuration.bDriveCount++; ++ } ++ } ++ ++ // Only return data on the first 240 drives ++ if( pKarg->Configuration.bDriveCount > 0xF0 ) { ++ pKarg->Configuration.bDriveCount = ++ CSMI_SAS_RAID_DRIVE_COUNT_TOO_BIG; ++ } ++ ++ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; ++ ++cim_get_raid_config_exit: ++ ++ if (pVolume0 != NULL) ++ pci_free_consistent(ioc->pcidev, volumepage0sz, pVolume0, ++ volume0_dma); ++ ++ if(pPhysDisk0 != NULL) ++ pci_free_consistent(ioc->pcidev, physdiskpage0sz, pPhysDisk0, ++ physdisk0_dma); ++ ++ if(pIocPage5 != NULL) ++ pci_free_consistent(ioc->pcidev, ioc_page5_sz, pIocPage5, ++ ioc_page5_dma); ++ ++ /* Copy the data from kernel memory to user memory ++ */ ++ ++ /* find the buffer size to copy depending on how much is filled-in */ ++ switch (pKarg->Configuration.bDataType) { ++ case CSMI_SAS_RAID_DATA_ADDITIONAL_DATA: ++ copy_buffer_sz = sizeof(IOCTL_HEADER) + ++ offsetof(CSMI_SAS_RAID_CONFIG,Data) + ++ sizeof(CSMI_SAS_RAID_SET_ADDITIONAL_DATA); ++ break; ++ case CSMI_SAS_RAID_DATA_DRIVES: ++ if (pKarg->Configuration.bDriveCount == ++ CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED) { ++ copy_buffer_sz = sizeof(IOCTL_HEADER) + ++ offsetof(CSMI_SAS_RAID_CONFIG,Drives); ++ } ++ else { ++ copy_buffer_sz = sizeof(IOCTL_HEADER) + ++ offsetof(CSMI_SAS_RAID_CONFIG,Drives) + ++ (pKarg->Configuration.bDriveCount * sizeof(CSMI_SAS_RAID_DRIVES)); ++ } ++ break; ++ case CSMI_SAS_RAID_DATA_DEVICE_ID: ++ copy_buffer_sz = sizeof(IOCTL_HEADER) + ++ offsetof(CSMI_SAS_RAID_CONFIG,DeviceId) + ++ sizeof(CSMI_SAS_RAID_DEVICE_ID); ++ break; ++ } ++ ++ if (copy_to_user((char *)arg, pKarg, copy_buffer_sz)) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to write out csmi_sas_get_raid_config @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ kfree(pKarg); ++ return -EFAULT; ++ } ++ ++ kfree(pKarg); ++ ++ return 0; ++} ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* Prototype Routine for the CSMI SAS Get RAID Features command. ++ * ++ * Outputs: None. ++ * Return: 0 if successful ++ * -EFAULT if data unavailable ++ * -ENODEV if no such device/adapter ++ */ ++static int ++mptctl_csmi_sas_get_raid_features(unsigned long arg) ++{ ++ CSMI_SAS_RAID_FEATURES_BUFFER __user *uarg = (void __user *) arg; ++ CSMI_SAS_RAID_FEATURES_BUFFER karg, *pKarg=NULL; ++ int i, csmi_sas_raid_features_buffer_sz, iocnum; ++ MPT_ADAPTER *ioc = NULL; ++ ++ u8 raidTypes[4] = { CSMI_SAS_RAID_TYPE_0, CSMI_SAS_RAID_TYPE_10, ++ CSMI_SAS_RAID_TYPE_1, CSMI_SAS_RAID_TYPE_1E }; ++ ++ dctlprintk((": %s called.\n",__FUNCTION__)); ++ ++ if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to read in csmi_sas_get_raid_features struct @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ csmi_sas_raid_features_buffer_sz = karg.IoctlHeader.Length; ++ pKarg = kmalloc(csmi_sas_raid_features_buffer_sz, GFP_KERNEL); ++ if(!pKarg){ ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to malloc @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__,pKarg); ++ return -EFAULT; ++ } ++ ++ if (copy_from_user(pKarg, uarg, csmi_sas_raid_features_buffer_sz)) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to read in csmi_sas_get_raid_features struct @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ kfree(pKarg); ++ return -EFAULT; ++ } ++ ++ if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber, ++ &ioc)) < 0) || (ioc == NULL)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not found!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ kfree(pKarg); ++ return -ENODEV; ++ } ++ ++ if (!mptctl_is_this_sas_cntr(ioc)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not SAS controller!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ kfree(pKarg); ++ return -ENODEV; ++ } ++ ++ if (pKarg->Information.uChangeCount != 0 && ++ pKarg->Information.uChangeCount != ioc->csmi_change_count ) { ++ pKarg->IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_INVALID_PARAMETER; ++ //pKarg->Information.uFailureCode = ++ // CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID; ++ goto cim_get_raid_features_exit; ++ } ++ ++ pKarg->Information.uFeatures = CSMI_SAS_RAID_FEATURE_REBUILD; ++ pKarg->Information.bDefaultTransformPriority = CSMI_SAS_PRIORITY_UNKNOWN; ++ pKarg->Information.bTransformPriority = CSMI_SAS_PRIORITY_UNKNOWN; ++ pKarg->Information.bDefaultRebuildPriority = CSMI_SAS_PRIORITY_UNKNOWN; ++ pKarg->Information.bRebuildPriority = pKarg->Information.bDefaultRebuildPriority; ++ pKarg->Information.bDefaultSurfaceScanPriority = CSMI_SAS_PRIORITY_UNKNOWN; ++ pKarg->Information.bSurfaceScanPriority = CSMI_SAS_PRIORITY_UNKNOWN; ++ pKarg->Information.uRaidSetTransformationRules = 0; ++ for (i=0; i<4; i++) { ++ pKarg->Information.RaidType[i].bRaidType = raidTypes[i]; ++ // Only support 64K stripe size ++ pKarg->Information.RaidType[i].uSupportedStripeSizeMap = 0x80; ++ } ++ pKarg->Information.RaidType[i].bRaidType = CSMI_SAS_RAID_TYPE_END; ++ pKarg->Information.bCacheRatiosSupported[0] = CSMI_SAS_RAID_CACHE_RATIO_END; ++ ++cim_get_raid_features_exit: ++ ++ /* ++ * Copy the data from kernel memory to user memory ++ */ ++ if (copy_to_user((char *)arg, pKarg, ++ sizeof(CSMI_SAS_RAID_FEATURES_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to write out csmi_sas_get_raid_features @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ kfree(pKarg); ++ return -EFAULT; ++ } ++ ++ kfree(pKarg); ++ ++ return 0; ++} ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* Prototype Routine for the CSMI SAS Get RAID Control command. ++ * ++ * Outputs: None. ++ * Return: 0 if successful ++ * -EFAULT if data unavailable ++ * -ENODEV if no such device/adapter ++ */ ++static int ++mptctl_csmi_sas_get_raid_control(unsigned long arg) ++{ ++ CSMI_SAS_RAID_CONTROL_BUFFER __user *uarg = (void __user *) arg; ++ CSMI_SAS_RAID_CONTROL_BUFFER karg, *pKarg=NULL; ++ int csmi_sas_raid_control_buffer_sz, iocnum; ++ MPT_ADAPTER *ioc = NULL; ++ ++ dctlprintk((": %s called.\n",__FUNCTION__)); ++ ++ if (copy_from_user(&karg, uarg, sizeof(IOCTL_HEADER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to read in csmi_sas_get_raid_control struct @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ csmi_sas_raid_control_buffer_sz = karg.IoctlHeader.Length; ++ pKarg = kmalloc(csmi_sas_raid_control_buffer_sz, GFP_KERNEL); ++ if(!pKarg){ ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to malloc @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__,pKarg); ++ return -EFAULT; ++ } ++ ++ if (copy_from_user(pKarg, uarg, csmi_sas_raid_control_buffer_sz)) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to read in csmi_sas_get_raid_features struct @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ kfree(pKarg); ++ return -EFAULT; ++ } ++ ++ if (((iocnum = mpt_verify_adapter(pKarg->IoctlHeader.IOControllerNumber, ++ &ioc)) < 0) || (ioc == NULL)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not found!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ kfree(pKarg); ++ return -ENODEV; ++ } ++ ++ if (!mptctl_is_this_sas_cntr(ioc)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not SAS controller!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ kfree(pKarg); ++ return -ENODEV; ++ } ++ ++ if (!ioc->raid_data.isRaid) { ++ pKarg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_get_raid_control_exit; ++ } ++ ++ if (pKarg->Information.uChangeCount != 0 && ++ pKarg->Information.uChangeCount != ioc->csmi_change_count ) { ++ pKarg->IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_INVALID_PARAMETER; ++ pKarg->Information.uFailureCode = ++ CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID; ++ goto cim_get_raid_control_exit; ++ } ++ ++ if (pKarg->Information.bTransformPriority != CSMI_SAS_PRIORITY_UNCHANGED) { ++ pKarg->IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_INVALID_PARAMETER; ++ //pKarg->Information.uFailureCode = ++ // CSMI_SAS_FAIL_CODE_EXPANSION_PRIORITY_INVALID; ++ } ++ if (pKarg->Information.bRebuildPriority != CSMI_SAS_PRIORITY_AUTO && ++ pKarg->Information.bRebuildPriority != CSMI_SAS_PRIORITY_UNCHANGED) { ++ pKarg->IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_INVALID_PARAMETER; ++ pKarg->Information.uFailureCode = ++ CSMI_SAS_FAIL_CODE_REBUILD_PRIORITY_INVALID; ++ } ++ if (pKarg->Information.bCacheRatioFlag == CSMI_SAS_RAID_CACHE_RATIO_ENABLE) { ++ pKarg->IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_INVALID_PARAMETER; ++ pKarg->Information.uFailureCode = ++ CSMI_SAS_FAIL_CODE_CACHE_RATIO_INVALID; ++ } ++ pKarg->Information.bFailureDescription[0] = '\0'; ++ ++cim_get_raid_control_exit: ++ ++ /* ++ * Copy the data from kernel memory to user memory ++ */ ++ if (copy_to_user((char *)arg, pKarg, ++ sizeof(CSMI_SAS_RAID_CONTROL_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to write out csmi_sas_get_raid_control @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ kfree(pKarg); ++ return -EFAULT; ++ } ++ ++ kfree(pKarg); ++ ++ return 0; ++} ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* Prototype Routine for the CSMI SAS Task Managment Config command. ++ * ++ * Outputs: None. ++ * Return: 0 if successful ++ * -EFAULT if data unavailable ++ * -ENODEV if no such device/adapter ++ */ ++static int ++mptctl_csmi_sas_task_managment(unsigned long arg) ++{ ++ CSMI_SAS_SSP_TASK_IU_BUFFER __user *uarg = (void __user *) arg; ++ CSMI_SAS_SSP_TASK_IU_BUFFER karg; ++ pSCSITaskMgmt_t pScsiTm; ++ pSCSITaskMgmtReply_t pScsiTmReply; ++ MPT_ADAPTER *ioc = NULL; ++ MPT_SCSI_HOST *hd; ++ MPT_FRAME_HDR *mf = NULL; ++ MPIHeader_t *mpi_hdr; ++ int iocnum; ++ u8 taskType; ++ u8 path; ++ u8 target; ++ u8 lun; ++ u8 queueTag; ++ u32 msgContext = 0; ++ int retval; ++ int i, ii; ++ u8 found_qtag; ++ int wait_timeout; ++ ++ dctlprintk((": %s called.\n",__FUNCTION__)); ++ ++ if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_SSP_TASK_IU_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to read in csmi_sas_task_managment struct @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, ++ &ioc)) < 0) || (ioc == NULL)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not found!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ if (!mptctl_is_this_sas_cntr(ioc)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not SAS controller!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ /* try to catch an error ++ */ ++ if ((karg.Parameters.uFlags & CSMI_SAS_TASK_IU) && ++ (karg.Parameters.uFlags & CSMI_SAS_HARD_RESET_SEQUENCE)) { ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER; ++ goto cim_get_task_managment_exit; ++ } ++ ++ if (karg.Parameters.uFlags & CSMI_SAS_TASK_IU) { ++ switch (karg.Parameters.bTaskManagementFunction) { ++ ++ case CSMI_SAS_SSP_ABORT_TASK: ++ taskType = MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK; ++ break; ++ case CSMI_SAS_SSP_ABORT_TASK_SET: ++ taskType = MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET; ++ break; ++ case CSMI_SAS_SSP_CLEAR_TASK_SET: ++ taskType = MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET; ++ break; ++ case CSMI_SAS_SSP_LOGICAL_UNIT_RESET: ++ taskType = MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET; ++ break; ++ case CSMI_SAS_SSP_CLEAR_ACA: ++ case CSMI_SAS_SSP_QUERY_TASK: ++ default: ++ karg.IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_INVALID_PARAMETER; ++ goto cim_get_task_managment_exit; ++ } ++ }else if (karg.Parameters.uFlags & CSMI_SAS_HARD_RESET_SEQUENCE) { ++ /* set the code up to do a hard reset ++ */ ++ taskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET; ++ }else { ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER; ++ goto cim_get_task_managment_exit; ++ } ++ ++ path = karg.Parameters.bPathId; ++ target = karg.Parameters.bTargetId; ++ lun = karg.Parameters.bLun; ++ queueTag = (u8)karg.Parameters.uQueueTag & 0xFF; ++ ++ if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL)) { ++ karg.IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_INVALID_PARAMETER; ++ goto cim_get_task_managment_exit; ++ } ++ else ++ hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; ++ ++ switch ( karg.Parameters.uInformation ) { ++ case CSMI_SAS_SSP_TEST: ++ dsasprintk(("TM request for test purposes\n")); ++ break; ++ case CSMI_SAS_SSP_EXCEEDED: ++ dsasprintk(("TM request due to timeout\n")); ++ break; ++ case CSMI_SAS_SSP_DEMAND: ++ dsasprintk(("TM request demanded by app\n")); ++ break; ++ case CSMI_SAS_SSP_TRIGGER: ++ dsasprintk(("TM request sent to trigger event\n")); ++ break; ++ } ++ ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; ++ ++ switch (taskType) { ++ ++ case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK: ++ /* ++ * look up qtag in the ScsiLookup[] table ++ */ ++ for (i=0,found_qtag=0;i<hd->ioc->req_depth;i++) { ++ if ((hd->ScsiLookup[i]) && ++ (hd->ScsiLookup[i]->tag == queueTag)) { ++ mf = MPT_INDEX_2_MFPTR(hd->ioc, i); ++ msgContext = ++ mf->u.frame.hwhdr.msgctxu.MsgContext; ++ found_qtag=1; ++ break; ++ } ++ } ++ ++ if(!found_qtag) { ++ karg.IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_INVALID_PARAMETER; ++ goto cim_get_task_managment_exit; ++ } ++ ++ case MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET: ++ case MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET: ++ case MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET: ++ /* for now, this should work ++ */ ++ case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET: ++ ++ /* Single threading .... ++ */ ++ if (mptctl_set_tm_flags(hd) != 0) { ++ karg.IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_FAILED; ++ goto cim_get_task_managment_exit; ++ } ++ ++ /* Send request ++ */ ++ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) { ++ dctlprintk((": no msg frames!\n")); ++ mptctl_free_tm_flags(ioc); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_get_task_managment_exit; ++ } ++ ++ mpi_hdr = (MPIHeader_t *) mf; ++ pScsiTm = (pSCSITaskMgmt_t ) mf; ++ ++ memset(pScsiTm,0,sizeof(SCSITaskMgmt_t)); ++ pScsiTm->TaskType = taskType; ++ pScsiTm->Bus = path; ++ pScsiTm->TargetID = target; ++ pScsiTm->LUN[1] = lun; ++ pScsiTm->MsgContext = mpi_hdr->MsgContext; ++ pScsiTm->TaskMsgContext = msgContext; ++ pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; ++ ++ ioc->ioctl->wait_done = 0; ++ ++ DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf); ++ ++ if ((retval = mpt_send_handshake_request(mptctl_id, ioc->ioctl->ioc, ++ sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) { ++ dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!" ++ " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, ++ hd->ioc, mf)); ++ goto cim_get_task_managment_exit; ++ } ++ ++ /* Now wait for the command to complete */ ++ wait_timeout=max_t(int,MPT_IOCTL_DEFAULT_TIMEOUT,karg.IoctlHeader.Timeout); ++ ii = wait_event_timeout(mptctl_wait, ++ ioc->ioctl->wait_done == 1, ++ HZ*wait_timeout); ++ ++ if(ii <=0 && (ioc->ioctl->wait_done != 1 )) { ++ /* Now we need to reset the board */ ++ mptctl_free_tm_flags(ioc); ++ mpt_free_msg_frame(hd->ioc, mf); ++ mptctl_timeout_expired(ioc->ioctl); ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_get_task_managment_exit; ++ } ++ ++ if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) { ++ pScsiTmReply = ++ (pSCSITaskMgmtReply_t ) ioc->ioctl->ReplyFrame; ++ ++ memset(&karg.Status,0, ++ sizeof(CSMI_SAS_SSP_PASSTHRU_STATUS)); ++ ++ if(le16_to_cpu(pScsiTmReply->IOCStatus) == MPI_IOCSTATUS_SUCCESS) { ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; ++ karg.Status.bSSPStatus = CSMI_SAS_SSP_STATUS_COMPLETED; ++ }else if(le16_to_cpu(pScsiTmReply->IOCStatus) == ++ MPI_IOCSTATUS_INSUFFICIENT_RESOURCES) { ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; ++ karg.Status.bSSPStatus = CSMI_SAS_SSP_STATUS_RETRY; ++ }else { ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ karg.Status.bSSPStatus = CSMI_SAS_SSP_STATUS_FATAL_ERROR; ++ } ++ }else{ ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ } ++ ++ break; ++ ++ default: ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER; ++ break; ++ } ++ ++ ++cim_get_task_managment_exit: ++ ++ /* Copy the data from kernel memory to user memory ++ */ ++ if (copy_to_user((char *)arg, &karg, ++ sizeof(CSMI_SAS_SSP_TASK_IU_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to write out csmi_sas_task_managment @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* ++ * map_sas_status_to_csmi - Conversion for Connection Status ++ * @mpi_sas_status: Sas status returned by the firmware ++ * ++ * Returns converted connection status ++ * ++ */ ++static u8 ++map_sas_status_to_csmi(u8 mpi_sas_status) ++{ ++ u8 csmi_connect_status; ++ ++ switch (mpi_sas_status) { ++ ++ case MPI_SASSTATUS_SUCCESS: ++ csmi_connect_status = CSMI_SAS_OPEN_ACCEPT; ++ break; ++ ++ case MPI_SASSTATUS_UTC_BAD_DEST: ++ csmi_connect_status = CSMI_SAS_OPEN_REJECT_BAD_DESTINATION; ++ break; ++ ++ case MPI_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED: ++ csmi_connect_status = CSMI_SAS_OPEN_REJECT_RATE_NOT_SUPPORTED; ++ break; ++ ++ case MPI_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED: ++ csmi_connect_status = CSMI_SAS_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED; ++ break; ++ ++ case MPI_SASSTATUS_UTC_STP_RESOURCES_BUSY: ++ csmi_connect_status = CSMI_SAS_OPEN_REJECT_STP_RESOURCES_BUSY; ++ break; ++ ++ case MPI_SASSTATUS_UTC_WRONG_DESTINATION: ++ csmi_connect_status = CSMI_SAS_OPEN_REJECT_WRONG_DESTINATION; ++ break; ++ ++ case MPI_SASSTATUS_SDSF_NAK_RECEIVED: ++ csmi_connect_status = CSMI_SAS_OPEN_REJECT_RETRY; ++ break; ++ ++ case MPI_SASSTATUS_SDSF_CONNECTION_FAILED: ++ csmi_connect_status = CSMI_SAS_OPEN_REJECT_PATHWAY_BLOCKED; ++ break; ++ ++ case MPI_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT: ++ csmi_connect_status = CSMI_SAS_OPEN_REJECT_NO_DESTINATION; ++ break; ++ ++ case MPI_SASSTATUS_UNKNOWN_ERROR: ++ case MPI_SASSTATUS_INVALID_FRAME: ++ case MPI_SASSTATUS_UTC_BREAK_RECEIVED: ++ case MPI_SASSTATUS_UTC_PORT_LAYER_REQUEST: ++ case MPI_SASSTATUS_SHORT_INFORMATION_UNIT: ++ case MPI_SASSTATUS_LONG_INFORMATION_UNIT: ++ case MPI_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA: ++ case MPI_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR: ++ case MPI_SASSTATUS_XFER_RDY_NOT_EXPECTED: ++ case MPI_SASSTATUS_DATA_INCORRECT_DATA_LENGTH: ++ case MPI_SASSTATUS_DATA_TOO_MUCH_READ_DATA: ++ case MPI_SASSTATUS_DATA_OFFSET_ERROR: ++ csmi_connect_status = CSMI_SAS_OPEN_REJECT_RESERVE_STOP; ++ break; ++ ++ default: ++ csmi_connect_status = CSMI_SAS_OPEN_REJECT_RESERVE_STOP; ++ break; ++ } ++ ++ return csmi_connect_status; ++} ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* mptctl_csmi_sas_phy_reset ++ * Issues a phy link reset or phy hard reset ++ * ++ * @ioc - Pointer to MPT_ADAPTER structure ++ * @PhyNum - phy number ++ * @opcode - {MPI_SAS_OP_PHY_LINK_RESET,MPI_SAS_OP_PHY_HARD_RESET} ++ * ++ * Returns: 0 for success, non-zero error ++ */ ++static int ++mptctl_csmi_sas_phy_reset(MPT_ADAPTER *ioc, u8 PhyNum, u8 opcode) ++{ ++ SasIoUnitControlRequest_t *sasIoUnitCntrReq; ++ SasIoUnitControlReply_t *sasIoUnitCntrReply; ++ MPT_FRAME_HDR *mf = NULL; ++ MPIHeader_t *mpi_hdr; ++ int ii; ++ ++ if ((opcode != MPI_SAS_OP_PHY_LINK_RESET) && ++ (opcode != MPI_SAS_OP_PHY_HARD_RESET)) ++ return -1; ++ ++ /* Get a MF for this command. ++ */ ++ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) { ++ dctlprintk((": no msg frames!\n")); ++ return -1; ++ } ++ ++ mpi_hdr = (MPIHeader_t *) mf; ++ sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf; ++ memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t)); ++ sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL; ++ sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext; ++ sasIoUnitCntrReq->Operation = opcode; ++ sasIoUnitCntrReq->PhyNum = PhyNum; ++ ++ ioc->ioctl->wait_done = 0; ++ mpt_put_msg_frame(mptctl_id, ioc, mf); ++ ++ /* Now wait for the command to complete */ ++ ii = wait_event_timeout(mptctl_wait, ++ ioc->ioctl->wait_done == 1, ++ HZ*MPT_IOCTL_DEFAULT_TIMEOUT /* 10 sec */); ++ ++ if(ii <=0 && (ioc->ioctl->wait_done != 1 )) { ++ /* Now we need to reset the board */ ++ mpt_free_msg_frame(ioc, mf); ++ mptctl_timeout_expired(ioc->ioctl); ++ return -1; ++ } ++ ++ if ((ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) == 0) ++ return -1; ++ ++ /* process the completed Reply Message Frame */ ++ sasIoUnitCntrReply = (SasIoUnitControlReply_t *)ioc->ioctl->ReplyFrame; ++ if (sasIoUnitCntrReply->IOCStatus != MPI_IOCSTATUS_SUCCESS) { ++ printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n", ++ __FUNCTION__, ++ sasIoUnitCntrReply->IOCStatus, ++ sasIoUnitCntrReply->IOCLogInfo); ++ return -1; ++ } ++ return 0; ++} ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* Prototype Routine for the CSMI SAS Phy Control command. ++ * ++ * Outputs: None. ++ * Return: 0 if successful ++ * -EFAULT if data unavailable ++ * -ENODEV if no such device/adapter ++ */ ++static int ++mptctl_csmi_sas_phy_control(unsigned long arg) ++{ ++ CSMI_SAS_PHY_CONTROL_BUFFER __user *uarg = (void __user *) arg; ++ IOCTL_HEADER ioctl_header; ++ PCSMI_SAS_PHY_CONTROL_BUFFER karg; ++ SasIOUnitPage0_t *sasIoUnitPg0=NULL; ++ dma_addr_t sasIoUnitPg0_dma; ++ int sasIoUnitPg0_data_sz=0; ++ SasIOUnitPage1_t *sasIoUnitPg1=NULL; ++ dma_addr_t sasIoUnitPg1_dma; ++ int sasIoUnitPg1_data_sz=0; ++ ConfigExtendedPageHeader_t hdr; ++ CONFIGPARMS cfg; ++ MPT_ADAPTER *ioc = NULL; ++ int iocnum; ++ int csmi_sas_phy_control_buffer_sz; ++ ++ dctlprintk((": %s called.\n",__FUNCTION__)); ++ ++ if (copy_from_user(&ioctl_header, uarg, sizeof(IOCTL_HEADER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to read in IOCTL_HEADER" ++ "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ csmi_sas_phy_control_buffer_sz = ioctl_header.Length; ++ karg = kmalloc(csmi_sas_phy_control_buffer_sz,GFP_KERNEL); ++ if(karg==NULL){ ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to malloc @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__,karg); ++ return -EFAULT; ++ } ++ ++ if (copy_from_user(karg, uarg, csmi_sas_phy_control_buffer_sz)) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to read in csmi_sas_phy_control_buffer " ++ "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg); ++ kfree(karg); ++ return -EFAULT; ++ } ++ ++ if (((iocnum = mpt_verify_adapter(ioctl_header.IOControllerNumber, ++ &ioc)) < 0) || (ioc == NULL)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not found!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ kfree(karg); ++ return -ENODEV; ++ } ++ ++ if (!mptctl_is_this_sas_cntr(ioc)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not SAS controller!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ kfree(karg); ++ return -ENODEV; ++ } ++ ++ if (karg->bPhyIdentifier >= ioc->numPhys) { ++ karg->IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_INVALID_PARAMETER; ++ goto cim_sas_phy_control_exit; ++ } ++ ++ /* ++ * Retreive SAS IOUNIT PAGE 0 ++ */ ++ ++ hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION; ++ hdr.ExtPageLength = 0; ++ hdr.PageNumber = 0; ++ hdr.Reserved1 = 0; ++ hdr.Reserved2 = 0; ++ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; ++ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; ++ ++ cfg.cfghdr.ehdr = &hdr; ++ cfg.physAddr = -1; ++ cfg.pageAddr = 0; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; ++ cfg.dir = 0; /* read */ ++ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; ++ ++ if (mpt_config(ioc, &cfg) != 0) { ++ dctlprintk(( ++ ": FAILED: READ MPI_SASIOUNITPAGE0: HEADER\n")); ++ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_sas_phy_control_exit; ++ } ++ ++ if (hdr.ExtPageLength == 0) { ++ dctlprintk((": hdr.ExtPageLength == 0\n")); ++ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_sas_phy_control_exit; ++ } ++ ++ sasIoUnitPg0_data_sz = hdr.ExtPageLength * 4; ++ sasIoUnitPg0 = (SasIOUnitPage0_t *) pci_alloc_consistent(ioc->pcidev, ++ sasIoUnitPg0_data_sz, &sasIoUnitPg0_dma); ++ ++ if (!sasIoUnitPg0) { ++ dctlprintk((": pci_alloc_consistent: FAILED\n")); ++ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_sas_phy_control_exit; ++ } ++ ++ memset((u8 *)sasIoUnitPg0, 0, sasIoUnitPg0_data_sz); ++ cfg.physAddr = sasIoUnitPg0_dma; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; ++ ++ if (mpt_config(ioc, &cfg) != 0) { ++ dctlprintk(( ++ ": FAILED: READ MPI_SASIOUNITPAGE0: CURRENT\n")); ++ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_sas_phy_control_exit; ++ } ++ ++ /* ++ * Retreive SAS IOUNIT PAGE 1 ++ */ ++ ++ hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION; ++ hdr.ExtPageLength = 0; ++ hdr.PageNumber = 1; ++ hdr.Reserved1 = 0; ++ hdr.Reserved2 = 0; ++ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; ++ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; ++ ++ cfg.cfghdr.ehdr = &hdr; ++ cfg.physAddr = -1; ++ cfg.pageAddr = 0; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; ++ cfg.dir = 0; /* read */ ++ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; ++ ++ if (mpt_config(ioc, &cfg) != 0) { ++ dctlprintk(( ++ ": FAILED: READ MPI_SASIOUNITPAGE1: HEADER\n")); ++ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_sas_phy_control_exit; ++ } ++ ++ if (hdr.ExtPageLength == 0) { ++ dctlprintk((": hdr.ExtPageLength == 0\n")); ++ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_sas_phy_control_exit; ++ } ++ ++ sasIoUnitPg1_data_sz = hdr.ExtPageLength * 4; ++ sasIoUnitPg1 = (SasIOUnitPage1_t *) pci_alloc_consistent(ioc->pcidev, ++ sasIoUnitPg1_data_sz, &sasIoUnitPg1_dma); ++ ++ if (!sasIoUnitPg1) { ++ dctlprintk((": pci_alloc_consistent: FAILED\n")); ++ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_sas_phy_control_exit; ++ } ++ ++ memset((u8 *)sasIoUnitPg1, 0, sasIoUnitPg1_data_sz); ++ cfg.physAddr = sasIoUnitPg1_dma; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; ++ ++ if (mpt_config(ioc, &cfg) != 0) { ++ dctlprintk(( ++ ": FAILED: READ MPI_SASIOUNITPAGE1: CURRENT\n")); ++ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_sas_phy_control_exit; ++ } ++ ++ switch (karg->uFunction) { ++ ++ case CSMI_SAS_PC_LINK_RESET: ++ case CSMI_SAS_PC_HARD_RESET: ++ { ++ u8 opcode = (karg->uFunction==CSMI_SAS_PC_LINK_RESET) ? ++ MPI_SAS_OP_PHY_LINK_RESET : MPI_SAS_OP_PHY_HARD_RESET; ++ ++ if((karg->uLinkFlags & CSMI_SAS_PHY_ACTIVATE_CONTROL) && ++ (karg->usLengthOfControl >= sizeof(CSMI_SAS_PHY_CONTROL)) && ++ (karg->bNumberOfControls > 0)){ ++ if(karg->Control[0].bRate == ++ CSMI_SAS_LINK_RATE_1_5_GBPS) { ++ sasIoUnitPg1->PhyData[karg->bPhyIdentifier].MaxMinLinkRate = ++ MPI_SAS_IOUNIT1_MAX_RATE_1_5 | ++ MPI_SAS_IOUNIT1_MIN_RATE_1_5; ++ } ++ else if(karg->Control[0].bRate == ++ CSMI_SAS_LINK_RATE_3_0_GBPS) { ++ sasIoUnitPg1->PhyData[karg->bPhyIdentifier].MaxMinLinkRate = ++ MPI_SAS_IOUNIT1_MAX_RATE_3_0 | ++ MPI_SAS_IOUNIT1_MIN_RATE_3_0; ++ } ++ sasIoUnitPg1->PhyData[karg->bPhyIdentifier].PhyFlags &= ++ ~MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE; ++ cfg.dir = 1; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM; ++ if (mpt_config(ioc, &cfg) != 0) { ++ dctlprintk(( ++ ": FAILED: WRITE MPI_SASIOUNITPAGE1 NVRAM\n")); ++ karg->IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_FAILED; ++ goto cim_sas_phy_control_exit; ++ } ++ cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; ++ if (mpt_config(ioc, &cfg) != 0) { ++ dctlprintk(( ++ ": FAILED: WRITE MPI_SASIOUNITPAGE1 CURRENT\n")); ++ karg->IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_FAILED; ++ goto cim_sas_phy_control_exit; ++ } ++ } ++ if (mptctl_csmi_sas_phy_reset(ioc, ++ karg->bPhyIdentifier, opcode) != 0) { ++ dctlprintk(( ++ ": FAILED: mptctl_csmi_sas_phy_reset\n")); ++ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_sas_phy_control_exit; ++ } ++ break; ++ ++ } ++ case CSMI_SAS_PC_PHY_DISABLE: ++ if(karg->usLengthOfControl || karg->bNumberOfControls) { ++ karg->IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_INVALID_PARAMETER; ++ break; ++ } ++ sasIoUnitPg1->PhyData[karg->bPhyIdentifier].PhyFlags |= ++ MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE; ++ cfg.dir = 1; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM; ++ if (mpt_config(ioc, &cfg) != 0) { ++ dctlprintk(( ++ ": FAILED: WRITE MPI_SASIOUNITPAGE1 NVRAM\n")); ++ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_sas_phy_control_exit; ++ } ++ cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; ++ if (mpt_config(ioc, &cfg) != 0) { ++ dctlprintk(( ++ ": FAILED: WRITE MPI_SASIOUNITPAGE1 CURRENT\n")); ++ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_sas_phy_control_exit; ++ } ++ if (mptctl_csmi_sas_phy_reset(ioc, ++ karg->bPhyIdentifier, MPI_SAS_OP_PHY_HARD_RESET) != 0) { ++ dctlprintk(( ++ ": FAILED: mptctl_csmi_sas_phy_reset\n")); ++ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ goto cim_sas_phy_control_exit; ++ } ++ break; ++ ++ case CSMI_SAS_PC_GET_PHY_SETTINGS: ++ if(karg->usLengthOfControl || karg->bNumberOfControls) { ++ karg->IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_INVALID_PARAMETER; ++ break; ++ } ++ if(csmi_sas_phy_control_buffer_sz < ++ offsetof(CSMI_SAS_PHY_CONTROL_BUFFER,Control) + ++ (4* sizeof(CSMI_SAS_PHY_CONTROL))) { ++ karg->IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_INVALID_PARAMETER; ++ break; ++ } ++ karg->usLengthOfControl = sizeof(CSMI_SAS_PHY_CONTROL); ++ karg->bNumberOfControls = 4; ++ karg->Control[0].bType = CSMI_SAS_SAS; ++ karg->Control[0].bRate = CSMI_SAS_LINK_RATE_1_5_GBPS; ++ karg->Control[1].bType = CSMI_SAS_SAS; ++ karg->Control[1].bRate = CSMI_SAS_LINK_RATE_3_0_GBPS; ++ karg->Control[2].bType = CSMI_SAS_SATA; ++ karg->Control[2].bRate = CSMI_SAS_LINK_RATE_1_5_GBPS; ++ karg->Control[3].bType = CSMI_SAS_SATA; ++ karg->Control[3].bRate = CSMI_SAS_LINK_RATE_3_0_GBPS; ++ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; ++ break; ++ default: ++ break; ++ } ++ ++cim_sas_phy_control_exit: ++ ++ if (sasIoUnitPg0) ++ pci_free_consistent(ioc->pcidev, sasIoUnitPg0_data_sz, ++ (u8 *) sasIoUnitPg0, sasIoUnitPg0_dma); ++ ++ if (sasIoUnitPg1) ++ pci_free_consistent(ioc->pcidev, sasIoUnitPg1_data_sz, ++ (u8 *) sasIoUnitPg1, sasIoUnitPg1_dma); ++ ++ /* Copy the data from kernel memory to user memory ++ */ ++ if (copy_to_user((char *)arg,karg,csmi_sas_phy_control_buffer_sz)) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to write out csmi_sas_phy_control_buffer @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ kfree(karg); ++ return -EFAULT; ++ } ++ ++ kfree(karg); ++ return 0; ++} ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* Prototype Routine for the CSMI SAS Get Connector info command. ++ * ++ * Outputs: None. ++ * Return: 0 if successful ++ * -EFAULT if data unavailable ++ * -ENODEV if no such device/adapter ++ */ ++static int ++mptctl_csmi_sas_get_connector_info(unsigned long arg) ++{ ++ CSMI_SAS_CONNECTOR_INFO_BUFFER __user *uarg = (void __user *) arg; ++ CSMI_SAS_CONNECTOR_INFO_BUFFER karg; ++ MPT_ADAPTER *ioc = NULL; ++ int iocnum; ++ int i; ++ ++ dctlprintk((": %s called.\n",__FUNCTION__)); ++ ++ if (copy_from_user(&karg, uarg, sizeof(CSMI_SAS_CONNECTOR_INFO_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to read in csmi_sas_connector_info_buffer" ++ " struct @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ if (((iocnum = mpt_verify_adapter(karg.IoctlHeader.IOControllerNumber, ++ &ioc)) < 0) || (ioc == NULL)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not found!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ if (!mptctl_is_this_sas_cntr(ioc)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not SAS controller!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ return -ENODEV; ++ } ++ ++ karg.IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; ++// TODO - to be implemented - This requires MPI changes to a Manufacturing page ++ for (i=0;i< ioc->numPhys;i++) { ++ karg.Reference[i].uPinout = CSMI_SAS_CON_UNKNOWN; ++ strcpy(karg.Reference[i].bConnector,""); ++ karg.Reference[i].bLocation = CSMI_SAS_CON_UNKNOWN; ++ } ++ ++// cim_sas_get_connector_info_exit: ++ ++ /* Copy the data from kernel memory to user memory ++ */ ++ if (copy_to_user((char *)arg, &karg, ++ sizeof(CSMI_SAS_CONNECTOR_INFO_BUFFER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to write out csmi_sas_connector_info_buffer @" ++ "%p\n", ++ __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ return 0; ++ ++} ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* mptctl_csmi_sas_fill_location_data ++ * ++ * Outputs: None. ++ * Return: 0 if successful ++ */ ++static int ++mptctl_csmi_sas_fill_location_data(MPT_ADAPTER *ioc, u8 target, u8 bus, u8 opcode, CSMI_SAS_LOCATION_IDENTIFIER * location_ident) ++{ ++ ++ ConfigExtendedPageHeader_t hdr; ++ CONFIGPARMS cfg; ++ int rc; ++ SasDevicePage0_t *sasDevicePg0=NULL; ++ SasEnclosurePage0_t *sasEnclosurePg0=NULL; ++ dma_addr_t sasDevicePg0_dma,sasEnclosurePg0_dma; ++ int sasDevicePg0_data_sz=0; ++ int sasEnclosurePg0_data_sz=0; ++ u64 SASAddress64; ++ ++ dctlprintk((": %s called.\n",__FUNCTION__)); ++ ++ /* SAS Device Page 0 */ ++ hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION; ++ hdr.ExtPageLength = 0; ++ hdr.PageNumber = 0; ++ hdr.Reserved1 = 0; ++ hdr.Reserved2 = 0; ++ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; ++ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE; ++ ++ cfg.cfghdr.ehdr = &hdr; ++ cfg.physAddr = -1; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; ++ cfg.dir = 0; /* read */ ++ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; ++ ++ if ((rc = mpt_config(ioc, &cfg)) != 0) { ++ rc=-1; ++ goto fill_location_data_exit; ++ } ++ ++ if (hdr.ExtPageLength == 0) { ++ rc=-1; ++ goto fill_location_data_exit; ++ } ++ ++ sasDevicePg0_data_sz = hdr.ExtPageLength * 4; ++ sasDevicePg0 = (SasDevicePage0_t *) pci_alloc_consistent( ++ ioc->pcidev, sasDevicePg0_data_sz, &sasDevicePg0_dma); ++ if (!sasDevicePg0) { ++ rc=-1; ++ goto fill_location_data_exit; ++ } ++ ++ memset((u8 *)sasDevicePg0, 0, sasDevicePg0_data_sz); ++ cfg.physAddr = sasDevicePg0_dma; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; ++ cfg.pageAddr = (bus << 8) + target ++ + (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << ++ MPI_SAS_DEVICE_PGAD_FORM_SHIFT); ++ ++ if ((rc = mpt_config(ioc, &cfg)) != 0) { ++ rc=-1; ++ goto fill_location_data_exit; ++ } ++ ++ location_ident->bLocationFlags |= CSMI_SAS_LOCATE_SAS_ADDRESS_VALID; ++ SASAddress64 = reverse_byte_order64((u64 *)&sasDevicePg0->SASAddress); ++ memcpy(&location_ident->bSASAddress,&SASAddress64,sizeof(u64)); ++ ++ location_ident->bLocationFlags |= CSMI_SAS_LOCATE_SAS_LUN_VALID; ++ memset(location_ident->bSASLun, 0, sizeof(location_ident->bSASLun)); ++ ++ /* SAS Enclosure Page 0 */ ++ hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION; ++ hdr.ExtPageLength = 0; ++ hdr.PageNumber = 0; ++ hdr.Reserved1 = 0; ++ hdr.Reserved2 = 0; ++ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; ++ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE; ++ ++ cfg.cfghdr.ehdr = &hdr; ++ cfg.physAddr = -1; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; ++ cfg.dir = 0; /* read */ ++ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; ++ ++ if ((rc = mpt_config(ioc, &cfg)) != 0) { ++ rc=0; ++ goto fill_location_data_exit; ++ } ++ ++ if (hdr.ExtPageLength == 0) { ++ rc=0; ++ goto fill_location_data_exit; ++ } ++ ++ sasEnclosurePg0_data_sz = hdr.ExtPageLength * 4; ++ sasEnclosurePg0 = (SasEnclosurePage0_t *) pci_alloc_consistent( ++ ioc->pcidev, sasEnclosurePg0_data_sz, &sasEnclosurePg0_dma); ++ if (!sasEnclosurePg0) { ++ rc=0; ++ goto fill_location_data_exit; ++ } ++ cfg.physAddr = sasEnclosurePg0_dma; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; ++ cfg.pageAddr = le16_to_cpu(sasDevicePg0->EnclosureHandle) ++ + (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE << ++ MPI_SAS_ENCLOS_PGAD_FORM_SHIFT); ++ ++ if ((rc = mpt_config(ioc, &cfg)) != 0) { ++ rc=0; ++ goto fill_location_data_exit; ++ } ++ ++ location_ident->bLocationFlags |= ++ CSMI_SAS_LOCATE_ENCLOSURE_IDENTIFIER_VALID; ++ SASAddress64 = reverse_byte_order64( ++ (u64 *)&sasEnclosurePg0->EnclosureLogicalID); ++ if (SASAddress64) ++ memcpy(&location_ident->bEnclosureIdentifier, ++ &SASAddress64,sizeof(u64)); ++ else ++ strcpy(location_ident->bEnclosureIdentifier,"Internal"); ++ ++// bBayPrefix - not supported ++ ++// TODO - We need to look at sasEnclosurePg0-.Flags , to determine ++// whether SEP BUS/TargetID is valid. Ifs its a SES device, then ++// issue internal inquiry to (bus/target) to gather the Enclosure name. ++// If the device is SMP, then issue SMP_MANUFACTURING to get enclosure name ++// If its direct attached, there is no enclosure name ++ location_ident->bLocationFlags |= CSMI_SAS_LOCATE_ENCLOSURE_NAME_VALID; ++ strcpy(location_ident->bEnclosureName,"Not Supported"); ++ ++ location_ident->bLocationFlags |= CSMI_SAS_LOCATE_LOCATION_STATE_VALID; ++ location_ident->bLocationState = CSMI_SAS_LOCATE_UNKNOWN; ++ ++ location_ident->bLocationFlags |= CSMI_SAS_LOCATE_BAY_IDENTIFIER_VALID; ++ location_ident->bBayIdentifier = le16_to_cpu(sasDevicePg0->Slot); ++ ++ ++// TODO - illuminating LEDs, ++// karg->bIdentify = CSMI_SAS_LOCATE_FORCE_OFF, CSMI_SAS_LOCATE_FORCE_ON ++// We can enable/disable LEDs by SCSI Enclosure Processor MPI request message ++// printk("Flags=0x%x\n",sasEnclosurePg0->Flags); ++ ++/* check sasEnclosurePg0->Flags - ++ * to validate whether we need to send the SEPRequest ++ * bit:5 should be set ++ * bit:3-0 any bit should be set. If zero, then SEPRequest will fail ++*/ ++ ++/* MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR ++ * Look in mpi_init.h ++ * SEPRequest_t = structure ++ * ++ * SEPRequest_t->Action should be set to MPI_SEP_REQ_ACTION_WRITE_STATUS ++ * ++ * SEPRequest_t->Flags should be set to ++ * MPI_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS, to pass along enclosure/slot ids ++ * ++ * SEPRequest_t->SlotStatus |= MPI_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST - this ++ * will illuminate the LEDs ++ */ ++ ++fill_location_data_exit: ++ ++ if (sasDevicePg0 != NULL) ++ pci_free_consistent(ioc->pcidev, sasDevicePg0_data_sz, ++ sasDevicePg0, sasDevicePg0_dma); ++ ++ if (sasEnclosurePg0 != NULL) ++ pci_free_consistent(ioc->pcidev, sasEnclosurePg0_data_sz, ++ sasEnclosurePg0, sasEnclosurePg0_dma); ++ return rc; ++} ++ ++ ++static int ++mptctl_csmi_sas_fill_location_data_raid(MPT_ADAPTER *ioc, PCSMI_SAS_GET_LOCATION_BUFFER karg, u8 volumeID, u8 VolumeBus) ++{ ++ pRaidVolumePage0_t pVolume0 = NULL; ++ pRaidPhysDiskPage0_t pPhysDisk0 = NULL; ++ CONFIGPARMS cfg; ++ ConfigPageHeader_t header; ++ u8 physDiskNumMax,physDiskNum; ++ int volumepage0sz = 0, physdiskpage0sz = 0; ++ dma_addr_t volume0_dma, physdisk0_dma; ++ int csmi_sas_get_location_sz; ++ int rc = 0,i; ++ ++ csmi_sas_get_location_sz = karg->IoctlHeader.Length; ++ physDiskNumMax = (csmi_sas_get_location_sz - ++ offsetof(CSMI_SAS_GET_LOCATION_BUFFER,Location)) ++ / sizeof(CSMI_SAS_LOCATION_IDENTIFIER); ++ karg->bNumberOfLocationIdentifiers=0; ++ ++ /* ++ * get RAID Volume Page 0 ++ */ ++ ++ header.PageVersion = 0; ++ header.PageLength = 0; ++ header.PageNumber = 0; ++ header.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME; ++ cfg.cfghdr.hdr = &header; ++ cfg.physAddr = -1; ++ cfg.pageAddr = (VolumeBus << 8) + volumeID; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; ++ cfg.dir = 0; ++ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; ++ if (mpt_config(ioc, &cfg) != 0) { ++ rc = -1; ++ goto sas_fill_location_data_raid_exit; ++ } ++ ++ if (header.PageLength == 0) { ++ rc = -1; ++ goto sas_fill_location_data_raid_exit; ++ } ++ ++ volumepage0sz = header.PageLength * 4; ++ pVolume0 = pci_alloc_consistent(ioc->pcidev, volumepage0sz, ++ &volume0_dma); ++ if (!pVolume0) { ++ rc = -1; ++ goto sas_fill_location_data_raid_exit; ++ } ++ ++ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; ++ cfg.physAddr = volume0_dma; ++ if (mpt_config(ioc, &cfg) != 0){ ++ rc = -1; ++ goto sas_fill_location_data_raid_exit; ++ } ++ ++ ++ /* ++ * get RAID Physical Disk Page 0 ++ */ ++ header.PageVersion = 0; ++ header.PageLength = 0; ++ header.PageNumber = 0; ++ header.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK; ++ cfg.cfghdr.hdr = &header; ++ cfg.physAddr = -1; ++ cfg.pageAddr = 0; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; ++ cfg.dir = 0; ++ cfg.timeout = MPT_IOCTL_DEFAULT_TIMEOUT; ++ if (mpt_config(ioc, &cfg) != 0) { ++ rc = -1; ++ goto sas_fill_location_data_raid_exit; ++ } ++ ++ if (header.PageLength == 0) { ++ rc = -1; ++ goto sas_fill_location_data_raid_exit; ++ } ++ ++ physdiskpage0sz = header.PageLength * 4; ++ pPhysDisk0 = pci_alloc_consistent(ioc->pcidev, physdiskpage0sz, ++ &physdisk0_dma); ++ if (!pPhysDisk0) { ++ rc = -1; ++ goto sas_fill_location_data_raid_exit; ++ } ++ cfg.physAddr = physdisk0_dma; ++ ++ for (i=0; i< min(pVolume0->NumPhysDisks, physDiskNumMax); i++) { ++ ++ physDiskNum = pVolume0->PhysDisk[i].PhysDiskNum; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; ++ cfg.pageAddr = physDiskNum; ++ if (mpt_config(ioc, &cfg) != 0){ ++ rc = -1; ++ goto sas_fill_location_data_raid_exit; ++ } ++ ++ if((mptctl_csmi_sas_fill_location_data(ioc, ++ pPhysDisk0->PhysDiskID, ++ karg->bPathId, karg->bIdentify, ++ &karg->Location[karg->bNumberOfLocationIdentifiers])) == 0) ++ karg->bNumberOfLocationIdentifiers++; ++ } ++ ++ ++sas_fill_location_data_raid_exit: ++ ++ if (pVolume0 != NULL) ++ pci_free_consistent(ioc->pcidev, volumepage0sz, pVolume0, ++ volume0_dma); ++ ++ if(pPhysDisk0 != NULL) ++ pci_free_consistent(ioc->pcidev, physdiskpage0sz, pPhysDisk0, ++ physdisk0_dma); ++ ++ return rc; ++} ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* Prototype Routine for the CSMI SAS Get location command. ++ * ++ * Outputs: None. ++ * Return: 0 if successful ++ * -EFAULT if data unavailable ++ * -ENODEV if no such device/adapter ++ */ ++static int ++mptctl_csmi_sas_get_location(unsigned long arg) ++{ ++ CSMI_SAS_GET_LOCATION_BUFFER __user *uarg = (void __user *) arg; ++ PCSMI_SAS_GET_LOCATION_BUFFER karg; ++ IOCTL_HEADER ioctl_header; ++ MPT_ADAPTER *ioc = NULL; ++ int iocnum,i; ++ int csmi_sas_get_location_sz; ++ ++ dctlprintk((": %s called.\n",__FUNCTION__)); ++ ++ if (copy_from_user(&ioctl_header, uarg, sizeof(IOCTL_HEADER))) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to read in IOCTL_HEADER" ++ "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ csmi_sas_get_location_sz = ioctl_header.Length; ++ karg = kmalloc(csmi_sas_get_location_sz,GFP_KERNEL); ++ if(karg==NULL){ ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to malloc @ %p\n", ++ __FILE__, __LINE__, __FUNCTION__,karg); ++ return -EFAULT; ++ } ++ ++ if (copy_from_user(karg, uarg, csmi_sas_get_location_sz)) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to read in csmi_sas_phy_control_buffer " ++ "struct @ %p\n", __FILE__, __LINE__, __FUNCTION__, uarg); ++ kfree(karg); ++ return -EFAULT; ++ } ++ ++ if (((iocnum = mpt_verify_adapter(karg->IoctlHeader.IOControllerNumber, ++ &ioc)) < 0) || (ioc == NULL)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not found!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ kfree(karg); ++ return -ENODEV; ++ } ++ ++ if (!mptctl_is_this_sas_cntr(ioc)) { ++ dctlprintk((KERN_ERR ++ "%s::%s() @%d - ioc%d not SAS controller!\n", ++ __FILE__, __FUNCTION__, __LINE__, iocnum)); ++ kfree(karg); ++ return -ENODEV; ++ } ++ ++ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_INVALID_PARAMETER; ++ if(karg->bLengthOfLocationIdentifier != sizeof(CSMI_SAS_LOCATION_IDENTIFIER)) ++ goto cim_sas_get_location_exit; ++ ++ ++ /* RAID SUPPORT */ ++ if (ioc->raid_data.isRaid && ioc->raid_data.pIocPg2) { ++ for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++){ ++ if (karg->bTargetId == ++ ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID) { ++ if(mptctl_csmi_sas_fill_location_data_raid(ioc, karg, ++ ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, ++ ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus) == 0) ++ karg->IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_SUCCESS; ++ else ++ karg->IoctlHeader.ReturnCode = ++ CSMI_SAS_STATUS_FAILED; ++ goto cim_sas_get_location_exit; ++ } ++ } ++ } ++ ++ /* NON-RAID SUPPORT */ ++ ++ /* make sure there's enough room to populate the Location[] struct */ ++ if ((csmi_sas_get_location_sz - ++ offsetof(CSMI_SAS_GET_LOCATION_BUFFER,Location)) < ++ sizeof(CSMI_SAS_LOCATION_IDENTIFIER)) ++ goto cim_sas_get_location_exit; ++ ++ karg->bNumberOfLocationIdentifiers=1; ++ karg->Location[0].bLocationFlags=0; ++ if((mptctl_csmi_sas_fill_location_data(ioc, karg->bTargetId, ++ karg->bPathId, karg->bIdentify, &karg->Location[0])) == 0) ++ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_SUCCESS; ++ else ++ karg->IoctlHeader.ReturnCode = CSMI_SAS_STATUS_FAILED; ++ ++cim_sas_get_location_exit: ++ ++ /* Copy the data from kernel memory to user memory ++ */ ++ if (copy_to_user((char *)arg, karg, csmi_sas_get_location_sz)) { ++ printk(KERN_ERR "%s@%d::%s() - " ++ "Unable to write out csmi_sas_get_location_buffer " ++ "@ %p\n",__FILE__, __LINE__, __FUNCTION__, uarg); ++ return -EFAULT; ++ } ++ ++ kfree(karg); ++ return 0; ++} +diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/csmisas.h linux-2.6.9-55.0.12/drivers/message/fusion/csmisas.h +--- linux-2.6.9-67.0.1/drivers/message/fusion/csmisas.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.9-55.0.12/drivers/message/fusion/csmisas.h 2007-11-02 09:10:23.000000000 +0100 +@@ -0,0 +1,1796 @@ ++/************************************************************************** ++ ++Module Name: ++ ++ CSMISAS.H ++ ++ ++Abstract: ++ ++ This file contains constants and data structure definitions used by drivers ++ that support the Common Storage Management Interface specification for ++ SAS or SATA in either the Windows or Linux. ++ ++ This should be considered as a reference implementation only. Changes may ++ be necessary to accommodate a specific build environment or target OS. ++ ++Revision History: ++ ++ 001 SEF 8/12/03 Initial release. ++ 002 SEF 8/20/03 Cleanup to match documentation. ++ 003 SEF 9/12/03 Additional cleanup, created combined header ++ 004 SEF 9/23/03 Changed base types to match linux defaults ++ Added RAID signature ++ Added bControllerFlags to CSMI_SAS_CNTLR_CONFIG ++ Changed CSMI_SAS_BEGIN_PACK to 8 for common structures ++ Fixed other typos identified in first compilation test ++ 005 SEF 10/03/03 Additions to match first version of CSMI document ++ 006 SEF 10/14/03 Fixed typedef struct _CSMI_SAS_SMP_PASSTHRU_BUFFER ++ Added defines for bConnectionRate ++ 007 SEF 10/15/03 Added Firmware Download Control Code and support ++ Added CSMI revision support ++ 008 SEF 10/30/03 No functional change, just updated version to track ++ spec changes ++ 009 SEF 12/09/03 No functional change, just updated version to track ++ spec changes ++ 010 SEF 3/11/04 Fixed typedef struct CSMI_SAS_RAID_DRIVES to include the ++ bFirmware member that is defined in the spec, but ++ was missing in this file, ++ added CC_CSMI_SAS_TASK_MANAGEMENT ++ 011 SEF 4/02/04 No functional change, added comment line before ++ CC_CSMI_SAS_TASK_MANAGEMENT ++ 012 SEF 4/16/04 Added IOControllerNumber to linux header, ++ Modified linux control codes to have upper word of ++ 0xCC77.... to indicate CSMI version 77 ++ Added bSignalClass to CC_CSMI_SET_PHY_INFO ++ Added CC_CSMI_SAS_PHY_CONTROL support ++ 013 SEF 5/14/04 Added CC_CSMI_SAS_GET_CONNECTOR_INFO support ++ 014 SEF 5/24/04 No functional change, just updated version to track spec ++ changes ++ 015 SEF 6/16/04 changed bPinout to uPinout to reflect proper size, ++ changed width of bLocation defines to reflect size ++ 016 SEF 6/17/04 changed bLengthOfControls in CSMI_SAS_PHY_CONTROL ++ to be proper size ++ 017 SEF 9/17/04 added CSMI_SAS_SATA_PORT_SELECTOR, ++ CSMI_SAS_LINK_VIRTUAL, CSMI_SAS_CON_NOT_PRESENT, and ++ CSMI_SAS_CON_NOT_CONNECTED ++ 018 SEF 9/20/04 added CSMI_SAS_PHY_USER_PATTERN, ++ changed definition of CSMI_SAS_PHY_FIXED_PATTERN to not ++ conflict with activate definition ++ 019 SEF 12/06/04 added CSMI_SAS_GET_LOCATION ++ added bSSPStatus to CSMI_SAS_SSP_PASSTHRU_STATUS ++ structure ++ 020 SEF 5/25/05 added CSMI_SAS_PHY_VIRTUAL_SMP, and changes to ++ CSMI_SAS_GET_LOCATION ++ 021 SEF 11/03/05 added new RAID creation functionality ++ 022 SEF 2/01/06 corrected typo bNegotitiatedLInkRate ++ Added two more RAID_TYPES, 7 and 8 ++ 023 SEF 4/04/06 added CSMI_RAID_TYPE_1E ++ changed structures that contained surface scan ++ to priority approach rather than time, causes ++ 0.89 to incompatible with 0.87, so a version ++ check is necessary when interpreting the ++ raid structures ++ Added netware section ++ ++**************************************************************************/ ++ ++#ifndef _CSMI_SAS_H_ ++#define _CSMI_SAS_H_ ++ ++// CSMI Specification Revision, the intent is that all versions of the ++// specification will be backward compatible after the 1.00 release. ++// Major revision number, corresponds to xxxx. of CSMI specification ++// Minor revision number, corresponds to .xxxx of CSMI specification ++#define CSMI_MAJOR_REVISION 0 ++#define CSMI_MINOR_REVISION 89 ++ ++/*************************************************************************/ ++/* PATCHES FOR TYPOS */ ++/*************************************************************************/ ++ ++#define bNegotitiatedLInkRate bNegotiatedLinkRate ++ ++/*************************************************************************/ ++/* TARGET OS LINUX SPECIFIC CODE */ ++/*************************************************************************/ ++ ++// EDM #ifdef _linux ++#ifdef __KERNEL__ ++ ++// Linux base types ++ ++#include <linux/types.h> ++ ++#define __i8 char ++ ++// pack definition ++ ++// EDM #define CSMI_SAS_BEGIN_PACK(x) pack(x) ++// EDM #define CSMI_SAS_END_PACK pack() ++ ++// IOCTL Control Codes ++// (IoctlHeader.ControlCode) ++ ++// Control Codes prior to 0.77 ++ ++// Control Codes requiring CSMI_ALL_SIGNATURE ++ ++// #define CC_CSMI_SAS_GET_DRIVER_INFO 0x12345678 ++// #define CC_CSMI_SAS_GET_CNTLR_CONFIG 0x23456781 ++// #define CC_CSMI_SAS_GET_CNTLR_STATUS 0x34567812 ++// #define CC_CSMI_SAS_FIRMWARE_DOWNLOAD 0x92345678 ++ ++// Control Codes requiring CSMI_RAID_SIGNATURE ++ ++// #define CC_CSMI_SAS_GET_RAID_INFO 0x45678123 ++// #define CC_CSMI_SAS_GET_RAID_CONFIG 0x56781234 ++ ++// Control Codes requiring CSMI_SAS_SIGNATURE ++ ++// #define CC_CSMI_SAS_GET_PHY_INFO 0x67812345 ++// #define CC_CSMI_SAS_SET_PHY_INFO 0x78123456 ++// #define CC_CSMI_SAS_GET_LINK_ERRORS 0x81234567 ++// #define CC_CSMI_SAS_SMP_PASSTHRU 0xA1234567 ++// #define CC_CSMI_SAS_SSP_PASSTHRU 0xB1234567 ++// #define CC_CSMI_SAS_STP_PASSTHRU 0xC1234567 ++// #define CC_CSMI_SAS_GET_SATA_SIGNATURE 0xD1234567 ++// #define CC_CSMI_SAS_GET_SCSI_ADDRESS 0xE1234567 ++// #define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0xF1234567 ++// #define CC_CSMI_SAS_TASK_MANAGEMENT 0xA2345678 ++ ++// Control Codes for 0.77 and later ++ ++// Control Codes requiring CSMI_ALL_SIGNATURE ++ ++#define CC_CSMI_SAS_GET_DRIVER_INFO 0xCC770001 ++#define CC_CSMI_SAS_GET_CNTLR_CONFIG 0xCC770002 ++#define CC_CSMI_SAS_GET_CNTLR_STATUS 0xCC770003 ++#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD 0xCC770004 ++ ++// Control Codes requiring CSMI_RAID_SIGNATURE ++ ++#define CC_CSMI_SAS_GET_RAID_INFO 0xCC77000A ++#define CC_CSMI_SAS_GET_RAID_CONFIG 0xCC77000B ++#define CC_CSMI_SAS_GET_RAID_FEATURES 0xCC77000C ++#define CC_CSMI_SAS_SET_RAID_CONTROL 0xCC77000D ++#define CC_CSMI_SAS_GET_RAID_ELEMENT 0xCC77000E ++#define CC_CSMI_SAS_SET_RAID_OPERATION 0xCC77000F ++ ++// Control Codes requiring CSMI_SAS_SIGNATURE ++ ++#define CC_CSMI_SAS_GET_PHY_INFO 0xCC770014 ++#define CC_CSMI_SAS_SET_PHY_INFO 0xCC770015 ++#define CC_CSMI_SAS_GET_LINK_ERRORS 0xCC770016 ++#define CC_CSMI_SAS_SMP_PASSTHRU 0xCC770017 ++#define CC_CSMI_SAS_SSP_PASSTHRU 0xCC770018 ++#define CC_CSMI_SAS_STP_PASSTHRU 0xCC770019 ++#define CC_CSMI_SAS_GET_SATA_SIGNATURE 0xCC770020 ++#define CC_CSMI_SAS_GET_SCSI_ADDRESS 0xCC770021 ++#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0xCC770022 ++#define CC_CSMI_SAS_TASK_MANAGEMENT 0xCC770023 ++#define CC_CSMI_SAS_GET_CONNECTOR_INFO 0xCC770024 ++#define CC_CSMI_SAS_GET_LOCATION 0xCC770025 ++ ++ ++// Control Codes requiring CSMI_PHY_SIGNATURE ++ ++#define CC_CSMI_SAS_PHY_CONTROL 0xCC77003C ++ ++// EDM #pragma CSMI_SAS_BEGIN_PACK(8) ++#pragma pack(8) ++ ++// IOCTL_HEADER ++typedef struct _IOCTL_HEADER { ++ __u32 IOControllerNumber; ++ __u32 Length; ++ __u32 ReturnCode; ++ __u32 Timeout; ++ __u16 Direction; ++} IOCTL_HEADER, ++ *PIOCTL_HEADER; ++ ++// EDM #pragma CSMI_SAS_END_PACK ++#pragma pack() ++ ++#endif ++ ++/*************************************************************************/ ++/* TARGET OS WINDOWS SPECIFIC CODE */ ++/*************************************************************************/ ++ ++#ifdef _WIN32 ++ ++// windows IOCTL definitions ++ ++#ifndef _NTDDSCSIH_ ++#include <ntddscsi.h> ++#endif ++ ++// pack definition ++ ++#if defined _MSC_VER ++ #define CSMI_SAS_BEGIN_PACK(x) pack(push,x) ++ #define CSMI_SAS_END_PACK pack(pop) ++#elif defined __BORLANDC__ ++ #define CSMI_SAS_BEGIN_PACK(x) option -a##x ++ #define CSMI_SAS_END_PACK option -a. ++#else ++ #error "CSMISAS.H - Must externally define a pack compiler designator." ++#endif ++ ++// base types ++ ++#define __u8 unsigned char ++#define __u16 unsigned short ++#define __u32 unsigned long ++#define __u64 unsigned __int64 ++ ++#define __i8 char ++ ++// IOCTL Control Codes ++// (IoctlHeader.ControlCode) ++ ++// Control Codes requiring CSMI_ALL_SIGNATURE ++ ++#define CC_CSMI_SAS_GET_DRIVER_INFO 1 ++#define CC_CSMI_SAS_GET_CNTLR_CONFIG 2 ++#define CC_CSMI_SAS_GET_CNTLR_STATUS 3 ++#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD 4 ++ ++// Control Codes requiring CSMI_RAID_SIGNATURE ++ ++#define CC_CSMI_SAS_GET_RAID_INFO 10 ++#define CC_CSMI_SAS_GET_RAID_CONFIG 11 ++#define CC_CSMI_SAS_GET_RAID_FEATURES 12 ++#define CC_CSMI_SAS_SET_RAID_CONTROL 13 ++#define CC_CSMI_SAS_GET_RAID_ELEMENT 14 ++#define CC_CSMI_SAS_SET_RAID_OPERATION 15 ++ ++// Control Codes requiring CSMI_SAS_SIGNATURE ++ ++#define CC_CSMI_SAS_GET_PHY_INFO 20 ++#define CC_CSMI_SAS_SET_PHY_INFO 21 ++#define CC_CSMI_SAS_GET_LINK_ERRORS 22 ++#define CC_CSMI_SAS_SMP_PASSTHRU 23 ++#define CC_CSMI_SAS_SSP_PASSTHRU 24 ++#define CC_CSMI_SAS_STP_PASSTHRU 25 ++#define CC_CSMI_SAS_GET_SATA_SIGNATURE 26 ++#define CC_CSMI_SAS_GET_SCSI_ADDRESS 27 ++#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 28 ++#define CC_CSMI_SAS_TASK_MANAGEMENT 29 ++#define CC_CSMI_SAS_GET_CONNECTOR_INFO 30 ++#define CC_CSMI_SAS_GET_LOCATION 31 ++ ++// Control Codes requiring CSMI_PHY_SIGNATURE ++ ++#define CC_CSMI_SAS_PHY_CONTROL 60 ++ ++#define IOCTL_HEADER SRB_IO_CONTROL ++#define PIOCTL_HEADER PSRB_IO_CONTROL ++ ++#endif ++ ++/*************************************************************************/ ++/* TARGET OS NETWARE SPECIFIC CODE */ ++/*************************************************************************/ ++ ++#ifdef _NETWARE ++ ++// NetWare IOCTL definitions ++ ++#define CSMI_SAS_BEGIN_PACK(x) pack(x) ++#define CSMI_SAS_END_PACK pack() ++ ++#ifndef LONG ++typedef unsigned long LONG; ++#endif ++ ++#ifndef WORD ++typedef unsigned short WORD; ++#endif ++ ++#ifndef BYTE ++typedef unsigned char BYTE; ++#endif ++ ++/* Need to have these definitions for Netware */ ++#define __u8 unsigned char ++#define __u16 unsigned short ++#define __u32 unsigned long ++#define __u64 unsigned __int64 ++ ++#define __i8 char ++ ++ ++#pragma CSMI_SAS_BEGIN_PACK(8) ++ ++// IOCTL_HEADER ++typedef struct _IOCTL_HEADER { ++ __u32 Length; ++ __u32 ReturnCode; ++} IOCTL_HEADER, ++ *PIOCTL_HEADER; ++ ++#pragma CSMI_SAS_END_PACK ++ ++// IOCTL Control Codes ++// (IoctlHeader.ControlCode) ++ ++// Control Codes requiring CSMI_ALL_SIGNATURE ++ ++#define CC_CSMI_SAS_GET_DRIVER_INFO 0x01FF0001 ++#define CC_CSMI_SAS_GET_CNTLR_CONFIG 0x01FF0002 ++#define CC_CSMI_SAS_GET_CNTLR_STATUS 0x01FF0003 ++#define CC_CSMI_SAS_FIRMWARE_DOWNLOAD 0x01FF0004 ++ ++// Control Codes requiring CSMI_RAID_SIGNATURE ++ ++#define CC_CSMI_SAS_GET_RAID_INFO 0x01FF000A ++#define CC_CSMI_SAS_GET_RAID_CONFIG 0x01FF000B ++#define CC_CSMI_SAS_GET_RAID_FEATURES 0x01FF000C ++#define CC_CSMI_SAS_SET_RAID_CONTROL 0x01FF000D ++#define CC_CSMI_SAS_GET_RAID_ELEMENT 0x01FF000E ++#define CC_CSMI_SAS_SET_RAID_OPERATION 0x01FF000F ++ ++// Control Codes requiring CSMI_SAS_SIGNATURE ++ ++#define CC_CSMI_SAS_GET_PHY_INFO 0x01FF0014 ++#define CC_CSMI_SAS_SET_PHY_INFO 0x01FF0015 ++#define CC_CSMI_SAS_GET_LINK_ERRORS 0x01FF0016 ++#define CC_CSMI_SAS_SMP_PASSTHRU 0x01FF0017 ++#define CC_CSMI_SAS_SSP_PASSTHRU 0x01FF0018 ++#define CC_CSMI_SAS_STP_PASSTHRU 0x01FF0019 ++#define CC_CSMI_SAS_GET_SATA_SIGNATURE 0x01FF001A ++#define CC_CSMI_SAS_GET_SCSI_ADDRESS 0x01FF001B ++#define CC_CSMI_SAS_GET_DEVICE_ADDRESS 0x01FF001C ++#define CC_CSMI_SAS_TASK_MANAGEMENT 0x01FF001D ++#define CC_CSMI_SAS_GET_CONNECTOR_INFO 0x01FF001E ++#define CC_CSMI_SAS_GET_LOCATION 0x01FF001F ++ ++// Control Codes requiring CSMI_PHY_SIGNATURE ++ ++#define CC_CSMI_SAS_PHY_CONTROL 60 ++ ++#endif ++ ++/*************************************************************************/ ++/* TARGET OS NOT DEFINED ERROR */ ++/*************************************************************************/ ++ ++// EDM #if (!_WIN32 && !_linux && !_NETWARE) ++//#if (!_WIN32 && !__KERNEL__ && !_NETWARE) ++// #error "Unknown target OS." ++//#endif ++ ++/*************************************************************************/ ++/* OS INDEPENDENT CODE */ ++/*************************************************************************/ ++ ++/* * * * * * * * * * Class Independent IOCTL Constants * * * * * * * * * */ ++ ++// Return codes for all IOCTL's regardless of class ++// (IoctlHeader.ReturnCode) ++ ++#define CSMI_SAS_STATUS_SUCCESS 0 ++#define CSMI_SAS_STATUS_FAILED 1 ++#define CSMI_SAS_STATUS_BAD_CNTL_CODE 2 ++#define CSMI_SAS_STATUS_INVALID_PARAMETER 3 ++#define CSMI_SAS_STATUS_WRITE_ATTEMPTED 4 ++ ++// Signature value ++// (IoctlHeader.Signature) ++ ++#define CSMI_ALL_SIGNATURE "CSMIALL" ++ ++// Timeout value default of 60 seconds ++// (IoctlHeader.Timeout) ++ ++#define CSMI_ALL_TIMEOUT 60 ++ ++// Direction values for data flow on this IOCTL ++// (IoctlHeader.Direction, Linux only) ++#define CSMI_SAS_DATA_READ 0 ++#define CSMI_SAS_DATA_WRITE 1 ++ ++// I/O Bus Types ++// ISA and EISA bus types are not supported ++// (bIoBusType) ++ ++#define CSMI_SAS_BUS_TYPE_PCI 3 ++#define CSMI_SAS_BUS_TYPE_PCMCIA 4 ++ ++// Controller Status ++// (uStatus) ++ ++#define CSMI_SAS_CNTLR_STATUS_GOOD 1 ++#define CSMI_SAS_CNTLR_STATUS_FAILED 2 ++#define CSMI_SAS_CNTLR_STATUS_OFFLINE 3 ++#define CSMI_SAS_CNTLR_STATUS_POWEROFF 4 ++ ++// Offline Status Reason ++// (uOfflineReason) ++ ++#define CSMI_SAS_OFFLINE_REASON_NO_REASON 0 ++#define CSMI_SAS_OFFLINE_REASON_INITIALIZING 1 ++#define CSMI_SAS_OFFLINE_REASON_BACKSIDE_BUS_DEGRADED 2 ++#define CSMI_SAS_OFFLINE_REASON_BACKSIDE_BUS_FAILURE 3 ++ ++// Controller Class ++// (bControllerClass) ++ ++#define CSMI_SAS_CNTLR_CLASS_HBA 5 ++ ++// Controller Flag bits ++// (uControllerFlags) ++ ++#define CSMI_SAS_CNTLR_SAS_HBA 0x00000001 ++#define CSMI_SAS_CNTLR_SAS_RAID 0x00000002 ++#define CSMI_SAS_CNTLR_SATA_HBA 0x00000004 ++#define CSMI_SAS_CNTLR_SATA_RAID 0x00000008 ++ ++// for firmware download ++#define CSMI_SAS_CNTLR_FWD_SUPPORT 0x00010000 ++#define CSMI_SAS_CNTLR_FWD_ONLINE 0x00020000 ++#define CSMI_SAS_CNTLR_FWD_SRESET 0x00040000 ++#define CSMI_SAS_CNTLR_FWD_HRESET 0x00080000 ++#define CSMI_SAS_CNTLR_FWD_RROM 0x00100000 ++ ++// for RAID configuration supported ++#define CSMI_SAS_CNTLR_RAID_CFG_SUPPORT 0x010000 ++ ++// Download Flag bits ++// (uDownloadFlags) ++#define CSMI_SAS_FWD_VALIDATE 0x00000001 ++#define CSMI_SAS_FWD_SOFT_RESET 0x00000002 ++#define CSMI_SAS_FWD_HARD_RESET 0x00000004 ++ ++// Firmware Download Status ++// (usStatus) ++#define CSMI_SAS_FWD_SUCCESS 0 ++#define CSMI_SAS_FWD_FAILED 1 ++#define CSMI_SAS_FWD_USING_RROM 2 ++#define CSMI_SAS_FWD_REJECT 3 ++#define CSMI_SAS_FWD_DOWNREV 4 ++ ++// Firmware Download Severity ++// (usSeverity> ++#define CSMI_SAS_FWD_INFORMATION 0 ++#define CSMI_SAS_FWD_WARNING 1 ++#define CSMI_SAS_FWD_ERROR 2 ++#define CSMI_SAS_FWD_FATAL 3 ++ ++/* * * * * * * * * * SAS RAID Class IOCTL Constants * * * * * * * * */ ++ ++// Return codes for the RAID IOCTL's regardless of class ++// (IoctlHeader.ReturnCode) ++ ++#define CSMI_SAS_RAID_SET_OUT_OF_RANGE 1000 ++#define CSMI_SAS_RAID_SET_BUFFER_TOO_SMALL 1001 ++#define CSMI_SAS_RAID_SET_DATA_CHANGED 1002 ++ ++// Signature value ++// (IoctlHeader.Signature) ++ ++#define CSMI_RAID_SIGNATURE "CSMIARY" ++ ++// Timeout value default of 60 seconds ++// (IoctlHeader.Timeout) ++ ++#define CSMI_RAID_TIMEOUT 60 ++ ++// RAID Types ++// (bRaidType) ++#define CSMI_SAS_RAID_TYPE_NONE 0 ++#define CSMI_SAS_RAID_TYPE_0 1 ++#define CSMI_SAS_RAID_TYPE_1 2 ++#define CSMI_SAS_RAID_TYPE_10 3 ++#define CSMI_SAS_RAID_TYPE_5 4 ++#define CSMI_SAS_RAID_TYPE_15 5 ++#define CSMI_SAS_RAID_TYPE_6 6 ++#define CSMI_SAS_RAID_TYPE_50 7 ++#define CSMI_SAS_RAID_TYPE_VOLUME 8 ++#define CSMI_SAS_RAID_TYPE_1E 9 ++#define CSMI_SAS_RAID_TYPE_OTHER 255 ++// the last value 255 was already defined for other ++// so end is defined as 254 ++#define CSMI_SAS_RAID_TYPE_END 254 ++ ++// RAID Status ++// (bStatus) ++#define CSMI_SAS_RAID_SET_STATUS_OK 0 ++#define CSMI_SAS_RAID_SET_STATUS_DEGRADED 1 ++#define CSMI_SAS_RAID_SET_STATUS_REBUILDING 2 ++#define CSMI_SAS_RAID_SET_STATUS_FAILED 3 ++#define CSMI_SAS_RAID_SET_STATUS_OFFLINE 4 ++#define CSMI_SAS_RAID_SET_STATUS_TRANSFORMING 5 ++#define CSMI_SAS_RAID_SET_STATUS_QUEUED_FOR_REBUILD 6 ++#define CSMI_SAS_RAID_SET_STATUS_QUEUED_FOR_TRANSFORMATION 7 ++ ++// RAID Drive Count ++// (bDriveCount, 0xF1 to 0xFF are reserved) ++#define CSMI_SAS_RAID_DRIVE_COUNT_TOO_BIG 0xF1 ++#define CSMI_SAS_RAID_DRIVE_COUNT_SUPRESSED 0xF2 ++ ++// RAID Data Type ++// (bDataType) ++#define CSMI_SAS_RAID_DATA_DRIVES 0 ++#define CSMI_SAS_RAID_DATA_DEVICE_ID 1 ++#define CSMI_SAS_RAID_DATA_ADDITIONAL_DATA 2 ++ ++// RAID Drive Status ++// (bDriveStatus) ++#define CSMI_SAS_DRIVE_STATUS_OK 0 ++#define CSMI_SAS_DRIVE_STATUS_REBUILDING 1 ++#define CSMI_SAS_DRIVE_STATUS_FAILED 2 ++#define CSMI_SAS_DRIVE_STATUS_DEGRADED 3 ++#define CSMI_SAS_DRIVE_STATUS_OFFLINE 4 ++#define CSMI_SAS_DRIVE_STATUS_QUEUED_FOR_REBUILD 5 ++ ++// RAID Drive Usage ++// (bDriveUsage) ++#define CSMI_SAS_DRIVE_CONFIG_NOT_USED 0 ++#define CSMI_SAS_DRIVE_CONFIG_MEMBER 1 ++#define CSMI_SAS_DRIVE_CONFIG_SPARE 2 ++#define CSMI_SAS_DRIVE_CONFIG_SPARE_ACTIVE 3 ++ ++// RAID Drive Type ++// (bDriveType) ++#define CSMI_SAS_DRIVE_TYPE_UNKNOWN 0 ++#define CSMI_SAS_DRIVE_TYPE_SINGLE_PORT_SAS 1 ++#define CSMI_SAS_DRIVE_TYPE_DUAL_PORT_SAS 2 ++#define CSMI_SAS_DRIVE_TYPE_SATA 3 ++#define CSMI_SAS_DRIVE_TYPE_SATA_PS 4 ++#define CSMI_SAS_DRIVE_TYPE_OTHER 255 ++ ++// RAID Write Protect ++// (bWriteProtect) ++#define CSMI_SAS_RAID_SET_WRITE_PROTECT_UNKNOWN 0 ++#define CSMI_SAS_RAID_SET_WRITE_PROTECT_UNCHANGED 0 ++#define CSMI_SAS_RAID_SET_WRITE_PROTECT_ENABLED 1 ++#define CSMI_SAS_RAID_SET_WRITE_PROTECT_DISABLED 2 ++ ++// RAID Cache Setting ++// (bCacheSetting) ++#define CSMI_SAS_RAID_SET_CACHE_UNKNOWN 0 ++#define CSMI_SAS_RAID_SET_CACHE_UNCHANGED 0 ++#define CSMI_SAS_RAID_SET_CACHE_ENABLED 1 ++#define CSMI_SAS_RAID_SET_CACHE_DISABLED 2 ++#define CSMI_SAS_RAID_SET_CACHE_CORRUPT 3 ++ ++// RAID Features ++// (uFeatures) ++#define CSMI_SAS_RAID_FEATURE_TRANSFORMATION 0x00000001 ++#define CSMI_SAS_RAID_FEATURE_REBUILD 0x00000002 ++#define CSMI_SAS_RAID_FEATURE_SPLIT_MIRROR 0x00000004 ++#define CSMI_SAS_RAID_FEATURE_MERGE_MIRROR 0x00000008 ++#define CSMI_SAS_RAID_FEATURE_LUN_RENUMBER 0x00000010 ++#define CSMI_SAS_RAID_FEATURE_SURFACE_SCAN 0x00000020 ++#define CSMI_SAS_RAID_FEATURE_SPARES_SHARED 0x00000040 ++ ++// RAID Priority ++// (bDefaultTransformPriority, etc.) ++#define CSMI_SAS_PRIORITY_UNKNOWN 0 ++#define CSMI_SAS_PRIORITY_UNCHANGED 0 ++#define CSMI_SAS_PRIORITY_AUTO 1 ++#define CSMI_SAS_PRIORITY_OFF 2 ++#define CSMI_SAS_PRIORITY_LOW 3 ++#define CSMI_SAS_PRIORITY_MEDIUM 4 ++#define CSMI_SAS_PRIORITY_HIGH 5 ++ ++// RAID Transformation Rules ++// (uRaidSetTransformationRules) ++#define CSMI_SAS_RAID_RULE_AVAILABLE_MEMORY 0x00000001 ++#define CSMI_SAS_RAID_RULE_OVERLAPPED_EXTENTS 0x00000002 ++ ++// RAID Cache Ratios Supported ++// (bCacheRatiosSupported) ++// from 0 to 100 defines the write to read ratio, 0 is 100% write ++#define CSMI_SAS_RAID_CACHE_RATIO_RANGE 101 ++#define CSMI_SAS_RAID_CACHE_RATIO_FIXED 102 ++#define CSMI_SAS_RAID_CACHE_RATIO_AUTO 103 ++#define CSMI_SAS_RAID_CACHE_RATIO_END 255 ++ ++// RAID Cache Ratio Flag ++// (bCacheRatioFlag) ++#define CSMI_SAS_RAID_CACHE_RATIO_DISABLE 0 ++#define CSMI_SAS_RAID_CACHE_RATIO_ENABLE 1 ++ ++// RAID Clear Configuration Signature ++// (bClearConfiguration) ++#define CSMI_SAS_RAID_CLEAR_CONFIGURATION_SIGNATURE "RAIDCLR" ++ ++// RAID Failure Codes ++// (uFailCode) ++#define CSMI_SAS_FAIL_CODE_OK 0 ++#define CSMI_SAS_FAIL_CODE_PARAMETER_INVALID 1000 ++#define CSMI_SAS_FAIL_CODE_TRANSFORM_PRIORITY_INVALID 1001 ++#define CSMI_SAS_FAIL_CODE_REBUILD_PRIORITY_INVALID 1002 ++#define CSMI_SAS_FAIL_CODE_CACHE_RATIO_INVALID 1003 ++#define CSMI_SAS_FAIL_CODE_SURFACE_SCAN_INVALID 1004 ++#define CSMI_SAS_FAIL_CODE_CLEAR_CONFIGURATION_INVALID 1005 ++#define CSMI_SAS_FAIL_CODE_ELEMENT_INDEX_INVALID 1006 ++#define CSMI_SAS_FAIL_CODE_SUBELEMENT_INDEX_INVALID 1007 ++#define CSMI_SAS_FAIL_CODE_EXTENT_INVALID 1008 ++#define CSMI_SAS_FAIL_CODE_BLOCK_COUNT_INVALID 1009 ++#define CSMI_SAS_FAIL_CODE_DRIVE_INDEX_INVALID 1010 ++#define CSMI_SAS_FAIL_CODE_EXISTING_LUN_INVALID 1011 ++#define CSMI_SAS_FAIL_CODE_RAID_TYPE_INVALID 1012 ++#define CSMI_SAS_FAIL_CODE_STRIPE_SIZE_INVALID 1013 ++#define CSMI_SAS_FAIL_CODE_TRANSFORMATION_INVALID 1014 ++#define CSMI_SAS_FAIL_CODE_CHANGE_COUNT_INVALID 1015 ++#define CSMI_SAS_FAIL_CODE_ENUMERATION_TYPE_INVALID 1016 ++ ++#define CSMI_SAS_FAIL_CODE_EXCEEDED_RAID_SET_COUNT 2000 ++#define CSMI_SAS_FAIL_CODE_DUPLICATE_LUN 2001 ++ ++#define CSMI_SAS_FAIL_CODE_WAIT_FOR_OPERATION 3000 ++ ++// RAID Enumeration Types ++// (uEnumerationType) ++#define CSMI_SAS_RAID_ELEMENT_TYPE_DRIVE 0 ++#define CSMI_SAS_RAID_ELEMENT_TYPE_MODULE 1 ++#define CSMI_SAS_RAID_ELEMENT_TYPE_DRIVE_RAID_SET 2 ++#define CSMI_SAS_RAID_ELEMENT_TYPE_EXTENT_DRIVE 3 ++ ++// RAID Extent Types ++// (bExtentType) ++#define CSMI_SAS_RAID_EXTENT_RESERVED 0 ++#define CSMI_SAS_RAID_EXTENT_METADATA 1 ++#define CSMI_SAS_RAID_EXTENT_ALLOCATED 2 ++#define CSMI_SAS_RAID_EXTENT_UNALLOCATED 3 ++ ++// RAID Operation Types ++// (uOperationType) ++#define CSMI_SAS_RAID_SET_CREATE 0 ++#define CSMI_SAS_RAID_SET_LABEL 1 ++#define CSMI_SAS_RAID_SET_TRANSFORM 2 ++#define CSMI_SAS_RAID_SET_DELETE 3 ++#define CSMI_SAS_RAID_SET_WRITE_PROTECT 4 ++#define CSMI_SAS_RAID_SET_CACHE 5 ++#define CSMI_SAS_RAID_SET_ONLINE_STATE 6 ++#define CSMI_SAS_RAID_SET_SPARE 7 ++ ++// RAID Transform Types ++// (bTransformType) ++#define CSMI_SAS_RAID_SET_TRANSFORM_SPLIT_MIRROR 0 ++#define CSMI_SAS_RAID_SET_TRANSFORM_MERGE_RAID_0 1 ++#define CSMI_SAS_RAID_SET_TRANSFORM_LUN_RENUMBER 2 ++#define CSMI_SAS_RAID_SET_TRANSFORM_RAID_SET 3 ++ ++// RAID Online State ++// (bOnlineState) ++#define CSMI_SAS_RAID_SET_STATE_UNKNOWN 0 ++#define CSMI_SAS_RAID_SET_STATE_ONLINE 1 ++#define CSMI_SAS_RAID_SET_STATE_OFFLINE 2 ++ ++/* * * * * * * * * * SAS HBA Class IOCTL Constants * * * * * * * * * */ ++ ++// Return codes for SAS IOCTL's ++// (IoctlHeader.ReturnCode) ++ ++#define CSMI_SAS_PHY_INFO_CHANGED CSMI_SAS_STATUS_SUCCESS ++#define CSMI_SAS_PHY_INFO_NOT_CHANGEABLE 2000 ++#define CSMI_SAS_LINK_RATE_OUT_OF_RANGE 2001 ++ ++#define CSMI_SAS_PHY_DOES_NOT_EXIST 2002 ++#define CSMI_SAS_PHY_DOES_NOT_MATCH_PORT 2003 ++#define CSMI_SAS_PHY_CANNOT_BE_SELECTED 2004 ++#define CSMI_SAS_SELECT_PHY_OR_PORT 2005 ++#define CSMI_SAS_PORT_DOES_NOT_EXIST 2006 ++#define CSMI_SAS_PORT_CANNOT_BE_SELECTED 2007 ++#define CSMI_SAS_CONNECTION_FAILED 2008 ++ ++#define CSMI_SAS_NO_SATA_DEVICE 2009 ++#define CSMI_SAS_NO_SATA_SIGNATURE 2010 ++#define CSMI_SAS_SCSI_EMULATION 2011 ++#define CSMI_SAS_NOT_AN_END_DEVICE 2012 ++#define CSMI_SAS_NO_SCSI_ADDRESS 2013 ++#define CSMI_SAS_NO_DEVICE_ADDRESS 2014 ++ ++// Signature value ++// (IoctlHeader.Signature) ++ ++#define CSMI_SAS_SIGNATURE "CSMISAS" ++ ++// Timeout value default of 60 seconds ++// (IoctlHeader.Timeout) ++ ++#define CSMI_SAS_TIMEOUT 60 ++ ++// Device types ++// (bDeviceType) ++ ++#define CSMI_SAS_PHY_UNUSED 0x00 ++#define CSMI_SAS_NO_DEVICE_ATTACHED 0x00 ++#define CSMI_SAS_END_DEVICE 0x10 ++#define CSMI_SAS_EDGE_EXPANDER_DEVICE 0x20 ++#define CSMI_SAS_FANOUT_EXPANDER_DEVICE 0x30 ++ ++// Protocol options ++// (bInitiatorPortProtocol, bTargetPortProtocol) ++ ++#define CSMI_SAS_PROTOCOL_SATA 0x01 ++#define CSMI_SAS_PROTOCOL_SMP 0x02 ++#define CSMI_SAS_PROTOCOL_STP 0x04 ++#define CSMI_SAS_PROTOCOL_SSP 0x08 ++ ++// Negotiated and hardware link rates ++// (bNegotiatedLinkRate, bMinimumLinkRate, bMaximumLinkRate) ++ ++#define CSMI_SAS_LINK_RATE_UNKNOWN 0x00 ++#define CSMI_SAS_PHY_DISABLED 0x01 ++#define CSMI_SAS_LINK_RATE_FAILED 0x02 ++#define CSMI_SAS_SATA_SPINUP_HOLD 0x03 ++#define CSMI_SAS_SATA_PORT_SELECTOR 0x04 ++#define CSMI_SAS_LINK_RATE_1_5_GBPS 0x08 ++#define CSMI_SAS_LINK_RATE_3_0_GBPS 0x09 ++#define CSMI_SAS_LINK_VIRTUAL 0x10 ++ ++// Discover state ++// (bAutoDiscover) ++ ++#define CSMI_SAS_DISCOVER_NOT_SUPPORTED 0x00 ++#define CSMI_SAS_DISCOVER_NOT_STARTED 0x01 ++#define CSMI_SAS_DISCOVER_IN_PROGRESS 0x02 ++#define CSMI_SAS_DISCOVER_COMPLETE 0x03 ++#define CSMI_SAS_DISCOVER_ERROR 0x04 ++ ++// Phy features ++ ++#define CSMI_SAS_PHY_VIRTUAL_SMP 0x01 ++ ++// Programmed link rates ++// (bMinimumLinkRate, bMaximumLinkRate) ++// (bProgrammedMinimumLinkRate, bProgrammedMaximumLinkRate) ++ ++#define CSMI_SAS_PROGRAMMED_LINK_RATE_UNCHANGED 0x00 ++#define CSMI_SAS_PROGRAMMED_LINK_RATE_1_5_GBPS 0x08 ++#define CSMI_SAS_PROGRAMMED_LINK_RATE_3_0_GBPS 0x09 ++ ++// Link rate ++// (bNegotiatedLinkRate in CSMI_SAS_SET_PHY_INFO) ++ ++#define CSMI_SAS_LINK_RATE_NEGOTIATE 0x00 ++#define CSMI_SAS_LINK_RATE_PHY_DISABLED 0x01 ++ ++// Signal class ++// (bSignalClass in CSMI_SAS_SET_PHY_INFO) ++ ++#define CSMI_SAS_SIGNAL_CLASS_UNKNOWN 0x00 ++#define CSMI_SAS_SIGNAL_CLASS_DIRECT 0x01 ++#define CSMI_SAS_SIGNAL_CLASS_SERVER 0x02 ++#define CSMI_SAS_SIGNAL_CLASS_ENCLOSURE 0x03 ++ ++// Link error reset ++// (bResetCounts) ++ ++#define CSMI_SAS_LINK_ERROR_DONT_RESET_COUNTS 0x00 ++#define CSMI_SAS_LINK_ERROR_RESET_COUNTS 0x01 ++ ++// Phy identifier ++// (bPhyIdentifier) ++ ++#define CSMI_SAS_USE_PORT_IDENTIFIER 0xFF ++ ++// Port identifier ++// (bPortIdentifier) ++ ++#define CSMI_SAS_IGNORE_PORT 0xFF ++ ++// Programmed link rates ++// (bConnectionRate) ++ ++#define CSMI_SAS_LINK_RATE_NEGOTIATED 0x00 ++#define CSMI_SAS_LINK_RATE_1_5_GBPS 0x08 ++#define CSMI_SAS_LINK_RATE_3_0_GBPS 0x09 ++ ++// Connection status ++// (bConnectionStatus) ++ ++#define CSMI_SAS_OPEN_ACCEPT 0 ++#define CSMI_SAS_OPEN_REJECT_BAD_DESTINATION 1 ++#define CSMI_SAS_OPEN_REJECT_RATE_NOT_SUPPORTED 2 ++#define CSMI_SAS_OPEN_REJECT_NO_DESTINATION 3 ++#define CSMI_SAS_OPEN_REJECT_PATHWAY_BLOCKED 4 ++#define CSMI_SAS_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED 5 ++#define CSMI_SAS_OPEN_REJECT_RESERVE_ABANDON 6 ++#define CSMI_SAS_OPEN_REJECT_RESERVE_CONTINUE 7 ++#define CSMI_SAS_OPEN_REJECT_RESERVE_INITIALIZE 8 ++#define CSMI_SAS_OPEN_REJECT_RESERVE_STOP 9 ++#define CSMI_SAS_OPEN_REJECT_RETRY 10 ++#define CSMI_SAS_OPEN_REJECT_STP_RESOURCES_BUSY 11 ++#define CSMI_SAS_OPEN_REJECT_WRONG_DESTINATION 12 ++ ++// SSP Status ++// (bSSPStatus) ++ ++#define CSMI_SAS_SSP_STATUS_UNKNOWN 0x00 ++#define CSMI_SAS_SSP_STATUS_WAITING 0x01 ++#define CSMI_SAS_SSP_STATUS_COMPLETED 0x02 ++#define CSMI_SAS_SSP_STATUS_FATAL_ERROR 0x03 ++#define CSMI_SAS_SSP_STATUS_RETRY 0x04 ++#define CSMI_SAS_SSP_STATUS_NO_TAG 0x05 ++ ++// SSP Flags ++// (uFlags) ++ ++#define CSMI_SAS_SSP_READ 0x00000001 ++#define CSMI_SAS_SSP_WRITE 0x00000002 ++#define CSMI_SAS_SSP_UNSPECIFIED 0x00000004 ++ ++#define CSMI_SAS_SSP_TASK_ATTRIBUTE_SIMPLE 0x00000000 ++#define CSMI_SAS_SSP_TASK_ATTRIBUTE_HEAD_OF_QUEUE 0x00000010 ++#define CSMI_SAS_SSP_TASK_ATTRIBUTE_ORDERED 0x00000020 ++#define CSMI_SAS_SSP_TASK_ATTRIBUTE_ACA 0x00000040 ++ ++// SSP Data present ++// (bDataPresent) ++ ++#define CSMI_SAS_SSP_NO_DATA_PRESENT 0x00 ++#define CSMI_SAS_SSP_RESPONSE_DATA_PRESENT 0x01 ++#define CSMI_SAS_SSP_SENSE_DATA_PRESENT 0x02 ++ ++// STP Flags ++// (uFlags) ++ ++#define CSMI_SAS_STP_READ 0x00000001 ++#define CSMI_SAS_STP_WRITE 0x00000002 ++#define CSMI_SAS_STP_UNSPECIFIED 0x00000004 ++#define CSMI_SAS_STP_PIO 0x00000010 ++#define CSMI_SAS_STP_DMA 0x00000020 ++#define CSMI_SAS_STP_PACKET 0x00000040 ++#define CSMI_SAS_STP_DMA_QUEUED 0x00000080 ++#define CSMI_SAS_STP_EXECUTE_DIAG 0x00000100 ++#define CSMI_SAS_STP_RESET_DEVICE 0x00000200 ++ ++// Task Management Flags ++// (uFlags) ++ ++#define CSMI_SAS_TASK_IU 0x00000001 ++#define CSMI_SAS_HARD_RESET_SEQUENCE 0x00000002 ++#define CSMI_SAS_SUPPRESS_RESULT 0x00000004 ++ ++// Task Management Functions ++// (bTaskManagement) ++ ++#define CSMI_SAS_SSP_ABORT_TASK 0x01 ++#define CSMI_SAS_SSP_ABORT_TASK_SET 0x02 ++#define CSMI_SAS_SSP_CLEAR_TASK_SET 0x04 ++#define CSMI_SAS_SSP_LOGICAL_UNIT_RESET 0x08 ++#define CSMI_SAS_SSP_CLEAR_ACA 0x40 ++#define CSMI_SAS_SSP_QUERY_TASK 0x80 ++ ++// Task Management Information ++// (uInformation) ++ ++#define CSMI_SAS_SSP_TEST 1 ++#define CSMI_SAS_SSP_EXCEEDED 2 ++#define CSMI_SAS_SSP_DEMAND 3 ++#define CSMI_SAS_SSP_TRIGGER 4 ++ ++// Connector Pinout Information ++// (uPinout) ++ ++#define CSMI_SAS_CON_UNKNOWN 0x00000001 ++#define CSMI_SAS_CON_SFF_8482 0x00000002 ++#define CSMI_SAS_CON_SFF_8470_LANE_1 0x00000100 ++#define CSMI_SAS_CON_SFF_8470_LANE_2 0x00000200 ++#define CSMI_SAS_CON_SFF_8470_LANE_3 0x00000400 ++#define CSMI_SAS_CON_SFF_8470_LANE_4 0x00000800 ++#define CSMI_SAS_CON_SFF_8484_LANE_1 0x00010000 ++#define CSMI_SAS_CON_SFF_8484_LANE_2 0x00020000 ++#define CSMI_SAS_CON_SFF_8484_LANE_3 0x00040000 ++#define CSMI_SAS_CON_SFF_8484_LANE_4 0x00080000 ++ ++// Connector Location Information ++// (bLocation) ++ ++// same as uPinout above... ++// #define CSMI_SAS_CON_UNKNOWN 0x01 ++#define CSMI_SAS_CON_INTERNAL 0x02 ++#define CSMI_SAS_CON_EXTERNAL 0x04 ++#define CSMI_SAS_CON_SWITCHABLE 0x08 ++#define CSMI_SAS_CON_AUTO 0x10 ++#define CSMI_SAS_CON_NOT_PRESENT 0x20 ++#define CSMI_SAS_CON_NOT_CONNECTED 0x80 ++ ++// Device location identification ++// (bIdentify) ++ ++#define CSMI_SAS_LOCATE_UNKNOWN 0x00 ++#define CSMI_SAS_LOCATE_FORCE_OFF 0x01 ++#define CSMI_SAS_LOCATE_FORCE_ON 0x02 ++ ++// Location Valid flags ++// (uLocationFlags) ++ ++#define CSMI_SAS_LOCATE_SAS_ADDRESS_VALID 0x00000001 ++#define CSMI_SAS_LOCATE_SAS_LUN_VALID 0x00000002 ++#define CSMI_SAS_LOCATE_ENCLOSURE_IDENTIFIER_VALID 0x00000004 ++#define CSMI_SAS_LOCATE_ENCLOSURE_NAME_VALID 0x00000008 ++#define CSMI_SAS_LOCATE_BAY_PREFIX_VALID 0x00000010 ++#define CSMI_SAS_LOCATE_BAY_IDENTIFIER_VALID 0x00000020 ++#define CSMI_SAS_LOCATE_LOCATION_STATE_VALID 0x00000040 ++ ++/* * * * * * * * SAS Phy Control Class IOCTL Constants * * * * * * * * */ ++ ++// Return codes for SAS Phy Control IOCTL's ++// (IoctlHeader.ReturnCode) ++ ++// Signature value ++// (IoctlHeader.Signature) ++ ++#define CSMI_PHY_SIGNATURE "CSMIPHY" ++ ++// Phy Control Functions ++// (bFunction) ++ ++// values 0x00 to 0xFF are consistent in definition with the SMP PHY CONTROL ++// function defined in the SAS spec ++#define CSMI_SAS_PC_NOP 0x00000000 ++#define CSMI_SAS_PC_LINK_RESET 0x00000001 ++#define CSMI_SAS_PC_HARD_RESET 0x00000002 ++#define CSMI_SAS_PC_PHY_DISABLE 0x00000003 ++// 0x04 to 0xFF reserved... ++#define CSMI_SAS_PC_GET_PHY_SETTINGS 0x00000100 ++ ++// Link Flags ++#define CSMI_SAS_PHY_ACTIVATE_CONTROL 0x00000001 ++#define CSMI_SAS_PHY_UPDATE_SPINUP_RATE 0x00000002 ++#define CSMI_SAS_PHY_AUTO_COMWAKE 0x00000004 ++ ++// Device Types for Phy Settings ++// (bType) ++#define CSMI_SAS_UNDEFINED 0x00 ++#define CSMI_SAS_SATA 0x01 ++#define CSMI_SAS_SAS 0x02 ++ ++// Transmitter Flags ++// (uTransmitterFlags) ++#define CSMI_SAS_PHY_PREEMPHASIS_DISABLED 0x00000001 ++ ++// Receiver Flags ++// (uReceiverFlags) ++#define CSMI_SAS_PHY_EQUALIZATION_DISABLED 0x00000001 ++ ++// Pattern Flags ++// (uPatternFlags) ++// #define CSMI_SAS_PHY_ACTIVATE_CONTROL 0x00000001 ++#define CSMI_SAS_PHY_DISABLE_SCRAMBLING 0x00000002 ++#define CSMI_SAS_PHY_DISABLE_ALIGN 0x00000004 ++#define CSMI_SAS_PHY_DISABLE_SSC 0x00000008 ++ ++#define CSMI_SAS_PHY_FIXED_PATTERN 0x00000010 ++#define CSMI_SAS_PHY_USER_PATTERN 0x00000020 ++ ++// Fixed Patterns ++// (bFixedPattern) ++#define CSMI_SAS_PHY_CJPAT 0x00000001 ++#define CSMI_SAS_PHY_ALIGN 0x00000002 ++ ++// Type Flags ++// (bTypeFlags) ++#define CSMI_SAS_PHY_POSITIVE_DISPARITY 0x01 ++#define CSMI_SAS_PHY_NEGATIVE_DISPARITY 0x02 ++#define CSMI_SAS_PHY_CONTROL_CHARACTER 0x04 ++ ++// Miscellaneous ++#define SLOT_NUMBER_UNKNOWN 0xFFFF ++ ++/*************************************************************************/ ++/* DATA STRUCTURES */ ++/*************************************************************************/ ++ ++/* * * * * * * * * * Class Independent Structures * * * * * * * * * */ ++ ++// EDM #pragma CSMI_SAS_BEGIN_PACK(8) ++#pragma pack(8) ++ ++// CC_CSMI_SAS_DRIVER_INFO ++ ++typedef struct _CSMI_SAS_DRIVER_INFO { ++ __u8 szName[81]; ++ __u8 szDescription[81]; ++ __u16 usMajorRevision; ++ __u16 usMinorRevision; ++ __u16 usBuildRevision; ++ __u16 usReleaseRevision; ++ __u16 usCSMIMajorRevision; ++ __u16 usCSMIMinorRevision; ++} CSMI_SAS_DRIVER_INFO, ++ *PCSMI_SAS_DRIVER_INFO; ++ ++typedef struct _CSMI_SAS_DRIVER_INFO_BUFFER { ++ IOCTL_HEADER IoctlHeader; ++ CSMI_SAS_DRIVER_INFO Information; ++} CSMI_SAS_DRIVER_INFO_BUFFER, ++ *PCSMI_SAS_DRIVER_INFO_BUFFER; ++ ++// CC_CSMI_SAS_CNTLR_CONFIGURATION ++ ++typedef struct _CSMI_SAS_PCI_BUS_ADDRESS { ++ __u8 bBusNumber; ++ __u8 bDeviceNumber; ++ __u8 bFunctionNumber; ++ __u8 bReserved; ++} CSMI_SAS_PCI_BUS_ADDRESS, ++ *PCSMI_SAS_PCI_BUS_ADDRESS; ++ ++typedef union _CSMI_SAS_IO_BUS_ADDRESS { ++ CSMI_SAS_PCI_BUS_ADDRESS PciAddress; ++ __u8 bReserved[32]; ++} CSMI_SAS_IO_BUS_ADDRESS, ++ *PCSMI_SAS_IO_BUS_ADDRESS; ++ ++typedef struct _CSMI_SAS_CNTLR_CONFIG { ++ __u32 uBaseIoAddress; ++ struct { ++ __u32 uLowPart; ++ __u32 uHighPart; ++ } BaseMemoryAddress; ++ __u32 uBoardID; ++ __u16 usSlotNumber; ++ __u8 bControllerClass; ++ __u8 bIoBusType; ++ CSMI_SAS_IO_BUS_ADDRESS BusAddress; ++ __u8 szSerialNumber[81]; ++ __u16 usMajorRevision; ++ __u16 usMinorRevision; ++ __u16 usBuildRevision; ++ __u16 usReleaseRevision; ++ __u16 usBIOSMajorRevision; ++ __u16 usBIOSMinorRevision; ++ __u16 usBIOSBuildRevision; ++ __u16 usBIOSReleaseRevision; ++ __u32 uControllerFlags; ++ __u16 usRromMajorRevision; ++ __u16 usRromMinorRevision; ++ __u16 usRromBuildRevision; ++ __u16 usRromReleaseRevision; ++ __u16 usRromBIOSMajorRevision; ++ __u16 usRromBIOSMinorRevision; ++ __u16 usRromBIOSBuildRevision; ++ __u16 usRromBIOSReleaseRevision; ++ __u8 bReserved[7]; ++} CSMI_SAS_CNTLR_CONFIG, ++ *PCSMI_SAS_CNTLR_CONFIG; ++ ++typedef struct _CSMI_SAS_CNTLR_CONFIG_BUFFER { ++ IOCTL_HEADER IoctlHeader; ++ CSMI_SAS_CNTLR_CONFIG Configuration; ++} CSMI_SAS_CNTLR_CONFIG_BUFFER, ++ *PCSMI_SAS_CNTLR_CONFIG_BUFFER; ++ ++// CC_CSMI_SAS_CNTLR_STATUS ++ ++typedef struct _CSMI_SAS_CNTLR_STATUS { ++ __u32 uStatus; ++ __u32 uOfflineReason; ++ __u8 bReserved[28]; ++} CSMI_SAS_CNTLR_STATUS, ++ *PCSMI_SAS_CNTLR_STATUS; ++ ++typedef struct _CSMI_SAS_CNTLR_STATUS_BUFFER { ++ IOCTL_HEADER IoctlHeader; ++ CSMI_SAS_CNTLR_STATUS Status; ++} CSMI_SAS_CNTLR_STATUS_BUFFER, ++ *PCSMI_SAS_CNTLR_STATUS_BUFFER; ++ ++// CC_CSMI_SAS_FIRMWARE_DOWNLOAD ++ ++typedef struct _CSMI_SAS_FIRMWARE_DOWNLOAD { ++ __u32 uBufferLength; ++ __u32 uDownloadFlags; ++ __u8 bReserved[32]; ++ __u16 usStatus; ++ __u16 usSeverity; ++} CSMI_SAS_FIRMWARE_DOWNLOAD, ++ *PCSMI_SAS_FIRMWARE_DOWNLOAD; ++ ++typedef struct _CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER { ++ IOCTL_HEADER IoctlHeader; ++ CSMI_SAS_FIRMWARE_DOWNLOAD Information; ++ __u8 bDataBuffer[1]; ++} CSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER, ++ *PCSMI_SAS_FIRMWARE_DOWNLOAD_BUFFER; ++ ++// CC_CSMI_SAS_RAID_INFO ++ ++typedef struct _CSMI_SAS_RAID_INFO { ++ __u32 uNumRaidSets; ++ __u32 uMaxDrivesPerSet; ++ __u32 uMaxRaidSets; ++ __u8 bMaxRaidTypes; ++ __u8 bReservedByteFields[7]; ++ __u64 ulMinRaidSetBlocks; ++ __u64 ulMaxRaidSetBlocks; ++ __u32 uMaxPhysicalDrives; ++ __u32 uMaxExtents; ++ __u32 uMaxModules; ++ __u32 uMaxTransformationMemory; ++ __u32 uChangeCount; ++ __u8 bReserved[44]; ++} CSMI_SAS_RAID_INFO, ++ *PCSMI_SAS_RAID_INFO; ++ ++typedef struct _CSMI_SAS_RAID_INFO_BUFFER { ++ IOCTL_HEADER IoctlHeader; ++ CSMI_SAS_RAID_INFO Information; ++} CSMI_SAS_RAID_INFO_BUFFER, ++ *PCSMI_SAS_RAID_INFO_BUFFER; ++ ++// CC_CSMI_SAS_GET_RAID_CONFIG ++ ++typedef struct _CSMI_SAS_RAID_DRIVES { ++ __u8 bModel[40]; ++ __u8 bFirmware[8]; ++ __u8 bSerialNumber[40]; ++ __u8 bSASAddress[8]; ++ __u8 bSASLun[8]; ++ __u8 bDriveStatus; ++ __u8 bDriveUsage; ++ __u8 bDriveType; ++ __u16 usBlockSize; ++ __u8 bReserved[15]; ++ __u32 uDriveIndex; ++ __u64 ulTotalUserBlocks; ++} CSMI_SAS_RAID_DRIVES, ++ *PCSMI_SAS_RAID_DRIVES; ++ ++typedef struct _CSMI_SAS_RAID_DEVICE_ID { ++ __u8 bDeviceIdentificationVPDPage[1]; ++} CSMI_SAS_RAID_DEVICE_ID, ++ *PCSMI_SAS_RAID_DEVICE_ID; ++ ++typedef struct _CSMI_SAS_RAID_SET_ADDITIONAL_DATA { ++ __u8 bLabel[16]; ++ __u8 bRaidSetLun[8]; ++ __u8 bWriteProtection; ++ __u8 bCacheSetting; ++ __u8 bCacheRatio; ++ __u16 usBlockSize; ++ __u8 bReservedBytes[11]; ++ __u64 ulRaidSetExtentOffset; ++ __u64 ulRaidSetBlocks; ++ __u32 uStripeSizeInBlocks; ++ __u32 uSectorsPerTrack; ++ __u8 bApplicationScratchPad[16]; ++ __u32 uNumberOfHeads; ++ __u32 uNumberOfTracks; ++ __u8 bReserved[24]; ++} CSMI_SAS_RAID_SET_ADDITIONAL_DATA, ++ *PCSMI_SAS_RAID_SET_ADDITIONAL_DATA; ++ ++typedef struct _CSMI_SAS_RAID_CONFIG { ++ __u32 uRaidSetIndex; ++ __u32 uCapacity; ++ __u32 uStripeSize; ++ __u8 bRaidType; ++ __u8 bStatus; ++ __u8 bInformation; ++ __u8 bDriveCount; ++ __u8 bDataType; ++ __u8 bReserved[15]; ++ __u32 uChangeCount; ++ union { ++ CSMI_SAS_RAID_DRIVES Drives[1]; ++ CSMI_SAS_RAID_DEVICE_ID DeviceId[1]; ++ CSMI_SAS_RAID_SET_ADDITIONAL_DATA Data[1]; ++ }; ++} CSMI_SAS_RAID_CONFIG, ++ *PCSMI_SAS_RAID_CONFIG; ++ ++typedef struct _CSMI_SAS_RAID_CONFIG_BUFFER { ++ IOCTL_HEADER IoctlHeader; ++ CSMI_SAS_RAID_CONFIG Configuration; ++} CSMI_SAS_RAID_CONFIG_BUFFER, ++ *PCSMI_SAS_RAID_CONFIG_BUFFER; ++ ++// CC_CSMI_SAS_GET_RAID_FEATURES ++ ++typedef struct _CSMI_SAS_RAID_TYPE_DESCRIPTION { ++ __u8 bRaidType; ++ __u8 bReservedBytes[7]; ++ __u32 uSupportedStripeSizeMap; ++ __u8 bReserved[24]; ++} CSMI_SAS_RAID_TYPE_DESCRIPTION, ++ *PCSMI_SAS_RAID_TYPE_DESCRIPTION; ++ ++typedef struct _CSMI_SAS_RAID_FEATURES { ++ __u32 uFeatures; ++ __u8 bReservedFeatures[32]; ++ __u8 bDefaultTransformPriority; ++ __u8 bTransformPriority; ++ __u8 bDefaultRebuildPriority; ++ __u8 bRebuildPriority; ++ __u8 bDefaultSurfaceScanPriority; ++ __u8 bSurfaceScanPriority; ++ __u16 usReserved; ++ __u32 uRaidSetTransformationRules; ++ __u32 uReserved[11]; ++ CSMI_SAS_RAID_TYPE_DESCRIPTION RaidType[24]; ++ __u8 bCacheRatiosSupported[104]; ++ __u32 uChangeCount; ++ __u8 bReserved[124]; ++} CSMI_SAS_RAID_FEATURES, ++ *PCSMI_SAS_RAID_FEATURES; ++ ++typedef struct _CSMI_SAS_RAID_FEATURES_BUFFER { ++ IOCTL_HEADER IoctlHeader; ++ CSMI_SAS_RAID_FEATURES Information; ++} CSMI_SAS_RAID_FEATURES_BUFFER, ++ *PCSMI_SAS_RAID_FEATURES_BUFFER; ++ ++// CC_CSMI_SAS_SET_RAID_CONTROL ++ ++typedef struct _CSMI_SAS_RAID_CONTROL { ++ __u8 bTransformPriority; ++ __u8 bRebuildPriority; ++ __u8 bCacheRatioFlag; ++ __u8 bCacheRatio; ++ __u8 bSurfaceScanPriority; ++ __u8 bReservedBytes[15]; ++ __u8 bClearConfiguration[8]; ++ __u32 uChangeCount; ++ __u8 bReserved[88]; ++ __u32 uFailureCode; ++ __u8 bFailureDescription[80]; ++} CSMI_SAS_RAID_CONTROL, ++ *PCSMI_SAS_RAID_CONTROL; ++ ++typedef struct _CSMI_SAS_RAID_CONTROL_BUFFER { ++ IOCTL_HEADER IoctlHeader; ++ CSMI_SAS_RAID_CONTROL Information; ++} CSMI_SAS_RAID_CONTROL_BUFFER, ++ *PCSMI_SAS_RAID_CONTROL_BUFFER; ++ ++// CC_CSMI_SAS_GET_RAID_ELEMENT ++ ++typedef struct _CSMI_SAS_DRIVE_EXTENT_INFO { ++ __u32 uDriveIndex; ++ __u8 bExtentType; ++ __u8 bReservedBytes[7]; ++ __u64 ulExtentOffset; ++ __u64 ulExtentBlocks; ++ __u32 uRaidSetIndex; ++ __u8 bReserved[96]; ++} CSMI_SAS_DRIVE_EXTENT_INFO, ++ *PCSMI_SAS_DRIVE_EXTENT_INFO; ++ ++typedef struct _CSMI_SAS_RAID_MODULE_INFO { ++ __u8 bReserved[128]; ++} CSMI_SAS_RAID_MODULE_INFO, ++ *PCSMI_SAS_RAID_MODULE_INFO; ++ ++typedef struct _CSMI_SAS_DRIVE_LOCATION { ++ __u8 bConnector[16]; ++ __u8 bBoxName[16]; ++ __u32 uBay; ++ __u8 bReservedBytes[4]; ++ __u8 bAttachedSASAddress[8]; ++ __u8 bAttachedPhyIdentifier; ++ __u8 bReserved[79]; ++} CSMI_SAS_DRIVE_LOCATION, ++ *PCSMI_SAS_DRIVE_LOCATION; ++ ++typedef struct _CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA { ++ __u8 bNegotiatedLinkRate[2]; ++ __u8 bReserved[126]; ++} CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA, ++ *PCSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA; ++ ++typedef struct _CSMI_SAS_DRIVE_INFO { ++ CSMI_SAS_RAID_DRIVES Device; ++ CSMI_SAS_RAID_DRIVES_ADDITIONAL_DATA Data; ++ CSMI_SAS_DRIVE_LOCATION Location; ++ __u8 bReserved[16]; ++} CSMI_SAS_DRIVE_INFO, ++ *PCSMI_SAS_DRIVE_INFO; ++ ++typedef struct _CSMI_SAS_RAID_ELEMENT { ++ __u32 uEnumerationType; ++ __u32 uElementIndex; ++ __u32 uNumElements; ++ __u32 uChangeCount; ++ __u32 uSubElementIndex; ++ __u8 bReserved[32]; ++ __u32 uFailureCode; ++ __u8 bFailureDescription[80]; ++ union { ++ CSMI_SAS_DRIVE_INFO Drive; ++ CSMI_SAS_RAID_MODULE_INFO Module; ++ CSMI_SAS_DRIVE_EXTENT_INFO Extent; ++ } Element; ++} CSMI_SAS_RAID_ELEMENT, ++ *PCSMI_SAS_RAID_ELEMENT; ++ ++typedef struct _CSMI_SAS_RAID_ELEMENT_BUFFER { ++ IOCTL_HEADER IoctlHeader; ++ CSMI_SAS_RAID_ELEMENT Information; ++} CSMI_SAS_RAID_ELEMENT_BUFFER, ++ *PCSMI_SAS_RAID_ELEMENT_BUFFER; ++ ++// CC_CSMI_SAS_SET_RAID_OPERATION ++ ++typedef struct _CSMI_SAS_RAID_SET_LIST { ++ __u32 uRaidSetIndex; ++ __u8 bExistingLun[8]; ++ __u8 bNewLun[8]; ++ __u8 bReserved[12]; ++} CSMI_SAS_RAID_SET_LIST, ++ *PCSMI_SAS_RAID_SET_LIST; ++ ++typedef struct _CSMI_SAS_RAID_SET_DRIVE_LIST { ++ __u32 uDriveIndex; ++ __u8 bDriveUsage; ++ __u8 bReserved[27]; ++} CSMI_SAS_RAID_SET_DRIVE_LIST, ++ *PCSMI_SAS_RAID_SET_DRIVE_LIST; ++ ++typedef struct _CSMI_SAS_RAID_SET_SPARE_INFO { ++ __u32 uRaidSetIndex; ++ __u32 uDriveCount; ++ __u8 bApplicationScratchPad[16]; ++ __u8 bReserved[104]; ++} CSMI_SAS_RAID_SET_SPARE_INFO, ++ *PCSMI_SAS_RAID_SET_SPARE_INFO; ++ ++typedef struct _CSMI_SAS_RAID_SET_ONLINE_STATE_INFO { ++ __u32 uRaidSetIndex; ++ __u8 bOnlineState; ++ __u8 bReserved[123]; ++} CSMI_SAS_RAID_SET_ONLINE_STATE_INFO, ++ *PCSMI_SAS_RAID_SET_ONLINE_STATE_INFO; ++ ++typedef struct _CSMI_SAS_RAID_SET_CACHE_INFO { ++ __u32 uRaidSetIndex; ++ __u8 bCacheSetting; ++ __u8 bCacheRatioFlag; ++ __u8 bCacheRatio; ++ __u8 bReserved[121]; ++} CSMI_SAS_RAID_SET_CACHE_INFO, ++ *PCSMI_SAS_RAID_SET_CACHE_INFO; ++ ++typedef struct _CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO { ++ __u32 uRaidSetIndex; ++ __u8 bWriteProtectSetting; ++ __u8 bReserved[123]; ++} CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO, ++ *PCSMI_SAS_RAID_SET_WRITE_PROTECT_INFO; ++ ++typedef struct _CSMI_SAS_RAID_SET_DELETE_INFO { ++ __u32 uRaidSetIndex; ++ __u8 bReserved[124]; ++} CSMI_SAS_RAID_SET_DELETE_INFO, ++ *PCSMI_SAS_RAID_SET_DELETE_INFO; ++ ++typedef struct _CSMI_SAS_RAID_SET_MODIFY_INFO { ++ __u8 bRaidType; ++ __u8 bReservedBytes[7]; ++ __u32 uStripeSize; ++ __u64 ulRaidSetBlocks; ++ __u64 ulRaidSetExtentOffset; ++ __u32 uDriveCount; ++ __u8 bReserved[96]; ++} CSMI_SAS_RAID_SET_MODIFY_INFO, ++ *PCSMI_SAS_RAID_SET_MODIFY_INFO; ++ ++typedef struct _CSMI_SAS_RAID_SET_TRANSFORM_INFO { ++ __u8 bTransformType; ++ __u8 bReservedBytes[3]; ++ __u32 uRaidSetIndex; ++ __u8 bRaidType; ++ __u8 bReservedBytes2[11]; ++ __u32 uAdditionalRaidSetIndex; ++ __u32 uRaidSetCount; ++ __u8 bApplicationScratchPad[16]; ++ CSMI_SAS_RAID_SET_MODIFY_INFO Modify; ++ __u8 bReserved[80]; ++} CSMI_SAS_RAID_SET_TRANSFORM_INFO, ++ *PCSMI_SAS_RAID_SET_TRANSFORM_INFO; ++ ++typedef struct _CSMI_SAS_RAID_SET_LABEL_INFO { ++ __u32 uRaidSetIndex; ++ __u8 bLabel[16]; ++ __u8 bReserved[108]; ++} CSMI_SAS_RAID_SET_LABEL_INFO, ++ *PCSMI_SAS_RAID_SET_LABEL_INFO; ++ ++typedef struct _CSMI_SAS_RAID_SET_CREATE_INFO { ++ __u8 bRaidType; ++ __u8 bReservedBytes[7]; ++ __u32 uStripeSize; ++ __u32 uTrackSectorCount; ++ __u64 ulRaidSetBlocks; ++ __u64 ulRaidSetExtentOffset; ++ __u32 uDriveCount; ++ __u8 bLabel[16]; ++ __u32 uRaidSetIndex; ++ __u8 bApplicationScratchPad[16]; ++ __u32 uNumberOfHeads; ++ __u32 uNumberOfTracks; ++ __u8 bReserved[48]; ++} CSMI_SAS_RAID_SET_CREATE_INFO, ++ *PCSMI_SAS_RAID_SET_CREATE_INFO; ++ ++typedef struct _CSMI_SAS_RAID_SET_OPERATION { ++ __u32 uOperationType; ++ __u32 uChangeCount; ++ __u32 uFailureCode; ++ __u8 bFailureDescription[80]; ++ __u8 bReserved[28]; ++ union { ++ CSMI_SAS_RAID_SET_CREATE_INFO Create; ++ CSMI_SAS_RAID_SET_LABEL_INFO Label; ++ CSMI_SAS_RAID_SET_TRANSFORM_INFO Transform; ++ CSMI_SAS_RAID_SET_DELETE_INFO Delete; ++ CSMI_SAS_RAID_SET_WRITE_PROTECT_INFO Protect; ++ CSMI_SAS_RAID_SET_CACHE_INFO Cache; ++ CSMI_SAS_RAID_SET_ONLINE_STATE_INFO State; ++ CSMI_SAS_RAID_SET_SPARE_INFO Spare; ++ } Operation; ++ union { ++ CSMI_SAS_RAID_SET_DRIVE_LIST DriveList[1]; ++ CSMI_SAS_RAID_SET_LIST RaidSetList[1]; ++ } Parameters; ++} CSMI_SAS_RAID_SET_OPERATION, ++ *PCSMI_SAS_RAID_SET_OPERATION; ++ ++typedef struct _CSMI_SAS_RAID_SET_OPERATION_BUFFER { ++ IOCTL_HEADER IoctlHeader; ++ CSMI_SAS_RAID_SET_OPERATION Information; ++} CSMI_SAS_RAID_SET_OPERATION_BUFFER, ++ *PCSMI_SAS_RAID_SET_OPERATION_BUFFER; ++ ++/* * * * * * * * * * SAS HBA Class Structures * * * * * * * * * */ ++ ++// CC_CSMI_SAS_GET_PHY_INFO ++ ++typedef struct _CSMI_SAS_IDENTIFY { ++ __u8 bDeviceType; ++ __u8 bRestricted; ++ __u8 bInitiatorPortProtocol; ++ __u8 bTargetPortProtocol; ++ __u8 bRestricted2[8]; ++ __u8 bSASAddress[8]; ++ __u8 bPhyIdentifier; ++ __u8 bSignalClass; ++ __u8 bReserved[6]; ++} CSMI_SAS_IDENTIFY, ++ *PCSMI_SAS_IDENTIFY; ++ ++typedef struct _CSMI_SAS_PHY_ENTITY { ++ CSMI_SAS_IDENTIFY Identify; ++ __u8 bPortIdentifier; ++ __u8 bNegotiatedLinkRate; ++ __u8 bMinimumLinkRate; ++ __u8 bMaximumLinkRate; ++ __u8 bPhyChangeCount; ++ __u8 bAutoDiscover; ++ __u8 bPhyFeatures; ++ __u8 bReserved; ++ CSMI_SAS_IDENTIFY Attached; ++} CSMI_SAS_PHY_ENTITY, ++ *PCSMI_SAS_PHY_ENTITY; ++ ++typedef struct _CSMI_SAS_PHY_INFO { ++ __u8 bNumberOfPhys; ++ __u8 bReserved[3]; ++ CSMI_SAS_PHY_ENTITY Phy[32]; ++} CSMI_SAS_PHY_INFO, ++ *PCSMI_SAS_PHY_INFO; ++ ++typedef struct _CSMI_SAS_PHY_INFO_BUFFER { ++ IOCTL_HEADER IoctlHeader; ++ CSMI_SAS_PHY_INFO Information; ++} CSMI_SAS_PHY_INFO_BUFFER, ++ *PCSMI_SAS_PHY_INFO_BUFFER; ++ ++// CC_CSMI_SAS_SET_PHY_INFO ++ ++typedef struct _CSMI_SAS_SET_PHY_INFO { ++ __u8 bPhyIdentifier; ++ __u8 bNegotiatedLinkRate; ++ __u8 bProgrammedMinimumLinkRate; ++ __u8 bProgrammedMaximumLinkRate; ++ __u8 bSignalClass; ++ __u8 bReserved[3]; ++} CSMI_SAS_SET_PHY_INFO, ++ *PCSMI_SAS_SET_PHY_INFO; ++ ++typedef struct _CSMI_SAS_SET_PHY_INFO_BUFFER { ++ IOCTL_HEADER IoctlHeader; ++ CSMI_SAS_SET_PHY_INFO Information; ++} CSMI_SAS_SET_PHY_INFO_BUFFER, ++ *PCSMI_SAS_SET_PHY_INFO_BUFFER; ++ ++// CC_CSMI_SAS_GET_LINK_ERRORS ++ ++typedef struct _CSMI_SAS_LINK_ERRORS { ++ __u8 bPhyIdentifier; ++ __u8 bResetCounts; ++ __u8 bReserved[2]; ++ __u32 uInvalidDwordCount; ++ __u32 uRunningDisparityErrorCount; ++ __u32 uLossOfDwordSyncCount; ++ __u32 uPhyResetProblemCount; ++} CSMI_SAS_LINK_ERRORS, ++ *PCSMI_SAS_LINK_ERRORS; ++ ++typedef struct _CSMI_SAS_LINK_ERRORS_BUFFER { ++ IOCTL_HEADER IoctlHeader; ++ CSMI_SAS_LINK_ERRORS Information; ++} CSMI_SAS_LINK_ERRORS_BUFFER, ++ *PCSMI_SAS_LINK_ERRORS_BUFFER; ++ ++// CC_CSMI_SAS_SMP_PASSTHRU ++ ++typedef struct _CSMI_SAS_SMP_REQUEST { ++ __u8 bFrameType; ++ __u8 bFunction; ++ __u8 bReserved[2]; ++ __u8 bAdditionalRequestBytes[1016]; ++} CSMI_SAS_SMP_REQUEST, ++ *PCSMI_SAS_SMP_REQUEST; ++ ++typedef struct _CSMI_SAS_SMP_RESPONSE { ++ __u8 bFrameType; ++ __u8 bFunction; ++ __u8 bFunctionResult; ++ __u8 bReserved; ++ __u8 bAdditionalResponseBytes[1016]; ++} CSMI_SAS_SMP_RESPONSE, ++ *PCSMI_SAS_SMP_RESPONSE; ++ ++typedef struct _CSMI_SAS_SMP_PASSTHRU { ++ __u8 bPhyIdentifier; ++ __u8 bPortIdentifier; ++ __u8 bConnectionRate; ++ __u8 bReserved; ++ __u8 bDestinationSASAddress[8]; ++ __u32 uRequestLength; ++ CSMI_SAS_SMP_REQUEST Request; ++ __u8 bConnectionStatus; ++ __u8 bReserved2[3]; ++ __u32 uResponseBytes; ++ CSMI_SAS_SMP_RESPONSE Response; ++} CSMI_SAS_SMP_PASSTHRU, ++ *PCSMI_SAS_SMP_PASSTHRU; ++ ++typedef struct _CSMI_SAS_SMP_PASSTHRU_BUFFER { ++ IOCTL_HEADER IoctlHeader; ++ CSMI_SAS_SMP_PASSTHRU Parameters; ++} CSMI_SAS_SMP_PASSTHRU_BUFFER, ++ *PCSMI_SAS_SMP_PASSTHRU_BUFFER; ++ ++// CC_CSMI_SAS_SSP_PASSTHRU ++ ++typedef struct _CSMI_SAS_SSP_PASSTHRU { ++ __u8 bPhyIdentifier; ++ __u8 bPortIdentifier; ++ __u8 bConnectionRate; ++ __u8 bReserved; ++ __u8 bDestinationSASAddress[8]; ++ __u8 bLun[8]; ++ __u8 bCDBLength; ++ __u8 bAdditionalCDBLength; ++ __u8 bReserved2[2]; ++ __u8 bCDB[16]; ++ __u32 uFlags; ++ __u8 bAdditionalCDB[24]; ++ __u32 uDataLength; ++} CSMI_SAS_SSP_PASSTHRU, ++ *PCSMI_SAS_SSP_PASSTHRU; ++ ++typedef struct _CSMI_SAS_SSP_PASSTHRU_STATUS { ++ __u8 bConnectionStatus; ++ __u8 bSSPStatus; ++ __u8 bReserved[2]; ++ __u8 bDataPresent; ++ __u8 bStatus; ++ __u8 bResponseLength[2]; ++ __u8 bResponse[256]; ++ __u32 uDataBytes; ++} CSMI_SAS_SSP_PASSTHRU_STATUS, ++ *PCSMI_SAS_SSP_PASSTHRU_STATUS; ++ ++typedef struct _CSMI_SAS_SSP_PASSTHRU_BUFFER { ++ IOCTL_HEADER IoctlHeader; ++ CSMI_SAS_SSP_PASSTHRU Parameters; ++ CSMI_SAS_SSP_PASSTHRU_STATUS Status; ++ __u8 bDataBuffer[1]; ++} CSMI_SAS_SSP_PASSTHRU_BUFFER, ++ *PCSMI_SAS_SSP_PASSTHRU_BUFFER; ++ ++// CC_CSMI_SAS_STP_PASSTHRU ++ ++typedef struct _CSMI_SAS_STP_PASSTHRU { ++ __u8 bPhyIdentifier; ++ __u8 bPortIdentifier; ++ __u8 bConnectionRate; ++ __u8 bReserved; ++ __u8 bDestinationSASAddress[8]; ++ __u8 bReserved2[4]; ++ __u8 bCommandFIS[20]; ++ __u32 uFlags; ++ __u32 uDataLength; ++} CSMI_SAS_STP_PASSTHRU, ++ *PCSMI_SAS_STP_PASSTHRU; ++ ++typedef struct _CSMI_SAS_STP_PASSTHRU_STATUS { ++ __u8 bConnectionStatus; ++ __u8 bReserved[3]; ++ __u8 bStatusFIS[20]; ++ __u32 uSCR[16]; ++ __u32 uDataBytes; ++} CSMI_SAS_STP_PASSTHRU_STATUS, ++ *PCSMI_SAS_STP_PASSTHRU_STATUS; ++ ++typedef struct _CSMI_SAS_STP_PASSTHRU_BUFFER { ++ IOCTL_HEADER IoctlHeader; ++ CSMI_SAS_STP_PASSTHRU Parameters; ++ CSMI_SAS_STP_PASSTHRU_STATUS Status; ++ __u8 bDataBuffer[1]; ++} CSMI_SAS_STP_PASSTHRU_BUFFER, ++ *PCSMI_SAS_STP_PASSTHRU_BUFFER; ++ ++// CC_CSMI_SAS_GET_SATA_SIGNATURE ++ ++typedef struct _CSMI_SAS_SATA_SIGNATURE { ++ __u8 bPhyIdentifier; ++ __u8 bReserved[3]; ++ __u8 bSignatureFIS[20]; ++} CSMI_SAS_SATA_SIGNATURE, ++ *PCSMI_SAS_SATA_SIGNATURE; ++ ++typedef struct _CSMI_SAS_SATA_SIGNATURE_BUFFER { ++ IOCTL_HEADER IoctlHeader; ++ CSMI_SAS_SATA_SIGNATURE Signature; ++} CSMI_SAS_SATA_SIGNATURE_BUFFER, ++ *PCSMI_SAS_SATA_SIGNATURE_BUFFER; ++ ++// CC_CSMI_SAS_GET_SCSI_ADDRESS ++ ++typedef struct _CSMI_SAS_GET_SCSI_ADDRESS_BUFFER { ++ IOCTL_HEADER IoctlHeader; ++ __u8 bSASAddress[8]; ++ __u8 bSASLun[8]; ++ __u8 bHostIndex; ++ __u8 bPathId; ++ __u8 bTargetId; ++ __u8 bLun; ++} CSMI_SAS_GET_SCSI_ADDRESS_BUFFER, ++ *PCSMI_SAS_GET_SCSI_ADDRESS_BUFFER; ++ ++// CC_CSMI_SAS_GET_DEVICE_ADDRESS ++ ++typedef struct _CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER { ++ IOCTL_HEADER IoctlHeader; ++ __u8 bHostIndex; ++ __u8 bPathId; ++ __u8 bTargetId; ++ __u8 bLun; ++ __u8 bSASAddress[8]; ++ __u8 bSASLun[8]; ++} CSMI_SAS_GET_DEVICE_ADDRESS_BUFFER, ++ *PCSMI_SAS_GET_DEVICE_ADDRESS_BUFFER; ++ ++// CC_CSMI_SAS_TASK_MANAGEMENT ++ ++typedef struct _CSMI_SAS_SSP_TASK_IU { ++ __u8 bHostIndex; ++ __u8 bPathId; ++ __u8 bTargetId; ++ __u8 bLun; ++ __u32 uFlags; ++ __u32 uQueueTag; ++ __u32 uReserved; ++ __u8 bTaskManagementFunction; ++ __u8 bReserved[7]; ++ __u32 uInformation; ++} CSMI_SAS_SSP_TASK_IU, ++ *PCSMI_SAS_SSP_TASK_IU; ++ ++typedef struct _CSMI_SAS_SSP_TASK_IU_BUFFER { ++ IOCTL_HEADER IoctlHeader; ++ CSMI_SAS_SSP_TASK_IU Parameters; ++ CSMI_SAS_SSP_PASSTHRU_STATUS Status; ++} CSMI_SAS_SSP_TASK_IU_BUFFER, ++ *PCSMI_SAS_SSP_TASK_IU_BUFFER; ++ ++// CC_CSMI_SAS_GET_CONNECTOR_INFO ++ ++typedef struct _CSMI_SAS_GET_CONNECTOR_INFO { ++ __u32 uPinout; ++ __u8 bConnector[16]; ++ __u8 bLocation; ++ __u8 bReserved[15]; ++} CSMI_SAS_CONNECTOR_INFO, ++ *PCSMI_SAS_CONNECTOR_INFO; ++ ++typedef struct _CSMI_SAS_CONNECTOR_INFO_BUFFER { ++ IOCTL_HEADER IoctlHeader; ++ CSMI_SAS_CONNECTOR_INFO Reference[32]; ++} CSMI_SAS_CONNECTOR_INFO_BUFFER, ++ *PCSMI_SAS_CONNECTOR_INFO_BUFFER; ++ ++// CC_CSMI_SAS_GET_LOCATION ++ ++typedef struct _CSMI_SAS_LOCATION_IDENTIFIER { ++ __u32 bLocationFlags; ++ __u8 bSASAddress[8]; ++ __u8 bSASLun[8]; ++ __u8 bEnclosureIdentifier[8]; ++ __u8 bEnclosureName[32]; ++ __u8 bBayPrefix[32]; ++ __u8 bBayIdentifier; ++ __u8 bLocationState; ++ __u8 bReserved[2]; ++} CSMI_SAS_LOCATION_IDENTIFIER, ++ *PCSMI_SAS_LOCATION_IDENTIFIER; ++ ++typedef struct _CSMI_SAS_GET_LOCATION_BUFFER { ++ IOCTL_HEADER IoctlHeader; ++ __u8 bHostIndex; ++ __u8 bPathId; ++ __u8 bTargetId; ++ __u8 bLun; ++ __u8 bIdentify; ++ __u8 bNumberOfLocationIdentifiers; ++ __u8 bLengthOfLocationIdentifier; ++ CSMI_SAS_LOCATION_IDENTIFIER Location[1]; ++} CSMI_SAS_GET_LOCATION_BUFFER, ++ *PCSMI_SAS_GET_LOCATION_BUFFER; ++ ++// CC_CSMI_SAS_PHY_CONTROL ++ ++typedef struct _CSMI_SAS_CHARACTER { ++ __u8 bTypeFlags; ++ __u8 bValue; ++} CSMI_SAS_CHARACTER, ++ *PCSMI_SAS_CHARACTER; ++ ++typedef struct _CSMI_SAS_PHY_CONTROL { ++ __u8 bType; ++ __u8 bRate; ++ __u8 bReserved[6]; ++ __u32 uVendorUnique[8]; ++ __u32 uTransmitterFlags; ++ __i8 bTransmitAmplitude; ++ __i8 bTransmitterPreemphasis; ++ __i8 bTransmitterSlewRate; ++ __i8 bTransmitterReserved[13]; ++ __u8 bTransmitterVendorUnique[64]; ++ __u32 uReceiverFlags; ++ __i8 bReceiverThreshold; ++ __i8 bReceiverEqualizationGain; ++ __i8 bReceiverReserved[14]; ++ __u8 bReceiverVendorUnique[64]; ++ __u32 uPatternFlags; ++ __u8 bFixedPattern; ++ __u8 bUserPatternLength; ++ __u8 bPatternReserved[6]; ++ CSMI_SAS_CHARACTER UserPatternBuffer[16]; ++} CSMI_SAS_PHY_CONTROL, ++ *PCSMI_SAS_PHY_CONTROL; ++ ++typedef struct _CSMI_SAS_PHY_CONTROL_BUFFER { ++ IOCTL_HEADER IoctlHeader; ++ __u32 uFunction; ++ __u8 bPhyIdentifier; ++ __u16 usLengthOfControl; ++ __u8 bNumberOfControls; ++ __u8 bReserved[4]; ++ __u32 uLinkFlags; ++ __u8 bSpinupRate; ++ __u8 bLinkReserved[7]; ++ __u32 uVendorUnique[8]; ++ CSMI_SAS_PHY_CONTROL Control[1]; ++} CSMI_SAS_PHY_CONTROL_BUFFER, ++ *PCSMI_SAS_PHY_CONTROL_BUFFER; ++ ++// EDN #pragma CSMI_SAS_END_PACK ++#pragma pack() ++ ++#endif // _CSMI_SAS_H_ +diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/Makefile linux-2.6.9-55.0.12/drivers/message/fusion/Makefile +--- linux-2.6.9-67.0.1/drivers/message/fusion/Makefile 2007-12-21 11:40:54.000000000 +0100 ++++ linux-2.6.9-55.0.12/drivers/message/fusion/Makefile 2007-11-02 09:10:23.000000000 +0100 +@@ -8,8 +8,6 @@ + #EXTRA_CFLAGS += -DMPT_DEBUG_EXIT + #EXTRA_CFLAGS += -DMPT_DEBUG_FAIL + #EXTRA_CFLAGS += -DMPT_DEBUG_SAS +-EXTRA_CFLAGS += -DCPQ_CIM +-EXTRA_CFLAGS += -DMPT_SUPPORT_FWDLB_IOCTL + + # + # driver/module specifics... +@@ -31,6 +29,7 @@ EXTRA_CFLAGS += -DMPT_SUPPORT_FWDLB_IOCT + # + # For mptctl: + #CFLAGS_mptctl.o += -DMPT_DEBUG_IOCTL ++CFLAGS_mptctl.o += -DCPQ_CIM + # + # For mptsas: + #CFLAGS_mptsas.o += -DMPT_DEBUG_HOTPLUG +diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptbase.c linux-2.6.9-55.0.12/drivers/message/fusion/mptbase.c +--- linux-2.6.9-67.0.1/drivers/message/fusion/mptbase.c 2007-12-21 11:40:54.000000000 +0100 ++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptbase.c 2007-11-02 09:10:23.000000000 +0100 +@@ -5,8 +5,8 @@ + * For use with LSI Logic PCI chip/adapter(s) + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * +- * Copyright (c) 1999-2007 LSI Logic Corporation +- * (mailto:mpt_linux_developer@lsi.com) ++ * Copyright (c) 1999-2005 LSI Logic Corporation ++ * (mailto:mpt_linux_developer@lsil.com) + * + * $Id: mptbase.c,v 1.130 2003/05/07 14:08:30 Exp $ + */ +@@ -93,8 +93,6 @@ MODULE_VERSION(MPT_LINUX_VERSION_COMMON) + char *mptbase = NULL; + + /* Command line args */ +- +- + int mpt_can_queue = 128; + module_param(mpt_can_queue, int, 0); + MODULE_PARM_DESC(mpt_can_queue, " Max IO depth per controller (default=128)"); +@@ -115,11 +113,6 @@ static int mpt_msi_enable = 0; + module_param(mpt_msi_enable, int, 0); + MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)"); + +-int mpt_enable_deadioc_detect = 0; +-module_param(mpt_enable_deadioc_detect, int, 0); +-MODULE_PARM_DESC(mpt_enable_deadioc_detect, "Detection of Dead IOC Enable (default=0)"); +- +-//@@@@ + #ifdef MFCNT + static int mfcounter = 0; + #define PRINT_MF_COUNT 20000 +@@ -163,13 +156,10 @@ static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq + */ + static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r); + static int mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply); +-int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, ++static int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, + u32 *req, int replyBytes, u16 *u16reply, int maxwait, + int sleepFlag); +-int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag); +-int mpt_writeSDP1(MPT_ADAPTER *hd, int portnum, int id, int flags); +-void mpt_setSDP1parameters (u8 width, u8 factor, u8 offset, u8 flags, int *requestedPtr, int *configurationPtr); +- ++static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag); + static void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev); + static void mpt_adapter_disable(MPT_ADAPTER *ioc); + static void mpt_adapter_dispose(MPT_ADAPTER *ioc); +@@ -187,7 +177,7 @@ static int mpt_do_upload(MPT_ADAPTER *io + int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag); + static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag); + static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag); +-int mpt_SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag); ++static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag); + static int PrimeIocFifos(MPT_ADAPTER *ioc); + static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag); + static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag); +@@ -197,6 +187,9 @@ static int GetFcPortPage0(MPT_ADAPTER *i + static int GetIoUnitPage2(MPT_ADAPTER *ioc); + static int GetManufPage5(MPT_ADAPTER *ioc, int numPorts); + static int GetManufPage0(MPT_ADAPTER *ioc); ++int mpt_sas_get_info(MPT_ADAPTER *ioc); ++static void mptbase_sas_process_event_data(MPT_ADAPTER *ioc, ++ MpiEventDataSasDeviceStatusChange_t * pSasEventData); + int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); + static void mptbase_raid_process_event_data(MPT_ADAPTER *ioc, + MpiEventDataRaid_t * pRaidEventData); +@@ -204,7 +197,6 @@ static int mpt_GetScsiPortSettings(MPT_A + static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum); + static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc); + static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc); +-static void mpt_read_ioc_pg_6(MPT_ADAPTER *ioc); + static void mpt_timer_expired(unsigned long data); + static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch); + static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp); +@@ -227,7 +219,6 @@ static void mpt_sp_ioc_info(MPT_ADAPTER + static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); + static void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info); + static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info); +-static void mpt_inactive_raid_list_free(MPT_ADAPTER *ioc); + + /* module entry point */ + static int __init fusion_init (void); +@@ -273,10 +264,10 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa + { + MPT_FRAME_HDR *mf = NULL; + MPT_FRAME_HDR *mr = NULL; +- int req_idx; ++ int req_idx = 0; + int cb_idx; + +- dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply pa=%08x\n", ++ dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n", + ioc->name, pa)); + + switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) { +@@ -312,9 +303,7 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa + break; + default: + cb_idx = 0; +- printk(MYIOC_s_WARN_FMT "%s: Invalid REPLY_TYPE in pa=%08x!\n", +- __FUNCTION__, ioc->name, pa); +-// BUG(); ++ BUG(); + } + + /* Check for (valid) IO callback! */ +@@ -342,12 +331,6 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa) + + u32 reply_dma_low; + u16 ioc_stat; +-#ifdef MPT_DEBUG_REPLY +- u8 function; +- MPT_FRAME_HDR *chain; +- int chain_idx, chain_number, next; +-#endif +- + + /* non-TURBO reply! Hmmm, something may be up... + * Newest turbo reply mechanism; get address +@@ -367,44 +350,21 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa) + cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx; + mf = MPT_INDEX_2_MFPTR(ioc, req_idx); + +- ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus); +-#ifdef MPT_DEBUG_REPLY +- if ((ioc_stat != MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE) && /* 0x0043 */ +- (ioc_stat != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN)) { /* 0x0045 */ +- function = mr->u.hdr.Function; +- dreplyprintk((MYIOC_s_WARN_FMT "non-TURBO reply context=%04x%04x Function=%x IOCStatus=%04x\n", +- ioc->name, cb_idx, req_idx, function, ioc_stat)); +- DBG_DUMP_REPLY_FRAME(mr) +- +- printk("Request:\n"); +- DBG_DUMP_REPLYS_REQUEST_FRAME(ioc, mf) +- chain_number = 1; +- chain_idx = ioc->ReqToChain[req_idx]; +- while (chain_idx != MPT_HOST_NO_CHAIN) { +- next = ioc->ChainToChain[chain_idx]; +- chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer +- + (chain_idx * ioc->req_sz)); +- printk("Chain %d:\n", chain_number++); +- DBG_DUMP_REPLYS_REQUEST_FRAME(ioc, chain) +- chain_idx = next; +- } +- } +-#endif ++ dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n", ++ ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function)); ++ DBG_DUMP_REPLY_FRAME(mr) + + /* Check/log IOC log info + */ ++ ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus); + if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { + u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo); + if (ioc->bus_type == FC) + mpt_fc_log_info(ioc, log_info); + else if (ioc->bus_type == SPI) + mpt_spi_log_info(ioc, log_info); +- else if (ioc->bus_type == SAS) { +- printk(MYIOC_s_INFO_FMT +- "IOCStatus=%04x LogInfo=%08x ", +- ioc->name, ioc_stat, log_info); ++ else if (ioc->bus_type == SAS) + mpt_sas_log_info(ioc, log_info); +- } + } + if (ioc_stat & MPI_IOCSTATUS_MASK) { + if (ioc->bus_type == SPI && +@@ -432,31 +392,6 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa) + if (freeme) + mpt_free_msg_frame(ioc, mf); + mb(); +-if (ioc->CheckFcLinkSpeed && +- ioc->FcLinkSpeedCheckNeeded && +- ioc->FcLinkSpeedReqActive == NULL && +- (mf = mpt_get_msg_frame(mpt_base_index, ioc))) { +- pConfig_t pConfigMsg; +- dma_addr_t physAddr; +- +- ioc->FcLinkSpeedCheckNeeded = 0; +- ioc->FcLinkSpeedReqActive = mf; +- pConfigMsg = (pConfig_t)mf; +- /* there's enough room, so FCPortPage0 will be put in the mf */ +- physAddr = ioc->req_frames_dma + sizeof(pConfig_t) + +- (u8 *)mf - (u8 *)ioc->req_frames; +- memset(pConfigMsg, 0, ioc->req_sz); +- pConfigMsg->Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- pConfigMsg->Function = MPI_FUNCTION_CONFIG; +- pConfigMsg->Header.PageType = MPI_CONFIG_PAGETYPE_FC_PORT; +- pConfigMsg->Header.PageNumber = 0; +- pConfigMsg->Header.PageLength = sizeof(FCPortPage0_t) / 4; +- pConfigMsg->Header.PageVersion = MPI_FCPORTPAGE0_PAGEVERSION; +- mpt_add_sge((char *)&pConfigMsg->PageBufferSGE, +- MPT_SGE_FLAGS_SSIMPLE_READ + sizeof(FCPortPage0_t), +- physAddr); +- mpt_put_msg_frame(mpt_base_index, ioc, mf); +- } + } + + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +@@ -543,17 +478,15 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRA + } + + /* +- * EventNotificationReply is an exception ++ * Hmmm... It seems that EventNotificationReply is an exception + * to the rule of one reply per request. + */ + if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) { + freereq = 0; + } else { +- devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns mf=%p evnp=%p\n", ioc->name, pEvReply, mf, ioc->evnp)); +- if ( (MPT_FRAME_HDR *)ioc->evnp == mf ) { +- ioc->evnp = NULL; +- } +- } ++ devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n", ++ ioc->name, pEvReply)); ++ } + + #ifdef CONFIG_PROC_FS + // LogEvent(ioc, pEvReply); +@@ -562,7 +495,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRA + } else if (func == MPI_FUNCTION_EVENT_ACK) { + dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n", + ioc->name)); +- } else if (func == MPI_FUNCTION_CONFIG ) { ++ } else if (func == MPI_FUNCTION_CONFIG) { + CONFIGPARMS *pCfg; + unsigned long flags; + +@@ -617,29 +550,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRA + */ + pCfg->wait_done = 1; + wake_up(&mpt_waitq); +- }else if (mf == ioc->FcLinkSpeedReqActive) { +- pFCPortPage0_t pFCPortPage0 = (pFCPortPage0_t)((u8 *)mf + sizeof(pConfig_t)); +- u8 OldSpeed = ioc->FcLinkSpeed; +- u8 NewSpeed = pFCPortPage0->CurrentSpeed; +- u8 State = pFCPortPage0->PortState; +- ioc->FcLinkSpeedReqActive = NULL; +- if (State != MPI_FCPORTPAGE0_PORTSTATE_OFFLINE && +- NewSpeed != MPI_FCPORTPAGE0_CURRENT_SPEED_UKNOWN) { +- char *old; +- char *new; +- old = OldSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT ? "1 Gbps" :OldSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT ? "2 Gbps" :OldSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT ? "4 Gbps" : +- "Unknown"; +-new = NewSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT ? "1 Gbps" :NewSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT ? "2 Gbps" : +-NewSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT ? "4 Gbps" : "Unknown"; +- +-if (OldSpeed == 0) { printk(MYIOC_s_NOTE_FMT "FC Link Established, Speed = %s\n", ioc->name, new); +- } else if (OldSpeed != NewSpeed) +-{ +-printk(MYIOC_s_WARN_FMT "FC Link Speed Change, Old Speed = %s, New Speed = %s\n",ioc->name, old, new); +-} +-ioc->FcLinkSpeed = NewSpeed; +-} +-} ++ } + } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) { + /* we should be always getting a reply frame */ + memcpy(ioc->persist_reply_frame, reply, +@@ -868,10 +779,6 @@ MPT_FRAME_HDR* + mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc) + { + MPT_FRAME_HDR *mf; +- #ifdef MPT_DEBUG_FAIL +- u8 *mem; +- #endif +- + unsigned long flags; + u16 req_idx; /* Request index */ + +@@ -884,10 +791,7 @@ mpt_get_msg_frame(int handle, MPT_ADAPTE + + /* If interrupts are not attached, do not return a request frame */ + if (!ioc->active) +- { +- printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame!!\n"); + return NULL; +- } + + spin_lock_irqsave(&ioc->FreeQlock, flags); + if (!list_empty(&ioc->FreeQ)) { +@@ -907,36 +811,10 @@ mpt_get_msg_frame(int handle, MPT_ADAPTE + #ifdef MFCNT + ioc->mfcnt++; + #endif +- } else { +-#ifdef MPT_DEBUG_FAIL +-dfailprintk((MYIOC_s_WARN_FMT "%s, No Free Message Frame!!\n", +- ioc->name,__FUNCTION__)); +- mem = (u8 *) ioc->req_frames; +- for (req_idx = 0; req_idx < 10; req_idx++) { +- { +- u32 *m = (u32 *)(mem); +- int ii, n; +- +- printk(KERN_WARNING MYNAM ": %s: msg frame %d @ %p:\n" KERN_INFO " ", +- ioc->name, req_idx, m); +- n = ioc->req_sz/4; +- for (ii=0; ii<n; ii++) { +- if (ii && ((ii%8)==0)) +- printk("\n"); +- printk("%08x ", le32_to_cpu(m[ii])); +- } +- printk("\n"); +- } +- mem += ioc->req_sz; +- } +-#endif +- +- +- +-mf = NULL; +-} +-spin_unlock_irqrestore(&ioc->FreeQlock, flags); +- ++ } ++ else ++ mf = NULL; ++ spin_unlock_irqrestore(&ioc->FreeQlock, flags); + + #ifdef MFCNT + if (mf == NULL) +@@ -984,13 +862,13 @@ mpt_put_msg_frame(int handle, MPT_ADAPTE + + printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ", + ioc->name, m); +- n = ioc->req_sz/4 ; ++ n = ioc->req_sz/4 - 1; + while (m[n] == 0) + n--; + for (ii=0; ii<=n; ii++) { + if (ii && ((ii%8)==0)) + printk("\n" KERN_INFO " "); +- printk("%08x ", le32_to_cpu(m[ii])); ++ printk(" %08x", le32_to_cpu(m[ii])); + } + printk("\n"); + } +@@ -1074,14 +952,16 @@ mpt_add_sge(char *pAddr, u32 flagslength + * Returns 0 for success, non-zero for failure. + */ + int +-mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, ulong timeout, int sleepFlag) ++mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag) + { +- int r = 0; ++ int r = 0; + u8 *req_as_bytes; +- int ii; ++ int ii; + +- dtmprintk((KERN_WARNING MYNAM ": %s: mpt_send_handshake_request reqBytes=%d\n", +- ioc->name, reqBytes)); ++ /* State is known to be good upon entering ++ * this function so issue the bus reset ++ * request. ++ */ + + /* + * Emulate what mpt_put_msg_frame() does /wrt to sanity +@@ -1089,16 +969,12 @@ mpt_send_handshake_request(int handle, M + * is in proper (pre-alloc'd) request buffer range... + */ + ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req); +- if (ii >= 0 && ii < ioc->req_depth) { ++ if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) { + MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req; + mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii); + mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; + } + +- ioc->tmPtr = (MPT_FRAME_HDR *)req; +- ioc->TMtimer.expires = jiffies + HZ*timeout; /* seconds */ +- add_timer(&ioc->TMtimer); +- + /* Make sure there are no doorbells */ + CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); + +@@ -1108,25 +984,20 @@ mpt_send_handshake_request(int handle, M + + /* Wait for IOC doorbell int */ + if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) { +- r= ii; +- goto mpt_send_handshake_failed; ++ return ii; + } + + /* Read doorbell and check for active bit */ +- if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE)){ +- r= -5; +- goto mpt_send_handshake_failed; +- } +- ++ if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE)) ++ return -5; + + dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n", + ioc->name, ii)); + + CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); + +- if ((WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) { +- r=-2; +- goto mpt_send_handshake_failed; ++ if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) { ++ return -2; + } + + /* Send request via doorbell handshake */ +@@ -1138,33 +1009,21 @@ mpt_send_handshake_request(int handle, M + (req_as_bytes[(ii*4) + 1] << 8) | + (req_as_bytes[(ii*4) + 2] << 16) | + (req_as_bytes[(ii*4) + 3] << 24)); +-dtmprintk((KERN_WARNING MYNAM ": %s: mpt_send_handshake_request word=%08x ii=%d\n",ioc->name, word, ii)); +- + CHIPREG_WRITE32(&ioc->chip->Doorbell, word); +- if ( WaitForDoorbellAck(ioc, 5, sleepFlag) < 0) { ++ if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) { + r = -3; +- goto mpt_send_handshake_failed; ++ break; + } + } + +- dtmprintk((KERN_WARNING MYNAM ": %s: mpt_send_handshake_request reqBytes=%d sent, WaitForDoorbellInt\n", +- ioc->name, reqBytes)); +- +- if ( WaitForDoorbellInt(ioc, 10, sleepFlag)< 0) ++ if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0) ++ r = 0; ++ else + r = -4; + + /* Make sure there are no doorbells */ + CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); + +-mpt_send_handshake_failed: +- if (r < 0) { +- del_timer(&ioc->TMtimer); +- ioc->tmPtr = NULL; +- } +- dtmprintk((KERN_WARNING MYNAM ": %s: mpt_send_handshake_request r=%d\n", +- ioc->name, r)); +- +- + return r; + } + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +@@ -1186,6 +1045,7 @@ mpt_send_handshake_failed: + static int + mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag) + { ++ int r = 0; + + /* return if in use */ + if (CHIPREG_READ32(&ioc->chip->Doorbell) +@@ -1200,7 +1060,7 @@ mpt_host_page_access_control(MPT_ADAPTER + (access_control_value<<12))); + + /* Wait for IOC to clear Doorbell Status bit */ +- if (( WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) { ++ if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) { + return -2; + }else + return 0; +@@ -1344,10 +1204,20 @@ mpt_bringup_adapter(MPT_ADAPTER *ioc, in + { + int r; + ++ if(ioc->alt_ioc) { ++ if((r=mpt_alt_ioc_wait(ioc->alt_ioc)!=0)) ++ return r; ++ } + + r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, + CAN_SLEEP); + ++ if(ioc->alt_ioc) { ++ spin_lock(&ioc->alt_ioc->initializing_hba_lock); ++ ioc->alt_ioc->initializing_hba_lock_flag=0; ++ spin_unlock(&ioc->alt_ioc->initializing_hba_lock); ++ } ++ + return r; + } + +@@ -1383,8 +1253,6 @@ mpt_attach(struct pci_dev *pdev, const s + u8 revision; + u8 pcixcmd; + static int mpt_ids = 0; +- unsigned long flags; +- + #ifdef CONFIG_PROC_FS + struct proc_dir_entry *dent, *ent; + #endif +@@ -1420,7 +1288,6 @@ mpt_attach(struct pci_dev *pdev, const s + ioc->reply_sz = MPT_REPLY_FRAME_SIZE; + + ioc->pcidev = pdev; +- ioc->IOCResetInProgress = 0; + ioc->diagPending = 0; + spin_lock_init(&ioc->diagLock); + spin_lock_init(&ioc->initializing_hba_lock); +@@ -1596,17 +1463,10 @@ mpt_attach(struct pci_dev *pdev, const s + if(ioc->errata_flag_1064) { + pci_disable_io_access(pdev); + } +- if(ioc->bus_type == FC) { +- ioc->CheckFcLinkSpeed = 1; +- ioc->FcLinkSpeed = 0; +- } +- + + sprintf(ioc->name, "ioc%d", ioc->id); + + spin_lock_init(&ioc->FreeQlock); +- spin_lock_init(&ioc->PendingMFlock); +- + + /* Disable all! */ + CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); +@@ -1659,43 +1519,22 @@ mpt_attach(struct pci_dev *pdev, const s + */ + mpt_detect_bound_ports(ioc, pdev); + +-if(mpt_enable_deadioc_detect){ +-/* The following list initializations is moved from PrimeIocFifos +- because the lists will not get initialize for non-operational +- IOCs and which cause a crash when the lists are accessed later +- */ +-/* Initialize the free chain Q.*/ +- +- INIT_LIST_HEAD(&ioc->FreeChainQ); +- spin_lock_irqsave(&ioc->FreeQlock, flags); +- INIT_LIST_HEAD(&ioc->FreeQ); +- spin_unlock_irqrestore(&ioc->FreeQlock, flags); +- init_MUTEX(&ioc->raid_data.inactive_list_mutex); +- INIT_LIST_HEAD(&ioc->raid_data.inactive_list); +- +- /* Even If there is any error in IOC bringup, the IOC is allowed to +- be attached with MPT drivers, This change is done to support +- Firmware download boot functionality for FW dead IOC */ +- mpt_bringup_adapter(ioc, CAN_SLEEP); +- } +- +-else { +- if ((r = mpt_bringup_adapter(ioc, CAN_SLEEP)) != 0){ +- printk(KERN_WARNING MYNAM +- ": WARNING - %s did not initialize properly! (%d)\n", +- ioc->name, r); +- list_del(&ioc->list); +- free_irq(ioc->pci_irq, ioc); +- if (mpt_msi_enable == 1) { +- pci_disable_msi(pdev); +- } +- iounmap(mem); +- kfree(ioc); +- pci_set_drvdata(pdev, NULL); +- return r; ++ if ((r = mpt_bringup_adapter(ioc, CAN_SLEEP)) != 0){ ++ printk(KERN_WARNING MYNAM ++ ": WARNING - %s did not initialize properly! (%d)\n", ++ ioc->name, r); ++ ++ list_del(&ioc->list); ++ free_irq(ioc->pci_irq, ioc); ++ if (mpt_msi_enable == 1) { ++ pci_disable_msi(pdev); ++ } ++ iounmap(mem); ++ kfree(ioc); ++ pci_set_drvdata(pdev, NULL); ++ return r; + } + +-} + /* call per device driver probe entry point */ + for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) { + if(MptDeviceDriverHandlers[ii] && +@@ -1812,7 +1651,7 @@ mpt_suspend(struct pci_dev *pdev, pm_mes + #endif + + /* put ioc into READY_STATE */ +- if(mpt_SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) { ++ if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) { + printk(MYIOC_s_ERR_FMT + "pci-suspend: IOC msg unit reset failed!\n", ioc->name); + } +@@ -1864,8 +1703,7 @@ mpt_resume(struct pci_dev *pdev) + if(!CHIPREG_READ32(&ioc->chip->Doorbell)) { + /* enable domain validation flags */ + for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { +- ioc->spi_data.dvStatus[ii] |= (MPT_SCSICFG_NEED_DV | +- MPT_SCSICFG_DV_NOT_DONE); ++ ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_NEED_DV; + } + } + +@@ -1905,19 +1743,23 @@ mpt_resume(struct pci_dev *pdev) + * + * Returns: + * 0 for success +- * -1 if failed to get board READY ++ * -1 if failed to get boardMODULE_VERSION(MPT_LINUX_VERSION_COMMON); ++ READY + * -2 if READY but IOCFacts Failed + * -3 if READY but PrimeIOCFifos Failed + * -4 if READY but IOCInit Failed + */ +-int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) +-{ unsigned long flags; ++static int ++mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) ++{ + int hard_reset_done = 0; ++ int alt_ioc_ready = 0; + int hard; + int rc = 0; + int ii; ++ int handlers; + int ret = 0; +- ++ int reset_alt_ioc_active = 0; + + printk(KERN_INFO MYNAM ": Initiating %s %s\n", + ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery"); +@@ -1926,15 +1768,13 @@ int mpt_do_ioc_recovery(MPT_ADAPTER *ioc + CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); + ioc->active = 0; + +-/* If an event notification has not returned +- * its request frame, +- * free resources associated with this request. +- */ +- if (ioc->evnp) { +- drsprintk((MYIOC_s_WARN_FMT "do_ioc_recovery: freeing evnp=%p\n", +- ioc->name, ioc->evnp)); +- mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)ioc->evnp); +- ioc->evnp = NULL; ++ if (ioc->alt_ioc) { ++ if (ioc->alt_ioc->active) ++ reset_alt_ioc_active = 1; ++ ++ /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */ ++ CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF); ++ ioc->alt_ioc->active = 0; + } + + hard = 1; +@@ -1945,39 +1785,68 @@ int mpt_do_ioc_recovery(MPT_ADAPTER *ioc + if (hard_reset_done == -4) { + printk(KERN_WARNING MYNAM ": %s Owned by PEER..skipping!\n", + ioc->name); ++ ++ if (reset_alt_ioc_active && ioc->alt_ioc) { ++ /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */ ++ dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", ++ ioc->alt_ioc->name)); ++ CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM); ++ ioc->alt_ioc->active = 1; ++ } ++ + } else { + printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n", + ioc->name); + } +- +- spin_lock_irqsave(&ioc->diagLock, flags); +- ioc->IOCResetInProgress = 0; +- spin_unlock_irqrestore(&ioc->diagLock, flags); + return -1; + } + ++ /* hard_reset_done = 0 if a soft reset was performed ++ * and 1 if a hard reset was performed. ++ */ ++ if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) { ++ if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0) ++ alt_ioc_ready = 1; ++ else ++ printk(KERN_WARNING MYNAM ++ ": alt-%s: Not ready WARNING!\n", ++ ioc->alt_ioc->name); ++ } ++ ++ for (ii=0; ii<5; ii++) { ++ /* Get IOC facts! Allow 5 retries */ ++ if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0) ++ break; ++ } + +-if (reason == MPT_HOSTEVENT_IOC_BRINGUP || +- mpt_enable_deadioc_detect){ +- for (ii=0; ii<5; ii++) { +- /* Get IOC facts! Allow 5 retries */ +- if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0) +- break; +-} + ++ if (ii == 5) { ++ dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc)); ++ ret = -2; ++ } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { ++ MptDisplayIocCapabilities(ioc); ++ } + +-if(ii==5) { +-dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name , rc)); +- ret = -2; +- } else { +- if (reason == MPT_HOSTEVENT_IOC_BRINGUP) +- MptDisplayIocCapabilities(ioc); ++ if (alt_ioc_ready) { ++ if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) { ++ dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc)); ++ /* Retry - alt IOC was initialized once ++ */ ++ rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason); ++ } ++ if (rc) { ++ dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc)); ++ alt_ioc_ready = 0; ++ reset_alt_ioc_active = 0; ++ } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { ++ MptDisplayIocCapabilities(ioc->alt_ioc); + } + } + + /* Prime reply & request queues! + * (mucho alloc's) Must be done prior to + * init as upper addresses are needed for init. ++ * If fails, continue with alt-ioc processing + */ + if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0)) + ret = -3; +@@ -1987,6 +1856,23 @@ dinitprintk((MYIOC_s_INFO_FMT "Retry Ioc + */ + if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0)) + ret = -4; ++// NEW! ++ if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) { ++ printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n", ++ ioc->alt_ioc->name, rc); ++ alt_ioc_ready = 0; ++ reset_alt_ioc_active = 0; ++ } ++ ++ if (alt_ioc_ready) { ++ if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) { ++ alt_ioc_ready = 0; ++ reset_alt_ioc_active = 0; ++ printk(KERN_WARNING MYNAM ++ ": alt-%s: (%d) init failure WARNING!\n", ++ ioc->alt_ioc->name, rc); ++ } ++ } + + if (reason == MPT_HOSTEVENT_IOC_BRINGUP){ + if (ioc->upload_fw) { +@@ -2024,6 +1910,13 @@ dinitprintk((MYIOC_s_INFO_FMT "Retry Ioc + ioc->active = 1; + } + ++ if (reset_alt_ioc_active && ioc->alt_ioc) { ++ /* (re)Enable alt-IOC! (reply interrupt) */ ++ dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", ++ ioc->alt_ioc->name)); ++ CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM); ++ ioc->alt_ioc->active = 1; ++ } + + /* Enable MPT base driver management of EventNotification + * and EventAck handling. +@@ -2031,6 +1924,9 @@ dinitprintk((MYIOC_s_INFO_FMT "Retry Ioc + if ((ret == 0) && (!ioc->facts.EventState)) + (void) SendEventNotification(ioc, 1); /* 1=Enable EventNotification */ + ++ if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState) ++ (void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */ ++ + /* Add additional "reason" check before call to GetLanConfigPages + * (combined with GetIoUnitPage2 call). This prevents a somewhat + * recursive scenario; GetLanConfigPages times out, timer expired +@@ -2038,30 +1934,32 @@ dinitprintk((MYIOC_s_INFO_FMT "Retry Ioc + * and we try GetLanConfigPages again... + */ + if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) { +- +- /* +- * Initalize link list for inactive raid volumes. +- */ +- init_MUTEX(&ioc->raid_data.inactive_list_mutex); +- INIT_LIST_HEAD(&ioc->raid_data.inactive_list); +- + if (ioc->bus_type == SAS) { ++ + /* + * Pre-fetch SAS Address for each port + */ + GetManufPage5(ioc, ioc->facts.NumberOfPorts); + ++ /* ++ * Pre-fetch Serial number for the board. ++ */ ++ GetManufPage0(ioc); ++ ++ /* ++ * Pre-fetch Hw Link Rates. (These may get ++ * overwritten so need to save them.) ++ * Save other SAS data needed for Ioctls. ++ */ ++ mpt_sas_get_info(ioc); ++ + /* clear persistency table */ + if(ioc->facts.IOCExceptions & + MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) { + ret = mptbase_sas_persist_operation(ioc, + MPI_SAS_OP_CLEAR_NOT_PRESENT); +- if(ret != 0){ +- spin_lock_irqsave(&ioc->diagLock, flags); +- ioc->IOCResetInProgress = 0; +- spin_unlock_irqrestore(&ioc->diagLock, flags); ++ if(ret != 0) + return -1; +- } + } + + /* Find IM volumes +@@ -2118,11 +2016,6 @@ dinitprintk((MYIOC_s_INFO_FMT "Retry Ioc + } + + GetIoUnitPage2(ioc); +- +- /* +- * Pre-fetch Serial number for the board. +- */ +- GetManufPage0(ioc); + } + + /* +@@ -2131,35 +2024,26 @@ dinitprintk((MYIOC_s_INFO_FMT "Retry Ioc + * NOTE: If we're doing _IOC_BRINGUP, there can be no + * MptResetHandlers[] registered yet. + */ +- if (ret == 0) { +- rc = 0; +- +- for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { +- if (MptResetHandlers[ii]) { +- drsprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\ n",ioc->name, ii)); +- ++ if (hard_reset_done) { ++ rc = handlers = 0; ++ for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { ++ if ((ret == 0) && MptResetHandlers[ii]) { ++ dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n", ++ ioc->name, ii)); + rc += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET); ++ handlers++; ++ } + ++ if (alt_ioc_ready && MptResetHandlers[ii]) { ++ drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n", ++ ioc->name, ioc->alt_ioc->name, ii)); ++ rc += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET); ++ handlers++; + } + } ++ /* FIXME? Examine results here? */ + } + +-if (ioc->bus_type == FC) { +- ioc->FcLinkSpeedCheckNeeded = 1; +- } +- +- if (ioc->bus_type == SPI) { +- drsprintk((MYIOC_s_WARN_FMT "%s: calling writeSDP1: ALL_IDS USE_NVRAM\n", +- ioc->name, __FUNCTION__)); +- dnegoprintk((MYIOC_s_WARN_FMT "%s: calling writeSDP1: ALL_IDS USE_NVRAM\n", +- ioc->name, __FUNCTION__)); +- mpt_writeSDP1(ioc, 0, 0, (MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM)); +- } +- +- spin_lock_irqsave(&ioc->diagLock, flags); +- ioc->IOCResetInProgress = 0; +- spin_unlock_irqrestore(&ioc->diagLock, flags); +- + return ret; + } + +@@ -2224,11 +2108,9 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc, + static void + mpt_adapter_disable(MPT_ADAPTER *ioc) + { +- struct _MPT_DEVICE *pMptTarget; +- VirtDevice *pTarget; ++ sas_device_info_t *sasDevice, * pNext; + int sz; + int ret, ii; +- int bus, id; + void * request_data; + dma_addr_t request_data_dma; + u32 request_data_sz; +@@ -2253,7 +2135,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) + if ( request_data ) { + request_data_sz = ioc->DiagBuffer_sz[ii]; + request_data_dma = ioc->DiagBuffer_dma[ii]; +- dexitprintk((KERN_INFO MYNAM ": %s: free DiagBuffer[%d] @ %p, sz=%d bytes\n", ++ dexitprintk((KERN_INFO MYNAM ": %s free DiagBuffer[%d] @ %p, sz=%d bytes\n", + ioc->name, ii, request_data, request_data_sz)); + pci_free_consistent(ioc->pcidev, request_data_sz, + request_data, +@@ -2264,7 +2146,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) + } + if (ioc->alloc != NULL) { + sz = ioc->alloc_sz; +- dexitprintk((KERN_INFO MYNAM ": %s: free alloc @ %p, sz=%d bytes\n", ++ dexitprintk((KERN_INFO MYNAM ": %s free alloc @ %p, sz=%d bytes\n", + ioc->name, ioc->alloc, ioc->alloc_sz)); + pci_free_consistent(ioc->pcidev, sz, + ioc->alloc, ioc->alloc_dma); +@@ -2276,7 +2158,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) + + if (ioc->sense_buf_pool != NULL) { + sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC); +- dexitprintk((KERN_INFO MYNAM ": %s: free sense_buf_pool @ %p, sz=%d bytes\n", ++ dexitprintk((KERN_INFO MYNAM ": %s free sense_buf_pool @ %p, sz=%d bytes\n", + ioc->name, ioc->sense_buf_pool, sz)); + pci_free_consistent(ioc->pcidev, sz, + ioc->sense_buf_pool, ioc->sense_buf_pool_dma); +@@ -2286,7 +2168,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) + + if (ioc->events != NULL){ + sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS); +- dexitprintk((KERN_INFO MYNAM ": %s: free events @ %p, sz=%d bytes\n", ++ dexitprintk((KERN_INFO MYNAM ": %s free events @ %p, sz=%d bytes\n", + ioc->name, ioc->events, sz)); + kfree(ioc->events); + ioc->events = NULL; +@@ -2295,7 +2177,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) + + if (ioc->cached_fw != NULL) { + sz = ioc->facts.FWImageSize; +- dexitprintk((KERN_INFO MYNAM ": %s: free cached_fw @ %p, sz=%d bytes\n", ++ dexitprintk((KERN_INFO MYNAM ": %s free cached_fw @ %p, sz=%d bytes\n", + ioc->name, ioc->cached_fw, sz)); + pci_free_consistent(ioc->pcidev, sz, + ioc->cached_fw, ioc->cached_fw_dma); +@@ -2304,29 +2186,22 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) + } + + if (ioc->spi_data.nvram != NULL) { +- dexitprintk((KERN_INFO MYNAM ": %s: free spi_data.nvram @ %p\n", ++ dexitprintk((KERN_INFO MYNAM ": %s free spi_data.nvram @ %p\n", + ioc->name, ioc->spi_data.nvram)); + kfree(ioc->spi_data.nvram); + ioc->spi_data.nvram = NULL; + } + + if (ioc->raid_data.pIocPg3 != NULL) { +- dexitprintk((KERN_INFO MYNAM ": %s: free spi_data.pIocPg3 @ %p\n", ++ dexitprintk((KERN_INFO MYNAM ": %s free spi_data.pIocPg3 @ %p\n", + ioc->name, ioc->raid_data.pIocPg3)); + kfree(ioc->raid_data.pIocPg3); + ioc->raid_data.pIocPg3 = NULL; + } + +- if (ioc->raid_data.pIocPg6 != NULL) { +- dexitprintk((KERN_INFO MYNAM ": %s: free raid_data.pIocPg6 @ %p\n", +- ioc->name, ioc->raid_data.pIocPg6)); +- kfree(ioc->raid_data.pIocPg6); +- ioc->raid_data.pIocPg6 = NULL; +- } +- + if (ioc->spi_data.pIocPg4 != NULL) { + sz = ioc->spi_data.IocPg4Sz; +- dexitprintk((KERN_INFO MYNAM ": %s: free spi_data.pIocPg4 @ %p size=%d\n", ++ dexitprintk((KERN_INFO MYNAM ": %s free spi_data.pIocPg4 @ %p size=%d\n", + ioc->name, ioc->spi_data.pIocPg4, sz)); + pci_free_consistent(ioc->pcidev, sz, + ioc->spi_data.pIocPg4, +@@ -2336,41 +2211,38 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) + } + + if (ioc->ReqToChain != NULL) { +- dexitprintk((KERN_INFO MYNAM ": %s: free ReqToChain @ %p\n", ++ dexitprintk((KERN_INFO MYNAM ": %s free ReqToChain @ %p\n", + ioc->name, ioc->ReqToChain)); + kfree(ioc->ReqToChain); + ioc->ReqToChain = NULL; + } + + if (ioc->RequestNB != NULL) { +- dexitprintk((KERN_INFO MYNAM ": %s: free RequestNB @ %p\n", ++ dexitprintk((KERN_INFO MYNAM ": %s free RequestNB @ %p\n", + ioc->name, ioc->RequestNB)); + kfree(ioc->RequestNB); + ioc->RequestNB = NULL; + } + + if (ioc->ChainToChain != NULL) { +- dexitprintk((KERN_INFO MYNAM ": %s: free ChainToChain @ %p\n", ++ dexitprintk((KERN_INFO MYNAM ": %s free ChainToChain @ %p\n", + ioc->name, ioc->ChainToChain)); + kfree(ioc->ChainToChain); + ioc->ChainToChain = NULL; + } + +- mpt_inactive_raid_list_free(ioc); ++ list_for_each_entry_safe(sasDevice, pNext, &ioc->sasDeviceList, list) { ++ list_del(&sasDevice->list); ++ dexitprintk((KERN_INFO MYNAM ": %s free sasDevice @ %p\n", ++ ioc->name, sasDevice)); ++ kfree(sasDevice); ++ } + +- for (bus = 0; bus < ioc->NumberOfBuses; bus++) { +- if ((pMptTarget = ioc->Target_List[bus])) { +- for (id = 0; id < ioc->DevicesPerBus; id++) { +- if ((pTarget = pMptTarget->Target[id])) { +- dexitprintk((KERN_INFO MYNAM ": %s: free bus=%d id=%d pTarget=%p\n", +- ioc->name, bus, id, pTarget)); +- kfree (pTarget); +- } +- } +- dexitprintk((KERN_INFO MYNAM ": %s: free bus=%d pMptTarget=%p\n", +- ioc->name, bus, pMptTarget)); +- kfree (pMptTarget); +- } ++ if (ioc->sasPhyInfo != NULL) { ++ dexitprintk((KERN_INFO MYNAM ": %s free sasPhyInfo @ %p\n", ++ ioc->name, ioc->sasPhyInfo)); ++ kfree(ioc->sasPhyInfo); ++ ioc->sasPhyInfo = NULL; + } + + /* emoore@lsil.com : Host Page Buffer Suport, start */ +@@ -2381,7 +2253,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) + ": %s: host page buffers free failed (%d)!\n", + __FUNCTION__, ret); + } +- dexitprintk((KERN_INFO MYNAM ": %s: HostPageBuffer free @ %p, sz=%d bytes\n", ++ dexitprintk((KERN_INFO MYNAM ": %s HostPageBuffer free @ %p, sz=%d bytes\n", + ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz)); + pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz, + ioc->HostPageBuffer, +@@ -2441,7 +2313,7 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc) + dexitprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n", + ioc->name, sz_first-sz_last+(int)sizeof(MPT_ADAPTER), sz_first)); + dexitprintk((KERN_INFO MYNAM ": %s: sz_first=%d sz_last=%d sizeof(MPT_ADAPTER)=%d\n", +- ioc->name, sz_first, sz_last, (int)sizeof(MPT_ADAPTER))); ++ ioc->name, sz_first, sz_last, sizeof(MPT_ADAPTER))); + + if (ioc->alt_ioc) + ioc->alt_ioc->alt_ioc = NULL; +@@ -2521,17 +2393,12 @@ MakeIocReady(MPT_ADAPTER *ioc, int force + + /* Get current [raw] IOC state */ + ioc_state = mpt_GetIocState(ioc, 0); +- drsprintk((KERN_INFO MYNAM ": %s : MakeIocReady [raw] state=%08x\n", ioc->name, ioc_state)); ++ dhsprintk((KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state)); + + for ( ii = 0; ii < MPI_DIAG_BUF_TYPE_COUNT; ii++) { + ioc->DiagBuffer[ii] = NULL; + ioc->DiagBuffer_Status[ii] = 0; + } +-if (ioc->bus_type == FC) { +- ioc->FcLinkSpeedCheckNeeded = 0; +- ioc->FcLinkSpeedReqActive = NULL; +-} +- + + /* + * Check to see if IOC got left/stuck in doorbell handshake +@@ -2544,12 +2411,9 @@ if (ioc->bus_type == FC) { + } + + /* Is it already READY? */ +- if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY) { +-drsprintk((KERN_INFO MYNAM ": %s : MakeIocReady ioc_state=%08x = READY\n", ioc->name, ioc_state)); +- /* Dont return for SAS IOCs */ +- if (ioc->bus_type != SAS) +- return 0; +- } ++ if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY) ++ return 0; ++ + /* + * Check to see if IOC is in FAULT state. + */ +@@ -2581,7 +2445,7 @@ drsprintk((KERN_INFO MYNAM ": %s : MakeI + return -4; + else { + if ((statefault == 0 ) && (force == 0)) { +-if ((r = mpt_SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0) ++ if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0) + return 0; + } + statefault = 3; +@@ -2604,7 +2468,7 @@ if ((r = mpt_SendIocReset(ioc, MPI_FUNCT + * BIOS or previous driver load left IOC in OP state. + * Reset messaging FIFOs. + */ +-if ((r = mpt_SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) { ++ if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) { + printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name); + return -2; + } +@@ -2613,7 +2477,7 @@ if ((r = mpt_SendIocReset(ioc, MPI_FUNCT + * Something is wrong. Try to get IOC back + * to a known state. + */ +-if ((r = mpt_SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) { ++ if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) { + printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name); + return -3; + } +@@ -2629,7 +2493,7 @@ if ((r = mpt_SendIocReset(ioc, MPI_FUNCT + if (sleepFlag == CAN_SLEEP) + msleep_interruptible(1); + else +- MPT_MDELAY(1); /* 1 msec delay */ ++ MPT_MDELAY(1); /* 1 msec delay */ + + } + +@@ -2766,9 +2630,6 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepF + facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word); + + facts->ProductID = le16_to_cpu(facts->ProductID); +- if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) +- > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) +- ioc->ir_firmware = 1; + facts->CurrentHostMfaHighAddr = + le32_to_cpu(facts->CurrentHostMfaHighAddr); + facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits); +@@ -2814,9 +2675,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepF + dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n", + ioc->name, vv, shiftFactor, r)); + +-/* Allow dead IOCs to get detected after FWDLB*/ +- if (reason == MPT_HOSTEVENT_IOC_BRINGUP ||mpt_enable_deadioc_detect) { +- ++ if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { + /* + * Set values for this IOC's request & reply frame sizes, + * and request & reply queue depths... +@@ -2870,7 +2729,6 @@ GetPortFacts(MPT_ADAPTER *ioc, int portn + int ii; + int req_sz; + int reply_sz; +- int max_id; + + /* IOC *must* NOT be in RESET state! */ + if (ioc->last_state == MPI_IOC_STATE_RESET) { +@@ -2913,31 +2771,6 @@ GetPortFacts(MPT_ADAPTER *ioc, int portn + pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo); + pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices); + pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID); +- +- switch (ioc->bus_type) { +- case SAS: +- max_id = pfacts->PortSCSIID; +- break; +- case FC: +- max_id = pfacts->MaxDevices; +- break; +- case SPI: +- default: +- max_id = MPT_MAX_SCSI_DEVICES; +- break; +- } +- +- ioc->DevicesPerBus = (max_id > 255) ? 256 : max_id; +- ioc->NumberOfBuses = (ioc->DevicesPerBus < 256) ? 1 : max_id/256; +- if ( ioc->NumberOfBuses > MPT_MAX_BUSES ) { +- dinitprintk((MYIOC_s_WARN_FMT "NumberOfBuses=%d > MPT_MAX_BUSES=%d\n", +- ioc->name, ioc->NumberOfBuses, MPT_MAX_BUSES)); +- ioc->NumberOfBuses = MPT_MAX_BUSES; +- } +- +- dinitprintk((MYIOC_s_WARN_FMT "Buses=%d MaxDevices=%d DevicesPerBus=%d\n", +- ioc->name, ioc->NumberOfBuses, max_id, ioc->DevicesPerBus)); +- + pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags); + pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers); + pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs); +@@ -2983,11 +2816,15 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepF + dinitprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n", + ioc->name, ioc->upload_fw, ioc->facts.Flags)); + +- ioc_init.MaxDevices = ioc->DevicesPerBus; +- ioc_init.MaxBuses = ioc->NumberOfBuses; +- +- dinitprintk((MYIOC_s_INFO_FMT "ioc_init.MaxDevices=%d MaxBuses=%d\n", +- ioc->name, ioc_init.MaxDevices, ioc_init.MaxBuses)); ++ if(ioc->bus_type == SAS) ++ ioc_init.MaxDevices = ioc->facts.MaxDevices; ++ else if(ioc->bus_type == FC) ++ ioc_init.MaxDevices = MPT_MAX_FC_DEVICES; ++ else ++ ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES; ++ ioc_init.MaxBuses = MPT_MAX_BUS; ++ dinitprintk((MYIOC_s_INFO_FMT "ioc_init.MaxDevice=%d\n", ++ ioc->name, ioc_init.MaxDevices)); + dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n", + ioc->name, ioc->facts.MsgVersion)); + /* emoore@lsil.com : Host Page Buffer Suport, start */ +@@ -3110,7 +2947,9 @@ SendPortEnable(MPT_ADAPTER *ioc, int por + + /* RAID FW may take a long time to enable + */ +- if (ioc->ir_firmware || ioc->bus_type == SAS) { ++ if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) ++ > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) || ++ (ioc->bus_type == SAS)) { + rc = mpt_handshake_req_reply_wait(ioc, req_sz, + (u32*)&port_enable, reply_sz, (u16*)&reply_buf, + 300 /*seconds*/, sleepFlag); +@@ -3151,7 +2990,7 @@ mpt_free_fw_memory(MPT_ADAPTER *ioc) + int sz; + + sz = ioc->facts.FWImageSize; +- dinitprintk((KERN_INFO MYNAM ": free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n", ++ dinitprintk((KERN_INFO MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n", + ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz)); + pci_free_consistent(ioc->pcidev, sz, + ioc->cached_fw, ioc->cached_fw_dma); +@@ -3285,43 +3124,14 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFw + u32 diag0val; + int count; + u32 *ptrFw; +- u32 diagRwData,doorbell; ++ u32 diagRwData; + u32 nextImage; + u32 load_addr; ++ u32 ioc_state=0; + +-ddlprintk((MYIOC_s_WARN_FMT "downloadboot: pFwHeader=%p\n",ioc->name, pFwHeader)); +- nextImage = pFwHeader->NextImageHeaderOffset; +- if (ioc->bus_type == SAS) { +- while (nextImage) { +- if ( (pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage)) ) { +- ddlprintk((MYIOC_s_WARN_FMT "downloadboot: SAS nextImage=%x pExtImage=%p ImageType=%x\n", +- ioc->name, nextImage, pExtImage, +- pExtImage->ImageType)); +- } else { +- ddlprintk((MYIOC_s_WARN_FMT "downloadboot: SAS nextImage=%x pExtImage=%p is NULL!\n", +- ioc->name, nextImage, pExtImage)); +- return -EFAULT; +- } +- +- if ( pExtImage->ImageType == MPI_EXT_IMAGE_TYPE_BOOTLOADER ) { +- fwSize = (pExtImage->ImageSize + 3)/4; +- ptrFw = (u32 *) pExtImage; +- load_addr = pExtImage->LoadStartAddress; +- goto imageFound; +- } +- nextImage = pExtImage->NextImageHeaderOffset; +- } +- ddlprintk((MYIOC_s_WARN_FMT "downloadboot: SAS BOOTLOADER not found\n", +- ioc->name)); +- /* Allow this image to be downloaded */ +- } +- fwSize = (pFwHeader->ImageSize + 3)/4; +- ptrFw = (u32 *) pFwHeader; +- load_addr = pFwHeader->LoadStartAddress; ++ ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n", ++ ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader)); + +-imageFound: +- ddlprintk((MYIOC_s_WARN_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p load_addr=%x\n", +- ioc->name, fwSize, fwSize, ptrFw, load_addr)); + + CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); + CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE); +@@ -3345,7 +3155,7 @@ imageFound: + for (count = 0; count < 30; count ++) { + diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); + if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) { +- ddlprintk((MYIOC_s_WARN_FMT "RESET_ADAPTER cleared, count=%d\n", ++ ddlprintk((MYIOC_s_INFO_FMT "RESET_ADAPTER cleared, count=%d\n", + ioc->name, count)); + break; + } +@@ -3357,7 +3167,7 @@ imageFound: + } + + if ( count == 30 ) { +- ddlprintk((MYIOC_s_WARN_FMT "downloadboot failed! Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n", ++ ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n", + ioc->name, diag0val)); + return -3; + } +@@ -3370,9 +3180,10 @@ imageFound: + CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE); + + /* Set the DiagRwEn and Disable ARM bits */ ++ CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM)); + +- diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); +-CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM)); ++ fwSize = (pFwHeader->ImageSize + 3)/4; ++ ptrFw = (u32 *) pFwHeader; + + /* Write the LoadStartAddress to the DiagRw Address Register + * using Programmed IO +@@ -3380,28 +3191,26 @@ CHIPREG_WRITE32(&ioc->chip->Diagnostic, + if(ioc->errata_flag_1064) { + pci_enable_io_access(ioc->pcidev); + } +-CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr); ++ CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress); ++ ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n", ++ ioc->name, pFwHeader->LoadStartAddress)); + +-ddlprintk((MYIOC_s_WARN_FMT "LoadStart addr written 0x%x \n",ioc->name, load_addr)); +-ddlprintk((MYIOC_s_WARN_FMT "Write FW Image: 0x%x (%d) bytes @ %p\n", +- ioc->name, fwSize*4, fwSize*4, ptrFw)); ++ ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x (%d) bytes @ %p\n", ++ ioc->name, fwSize*4, fwSize*4, ptrFw)); + while (fwSize--) { + CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++); + } + +- if (ioc->bus_type == SAS) { +- pFwHeader->IopResetVectorValue = load_addr + 0x18; +- } else { +- +- while (nextImage) { +- pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage); ++ nextImage = pFwHeader->NextImageHeaderOffset; ++ while (nextImage) { ++ pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage); + + load_addr = pExtImage->LoadStartAddress; + + fwSize = (pExtImage->ImageSize + 3) >> 2; + ptrFw = (u32 *)pExtImage; + +- ddlprintk((MYIOC_s_WARN_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n", ++ ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n", + ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr)); + CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr); + +@@ -3411,18 +3220,20 @@ ddlprintk((MYIOC_s_WARN_FMT "Write FW Im + nextImage = pExtImage->NextImageHeaderOffset; + } + +- } + /* Write the IopResetVectorRegAddr */ +- ddlprintk((MYIOC_s_WARN_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr)); ++ ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr)); + CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr); + + /* Write the IopResetVectorValue */ +- ddlprintk((MYIOC_s_WARN_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue)); ++ ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue)); + CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue); + ++ /* Clear the internal flash bad bit - autoincrementing register, ++ * so must do two writes. ++ */ + if (ioc->bus_type == SPI) { + /* +- * 1030 H/W errata, workaround to access ++ * 1030 and 1035 H/W errata, workaround to access + * the ClearFlashBadSignatureBit + */ + CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000); +@@ -3431,6 +3242,16 @@ ddlprintk((MYIOC_s_WARN_FMT "Write FW Im + CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000); + CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData); + ++ } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ { ++ diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); ++ CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | ++ MPI_DIAG_CLEAR_FLASH_BAD_SIG); ++ ++ /* wait 1 msec */ ++ if (sleepFlag == CAN_SLEEP) ++ msleep_interruptible(1); ++ else ++ MPT_MDELAY(1); + } + + if(ioc->errata_flag_1064) { +@@ -3438,77 +3259,48 @@ ddlprintk((MYIOC_s_WARN_FMT "Write FW Im + } + + diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); +- ddlprintk((MYIOC_s_WARN_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n", ++ ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n", + ioc->name, diag0val)); +- +-diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM); +-ddlprintk((MYIOC_s_WARN_FMT "downloadboot: now diag0val=%x\n", ++ diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE); ++ ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n", + ioc->name, diag0val)); + CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val); + +-if (ioc->bus_type == SAS ) { +-/* wait 1 sec */ +-if (sleepFlag == CAN_SLEEP) +-{ +-msleep_interruptible(1000); +- +-} +-else +-MPT_MDELAY(1000); +- +- +- ++ /* Write 0xFF to reset the sequencer */ ++ CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); + +-diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); +-ddlprintk((MYIOC_s_WARN_FMT "downloadboot: diag0val=%x, turning off RW_ENABLE\n" +- ioc->name, diag0val)); +-diag0val &= ~(MPI_DIAG_RW_ENABLE); +-ddlprintk((MYIOC_s_WARN_FMT "downloadboot: now diag0val=%x\n", +- ioc->name, diag0val)); +-CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val); +-diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); +-if (diag0val & MPI_DIAG_FLASH_BAD_SIG) { +-diag0val |= MPI_DIAG_CLEAR_FLASH_BAD_SIG; +-CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val); +-diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); ++ if (ioc->bus_type == SAS) { ++ ioc_state = mpt_GetIocState(ioc, 0); ++ if ( (GetIocFacts(ioc, sleepFlag, ++ MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) { ++ ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed: IocState=%x\n", ++ ioc->name, ioc_state)); ++ return -EFAULT; + } +-diag0val &= ~(MPI_DIAG_DISABLE_ARM); +-CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val); +-diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); +-CHIPREG_WRITE32(&ioc->chip->DiagRwAddress, 0x3f000004); + } +-/* Write 0xFF to reset the sequencer */ +-CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); +- +- for (count = 0; count < 30; count ++) { +- doorbell = CHIPREG_READ32(&ioc->chip->Doorbell); +- doorbell &= MPI_IOC_STATE_MASK; +- +- if (doorbell == MPI_IOC_STATE_READY) { + ++ for (count=0; count<HZ*20; count++) { ++ if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) { ++ ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n", ++ ioc->name, count, ioc_state)); + if (ioc->bus_type == SAS) { + return 0; + } +- +- +- if ((SendIocInit(ioc, sleepFlag)) != 0) { +- ddlprintk((MYIOC_s_WARN_FMT "downloadboot: SendIocInit failed\n", ++ if ((SendIocInit(ioc, sleepFlag)) != 0) { ++ ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n", + ioc->name)); + return -EFAULT; + } +- ddlprintk((MYIOC_s_WARN_FMT "downloadboot: SendIocInit successful\n", ++ ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit successful\n", + ioc->name)); + return 0; + } +- ddlprintk((MYIOC_s_WARN_FMT "downloadboot: looking for READY STATE:doorbell=%x count=%d\n",ioc->name, doorbell, count)); +- /* wait 1 sec */ +- + if (sleepFlag == CAN_SLEEP) +- msleep_interruptible(1000); ++ msleep_interruptible(10); + else +- MPT_MDELAY(1000); ++ MPT_MDELAY(10); + } +- ddlprintk((MYIOC_s_WARN_FMT "downloadboot failed! IocState=%x\n", ++ ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! IocState=%x\n", + ioc->name, ioc_state)); + return -EFAULT; + } +@@ -3552,7 +3344,8 @@ KickStart(MPT_ADAPTER *ioc, int force, i + /* Always issue a Msg Unit Reset first. This will clear some + * SCSI bus hang conditions. + */ +- mpt_SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag); ++ SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag); ++ + if (sleepFlag == CAN_SLEEP) + msleep_interruptible(1000); + else +@@ -3624,26 +3417,6 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign + msleep_interruptible(1); + else + MPT_MDELAY(1); +-/* +- * Call each currently registered protocol IOC reset handler +- * with post-reset indication. +- * NOTE: If we're doing _IOC_BRINGUP, there can be no +- * MptResetHandlers[] registered yet. +- */ +- { +- int ii; +- int r=0; +- +- for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { +- if (MptResetHandlers[ii]) { +- drsprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",ioc->name, ii)); +- r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET); +- +- } +-} +-/* FIXME? Examine results here? */ +- +-} + + for (count = 0; count < 60; count ++) { + doorbell = CHIPREG_READ32(&ioc->chip->Doorbell); +@@ -3746,11 +3519,11 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign + + for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { + if (MptResetHandlers[ii]) { +- drsprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n", ++ dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n", + ioc->name, ii)); + r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_PRE_RESET); + if (ioc->alt_ioc) { +- drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n", ++ dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n", + ioc->name, ioc->alt_ioc->name, ii)); + r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_PRE_RESET); + } +@@ -3901,31 +3674,18 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign + * + * Returns 0 for success, non-zero for failure. + */ +-int +-mpt_SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag) ++static int ++SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag) + { +- unsigned long flags; + int r; +- u32 state, Doorbell; ++ u32 state; + int cntdn, count; + +-Doorbell = (reset_type<<MPI_DOORBELL_FUNCTION_SHIFT); +- +-drsprintk((MYIOC_s_WARN_FMT ": %s: reset_type=%02x Doorbell=%08x!\n", +-ioc->name, __FUNCTION__, reset_type, Doorbell)); +-CHIPREG_WRITE32(&ioc->chip->Doorbell, Doorbell); +- +-if ((r = WaitForDoorbellAck(ioc, 15, sleepFlag)) < 0){ +- drsprintk((MYIOC_s_WARN_FMT ": %s: WaitForDoorbellAck failed r=%d after IOC Rese +-t type=%02x!\n", +- ioc->name, __FUNCTION__, r, reset_type)); +- return r; +-} +- +-spin_lock_irqsave(&ioc->diagLock, flags); +-ioc->IOCResetInProgress = 1; +-spin_unlock_irqrestore(&ioc->diagLock, flags); +- ++ drsprintk((KERN_INFO MYNAM ": %s: Sending IOC reset(0x%02x)!\n", ++ ioc->name, reset_type)); ++ CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT); ++ if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) ++ return r; + + /* FW ACK'd request, wait for READY state + */ +@@ -3950,13 +3710,13 @@ spin_unlock_irqrestore(&ioc->diagLock, f + MPT_MDELAY(1); /* 1 msec delay */ + } + ++ /* TODO! ++ * Cleanup all event stuff for this IOC; re-issue EventNotification ++ * request if needed. ++ */ + if (ioc->facts.Function) + ioc->facts.EventState = 0; +-spin_lock_irqsave(&ioc->diagLock, flags); +-ioc->IOCResetInProgress = 0; +-spin_unlock_irqrestore(&ioc->diagLock, flags); +-drsprintk((MYIOC_s_WARN_FMT ": %s: IOC reset completed successfully state=%08x count=%d\ n", +-ioc->name, __FUNCTION__, state, count)); ++ + return 0; + } + +@@ -4044,9 +3804,8 @@ PrimeIocFifos(MPT_ADAPTER *ioc) + unsigned long flags; + dma_addr_t alloc_dma; + u8 *mem; +- int i, reply_sz, req_sz, sz, total_size, num_chain, total_num_chain; +- int scale, scale1, num_sge, numSGE, maxSGEs, SGE_size; +- int max_sg_tablesize; ++ int i, reply_sz, sz, total_size, num_chain, total_num_chain; ++ int scale, scale1, num_sge, numSGE, maxSGEs, SGE_size; + + /* Prime reply FIFO... */ + +@@ -4073,13 +3832,12 @@ PrimeIocFifos(MPT_ADAPTER *ioc) + " numSGE=%d MaxChainDepth=%d maxSGEs=%d mpt_sg_tablesize=%d\n", + ioc->name, ioc->req_sz, SGE_size, scale, num_sge, numSGE, + ioc->facts.MaxChainDepth, maxSGEs, mpt_sg_tablesize)); +- max_sg_tablesize = mpt_sg_tablesize; +- if (max_sg_tablesize > maxSGEs) { +- max_sg_tablesize = maxSGEs; +- dinitprintk((KERN_INFO MYNAM ": %s max_sg_tablesize=%d now\n", +- ioc->name, max_sg_tablesize)); +- } else if (max_sg_tablesize < maxSGEs) { +- numSGE = max_sg_tablesize - num_sge; ++ if (mpt_sg_tablesize > maxSGEs) { ++ mpt_sg_tablesize = maxSGEs; ++ dinitprintk((KERN_INFO MYNAM ": %s mpt_sg_tablesize=%d now\n", ++ ioc->name, mpt_sg_tablesize)); ++ } else if (mpt_sg_tablesize < maxSGEs) { ++ numSGE = mpt_sg_tablesize - num_sge; + dinitprintk((KERN_INFO MYNAM ": %s numSGE=%d now\n", + ioc->name, numSGE)); + } +@@ -4099,12 +3857,11 @@ PrimeIocFifos(MPT_ADAPTER *ioc) + + numSGE = scale1 * (total_num_chain-1); + maxSGEs = num_sge + numSGE; +- if (max_sg_tablesize > maxSGEs) { +- max_sg_tablesize = maxSGEs; +- dinitprintk((KERN_INFO MYNAM ": %s max_sg_tablesize=%d now, maxSGEs=%d numSGE=%d\n", +- ioc->name, max_sg_tablesize, maxSGEs, numSGE)); ++ if (mpt_sg_tablesize > maxSGEs) { ++ mpt_sg_tablesize = maxSGEs; ++ dinitprintk((KERN_INFO MYNAM ": %s mpt_sg_tablesize=%d now, maxSGEs=%d numSGE=%d\n", ++ ioc->name, mpt_sg_tablesize, maxSGEs, numSGE)); + } +- ioc->sg_tablesize = max_sg_tablesize; + + dinitprintk((KERN_INFO MYNAM ": %s req_depth=%d max num_chain=%d mpt_chain_alloc_percent=%d total_num_chain=%d\n", + ioc->name, ioc->req_depth, num_chain, mpt_chain_alloc_percent, total_num_chain)); +@@ -4116,17 +3873,14 @@ PrimeIocFifos(MPT_ADAPTER *ioc) + dinitprintk((KERN_INFO MYNAM ": %s Total ReplyBuffer sz=%d[%x] bytes\n", + ioc->name, reply_sz, reply_sz)); + +- req_sz = ioc->req_sz; +- sz = (req_sz * ioc->req_depth); +- +- dinitprintk((KERN_INFO MYNAM ": %s RequestBuffer sz=%d bytes, RequestDepth=%d\n", +- ioc->name, req_sz, ioc->req_depth)); +- ++ sz = (ioc->req_sz * ioc->req_depth); ++ dinitprintk((KERN_INFO MYNAM ": %s RequestBuffer sz=%d bytes, RequestDepth=%d\n", ++ ioc->name, ioc->req_sz, ioc->req_depth)); + dinitprintk((KERN_INFO MYNAM ": %s Total RequestBuffer sz=%d[%x] bytes\n", + ioc->name, sz, sz)); + total_size += sz; + +- sz = total_num_chain *req_sz; /* chain buffer pool size */ ++ sz = total_num_chain * ioc->req_sz; /* chain buffer pool size */ + dinitprintk((KERN_INFO MYNAM ": %s Total ChainBuffer sz=%d[%x] bytes total_num_chain=%d\n", + ioc->name, sz, sz, total_num_chain)); + +@@ -4182,14 +3936,14 @@ PrimeIocFifos(MPT_ADAPTER *ioc) + #endif + + for (i = 0; i < ioc->req_depth; i++) { +- alloc_dma += req_sz; +- mem += req_sz; ++ alloc_dma += ioc->req_sz; ++ mem += ioc->req_sz; + } + + ioc->ChainBuffer = mem; + ioc->ChainBufferDMA = alloc_dma; + +- dinitprintk((KERN_INFO MYNAM ": %s ChainBuffers @ %p(%p)\n", ++ dinitprintk((KERN_INFO MYNAM " :%s ChainBuffers @ %p(%p)\n", + ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA)); + + /* Initialize the free chain Q. +@@ -4197,6 +3951,10 @@ PrimeIocFifos(MPT_ADAPTER *ioc) + + INIT_LIST_HEAD(&ioc->FreeChainQ); + ++ /* initialize the SAS device list */ ++ ++ INIT_LIST_HEAD(&ioc->sasDeviceList); ++ + /* Post the chain buffers to the FreeChainQ. + */ + mem = (u8 *)ioc->ChainBuffer; +@@ -4205,7 +3963,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc) + list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ); + // dinitprintk((MYIOC_s_INFO_FMT "Adding %p to FreeChainQ at %d\n", + // ioc->name, mf, i)); +- mem += req_sz; ++ mem += ioc->req_sz; + } + + /* Initialize Request frames linked list +@@ -4220,7 +3978,7 @@ PrimeIocFifos(MPT_ADAPTER *ioc) + + /* Queue REQUESTs *internally*! */ + list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ); +- mem += req_sz; ++ mem += ioc->req_sz; + } + spin_unlock_irqrestore(&ioc->FreeQlock, flags); + +@@ -4293,7 +4051,8 @@ out_fail: + * + * Returns 0 for success, non-zero for failure. + */ +-int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req, ++static int ++mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req, + int replyBytes, u16 *u16reply, int maxwait, int sleepFlag) + { + MPIDefaultReply_t *mptReply; +@@ -4412,7 +4171,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int + intstat = CHIPREG_READ32(&ioc->chip->IntStatus); + if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS)) + break; +- msleep_interruptible(10); ++ msleep_interruptible(1); + count++; + } + } else { +@@ -4420,7 +4179,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int + intstat = CHIPREG_READ32(&ioc->chip->IntStatus); + if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS)) + break; +- udelay(1000); ++ MPT_MDELAY(1); + count++; + } + } +@@ -4461,7 +4220,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int + intstat = CHIPREG_READ32(&ioc->chip->IntStatus); + if (intstat & MPI_HIS_DOORBELL_INTERRUPT) + break; +- msleep_interruptible(10); ++ msleep_interruptible(1); + count++; + } + } else { +@@ -4469,7 +4228,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int + intstat = CHIPREG_READ32(&ioc->chip->IntStatus); + if (intstat & MPI_HIS_DOORBELL_INTERRUPT) + break; +- udelay(1000); ++ MPT_MDELAY(1); + count++; + } + } +@@ -4944,40 +4703,481 @@ GetManufPage0_exit: + return rc; + } + ++ + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + /* +- * mptbase_sas_persist_operation - Perform operation on SAS Persitent Table ++ * mpt_sas_get_info - Fetch Hw Max and Min Link Rates. These values ++ * get overwritten, so must be saved at init time. + * @ioc: Pointer to MPT_ADAPTER structure +- * @sas_address: 64bit SAS Address for operation. +- * @target_id: specified target for operation +- * @bus: specified bus for operation +- * @persist_opcode: see below +- * +- * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for +- * devices not currently present. +- * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings +- * +- * NOTE: Don't use not this function during interrupt time. ++ * @numPorts: number of ports for this IOC + * +- * Returns: 0 for success, non-zero error ++ * Return: 0 for success ++ * -ENOMEM if no memory available ++ * -EPERM if not allowed due to ISR context ++ * -EAGAIN if no msg frames currently available ++ * -EFAULT for non-successful reply or no reply (timeout) + */ +- +-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + int +-mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode) ++mpt_sas_get_info(MPT_ADAPTER *ioc) + { +- SasIoUnitControlRequest_t *sasIoUnitCntrReq; +- SasIoUnitControlReply_t *sasIoUnitCntrReply; +- MPT_FRAME_HDR *mf = NULL; +- MPIHeader_t *mpi_hdr; ++ ConfigExtendedPageHeader_t hdr; ++ CONFIGPARMS cfg; ++ SasIOUnitPage0_t *sasIoUnitPg0=NULL; ++ dma_addr_t sasIoUnitPg0_dma; ++ SasPhyPage0_t *sasPhyPg0=NULL; ++ dma_addr_t sasPhyPg0_dma; ++ SasDevicePage0_t *sasDevicePg0=NULL; ++ dma_addr_t sasDevicePg0_dma; ++ sas_device_info_t *sasDevice; ++ u32 devHandle; ++ int sasIoUnitPg0_data_sz=0; ++ int sasPhyPg0_data_sz=0; ++ int sasDevicePg0_data_sz=0; ++ int sz; ++ int rc; ++ int ii; ++ int phyCounter; ++ u8 *mem; ++ u64 SASAddress64; ++ char *ds = NULL; + ++ /* Issue a config request to get the number of phys ++ */ ++ ioc->sasPhyInfo=NULL; + +- /* insure garbage is not sent to fw */ +- switch(persist_opcode) { ++ hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION; ++ hdr.ExtPageLength = 0; ++ hdr.PageNumber = 0; ++ hdr.Reserved1 = 0; ++ hdr.Reserved2 = 0; ++ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; ++ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; + +- case MPI_SAS_OP_CLEAR_NOT_PRESENT: +- case MPI_SAS_OP_CLEAR_ALL_PERSISTENT: +- break; ++ cfg.cfghdr.ehdr = &hdr; ++ cfg.physAddr = -1; ++ cfg.pageAddr = 0; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; ++ cfg.dir = 0; /* read */ ++ cfg.timeout = 10; ++ ++ if ((rc = mpt_config(ioc, &cfg)) != 0) { ++ goto mpt_sas_get_info_exit; ++ } ++ ++ if (hdr.ExtPageLength == 0) { ++ rc = -EFAULT; ++ goto mpt_sas_get_info_exit; ++ } ++ ++ sasIoUnitPg0_data_sz = hdr.ExtPageLength * 4; ++ sasIoUnitPg0 = (SasIOUnitPage0_t *) pci_alloc_consistent(ioc->pcidev, ++ sasIoUnitPg0_data_sz, &sasIoUnitPg0_dma); ++ if (!sasIoUnitPg0) { ++ rc = -ENOMEM; ++ goto mpt_sas_get_info_exit; ++ } ++ ++ memset((u8 *)sasIoUnitPg0, 0, sasIoUnitPg0_data_sz); ++ cfg.physAddr = sasIoUnitPg0_dma; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; ++ ++ if ((rc = mpt_config(ioc, &cfg)) != 0) { ++ goto mpt_sas_get_info_exit; ++ } ++ ++ /* save the data */ ++ ioc->numPhys = sasIoUnitPg0->NumPhys; ++ ++ dsasprintk((MYIOC_s_INFO_FMT "Number of PHYS=%d\n", ++ ioc->name, sasIoUnitPg0->NumPhys)); ++ ++ sz = ioc->numPhys * sizeof (sas_phy_info_t); ++ ++ if ((mem = kmalloc(sz, GFP_ATOMIC)) == NULL) { ++ rc = -ENOMEM; ++ goto mpt_sas_get_info_exit; ++ } ++ ++ memset(mem, 0, sz); ++ ioc->alloc_total += sz; ++ ioc->sasPhyInfo = (sas_phy_info_t *) mem; ++ ++ /* Issue a config request to get phy information. */ ++ hdr.PageVersion = MPI_SASPHY0_PAGEVERSION; ++ hdr.ExtPageLength = 0; ++ hdr.PageNumber = 0; ++ hdr.Reserved1 = 0; ++ hdr.Reserved2 = 0; ++ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; ++ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY; ++ ++ cfg.cfghdr.ehdr = &hdr; ++ cfg.dir = 0; /* read */ ++ cfg.timeout = 10; ++ ++ /* Fill in information for each phy. */ ++ for (ii = 0; ii < ioc->numPhys; ii++) { ++ ++ /* Get Phy Pg 0 for each Phy. */ ++ cfg.pageAddr = ii; ++ cfg.physAddr = -1; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; ++ ++ if ((rc = mpt_config(ioc, &cfg)) != 0) { ++ goto mpt_sas_get_info_exit; ++ } ++ ++ if (hdr.ExtPageLength == 0) { ++ rc = -EFAULT; ++ goto mpt_sas_get_info_exit; ++ } ++ ++ sasPhyPg0_data_sz = hdr.ExtPageLength * 4; ++ sasPhyPg0 = (SasPhyPage0_t *) pci_alloc_consistent( ++ ioc->pcidev, sasPhyPg0_data_sz, &sasPhyPg0_dma); ++ if (!sasPhyPg0) { ++ rc = -ENOMEM; ++ goto mpt_sas_get_info_exit; ++ } ++ ++ memset((u8 *)sasPhyPg0, 0, sasPhyPg0_data_sz); ++ cfg.physAddr = sasPhyPg0_dma; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; ++ ++ /* Save HwLinkRate. ++ * It may be modified accidently via FW ++ */ ++ if ((rc = mpt_config(ioc, &cfg)) != 0) { ++ goto mpt_sas_get_info_exit; ++ } ++ ++ ioc->sasPhyInfo[ii].hwLinkRate = sasPhyPg0->HwLinkRate; ++ ioc->sasPhyInfo[ii].phyId = ii; ++ ioc->sasPhyInfo[ii].port = sasIoUnitPg0->PhyData[ii].Port; ++ ioc->sasPhyInfo[ii].ControllerDevHandle = ++ le16_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerDevHandle); ++ ioc->sasPhyInfo[ii].PortFlags = ++ sasIoUnitPg0->PhyData[ii].PortFlags; ++ ioc->sasPhyInfo[ii].PhyFlags = ++ sasIoUnitPg0->PhyData[ii].PhyFlags; ++ ioc->sasPhyInfo[ii].NegotiatedLinkRate = ++ sasIoUnitPg0->PhyData[ii].NegotiatedLinkRate; ++ ioc->sasPhyInfo[ii].ControllerPhyDeviceInfo = ++ le32_to_cpu(sasIoUnitPg0->PhyData[ii].ControllerPhyDeviceInfo); ++ ++ memcpy(&SASAddress64,&sasPhyPg0->SASAddress,sizeof(sasPhyPg0->SASAddress)); ++ le64_to_cpus(&SASAddress64); ++ if (SASAddress64) { ++ dsasprintk(("---- SAS PHY PAGE 0 ------------\n")); ++ dsasprintk(("Handle=0x%X\n", ++ le16_to_cpu(sasPhyPg0->AttachedDevHandle))); ++ dsasprintk(("SAS Address=0x%llX\n",SASAddress64)); ++ dsasprintk(("Attached PHY Identifier=0x%X\n", ++ sasPhyPg0->AttachedPhyIdentifier)); ++ dsasprintk(("Attached Device Info=0x%X\n", ++ le32_to_cpu(sasPhyPg0->AttachedDeviceInfo))); ++ dsasprintk(("Programmed Link Rate=0x%X\n", ++ sasPhyPg0->ProgrammedLinkRate)); ++ dsasprintk(("Hardware Link Rate=0x%X\n", ++ ioc->sasPhyInfo[ii].hwLinkRate)); ++ dsasprintk(("Change Count=0x%X\n", ++ sasPhyPg0->ChangeCount)); ++ dsasprintk(("PHY Info=0x%X\n", ++ le32_to_cpu(sasPhyPg0->PhyInfo))); ++ dsasprintk(("\n")); ++ } ++ ++ pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz, ++ (u8 *) sasPhyPg0, sasPhyPg0_dma); ++ ++ sasPhyPg0=NULL; ++ } ++ ++ ++ /* Get all Device info and store in linked list. */ ++ devHandle = 0xFFFF; ++ phyCounter=0; ++ while(1) { ++ /* Get SAS device page 0 */ ++ ++ hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION; ++ hdr.ExtPageLength = 0; ++ hdr.PageNumber = 0; ++ hdr.Reserved1 = 0; ++ hdr.Reserved2 = 0; ++ hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; ++ hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE; ++ ++ cfg.cfghdr.ehdr = &hdr; ++ cfg.physAddr = -1; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; ++ cfg.dir = 0; /* read */ ++ cfg.timeout = 10; ++ ++ if ((rc = mpt_config(ioc, &cfg)) != 0) { ++ goto mpt_sas_get_info_exit; ++ } ++ ++ if (hdr.ExtPageLength == 0) { ++ rc = -EFAULT; ++ goto mpt_sas_get_info_exit; ++ } ++ ++ sasDevicePg0_data_sz = hdr.ExtPageLength * 4; ++ sasDevicePg0 = (SasDevicePage0_t *) pci_alloc_consistent( ++ ioc->pcidev, sasDevicePg0_data_sz, &sasDevicePg0_dma); ++ if (!sasDevicePg0) { ++ rc = -ENOMEM; ++ goto mpt_sas_get_info_exit; ++ } ++ ++ memset((u8 *)sasDevicePg0, 0, sasDevicePg0_data_sz); ++ cfg.physAddr = sasDevicePg0_dma; ++ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; ++ cfg.pageAddr = devHandle; ++ ++ if ((rc = mpt_config(ioc, &cfg)) != 0) { ++ ++ /* ++ * break from the while loop when this fails ++ * which means we have discovered all devices ++ */ ++ rc=0; ++ goto mpt_sas_get_info_exit; ++ } ++ ++ dsasprintk(("---- SAS DEVICE PAGE 0 ---------\n")); ++ dsasprintk(("Handle=0x%X\n",le16_to_cpu(sasDevicePg0->DevHandle))); ++ dsasprintk(("Enclosure Handle=0x%X\n",le16_to_cpu(sasDevicePg0->EnclosureHandle))); ++ dsasprintk(("Slot=0x%X\n",le16_to_cpu(sasDevicePg0->Slot))); ++ memcpy(&SASAddress64,&sasDevicePg0->SASAddress,sizeof(sasDevicePg0->SASAddress)); ++ le64_to_cpus(&SASAddress64); ++ dsasprintk(("SAS Address=0x%llX\n",SASAddress64)); ++ dsasprintk(("Target ID=0x%X\n",sasDevicePg0->TargetID)); ++ dsasprintk(("Bus=0x%X\n",sasDevicePg0->Bus)); ++ dsasprintk(("PhyNum=0x%X\n",sasDevicePg0->PhyNum)); ++ dsasprintk(("AccessStatus=0x%X\n",le16_to_cpu(sasDevicePg0->AccessStatus))); ++ dsasprintk(("Device Info=0x%X\n",le32_to_cpu(sasDevicePg0->DeviceInfo))); ++ dsasprintk(("Flags=0x%X\n",le16_to_cpu(sasDevicePg0->Flags))); ++ dsasprintk(("Physical Port=0x%X\n",sasDevicePg0->PhysicalPort)); ++ dsasprintk(("\n")); ++ ++ if(phyCounter < ioc->numPhys) { ++ ioc->sasPhyInfo[phyCounter].SASAddress = SASAddress64; ++ ioc->sasPhyInfo[phyCounter].devHandle = ++ le16_to_cpu(sasDevicePg0->DevHandle); ++ phyCounter++; ++ }else { ++ if (le32_to_cpu(sasDevicePg0->DeviceInfo) & ++ (MPI_SAS_DEVICE_INFO_SSP_TARGET | ++ MPI_SAS_DEVICE_INFO_STP_TARGET | ++ MPI_SAS_DEVICE_INFO_SATA_DEVICE )) { ++ ++ if ((sasDevice = kmalloc(sizeof (sas_device_info_t), ++ GFP_ATOMIC)) == NULL) { ++ rc = -ENOMEM; ++ goto mpt_sas_get_info_exit; ++ } ++ ++ memset(sasDevice, 0, sizeof (sas_device_info_t)); ++ ioc->alloc_total += sizeof (sas_device_info_t); ++ list_add_tail(&sasDevice->list, &ioc->sasDeviceList); ++ sasDevice->SASAddress = SASAddress64; ++ sasDevice->TargetId = sasDevicePg0->TargetID; ++ sasDevice->Bus = sasDevicePg0->Bus; ++ sasDevice->DeviceInfo = ++ le32_to_cpu(sasDevicePg0->DeviceInfo); ++ sasDevice->DevHandle = ++ le16_to_cpu(sasDevicePg0->DevHandle); ++ sasDevice->Flags = ++ le16_to_cpu(sasDevicePg0->Flags); ++ sasDevice->PhyNum = sasDevicePg0->PhyNum; ++ sasDevice->PhysicalPort = ++ sasDevicePg0->PhysicalPort; ++ if(sasDevice->DeviceInfo & ++ MPI_SAS_DEVICE_INFO_SSP_TARGET) ++ ds = "sas"; ++ if(sasDevice->DeviceInfo & ++ MPI_SAS_DEVICE_INFO_STP_TARGET) ++ ds = "stp"; ++ if(sasDevice->DeviceInfo & ++ MPI_SAS_DEVICE_INFO_SATA_DEVICE) ++ ds = "sata"; ++ dsasprintk(( ++ "Inserting %s device, channel %d, id %d, phy %d\n\n", ++ ds,sasDevice->Bus, ++ sasDevice->TargetId, ++ sasDevicePg0->PhyNum)); ++ } ++ } ++ ++ devHandle = (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE ++ << MPI_SAS_DEVICE_PGAD_FORM_SHIFT) | ++ le16_to_cpu(sasDevicePg0->DevHandle); ++ ++ pci_free_consistent(ioc->pcidev, sasDevicePg0_data_sz, ++ (u8 *) sasDevicePg0, sasDevicePg0_dma); ++ ++ sasDevicePg0=NULL; ++ ++ }; ++ ++mpt_sas_get_info_exit: ++ ++ ++ if (sasPhyPg0) ++ pci_free_consistent(ioc->pcidev, sasPhyPg0_data_sz, ++ (u8 *) sasPhyPg0, sasPhyPg0_dma); ++ ++ if (sasIoUnitPg0) ++ pci_free_consistent(ioc->pcidev, sasIoUnitPg0_data_sz, ++ (u8 *) sasIoUnitPg0, sasIoUnitPg0_dma); ++ ++ if (sasDevicePg0) ++ pci_free_consistent(ioc->pcidev, sasDevicePg0_data_sz, ++ (u8 *) sasDevicePg0, sasDevicePg0_dma); ++ ++ return rc; ++} ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++ ++static void ++mptbase_sas_process_event_data(MPT_ADAPTER *ioc, ++ MpiEventDataSasDeviceStatusChange_t * pSasEventData) ++{ ++ sas_device_info_t *sasDevice; ++ int ii; ++ char *ds=NULL; ++ ++ switch(pSasEventData->ReasonCode) { ++ case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: ++ ++ // sanity check so we are not adding a target that is already in the list. ++ list_for_each_entry(sasDevice, &ioc->sasDeviceList, list) { ++ if (pSasEventData->TargetID == ++ sasDevice->TargetId) ++ return; ++ break; ++ } ++ ++ if ((le32_to_cpu(pSasEventData->DeviceInfo) & ++ (MPI_SAS_DEVICE_INFO_SSP_TARGET | ++ MPI_SAS_DEVICE_INFO_STP_TARGET | ++ MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0) { ++ break; ++ } ++ ++ if ((sasDevice = kmalloc(sizeof (sas_device_info_t), ++ GFP_ATOMIC)) == NULL) { ++ break; ++ } ++ ++ memset(sasDevice, 0, sizeof (sas_device_info_t)); ++ list_add_tail(&sasDevice->list, &ioc->sasDeviceList); ++ ioc->alloc_total += sizeof (sas_device_info_t); ++ ++ memcpy(&sasDevice->SASAddress,&pSasEventData->SASAddress,sizeof(u64)); ++ le64_to_cpus(&sasDevice->SASAddress); ++ sasDevice->TargetId = pSasEventData->TargetID; ++ sasDevice->Bus = pSasEventData->Bus; ++ sasDevice->DeviceInfo = ++ le32_to_cpu(pSasEventData->DeviceInfo); ++ sasDevice->DevHandle = ++ le16_to_cpu(pSasEventData->DevHandle); ++ sasDevice->PhyNum = pSasEventData->PhyNum; ++ pSasEventData->ParentDevHandle = ++ le16_to_cpu(pSasEventData->ParentDevHandle); ++ ++ for(ii=0;ii<ioc->numPhys;ii++) { ++ if(pSasEventData->ParentDevHandle == ++ ioc->sasPhyInfo[ii].ControllerDevHandle) { ++ sasDevice->PhysicalPort = ++ ioc->sasPhyInfo[ii].port; ++ } ++ } ++ ++ if(sasDevice->DeviceInfo & ++ MPI_SAS_DEVICE_INFO_SSP_TARGET) ++ ds = "sas"; ++ if(sasDevice->DeviceInfo & ++ MPI_SAS_DEVICE_INFO_STP_TARGET) ++ ds = "stp"; ++ if(sasDevice->DeviceInfo & ++ MPI_SAS_DEVICE_INFO_SATA_DEVICE) ++ ds = "sata"; ++ dsasprintk(( ++ "Inserting %s device, channel %d, id %d, phy %d\n\n", ++ ds,sasDevice->Bus, ++ sasDevice->TargetId, ++ sasDevice->PhyNum)); ++ dsasprintk(("SAS Address=0x%llX\n",sasDevice->SASAddress)); ++ dsasprintk(("Device Info=0x%X\n",sasDevice->DeviceInfo)); ++ dsasprintk(("Physical Port=0x%X\n",sasDevice->PhysicalPort)); ++ dsasprintk(("\n")); ++ ++ break; ++ ++ case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: ++ ++ list_for_each_entry(sasDevice, &ioc->sasDeviceList, list) { ++ ++ if (le16_to_cpu(pSasEventData->DevHandle) == ++ sasDevice->DevHandle) { ++ ++ dsasprintk(("Removing device from link list!!!\n\n")); ++ list_del(&sasDevice->list); ++ kfree(sasDevice); ++ ioc->alloc_total -= sizeof (sas_device_info_t); ++ break; ++ } ++ } ++ break; ++ ++ case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: ++ case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED: ++ case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED: ++ default: ++ break; ++ } ++ ++ ++} ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* ++ * mptbase_sas_persist_operation - Perform operation on SAS Persitent Table ++ * @ioc: Pointer to MPT_ADAPTER structure ++ * @sas_address: 64bit SAS Address for operation. ++ * @target_id: specified target for operation ++ * @bus: specified bus for operation ++ * @persist_opcode: see below ++ * ++ * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for ++ * devices not currently present. ++ * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings ++ * ++ * NOTE: Don't use not this function during interrupt time. ++ * ++ * Returns: 0 for success, non-zero error ++ */ ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++int ++mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode) ++{ ++ SasIoUnitControlRequest_t *sasIoUnitCntrReq; ++ SasIoUnitControlReply_t *sasIoUnitCntrReply; ++ MPT_FRAME_HDR *mf = NULL; ++ MPIHeader_t *mpi_hdr; ++ ++ ++ /* insure garbage is not sent to fw */ ++ switch(persist_opcode) { ++ ++ case MPI_SAS_OP_CLEAR_NOT_PRESENT: ++ case MPI_SAS_OP_CLEAR_ALL_PERSISTENT: ++ break; + + default: + return -1; +@@ -4992,7 +5192,7 @@ mptbase_sas_persist_operation(MPT_ADAPTE + dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n", + ioc->name,__FUNCTION__)); + return -1; +- } ++ } + + mpi_hdr = (MPIHeader_t *) mf; + sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf; +@@ -5303,7 +5503,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc + + if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) { + ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS; +- ddvprintk((KERN_INFO MYNAM ": %s noQas due to Capabilities=%x\n", ++ ddvprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n", + ioc->name, pPP0->Capabilities)); + } + ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0; +@@ -5452,188 +5652,6 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTE + return 0; + } + +-/** +- * mpt_raid_phys_disk_pg0 - returns phys disk page zero +- * @ioc: Pointer to a Adapter Structure +- * @phys_disk_num: io unit unique phys disk num generated by the ioc +- * @phys_disk: requested payload data returned +- * +- * Return: +- * 0 on success +- * -EFAULT if read of config page header fails or data pointer not NULL +- * -ENOMEM if pci_alloc failed +- **/ +-int +-mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk) +-{ +- CONFIGPARMS cfg; +- ConfigPageHeader_t hdr; +- dma_addr_t dma_handle; +- pRaidPhysDiskPage0_t buffer = NULL; +- int rc; +- +- memset(&cfg, 0 , sizeof(CONFIGPARMS)); +- memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); +- +- hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK; +- cfg.cfghdr.hdr = &hdr; +- cfg.physAddr = -1; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- +- if (mpt_config(ioc, &cfg) != 0) { +- rc = -EFAULT; +- goto out; +- } +- +- if (!hdr.PageLength) { +- rc = -EFAULT; +- goto out; +- } +- +- buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, +- &dma_handle); +- +- if (!buffer) { +- rc = -ENOMEM; +- goto out; +- } +- +- cfg.physAddr = dma_handle; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- cfg.pageAddr = phys_disk_num; +- +- if (mpt_config(ioc, &cfg) != 0) { +- rc = -EFAULT; +- goto out; +- } +- +- rc = 0; +- memcpy(phys_disk, buffer, sizeof(*buffer)); +- phys_disk->MaxLBA = le32_to_cpu(buffer->MaxLBA); +- +- out: +- +- if (buffer) +- pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, +- dma_handle); +- +- return rc; +-} +- +-/** +- * 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) +-{ +- struct inactive_raid_component_info *component_info, *pNext; +- +- if (list_empty(&ioc->raid_data.inactive_list)) +- return; +- +- down(&ioc->raid_data.inactive_list_mutex); +- list_for_each_entry_safe(component_info, pNext, +- &ioc->raid_data.inactive_list, list) { +- list_del(&component_info->list); +- kfree(component_info); +- } +- up(&ioc->raid_data.inactive_list_mutex); +-} +- +-/** +- * 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 +- * +- * +- **/ +-static void +-mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id) +-{ +- CONFIGPARMS cfg; +- ConfigPageHeader_t hdr; +- dma_addr_t dma_handle; +- pRaidVolumePage0_t buffer = NULL; +- int i; +- RaidPhysDiskPage0_t phys_disk; +- struct inactive_raid_component_info *component_info; +- int handle_inactive_volumes; +- +- memset(&cfg, 0 , sizeof(CONFIGPARMS)); +- memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); +- hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME; +- cfg.pageAddr = (channel << 8) + id; +- cfg.cfghdr.hdr = &hdr; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- +- if (mpt_config(ioc, &cfg) != 0) +- goto out; +- +- if (!hdr.PageLength) +- goto out; +- +- buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, +- &dma_handle); +- +- if (!buffer) +- goto out; +- +- cfg.physAddr = dma_handle; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- +- if (mpt_config(ioc, &cfg) != 0) +- goto out; +- +- if (!buffer->NumPhysDisks) +- goto out; +- +- handle_inactive_volumes = +- (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE || +- (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED) == 0 || +- buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_FAILED || +- buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_MISSING) ? 1 : 0; +- +- if (!handle_inactive_volumes) +- goto out; +- +- down(&ioc->raid_data.inactive_list_mutex); +- for (i = 0; i < buffer->NumPhysDisks; i++) { +- if(mpt_raid_phys_disk_pg0(ioc, +- buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0) +- continue; +- +- if ((component_info = kmalloc(sizeof (*component_info), +- GFP_KERNEL)) == NULL) +- continue; +- +- component_info->volumeID = id; +- component_info->volumeBus = channel; +- component_info->d.PhysDiskNum = phys_disk.PhysDiskNum; +- component_info->d.PhysDiskBus = phys_disk.PhysDiskBus; +- component_info->d.PhysDiskID = phys_disk.PhysDiskID; +- component_info->d.PhysDiskIOC = phys_disk.PhysDiskIOC; +- +- list_add_tail(&component_info->list, +- &ioc->raid_data.inactive_list); +- } +- up(&ioc->raid_data.inactive_list_mutex); +- +- out: +- if (buffer) +- pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, +- dma_handle); +-} +- +- + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + /** + * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes +@@ -5657,16 +5675,8 @@ mpt_findImVolumes(MPT_ADAPTER *ioc) + int jj; + int rc = 0; + int iocpage2sz; +- +- if (!ioc->ir_firmware) +- return 0; +- +- /* Free the old page +- */ +- kfree(ioc->raid_data.pIocPg2); +- ioc->raid_data.pIocPg2 = NULL; +- mpt_inactive_raid_list_free(ioc); +- ioc->raid_data.isRaid = 0; ++ u8 nVols, nPhys; ++ u8 vid, vbus, vioc; + + /* Read IOCP2 header then the page. + */ +@@ -5696,35 +5706,53 @@ mpt_findImVolumes(MPT_ADAPTER *ioc) + if (mpt_config(ioc, &cfg) != 0) + goto done_and_free; + +- mem = kmalloc(iocpage2sz, GFP_ATOMIC); +- if (!mem) +- goto done_and_free; +- ++ if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) { ++ mem = kmalloc(iocpage2sz, GFP_ATOMIC); ++ if (mem) { ++ ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem; ++ } else { ++ goto done_and_free; ++ } ++ } + memcpy(mem, (u8 *)pIoc2, iocpage2sz); +- ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem; + + /* Identify RAID Volume Id's */ +- if (pIoc2->NumActiveVolumes) { +- +- pIocRv = pIoc2->RaidVolume; +- /* +- * WARNING - ioc->raid_data.isRaid +- * doesn't consider channels ++ nVols = pIoc2->NumActiveVolumes; ++ if ( nVols == 0) { ++ /* No RAID Volume. + */ +- for (jj = 0; jj < pIoc2->NumActiveVolumes; jj++, pIocRv++) { +- if (pIocRv->VolumeBus) +- continue; +- ioc->raid_data.isRaid |= (1 << pIocRv->VolumeID); +- mpt_inactive_raid_volumes(ioc, +- pIoc2->RaidVolume[jj].VolumeBus, +- pIoc2->RaidVolume[jj].VolumeID); ++ goto done_and_free; ++ } else { ++ /* At least 1 RAID Volume ++ */ ++ pIocRv = pIoc2->RaidVolume; ++ ioc->raid_data.isRaid = 0; ++ for (jj = 0; jj < nVols; jj++, pIocRv++) { ++ vid = pIocRv->VolumeID; ++ vbus = pIocRv->VolumeBus; ++ vioc = pIocRv->VolumeIOC; ++ ++ /* find the match ++ */ ++ if (vbus == 0) { ++ ioc->raid_data.isRaid |= (1 << vid); ++ } else { ++ /* Error! Always bus 0 ++ */ ++ } + } +- mpt_read_ioc_pg_3(ioc); +- mpt_read_ioc_pg_6(ioc); +- } ++ } + ++ /* Identify Hidden Physical Disk Id's */ ++ nPhys = pIoc2->NumActivePhysDisks; ++ if (nPhys == 0) { ++ /* No physical disks. ++ */ ++ } else { ++ mpt_read_ioc_pg_3(ioc); ++ } + +- done_and_free: ++done_and_free: + pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma); + + return rc; +@@ -5845,65 +5873,6 @@ mpt_read_ioc_pg_4(MPT_ADAPTER *ioc) + } + + static void +-mpt_read_ioc_pg_6(MPT_ADAPTER *ioc) +-{ +- IOCPage6_t *pIoc6; +- u8 *mem; +- CONFIGPARMS cfg; +- ConfigPageHeader_t header; +- dma_addr_t ioc6_dma; +- int iocpage6sz = 0; +- +- /* Free the old page +- */ +- if (ioc->raid_data.pIocPg6) { +- kfree(ioc->raid_data.pIocPg6); +- ioc->raid_data.pIocPg6 = NULL; +- } +- +- /* There is at least one physical disk. +- * Read and save IOC Page 3 +- */ +- header.PageVersion = 0; +- header.PageLength = 0; +- header.PageNumber = 6; +- header.PageType = MPI_CONFIG_PAGETYPE_IOC; +- cfg.cfghdr.hdr = &header; +- cfg.physAddr = -1; +- cfg.pageAddr = 0; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.dir = 0; +- cfg.timeout = 0; +- if (mpt_config(ioc, &cfg) != 0) +- return; +- +- if (header.PageLength == 0) +- return; +- +- /* Read Header good, alloc memory +- */ +- iocpage6sz = header.PageLength * 4; +- pIoc6 = pci_alloc_consistent(ioc->pcidev, iocpage6sz, &ioc6_dma); +- if (!pIoc6) +- return; +- +- /* Read the Page and save the data +- * into malloc'd memory. +- */ +- cfg.physAddr = ioc6_dma; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- if (mpt_config(ioc, &cfg) == 0) { +- mem = kmalloc(iocpage6sz, GFP_ATOMIC); +- if (mem) { +- memcpy(mem, (u8 *)pIoc6, iocpage6sz); +- ioc->raid_data.pIocPg6 = (IOCPage6_t *) mem; +- } +- } +- +- pci_free_consistent(ioc->pcidev, iocpage6sz, pIoc6, ioc6_dma); +-} +- +-static void + mpt_read_ioc_pg_1(MPT_ADAPTER *ioc) + { + IOCPage1_t *pIoc1; +@@ -6007,12 +5976,13 @@ SendEventNotification(MPT_ADAPTER *ioc, + ioc->name,__FUNCTION__)); + return 0; + } +- ioc->evnp = evnp; +- memset(evnp, 0, sizeof(*evnp)); ++ memset(evnp, 0, sizeof(*evnp)); + + devtprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp)); + + evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION; ++ evnp->ChainOffset = 0; ++ evnp->MsgFlags = 0; + evnp->Switch = EvSwitch; + + mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp); +@@ -6037,10 +6007,13 @@ SendEventAck(MPT_ADAPTER *ioc, EventNoti + return -1; + } + +- devtprintk((MYIOC_s_INFO__FMT "Sending EventAck\n", ioc->name)); +- memset(pAck, 0, sizeof(*pAck)); ++ devtprintk((MYIOC_s_WARN_FMT "Sending EventAck\n", ioc->name)); + + pAck->Function = MPI_FUNCTION_EVENT_ACK; ++ pAck->ChainOffset = 0; ++ pAck->Reserved[0] = pAck->Reserved[1] = 0; ++ pAck->MsgFlags = 0; ++ pAck->Reserved1[0] = pAck->Reserved1[1] = pAck->Reserved1[2] = 0; + pAck->Event = evnp->Event; + pAck->EventContext = evnp->EventContext; + DBG_DUMP_EVENT_REQUEST_FRAME(pAck); +@@ -6080,7 +6053,7 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS + */ + in_isr = in_interrupt(); + if (in_isr) { +- dfailprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n", ++ dcprintk((MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n", + ioc->name)); + return -EPERM; + } +@@ -6607,12 +6580,11 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, i + * mpt_do_ioc_recovery at any instant in time. + */ + spin_lock_irqsave(&ioc->diagLock, flags); +- if (ioc->IOCResetInProgress){ ++ if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){ + spin_unlock_irqrestore(&ioc->diagLock, flags); +- dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler: IOCResetInProgress!\n", +- ioc->name)); +- +- return 0; ++ return 0; ++ } else { ++ ioc->diagPending = 1; + } + spin_unlock_irqrestore(&ioc->diagLock, flags); + +@@ -6633,6 +6605,11 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, i + dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n", + ioc->name, ii)); + r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_SETUP_RESET); ++ if (ioc->alt_ioc) { ++ dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n", ++ ioc->name, ioc->alt_ioc->name, ii)); ++ r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_SETUP_RESET); ++ } + } + } + } +@@ -6642,307 +6619,23 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, i + rc, ioc->name); + } + ioc->reload_fw = 0; ++ if (ioc->alt_ioc) ++ ioc->alt_ioc->reload_fw = 0; + +- if (ioc->alt_ioc) { +- dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler alt_ioc: checking IOCResetInProgress=%d\n", +- ioc->alt_ioc->name, ioc->alt_ioc->IOCResetInProgress)); +- spin_lock_irqsave(&ioc->alt_ioc->diagLock, flags); +- +-if (ioc->alt_ioc->IOCResetInProgress) { +- dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler: alt_ioc IOCResetInProgress!\n", ioc->alt_ioc->name)); +- +-spin_unlock_irqrestore(&ioc->alt_ioc->diagLock, flags); +-return 0; +-} +-spin_unlock_irqrestore(&ioc->alt_ioc->diagLock, flags); +-if ((rc = mpt_do_ioc_recovery(ioc->alt_ioc, MPT_HOSTEVENT_IOC_RECOVER, +-sleepFlag)) != 0) { +-printk(KERN_WARNING MYNAM ": WARNING - alt_%s mpt_do_ioc_recovery failed rc=%x\n", ioc->name, rc ); +- } +-ioc->alt_ioc->reload_fw = 0; +-} +- ++ spin_lock_irqsave(&ioc->diagLock, flags); ++ ioc->diagPending = 0; ++ if (ioc->alt_ioc) ++ ioc->alt_ioc->diagPending = 0; ++ spin_unlock_irqrestore(&ioc->diagLock, flags); + + dtmprintk((MYIOC_s_INFO_FMT "HardResetHandler rc = %d!\n", ioc->name, rc)); + + return rc; + } + +-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +-/* mpt_writeSDP1 - write SCSI Device Page 1 +- * @ioc: Pointer to a SCSI Host Adapter Structure +- * @portnum: IOC port number +- * @id: writeSDP1 for single ID +- * @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO +- * +- * Return: -EFAULT if read of config page header fails +- * or 0 if success. +- * +- * Remark: If a target has been found, the settings from the +- * target structure are used, else the device is set +- * to async/narrow. +- * +- * Remark: Called during init and after a FW reload. +- * Remark: We do not wait for a return, write pages sequentially. +- */ +-int +-mpt_writeSDP1(MPT_ADAPTER *ioc, int portnum, int id, int flags) +-{ +- Config_t *pReq; +- SCSIDevicePage1_t *pData; +- struct _MPT_DEVICE *pMptTarget; +- VirtDevice *pTarget; +- MPT_FRAME_HDR *mf; +- dma_addr_t dataDma; +- u16 req_idx; +- u32 frameOffset; +- u32 requested, configuration, flagsLength; +- int ii, nvram; +- int loop_id, loop_end; +- u8 width; +- u8 factor; +- u8 offset; +- u8 bus = 0; +- u8 negoFlags; +- u8 maxwidth, maxoffset, maxfactor; +- +- if ((pMptTarget = ioc->Target_List[0]) == NULL) +- return 0; +- +- if (ioc->spi_data.sdp1length == 0) +- return 0; +- +- if (flags & MPT_SCSICFG_ALL_IDS) { +- loop_id = 0; +- loop_end = ioc->DevicesPerBus; +- } else { +- loop_id = id; +- loop_end = id+1; +- } +- +- for (; loop_id < loop_end; loop_id++) { +- +- if (loop_id == ioc->pfacts[portnum].PortSCSIID) +- continue; +- +- +- pTarget = pMptTarget->Target[loop_id]; +- +- /* Use NVRAM to get adapter and target maximums +- * Data over-riden by target structure information, if present +- */ +- maxwidth = ioc->spi_data.maxBusWidth; +- maxoffset = ioc->spi_data.maxSyncOffset; +- maxfactor = ioc->spi_data.minSyncFactor; +- if (ioc->spi_data.nvram && (ioc->spi_data.nvram[loop_id] != MPT_HOST_NVRAM_INVALID)) { +- nvram = ioc->spi_data.nvram[loop_id]; +- +- if (maxwidth) +- maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; +- +- if (maxoffset > 0) { +- maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8; +- if (maxfactor == 0) { +- /* Key for async */ +- maxfactor = MPT_ASYNC; +- maxoffset = 0; +- } else if (maxfactor < ioc->spi_data.minSyncFactor) { +- maxfactor = ioc->spi_data.minSyncFactor; +- } +- } else +- maxfactor = MPT_ASYNC; +- } +- +- /* Set the negotiation flags. +- */ +- negoFlags = ioc->spi_data.noQas; +- if (!maxwidth) +- negoFlags |= MPT_TARGET_NO_NEGO_WIDE; +- +- if (!maxoffset) +- negoFlags |= MPT_TARGET_NO_NEGO_SYNC; +- +- if (flags & MPT_SCSICFG_USE_NVRAM) { +- width = maxwidth; +- factor = maxfactor; +- offset = maxoffset; +- dnegoprintk(("%s: writeSDP1: USE_NVRAM id=%d width=%d factor=%x offset=%x negoFlags=%x\n", +- ioc->name, loop_id, width, factor, offset, negoFlags)); +- } else { +- width = 0; +- factor = MPT_ASYNC; +- offset = 0; +- //negoFlags = 0; +- //negoFlags = MPT_TARGET_NO_NEGO_SYNC; +- dnegoprintk(("%s: writeSDP1: !USE_NVRAM: Going Async/Narrow id=%d width=%d factor=%x offset=%x negoFlags=%x\n", +- ioc->name, loop_id, width, factor, offset, negoFlags)); +- } +- +- /* If id is not a raid volume, get the updated +- * transmission settings from the target structure. +- */ +- if ( pTarget && !pTarget->raidVolume) { +- width = pTarget->maxWidth; +- factor = pTarget->minSyncFactor; +- offset = pTarget->maxOffset; +- negoFlags |= pTarget->negoFlags; +- dnegoprintk(("%s: writeSDP1: NOT RAID id=%d width=%d factor=%x offset=%x negoFlags=%x\n", +- ioc->name, loop_id, width, factor, offset, negoFlags)); +- } +- +-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION +- /* Force to async and narrow if DV has not been executed +- * for this ID +- */ +- if ((ioc->spi_data.dvStatus[loop_id] & MPT_SCSICFG_DV_NOT_DONE) != 0) { +- width = 0; +- factor = MPT_ASYNC; +- offset = 0; +- dnegoprintk(("%s: writeSDP1: DV_NOT_DONE: Going Async/Narrow id=%d width=%d factor=%x offset=%x negoFlags=%x\n", +- ioc->name, loop_id, width, factor, offset, negoFlags)); +- } +-#endif +- +- if (flags & MPT_SCSICFG_BLK_NEGO) { +- negoFlags |= MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC; +- dnegoprintk(("%s: writeSDP1: BLK_NEGO id=%d width=%d factor=%x offset=%x negoFlags=%x\n", +- ioc->name, loop_id, width, factor, offset, negoFlags)); +- } +- +- mpt_setSDP1parameters(width, factor, offset, negoFlags, +- &requested, &configuration); +- +- /* Get a MF for this command. +- */ +- if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) { +- dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n", +- ioc->name,__FUNCTION__)); +- return -EAGAIN; +- } +- +- /* Set the request and the data pointers. +- * Request takes: 36 bytes (32 bit SGE) +- * SCSI Device Page 1 requires 16 bytes +- * 40 + 16 <= size of SCSI IO Request = 56 bytes +- * and MF size >= 64 bytes. +- * Place data at end of MF. +- */ +- pReq = (Config_t *)mf; +- +- req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); +- frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t); +- +- pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset); +- dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset; +- +- /* Complete the request frame (same for all requests). +- */ +- pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; +- pReq->Reserved = 0; +- pReq->ChainOffset = 0; +- pReq->Function = MPI_FUNCTION_CONFIG; +- pReq->ExtPageLength = 0; +- pReq->ExtPageType = 0; +- pReq->MsgFlags = 0; +- for (ii=0; ii < 8; ii++) { +- pReq->Reserved2[ii] = 0; +- } +- pReq->Header.PageVersion = ioc->spi_data.sdp1version; +- pReq->Header.PageLength = ioc->spi_data.sdp1length; +- pReq->Header.PageNumber = 1; +- pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; +- pReq->PageAddress = cpu_to_le32(loop_id | (bus << 8 )); +- +- /* Add a SGE to the config request. +- */ +- flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4; +- +- mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma); +- +- /* Set up the common data portion +- */ +- pData->Header.PageVersion = pReq->Header.PageVersion; +- pData->Header.PageLength = pReq->Header.PageLength; +- pData->Header.PageNumber = pReq->Header.PageNumber; +- pData->Header.PageType = pReq->Header.PageType; +- pData->RequestedParameters = cpu_to_le32(requested); +- pData->Reserved = 0; +- pData->Configuration = cpu_to_le32(configuration); +- +- if ( pTarget ) { +- if ( requested & MPI_SCSIDEVPAGE1_RP_IU ) { +- pTarget->last_lun = MPT_LAST_LUN; +- } else { +- pTarget->last_lun = MPT_NON_IU_LAST_LUN; +- } +- dsprintk((MYIOC_s_INFO_FMT +- "writeSDP1: last_lun=%d on id=%d\n", +- ioc->name, pTarget->last_lun, loop_id)); +- } +- +- dnegoprintk((MYIOC_s_INFO_FMT +- "write SDP1: id=%d pgaddr=0x%x requested=%08x configuration=%08x\n", +- ioc->name, loop_id, (loop_id | (bus<<8)), +- requested, configuration)); +- +- mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); +- } +- return 0; +-} +- +-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +-/* mpt_setSDP1parameters - set SDP1 Requested and Configuration +- * fields based on width, factor, offset and flags parameters. +- * @width: bus width +- * @factor: sync factor +- * @offset: sync offset +- * @flags: flags to block WDTR or SDTR negotiation +- * @requestedPtr: pointer to SDP1 Requested value (updated) +- * @configurationPtr: pointer to SDP1 Configuration value (updated) +- * +- * Return: None. +- * +- * Remark: Called by writeSDP1 and _dv_params +- */ +-void +-mpt_setSDP1parameters (u8 width, u8 factor, u8 offset, u8 flags, int *requestedPtr, int *configurationPtr) +-{ +- u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE; +- u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC; +- +- *configurationPtr = 0; +- *requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0; +- *requestedPtr |= (offset << 16) | (factor << 8); +- +- if (width && offset && !nowide && !nosync) { +- if (factor < MPT_ULTRA160) { +- *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT); +- if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0) +- *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS; +- if (flags & MPT_TAPE_NEGO_IDP) +- *requestedPtr |= 0x08000000; +- } else if (factor < MPT_ULTRA2) { +- *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT; +- } +- } +- +- if (nowide) +- *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED; +- +- if (nosync) +- *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED; +- +- return; +-} +- + # define EVENT_DESCR_STR_SZ 100 + + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +- +- +- +- +- + static void + EventDescriptionStr(u8 event, u32 evData0, char *evStr) + { +@@ -6969,6 +6662,9 @@ EventDescriptionStr(u8 event, u32 evData + break; + case MPI_EVENT_RESCAN: + ds = "Bus Rescan Event"; ++ /* Ok, do we need to do anything here? As far as ++ I can tell, this is when a new device gets added ++ to the loop. */ + break; + case MPI_EVENT_LINK_STATUS_CHANGE: + if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE) +@@ -6980,9 +6676,9 @@ EventDescriptionStr(u8 event, u32 evData + if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP) + ds = "Loop State(LIP) Change"; + else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE) +- ds = "Loop State(LPE) Change"; /* ??? */ ++ ds = "Loop State(LPE) Change"; /* ??? */ + else +- ds = "Loop State(LPB) Change"; /* ??? */ ++ ds = "Loop State(LPB) Change"; /* ??? */ + break; + case MPI_EVENT_LOGOUT: + ds = "Logout"; +@@ -6995,6 +6691,9 @@ EventDescriptionStr(u8 event, u32 evData + break; + case MPI_EVENT_INTEGRATED_RAID: + { ++#if defined(CPQ_CIM) ++ ioc->csmi_change_count++; ++#endif + u8 ReasonCode = (u8)(evData0 >> 16); + switch (ReasonCode) { + case MPI_EVENT_RAID_RC_VOLUME_CREATED : +@@ -7044,65 +6743,36 @@ EventDescriptionStr(u8 event, u32 evData + break; + case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: + { +- u8 id = (u8)(evData0); +- u8 channel = (u8)(evData0 >> 8); ++ u8 id = (u8)(evData0); + u8 ReasonCode = (u8)(evData0 >> 16); + switch (ReasonCode) { + case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: + snprintf(evStr, EVENT_DESCR_STR_SZ, +- "SAS Device Status Change: Added: " +- "id=%d channel=%d", id, channel); ++ "SAS Device Status Change: Added: id=%d", id); + break; + case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: + snprintf(evStr, EVENT_DESCR_STR_SZ, +- "SAS Device Status Change: Deleted: " +- "id=%d channel=%d", id, channel); ++ "SAS Device Status Change: Deleted: id=%d", id); + break; + case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: + snprintf(evStr, EVENT_DESCR_STR_SZ, +- "SAS Device Status Change: SMART Data: " +- "id=%d channel=%d", id, channel); ++ "SAS Device Status Change: SMART Data: id=%d", ++ id); + break; + case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED: + snprintf(evStr, EVENT_DESCR_STR_SZ, +- "SAS Device Status Change: No Persistancy: " +- "id=%d channel=%d", id, channel); +- break; +- case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED: +- snprintf(evStr, EVENT_DESCR_STR_SZ, +- "SAS Device Status Change: Unsupported Device " +- "Discovered : id=%d channel=%d", id, channel); +- break; +- case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: +- snprintf(evStr, EVENT_DESCR_STR_SZ, +- "SAS Device Status Change: Internal Device " +- "Reset : id=%d channel=%d", id, channel); +- break; +- case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL: +- snprintf(evStr, EVENT_DESCR_STR_SZ, +- "SAS Device Status Change: Internal Task " +- "Abort : id=%d channel=%d", id, channel); +- break; +- case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL: +- snprintf(evStr, EVENT_DESCR_STR_SZ, +- "SAS Device Status Change: Internal Abort " +- "Task Set : id=%d channel=%d", id, channel); +- break; +- case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL: +- snprintf(evStr, EVENT_DESCR_STR_SZ, +- "SAS Device Status Change: Internal Clear " +- "Task Set : id=%d channel=%d", id, channel); +- break; +- case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL: +- snprintf(evStr, EVENT_DESCR_STR_SZ, +- "SAS Device Status Change: Internal Query " +- "Task : id=%d channel=%d", id, channel); ++ "SAS Device Status Change: No Persistancy " ++ "Added: id=%d", id); + break; ++ case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: ++ snprintf(evStr, EVENT_DESCR_STR_SZ, ++ "SAS Device Status Change: Internal Device Reset: " ++ "id=%d", id); ++ break; + default: + snprintf(evStr, EVENT_DESCR_STR_SZ, +- "SAS Device Status Change: Unknown: " +- "id=%d channel=%d", id, channel); +- break; ++ "SAS Device Status Change: Unknown: id=%d", id); ++ break; + } + break; + } +@@ -7205,86 +6875,15 @@ EventDescriptionStr(u8 event, u32 evData + } + case MPI_EVENT_SAS_DISCOVERY: + { +- if (evData0) +- ds = "SAS Discovery: Start"; +- else +- ds = "SAS Discovery: Stop"; ++ char buf[40]; ++ sprintf(buf,"SAS Discovery: Condition=0x%x:",evData0); ++ ds = buf; + break; + } + case MPI_EVENT_LOG_ENTRY_ADDED: + ds = "SAS Log Entry Added"; + break; + +- case MPI_EVENT_SAS_BROADCAST_PRIMITIVE: +- { +- u8 phy_num = (u8)(evData0); +- u8 port_num = (u8)(evData0 >> 8); +- u8 port_width = (u8)(evData0 >> 16); +- u8 primative = (u8)(evData0 >> 24); +- snprintf(evStr, EVENT_DESCR_STR_SZ, +- "SAS Broadcase Primative: phy=%d port=%d " +- "width=%d primative=0x%02x", +- phy_num, port_num, port_width, primative); +- break; +- } +- +- case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE: +- { +- u8 reason = (u8)(evData0); +- u8 port_num = (u8)(evData0 >> 8); +- u16 handle = le16_to_cpu(evData0 >> 16); +- +- snprintf(evStr, EVENT_DESCR_STR_SZ, +- "SAS Initiator Device Status Change: reason=0x%02x " +- "port=%d handle=0x%04x", +- reason, port_num, handle); +- break; +- } +- +- case MPI_EVENT_SAS_INIT_TABLE_OVERFLOW: +- { +- u8 max_init = (u8)(evData0); +- u8 current_init = (u8)(evData0 >> 8); +- +- snprintf(evStr, EVENT_DESCR_STR_SZ, +- "SAS Initiator Device Table Overflow: max initiators=%02d " +- "current initators=%02d", +- max_init, current_init); +- break; +- } +- case MPI_EVENT_SAS_SMP_ERROR: +- { +- u8 status = (u8)(evData0); +- u8 port_num = (u8)(evData0 >> 8); +- u8 result = (u8)(evData0 >> 16); +- +- if (status == MPI_EVENT_SAS_SMP_FUNCTION_RESULT_VALID) +- snprintf(evStr, EVENT_DESCR_STR_SZ, +- "SAS SMP Error: port=%d result=0x%02x", +- port_num, result); +- else if (status == MPI_EVENT_SAS_SMP_CRC_ERROR) +- snprintf(evStr, EVENT_DESCR_STR_SZ, +- "SAS SMP Error: port=%d : CRC Error", +- port_num); +- else if (status == MPI_EVENT_SAS_SMP_TIMEOUT) +- snprintf(evStr, EVENT_DESCR_STR_SZ, +- "SAS SMP Error: port=%d : Timeout", +- port_num); +- else if (status == MPI_EVENT_SAS_SMP_NO_DESTINATION) +- snprintf(evStr, EVENT_DESCR_STR_SZ, +- "SAS SMP Error: port=%d : No Destination", +- port_num); +- else if (status == MPI_EVENT_SAS_SMP_BAD_DESTINATION) +- snprintf(evStr, EVENT_DESCR_STR_SZ, +- "SAS SMP Error: port=%d : Bad Destination", +- port_num); +- else +- snprintf(evStr, EVENT_DESCR_STR_SZ, +- "SAS SMP Error: port=%d : status=0x%02x", +- port_num, status); +- break; +- } +- + /* + * MPT base "custom" events may be added here... + */ +@@ -7329,20 +6928,24 @@ ProcessEventNotification(MPT_ADAPTER *io + } + + EventDescriptionStr(event, evData0, evStr); +- devtprintk((MYIOC_s_WARN_FMT "MPT event:(%02Xh) : %s\n", +- ioc->name, event, evStr)); ++ devtprintk((MYIOC_s_WARN_FMT "MPT Event=%02Xh (%s) detected!\n", ++ ioc->name, event, evStr)); ++ + #if defined(MPT_DEBUG) || defined(MPT_DEBUG_EVENTS) +- printk(KERN_WARN MYNAM ": Event data:\n" KERN_INFO); +- for (ii = 0; ii < evDataLen; ii++) +- printk(" %08x", le32_to_cpu(pEventReply->Data[ii])); +- printk("\n"); ++ printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO); ++ for (ii = 0; ii < evDataLen; ii++) ++ printk(" %08x", le32_to_cpu(pEventReply->Data[ii])); ++ printk("\n"); + #endif + +- +- /* ++ /* + * Do general / base driver event processing + */ + switch(event) { ++ case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: /* 0F */ ++ mptbase_sas_process_event_data(ioc, ++ (MpiEventDataSasDeviceStatusChange_t *)pEventReply->Data); ++ break; + case MPI_EVENT_EVENT_CHANGE: /* 0A */ + if (evDataLen) { + u8 evState = evData0 & 0xFF; +@@ -7359,11 +6962,6 @@ ProcessEventNotification(MPT_ADAPTER *io + mptbase_raid_process_event_data(ioc, + (MpiEventDataRaid_t *)pEventReply->Data); + break; +-case MPI_EVENT_RESCAN: +-case MPI_EVENT_LINK_STATUS_CHANGE: +-ioc->FcLinkSpeedCheckNeeded = 1; +-break; +- + default: + break; + } +@@ -7396,10 +6994,9 @@ break; + */ + for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { + if (MptEvHandlers[ii]) { +- devtprintk((MYIOC_s_WARN_FMT "Routing Event to event handler #%d\n", +- ioc->name, ii)); +- +- r += (*(MptEvHandlers[ii]))(ioc, pEventReply); ++ devtprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n", ++ ioc->name, ii)); ++ r += (*(MptEvHandlers[ii]))(ioc, pEventReply); + handlers++; + } + } +@@ -7412,7 +7009,7 @@ break; + devtprintk((MYIOC_s_WARN_FMT + "EventAck required\n",ioc->name)); + if ((ii = SendEventAck(ioc, pEventReply)) != 0) { +- devtprintk((MYIOC_s_INFO_FMT "SendEventAck returned %d\n", ++ devtprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n", + ioc->name, ii)); + } + } +@@ -7599,14 +7196,20 @@ union loginfo_type { + } + + if (code_desc != NULL) +- printk("Originator={%s}, Code={%s}," ++ printk(MYIOC_s_INFO_FMT ++ "LogInfo(0x%08x): Originator={%s}, Code={%s}," + " SubCode(0x%04x)\n", ++ ioc->name, ++ log_info, + originator_str[sas_loginfo.dw.originator], + code_desc, + sas_loginfo.dw.subcode); + else +- printk("Originator={%s}, Code=(0x%02x)," ++ printk(MYIOC_s_INFO_FMT ++ "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x)," + " SubCode(0x%04x)\n", ++ ioc->name, ++ log_info, + originator_str[sas_loginfo.dw.originator], + sas_loginfo.dw.code, + sas_loginfo.dw.subcode); +@@ -7625,12 +7228,7 @@ static void + mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) + { + u32 status = ioc_status & MPI_IOCSTATUS_MASK; +- char *desc = NULL; +- +- SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf; +- U8 cdb = pScsiReq->CDB[0]; +- U8 id = pScsiReq->TargetID; +- U8 lun = pScsiReq->LUN[1]; ++ char *desc = ""; + + switch (status) { + case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */ +@@ -7639,8 +7237,6 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 io + + case MPI_IOCSTATUS_BUSY: /* 0x0002 */ + desc = "Busy"; +- ddvprintk (("%s IOCSTATUS_BUSY", ioc->name)); +- DBG_DUMP_RESET_REQUEST_FRAME(ioc, mf) + break; + + case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */ +@@ -7692,11 +7288,11 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 io + + case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ + { +-#ifdef MPT_DEBUG_REPLY ++ SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf; ++ U8 cdb = pScsiReq->CDB[0]; + if (cdb != 0x12) { /* Inquiry is issued for device scanning */ + desc = "SCSI Device Not There"; + } +-#endif + break; + } + +@@ -7742,16 +7338,8 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 io + desc = "Others"; + break; + } +- if (desc != NULL) { +- U8 function = pScsiReq->Function; +- if (function == MPI_FUNCTION_SCSI_IO_REQUEST || +- function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) { +- printk(MYIOC_s_WARN_FMT "IOCStatus(0x%04x): %s on CDB=%x id=%d lun=%d\n", ioc->name, status, desc, cdb, id, lun); +- } else { +- printk(MYIOC_s_WARN_FMT "IOCStatus(0x%04x): %s on Function=%02x\n", ioc->name, status, desc, function); +- } +- DBG_DUMP_REPLYS_REQUEST_FRAME(ioc, mf) +- } ++ if (desc != "") ++ printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04x): %s\n", ioc->name, status, desc); + } + + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +@@ -7770,6 +7358,7 @@ mpt_poll_interrupt(MPT_ADAPTER *ioc) + if (intstat & MPI_HIS_REPLY_MESSAGE_INTERRUPT) + mpt_interrupt(0, ioc, NULL); + } ++ + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + EXPORT_SYMBOL(mpt_attach); + EXPORT_SYMBOL(mpt_detach); +@@ -7779,6 +7368,7 @@ EXPORT_SYMBOL(mpt_suspend); + #endif + EXPORT_SYMBOL(ioc_list); + EXPORT_SYMBOL(mpt_can_queue); ++EXPORT_SYMBOL(mpt_sg_tablesize); + EXPORT_SYMBOL(mpt_proc_root_dir); + EXPORT_SYMBOL(mpt_register); + EXPORT_SYMBOL(mpt_deregister); +@@ -7800,21 +7390,16 @@ EXPORT_SYMBOL(mpt_print_ioc_summary); + EXPORT_SYMBOL(mpt_lan_index); + EXPORT_SYMBOL(mpt_stm_index); + EXPORT_SYMBOL(mpt_HardResetHandler); +-EXPORT_SYMBOL(mpt_SendIocReset); +-EXPORT_SYMBOL(mpt_do_ioc_recovery); +-EXPORT_SYMBOL(mpt_writeSDP1); +-EXPORT_SYMBOL(mpt_setSDP1parameters); + EXPORT_SYMBOL(mpt_config); + EXPORT_SYMBOL(mpt_findImVolumes); + EXPORT_SYMBOL(mpt_read_ioc_pg_3); + EXPORT_SYMBOL(mpt_alloc_fw_memory); + EXPORT_SYMBOL(mpt_free_fw_memory); + EXPORT_SYMBOL(mptbase_sas_persist_operation); ++EXPORT_SYMBOL(mpt_sas_get_info); + EXPORT_SYMBOL_GPL(mpt_poll_interrupt); + EXPORT_SYMBOL(mpt_alt_ioc_wait); +-EXPORT_SYMBOL(mpt_raid_phys_disk_pg0); +-EXPORT_SYMBOL(mpt_enable_deadioc_detect); +-EXPORT_SYMBOL(mpt_handshake_req_reply_wait); ++ + + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + /* +diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptbase.h linux-2.6.9-55.0.12/drivers/message/fusion/mptbase.h +--- linux-2.6.9-67.0.1/drivers/message/fusion/mptbase.h 2007-12-21 11:40:54.000000000 +0100 ++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptbase.h 2007-11-02 09:10:23.000000000 +0100 +@@ -5,8 +5,8 @@ + * LSIFC9xx/LSI409xx Fibre Channel + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * +- * Copyright (c) 1999-2007 LSI Logic Corporation +- * ( mpt_linux_developer@lsi.com) ++ * Copyright (c) 1999-2005 LSI Logic Corporation ++ * (mailto:mpt_linux_developer@lsil.com) + * + * $Id: mptbase.h,v 1.149 2003/05/07 14:08:31 Exp $ + */ +@@ -78,14 +78,14 @@ + #endif + + #ifndef COPYRIGHT +-#define COPYRIGHT "Copyright (c) 1999-2007 " MODULEAUTHOR ++#define COPYRIGHT "Copyright (c) 1999-2006 " MODULEAUTHOR + #endif + +-#define MPT_LINUX_VERSION_COMMON "3.02.99.00rh" +-#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.02.99.00rh" ++#define MPT_LINUX_VERSION_COMMON "3.02.73rh" ++#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.02.73rh" + #define MPT_LINUX_MAJOR_VERSION 3 + #define MPT_LINUX_MINOR_VERSION 02 +-#define MPT_LINUX_BUILD_VERSION 99 ++#define MPT_LINUX_BUILD_VERSION 73 + #define MPT_LINUX_RELEASE_VERSION 00 + #define WHAT_MAGIC_STRING "@" "(" "#" ")" + +@@ -96,8 +96,10 @@ + /* + * Fusion MPT(linux) driver configurable stuff... + */ ++#define MPT_MAX_ADAPTERS 18 + #define MPT_MAX_PROTOCOL_DRIVERS 16 +-#define MPT_MAX_BUSES 8 ++#define MPT_MAX_BUS 1 /* Do not change */ ++#define MPT_MAX_FC_DEVICES 255 + #define MPT_MAX_SCSI_DEVICES 16 + #define MPT_LAST_LUN 255 + #define MPT_NON_IU_LAST_LUN 63 +@@ -137,9 +139,6 @@ + #define CAN_SLEEP 1 + #define NO_SLEEP 0 + +-#define MPT_HZ 1000 +-#define MPT_JIFFY 100 +- + #define MPT_COALESCING_TIMEOUT 0x10 + + /* +@@ -170,9 +169,7 @@ + /* + * Default MAX_SGE value. Can be changed by using mptbase sg_count parameter. + */ +-#ifndef CONFIG_FUSION_MAX_SGE +-#define CONFIG_FUSION_MAX_SGE 128 +-#endif ++#define MPT_SCSI_SG_DEPTH 128 + + #ifdef __KERNEL__ /* { */ + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +@@ -218,6 +215,8 @@ typedef union _MPT_FRAME_TRACKER { + struct { + struct list_head list; + u32 arg1; ++ u32 pad; ++ void *argp1; + } linkage; + /* + * NOTE: When request frames are free, on the linkage structure +@@ -277,12 +276,6 @@ typedef struct _MPT_FRAME_HDR { + } u; + } MPT_FRAME_HDR; + +-typedef struct _MPT_LINKAGE { +- struct list_head list; +- MPT_FRAME_HDR *mf; +-} MPT_LINKAGE; +- +- + #define MPT_REQ_MSGFLAGS_DROPME 0x80 + + typedef struct _MPT_SGL_HDR { +@@ -336,31 +329,15 @@ typedef struct _SYSIF_REGS + #define MPT_TARGET_NO_NEGO_QAS 0x04 + #define MPT_TAPE_NEGO_IDP 0x08 + +-#if defined(CPQ_CIM) +-struct sas_mapping{ +- u8 id; +- u8 channel; +-}; +- +-struct sas_device_info { +- struct list_head list; +- struct sas_mapping os; /* operating system mapping*/ +- struct sas_mapping fw; /* firmware mapping */ +- u64 sas_address; +- u32 device_info; /* specific bits for devices */ +- u8 is_logical_volume; /* is this logical volume */ +- u8 is_cached; /* cached data for a removed device */ +-}; +-#endif +- + /* + * VirtDevice - FC LUN device or SCSI target device + */ + typedef struct _VirtDevice { +- struct _MPT_ADAPTER *ioc; ++ struct scsi_device *device; + u16 tflags; +- u8 id; +- u8 bus; ++ u8 ioc_id; ++ u8 target_id; ++ u8 bus_id; + u8 minSyncFactor; /* 0xFF is async */ + u8 maxOffset; /* 0 if async */ + u8 maxWidth; /* 0 if narrow, 1 if wide */ +@@ -385,13 +362,9 @@ typedef struct _VirtDevice { + u8 pad2[4]; + U64 WWPN; + U64 WWNN; +- struct work_struct dvTask; +- u8 configured_lun; ++ u8 configured_lun; + } VirtDevice; + +-typedef struct _MPT_DEVICE { +- VirtDevice *Target[0]; +-} MPT_DEVICE; + /* + * Fibre Channel (SCSI) target device and associated defines... + */ +@@ -440,6 +413,7 @@ do { \ + #define MPT_IOCTL_STATUS_SENSE_VALID 0x08 /* Sense data is valid */ + #define MPT_IOCTL_STATUS_COMMAND_GOOD 0x10 /* Command Status GOOD */ + #define MPT_IOCTL_STATUS_TMTIMER_ACTIVE 0x20 /* The TM timer is running */ ++#define MPT_IOCTL_STATUS_TM_FAILED 0x40 /* User TM request failed */ + + #define MPTCTL_RESET_OK 0x01 /* Issue Bus Reset */ + +@@ -448,10 +422,10 @@ typedef struct _MPT_IOCTL { + u8 ReplyFrame[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */ + u8 sense[MPT_SENSE_BUFFER_ALLOC]; + int wait_done; /* wake-up value for this ioc */ ++ u8 rsvd; + u8 status; /* current command status */ + u8 reset; /* 1 if bus reset allowed */ +- u8 bus; /* bus */ +- u8 id; /* id for reset */ ++ u8 target; /* target for reset */ + struct semaphore sem_ioc; + } MPT_IOCTL; + +@@ -462,7 +436,7 @@ typedef struct _MPT_IOCTL { + typedef struct _mpt_ioctl_events { + u32 event; /* Specified by define above */ + u32 eventContext; /* Index or counter */ +- u32 data[2]; /* First 8 bytes of Event Data */ ++ int data[2]; /* First 8 bytes of Event Data */ + } MPT_IOCTL_EVENTS; + + /* +@@ -477,14 +451,14 @@ typedef struct _mpt_ioctl_events { + /* dvStatus defines: */ + #define MPT_SCSICFG_NEGOTIATE 0x01 /* Negotiate on next IO */ + #define MPT_SCSICFG_NEED_DV 0x02 /* Schedule DV */ +-#define MPT_SCSICFG_DV_IN_PROGRESS 0x04 /* DV on this physical id*/ ++#define MPT_SCSICFG_DV_PENDING 0x04 /* DV on this physical id pending */ + #define MPT_SCSICFG_DV_NOT_DONE 0x08 /* DV has not been performed */ +-#define MPT_SCSICFG_PHYSDISK_DV_ONLY 0x10 /* DV only on this PhysDisk*/ +-#define MPT_SCSICFG_BLK_NEGO 0x20 /* WriteSDP1 with WDTR and SDTR disabled*/ +-#define MPT_SCSICFG_RELOAD_IOC_PG3 0x40 /* IOC Pg 3 data is obsolete */ ++#define MPT_SCSICFG_BLK_NEGO 0x10 /* WriteSDP1 with WDTR and SDTR disabled */ ++#define MPT_SCSICFG_RELOAD_IOC_PG3 0x20 /* IOC Pg 3 data is obsolete */ + /* Args passed to writeSDP1: */ + #define MPT_SCSICFG_USE_NVRAM 0x01 /* WriteSDP1 using NVRAM */ + #define MPT_SCSICFG_ALL_IDS 0x02 /* WriteSDP1 to all IDS */ ++/* #define MPT_SCSICFG_BLK_NEGO 0x10 WriteSDP1 with WDTR and SDTR disabled */ + + typedef struct _SpiCfgData { + u32 PortFlags; +@@ -520,36 +494,48 @@ typedef struct _SasCfgData { + * automatic clearing. + */ + u8 mpt_sas_hot_plug_enable; /* disables hot swap device remove support */ +- ManufacturingPage7_t *pManufPg7; /* Connector Info on SAS controllers */ + }SasCfgData; + +-/* +- * Inactive volume link list of raid component data +- * @inactive_list +- */ +-struct inactive_raid_component_info { +- struct list_head list; +- u8 volumeID; /* volume target id */ +- u8 volumeBus; /* volume channel */ +- IOC_3_PHYS_DISK d; /* phys disk info */ +-}; +- + typedef struct _RaidCfgData { + IOCPage2_t *pIocPg2; /* table of Raid Volumes */ + IOCPage3_t *pIocPg3; /* table of physical disks */ +- IOCPage6_t *pIocPg6; /* table of IR static data */ +- int isRaid; /* bit field, 1 if RAID */ +- struct semaphore inactive_list_mutex; +- struct list_head inactive_list; /* link list for physical +- disk that belong in +- inactive volumes */ ++ int isRaid; /* bit field, 1 if RAID */ + } RaidCfgData; + + /* +- * Adapter Structure - pci_dev specific. ++ * sas device info link list + */ ++typedef struct _sas_device_info { ++ struct list_head list; ++ u64 SASAddress; ++ u8 TargetId; ++ u8 Bus; ++ u8 PhysicalPort; ++ u8 PhyNum; ++ u32 DeviceInfo; ++ u16 DevHandle; ++ u16 Flags; ++} sas_device_info_t; ++ ++/* ++ * hba phy info array ++ */ ++typedef struct _sas_phy_info { ++ u64 SASAddress; ++ u8 port; ++ u8 PortFlags; ++ u8 PhyFlags; ++ u8 NegotiatedLinkRate; ++ u16 ControllerDevHandle; ++ u16 devHandle; ++ u32 ControllerPhyDeviceInfo; ++ u8 phyId; ++ u8 hwLinkRate; ++ u8 reserved; ++} sas_phy_info_t; ++ + /* +- * Adapter Structure - pci_dev specific. ++ * Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS + */ + typedef struct _MPT_ADAPTER + { +@@ -561,18 +547,13 @@ typedef struct _MPT_ADAPTER + SYSIF_REGS __iomem *pio_chip; /* Programmed IO (downloadboot) */ + u8 bus_type; /* Parallel SCSI i/f */ + u8 pci_slot_number; /* ioc page 1 - pci slot number */ +- u8 ir_firmware; /* =1 if IR firmware detected */ + u16 deviceID; + u32 mem_phys; /* == f4020000 (mmap) */ + u32 pio_mem_phys; /* Programmed IO (downloadboot) */ + int mem_size; /* mmap memory size */ +- int sg_tablesize; /* max SGE's per IO */ +- int NumberOfBuses; +- int DevicesPerBus; + int alloc_total; + u32 last_state; + int active; +- struct _MPT_DEVICE *Target_List[MPT_MAX_BUSES]; + u8 *alloc; /* frames alloc ptr */ + dma_addr_t alloc_dma; + u32 alloc_sz; +@@ -600,12 +581,7 @@ typedef struct _MPT_ADAPTER + int req_depth; /* Number of request frames */ + int req_sz; /* Request frame size (bytes) */ + spinlock_t FreeQlock; +- spinlock_t PendingMFlock; + struct list_head FreeQ; +- MPT_FRAME_HDR *PendingMF; +- struct scsi_cmnd *PendingSCpnt; +- struct timer_list TMtimer; /* Timer for TM commands ONLY */ +- MPT_FRAME_HDR *tmPtr; /* Ptr to TM request*/ + /* Pool of SCSI sense buffers for commands coming from + * the SCSI mid-layer. We have one 256 byte sense buffer + * for each REQ entry. +@@ -638,12 +614,10 @@ typedef struct _MPT_ADAPTER + struct _MPT_ADAPTER *alt_ioc; /* ptr to 929 bound adapter port */ + spinlock_t diagLock; /* diagnostic reset lock */ + int diagPending; +- int IOCResetInProgress; + u32 biosVersion; /* BIOS version from IO Unit Page 2 */ + int eventTypes; /* Event logging parameters */ + int eventContext; /* Next event context */ + struct _mpt_ioctl_events *events; /* pointer to event log */ +- EventNotification_t *evnp; /* event message frame pointer */ + u8 *cached_fw; /* Pointer to FW */ + dma_addr_t cached_fw_dma; + struct list_head configQ; /* linked list of config. requests */ +@@ -662,12 +636,10 @@ typedef struct _MPT_ADAPTER + /* emoore@lsil.com - sas support - start */ + U64 sas_port_WWID[4]; + u8 BoardTracerNumber[16]; ++ u8 numPhys; + u16 vendorID; +-#if defined(CPQ_CIM) +- struct list_head sas_device_info_list; +- struct semaphore sas_device_info_mutex; +- u32 num_ports; +-#endif ++ sas_phy_info_t *sasPhyInfo; ++ struct list_head sasDeviceList; + struct semaphore hot_plug_semaphore; + struct work_struct mptscsih_persistTask; + struct timer_list persist_timer; /* persist table timer */ +@@ -680,7 +652,7 @@ typedef struct _MPT_ADAPTER + u32 PciState[64]; /* save PCI state to this area */ + #endif + #if defined(CPQ_CIM) +- u32 csmi_change_count; /* count to track all IR events for CSMI */ ++ u32 csmi_change_count; /* count to track all IR events for CSMI */ + #endif + /* + * Description: errata_flag_1064 +@@ -694,11 +666,7 @@ typedef struct _MPT_ADAPTER + u8 upload_fw; /* If set, do a fw upload */ + u8 reload_fw; /* Force a FW Reload on next reset */ + u8 NBShiftFactor; /* NB Shift Factor based on Block Size (Facts) */ +- u8 pad1; +- u8 CheckFcLinkSpeed; +- u8 FcLinkSpeedCheckNeeded; +- u8 FcLinkSpeed; +- MPT_FRAME_HDR *FcLinkSpeedReqActive; ++ u8 pad1[4]; + int DoneCtx; + int TaskCtx; + int InternalCtx; +@@ -811,25 +779,6 @@ typedef struct _mpt_sge { + #define DBG_DUMP_EVENT_REQUEST_FRAME(mfp) + #endif + +-#ifdef MPT_DEBUG_PEND +-#define dpendprintk(x) printk x +-#define DBG_DUMP_PENDING_REQUEST_FRAME(ioc, mfp) \ +- { int i, n = ioc->req_sz/4; \ +- u32 *m = (u32 *)(mfp); \ +- for (i=0; i<n; i++) { \ +- if (i && ((i%8)==0)) \ +- printk("\n"); \ +- printk("%08x ", le32_to_cpu(m[i])); \ +- } \ +- printk("\n"); \ +- } +-#else +-#define dpendprintk(x) +-#define DBG_DUMP_PENDING_REQUEST_FRAME(ioc, mfp) +-#endif +- +- +- + #ifdef MPT_DEBUG_HOTPLUG + #define dhotpprintk(x) printk x + #else +@@ -838,51 +787,16 @@ typedef struct _mpt_sge { + + #ifdef MPT_DEBUG_RESET + #define drsprintk(x) printk x +-#define DBG_DUMP_RESET_REQUEST_FRAME(ioc, mfp) \ +- { int i, n = ioc->req_sz/4; \ +- u32 *m = (u32 *)(mfp); \ +- for (i=0; i<n; i++) { \ +- if (i && ((i%8)==0)) \ +- printk("\n"); \ +- printk("%08x ", le32_to_cpu(m[i])); \ +- } \ +- printk("\n"); \ +- } + #else + #define drsprintk(x) +-#define DBG_DUMP_RESET_REQUEST_FRAME(ioc, mfp) + #endif + + //#if defined(MPT_DEBUG) || defined(MPT_DEBUG_MSG_FRAME) + #if defined(MPT_DEBUG_MSG_FRAME) + #define dmfprintk(x) printk x +-#define DBG_DUMP_REQUEST_FRAME(ioc,mfp) \ +- { int i, n = ioc->req_sz/4; +- u32 *m = (u32 *)(mfp); \ +- for (i=0; i<n; i++) { \ +- if (i && ((i%8)==0)) \ +- printk("\n"); \ +- printk("%08x ", le32_to_cpu(m[i])); \ +- } \ +- printk("\n"); \ +- } +-#else +-#define dmfprintk(x) +-#define DBG_DUMP_REQUEST_FRAME(ioc,mfp) +-#endif +- +-#if defined(MPT_DEBUG_IOS) +-#define dioprintk(x) printk x +-#else +-#define dioprintk(x) +-#endif +- +- +-#if defined(MPT_DEBUG_CSMI) +-#define DBG_DUMP_CSMI_FRAME(mfp) \ ++#define DBG_DUMP_REQUEST_FRAME(mfp) \ + { int i, n = 24; \ + u32 *m = (u32 *)(mfp); \ +- printk("CSMI MessageFrame:\n"); \ + for (i=0; i<n; i++) { \ + if (i && ((i%8)==0)) \ + printk("\n"); \ +@@ -891,7 +805,8 @@ typedef struct _mpt_sge { + printk("\n"); \ + } + #else +-#define DBG_DUMP_CSMI_FRAME(mfp) ++#define dmfprintk(x) ++#define DBG_DUMP_REQUEST_FRAME(mfp) + #endif + + #ifdef MPT_DEBUG_SG +@@ -918,22 +833,28 @@ typedef struct _mpt_sge { + #define dnegoprintk(x) + #endif + ++#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY) ++#define ddvtprintk(x) printk x ++#else ++#define ddvtprintk(x) ++#endif ++ + #ifdef MPT_DEBUG_IOCTL + #define dctlprintk(x) printk x + #else + #define dctlprintk(x) + #endif + +-#ifdef MPT_DEBUG_SAS +-#define dsasprintk(x) printk x ++#ifdef MPT_DEBUG_REPLY ++#define dreplyprintk(x) printk x + #else +-#define dsasprintk(x) ++#define dreplyprintk(x) + #endif + +-#ifdef MPT_DEBUG_CSMISAS +-#define dcsmisasprintk(x) printk x ++#ifdef MPT_DEBUG_SAS ++#define dsasprintk(x) printk x + #else +-#define dcsmisasprintk(x) ++#define dsasprintk(x) + #endif + + #ifdef MPT_DEBUG_TM +@@ -988,8 +909,7 @@ typedef struct _mpt_sge { + #define MPT_INDEX_2_RFPTR(ioc,idx) \ + (MPT_FRAME_HDR*)( (u8*)(ioc)->reply_frames + (ioc)->req_sz * (idx) ) + +-#if defined(MPT_DEBUG_REPLY) || defined(MPT_DEBUG_MSG_FRAME) || defined(MPT_DEBUG_HANDSHAKE) +-#define dreplyprintk(x) printk x ++#if defined(MPT_DEBUG) || defined(MPT_DEBUG_MSG_FRAME) || defined(MPT_DEBUG_HANDSHAKE) + #define DBG_DUMP_REPLY_FRAME(mfp) \ + { u32 *m = (u32 *)(mfp); \ + int i, n = (le32_to_cpu(m[0]) & 0x00FF0000) >> 16; \ +@@ -1006,36 +926,9 @@ typedef struct _mpt_sge { + printk(" %08x", le32_to_cpu(m[i])); \ + printk("\n"); \ + } +-#define DBG_DUMP_REPLYS_REQUEST_FRAME(ioc,mfp) \ +- { int i, n = ioc->req_sz/4;; \ +- u32 *m = (u32 *)(mfp); \ +- for (i=0; i<n; i++) { \ +- if (i && ((i%8)==0)) \ +- printk("\n"); \ +- printk("%08x ", le32_to_cpu(m[i])); \ +- } \ +- printk("\n"); \ +- } +-#define DBG_DUMP_SENSE_DATA(mfp) \ +- { int i, n = 8; \ +- u32 *m = (u32 *)(mfp); \ +- printk(KERN_INFO "SENSE DATA: "); \ +- for (i=0; i<n; i++) \ +- printk(" %08x", le32_to_cpu(m[i])); \ +- printk("\n"); \ +- } + #else +-#define dreplyprintk(x) + #define DBG_DUMP_REPLY_FRAME(mfp) + #define DBG_DUMP_REQUEST_FRAME_HDR(mfp) +-#define DBG_DUMP_REPLYS_REQUEST_FRAME(ioc,mfp) +-#define DBG_DUMP_SENSE_DATA(mfp) +-#endif +- +-#if defined (MPT_DEBUG_ERROR) || defined(MPT_DEBUG_REPLY) +-#define derrprintk(x) printk x +-#else +-#define derrprintk(x) + #endif + + +@@ -1095,34 +988,32 @@ typedef struct _MPT_SCSI_HOST { + u32 pad0; + struct scsi_cmnd **ScsiLookup; + struct scsi_device *device; ++ VirtDevice **Targets; + MPT_LOCAL_REPLY *pLocal; /* used for internal commands */ +- struct timer_list InternalCmdTimer; ++ struct timer_list timer; + /* Pool of memory for holding SCpnts before doing + * OS callbacks. freeQ is the free pool. + */ + u8 tmPending; + u8 resetPending; ++ u8 negoNvram; /* DV disabled, nego NVRAM */ ++ u8 pad1; + u8 tmState; +- u8 rsvd[4]; ++ u8 rsvd[2]; + MPT_FRAME_HDR *cmdPtr; /* Ptr to nonOS request */ + struct scsi_cmnd *abortSCpnt; + MPT_LOCAL_REPLY localReply; /* internal cmd reply struct */ + unsigned long hard_resets; /* driver forced bus resets count */ + unsigned long soft_resets; /* fw/external bus resets count */ + unsigned long timeouts; /* cmd timeouts */ +- ushort sel_timeout[MPT_MAX_SCSI_DEVICES]; ++ ushort sel_timeout[MPT_MAX_FC_DEVICES]; + char *info_kbuf; + wait_queue_head_t scandv_waitq; + int scandv_wait_done; +- wait_queue_head_t TM_waitq; +- int TM_wait_done; + long last_queue_full; +- u8 mpt_pq_filter; +- u16 tm_iocstatus; +- struct list_head target_reset_list; ++ u8 mpt_pq_filter; + } MPT_SCSI_HOST; + +- + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + /* + * More Dynamic Multi-Pathing stuff... +@@ -1176,29 +1067,20 @@ extern void mpt_free_msg_frame(MPT_ADAP + extern void mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf); + extern void mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr); + +-extern int mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, +-u32 *req, ulong timeout, int sleepFlag); +- ++extern int mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag); + extern int mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp); + extern u32 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked); + extern void mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len, int showlan); + extern int mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag); +- +-extern int mpt_SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag); +-extern void mptscsih_TM_timeout(unsigned long data); +- + extern int mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg); +-extern int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag); +-extern int mpt_writeSDP1(MPT_ADAPTER *ioc, int portnum, int id, int flags); +-extern void mpt_setSDP1parameters (u8 width, u8 factor, u8 offset, u8 flags, int *requestedPtr, int *configurationPtr); + extern void mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size); + extern void mpt_free_fw_memory(MPT_ADAPTER *ioc); + extern int mpt_findImVolumes(MPT_ADAPTER *ioc); + extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); + extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); ++extern int mpt_sas_get_info(MPT_ADAPTER *ioc); ++extern void mpt_poll_interrupt(MPT_ADAPTER *ioc); + extern int mpt_alt_ioc_wait(MPT_ADAPTER *ioc); +-extern void mpt_poll_interrupt(MPT_ADAPTER *ioc); +-extern int mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk); + + /* + * Public data decl's... +@@ -1237,7 +1119,7 @@ extern int mpt_sg_tablesize; + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + #endif /* } __KERNEL__ */ + +-#if defined(__alpha__) || defined(__sparc_v9__) || defined(__ia64__) || defined(__x86_64__) || defined(__powerpc__) ++#if defined(__alpha__) || defined(__sparc_v9__) || defined(__ia64__) || defined(__x86_64__) + #define CAST_U32_TO_PTR(x) ((void *)(u64)x) + #define CAST_PTR_TO_U32(x) ((u32)(u64)x) + #else +diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptctl.c linux-2.6.9-55.0.12/drivers/message/fusion/mptctl.c +--- linux-2.6.9-67.0.1/drivers/message/fusion/mptctl.c 2007-12-21 11:40:54.000000000 +0100 ++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptctl.c 2007-11-02 09:10:23.000000000 +0100 +@@ -4,8 +4,8 @@ + * For use with LSI Logic PCI chip/adapters + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * +- * Copyright (c) 1999-2007 LSI Logic Corporation +- * (mailto:mpt_linux_developer@lsi.com) ++ * Copyright (c) 1999-2005 LSI Logic Corporation ++ * (mailto:mpt_linux_developer@lsil.com) + * + */ + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +@@ -57,6 +57,9 @@ + #include <linux/miscdevice.h> + #include <linux/smp_lock.h> + #include <linux/compat.h> ++#if defined(CPQ_CIM) ++#include "csmisas.h" ++#endif // CPQ_CIM + + #include <asm/io.h> + #include <asm/uaccess.h> +@@ -67,16 +70,11 @@ + #include <scsi/scsi_host.h> + #include <scsi/scsi_tcq.h> + +-#define COPYRIGHT "Copyright (c) 1999-2007 LSI Logic Corporation" ++#define COPYRIGHT "Copyright (c) 1999-2005 LSI Logic Corporation" + #define MODULEAUTHOR "LSI Logic Corporation" + #include "mptbase.h" + #include "mptctl.h" + +-#if defined(CPQ_CIM) +-#include "mptsas.h" +-#include "csmi/csmisas.h" +-#endif // CPQ_CIM +- + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + #define my_NAME "Fusion MPT misc device (ioctl) driver" + #define my_VERSION MPT_LINUX_VERSION_COMMON +@@ -85,12 +83,10 @@ + MODULE_AUTHOR(MODULEAUTHOR); + MODULE_DESCRIPTION(my_NAME); + MODULE_LICENSE("GPL"); +-MODULE_VERSION(my_VERSION); + + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + + extern int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag); +-extern int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req, int replyBytes, u16 *u16reply, int maxwait, int sleepFlag); + + static int mptctl_id = -1; + +@@ -119,10 +115,6 @@ static int mptctl_eventenable(unsigned l + static int mptctl_eventreport(unsigned long arg); + static int mptctl_replace_fw(unsigned long arg); + +-#ifdef MPT_SUPPORT_FWDLB_IOCTL +-static int mptctl_hba_pciinfo(unsigned long arg); +-#endif +- + static int mptctl_do_reset(unsigned long arg); + static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd); + static int mptctl_hp_targetinfo(unsigned long arg); +@@ -133,29 +125,27 @@ static int mptctl_unregister_diag_buffer + static int mptctl_query_diag_buffer(unsigned long arg); + static int mptctl_read_diag_buffer(unsigned long arg); + #if defined(CPQ_CIM) +-static int csmisas_get_driver_info(unsigned long arg); +-static int csmisas_get_cntlr_status(unsigned long arg); +-static int csmisas_get_cntlr_config(unsigned long arg); +-static int csmisas_get_phy_info(unsigned long arg); +-static int csmisas_get_scsi_address(unsigned long arg); +-static int csmisas_get_link_errors(unsigned long arg); +-static int csmisas_smp_passthru(unsigned long arg); +-static int csmisas_firmware_download(unsigned long arg); +-static int csmisas_get_raid_info(unsigned long arg); +-static int csmisas_get_raid_config(unsigned long arg); +-static int csmisas_get_raid_features(unsigned long arg); +-static int csmisas_set_raid_control(unsigned long arg); +-static int csmisas_get_raid_element(unsigned long arg); +-static int csmisas_set_raid_operation(unsigned long arg); +-static int csmisas_set_phy_info(unsigned long arg); +-static int csmisas_ssp_passthru(unsigned long arg); +-static int csmisas_stp_passthru(unsigned long arg); +-static int csmisas_get_sata_signature(unsigned long arg); +-static int csmisas_get_device_address(unsigned long arg); +-static int csmisas_task_managment(unsigned long arg); +-static int csmisas_phy_control(unsigned long arg); +-static int csmisas_get_connector_info(unsigned long arg); +-static int csmisas_get_location(unsigned long arg); ++static int mptctl_csmi_sas_get_driver_info(unsigned long arg); ++static int mptctl_csmi_sas_get_cntlr_status(unsigned long arg); ++static int mptctl_csmi_sas_get_cntlr_config(unsigned long arg); ++static int mptctl_csmi_sas_get_phy_info(unsigned long arg); ++static int mptctl_csmi_sas_get_scsi_address(unsigned long arg); ++static int mptctl_csmi_sas_get_link_errors(unsigned long arg); ++static int mptctl_csmi_sas_smp_passthru(unsigned long arg); ++static int mptctl_csmi_sas_firmware_download(unsigned long arg); ++static int mptctl_csmi_sas_get_raid_info(unsigned long arg); ++static int mptctl_csmi_sas_get_raid_config(unsigned long arg); ++static int mptctl_csmi_sas_get_raid_features(unsigned long arg); ++static int mptctl_csmi_sas_get_raid_control(unsigned long arg); ++static int mptctl_csmi_sas_set_phy_info(unsigned long arg); ++static int mptctl_csmi_sas_ssp_passthru(unsigned long arg); ++static int mptctl_csmi_sas_stp_passthru(unsigned long arg); ++static int mptctl_csmi_sas_get_sata_signature(unsigned long arg); ++static int mptctl_csmi_sas_get_device_address(unsigned long arg); ++static int mptctl_csmi_sas_task_managment(unsigned long arg); ++static int mptctl_csmi_sas_phy_control(unsigned long arg); ++static int mptctl_csmi_sas_get_connector_info(unsigned long arg); ++static int mptctl_csmi_sas_get_location(unsigned long arg); + #endif // CPQ_CIM + + static int mptctl_probe(struct pci_dev *, const struct pci_device_id *); +@@ -230,7 +220,7 @@ static inline int + mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock) + { + int rc = 0; +- dctlprintk((KERN_INFO MYNAM ": mptctl_syscall_down(%p,%d) called\n", ioc, nonblock)); ++ dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock)); + + if (nonblock) { + if (down_trylock(&ioc->ioctl->sem_ioc)) +@@ -239,7 +229,7 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, in + if (down_interruptible(&ioc->ioctl->sem_ioc)) + rc = -ERESTARTSYS; + } +- dctlprintk((KERN_INFO MYNAM ": mptctl_syscall_down return %d\n", rc)); ++ dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc)); + return rc; + } + +@@ -304,17 +294,9 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME + + if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) || + (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) { +- +- dcsmisasprintk(("\tiocstatus = 0x%x, " +- "scsi_status = 0x%x, scsi_state = 0x%x\n", +- reply->u.sreply.IOCStatus, +- reply->u.sreply.SCSIStatus, +- reply->u.sreply.SCSIState)); +- + ioc->ioctl->reset &= ~MPTCTL_RESET_OK; + + if ((iocStatus == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) || +- (iocStatus == MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH) || + (iocStatus == MPI_IOCSTATUS_SCSI_RECOVERED_ERROR)) { + ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD; + } +@@ -438,8 +420,8 @@ mptctl_bus_reset(MPT_IOCTL *ioctl) + ioctl->ioc->name, mf)); + + pScsiTm = (SCSITaskMgmt_t *) mf; +- pScsiTm->TargetID = ioctl->id; +- pScsiTm->Bus = ioctl->bus; ++ pScsiTm->TargetID = ioctl->target; ++ pScsiTm->Bus = hd->port; /* 0 */ + pScsiTm->ChainOffset = 0; + pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; + pScsiTm->Reserved = 0; +@@ -460,7 +442,7 @@ mptctl_bus_reset(MPT_IOCTL *ioctl) + + ioctl->wait_done=0; + if ((retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc, +- sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,10, CAN_SLEEP)) != 0) { ++ sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) { + dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!" + " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, + hd->ioc, mf)); +@@ -652,7 +634,7 @@ __mptctl_ioctl(struct file *file, unsign + dctlprintk(("mptctl_ioctl() called with cmd=%x\n", cmd)); + + if (copy_from_user(&khdr, uhdr, sizeof(khdr))) { +- printk(KERN_ERR "%s: mptctl_ioctl() @%d - " ++ printk(KERN_ERR "%s::mptctl_ioctl() @%d - " + "Unable to copy mpt_ioctl_header data @ %p\n", + __FILE__, __LINE__, uhdr); + return -EFAULT; +@@ -693,38 +675,28 @@ __mptctl_ioctl(struct file *file, unsign + return mptctl_query_diag_buffer(arg); + } else if (cmd == MPTDIAGUNREGISTER) { + return mptctl_unregister_diag_buffer(arg); +- +- } +-#ifdef MPT_SUPPORT_FWDLB_IOCTL +- else if (cmd == MPTHBAPCIINFO) { +- return mptctl_hba_pciinfo(arg); + } +-#endif + + #if defined(CPQ_CIM) + else if (cmd == CC_CSMI_SAS_GET_DRIVER_INFO) { +- return csmisas_get_driver_info(arg); ++ return mptctl_csmi_sas_get_driver_info(arg); + } else if (cmd == CC_CSMI_SAS_GET_CNTLR_CONFIG) { +- return csmisas_get_cntlr_config(arg); ++ return mptctl_csmi_sas_get_cntlr_config(arg); + } else if (cmd == CC_CSMI_SAS_GET_CNTLR_STATUS) { +- return csmisas_get_cntlr_status(arg); ++ return mptctl_csmi_sas_get_cntlr_status(arg); + } else if (cmd == CC_CSMI_SAS_GET_SCSI_ADDRESS) { +- return csmisas_get_scsi_address(arg); ++ return mptctl_csmi_sas_get_scsi_address(arg); + } else if (cmd == CC_CSMI_SAS_GET_DEVICE_ADDRESS){ +- return csmisas_get_device_address(arg); ++ return mptctl_csmi_sas_get_device_address(arg); + } + #endif // CPQ_CIM + +- dctlprintk(("mptctl_ioctl() called with cmd=%x, interrupt required\n", cmd)); + /* All of these commands require an interrupt or + * are unknown/illegal. + */ +- if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0) { +- dctlprintk(("mptctl_ioctl() called with cmd=%x ret=%d, syscall_down failed\n", cmd, ret)); ++ if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0) + return ret; +- } + +- dctlprintk(("mptctl_ioctl() called with cmd=%x, syscall_down completed\n", cmd)); + if (cmd == MPTFWDOWNLOAD) + ret = mptctl_fw_download(arg); + else if (cmd == MPTFWDOWNLOADBOOT) +@@ -745,41 +717,37 @@ __mptctl_ioctl(struct file *file, unsign + ret = mptctl_read_diag_buffer(arg); + #if defined(CPQ_CIM) + else if (cmd == CC_CSMI_SAS_GET_PHY_INFO) +- ret = csmisas_get_phy_info(arg); ++ ret = mptctl_csmi_sas_get_phy_info(arg); + else if (cmd == CC_CSMI_SAS_GET_SATA_SIGNATURE) +- ret = csmisas_get_sata_signature(arg); ++ ret = mptctl_csmi_sas_get_sata_signature(arg); + else if (cmd == CC_CSMI_SAS_GET_LINK_ERRORS) +- ret = csmisas_get_link_errors(arg); ++ ret = mptctl_csmi_sas_get_link_errors(arg); + else if (cmd == CC_CSMI_SAS_SMP_PASSTHRU) +- ret = csmisas_smp_passthru(arg); ++ ret = mptctl_csmi_sas_smp_passthru(arg); + else if (cmd == CC_CSMI_SAS_SSP_PASSTHRU) +- ret = csmisas_ssp_passthru(arg); ++ ret = mptctl_csmi_sas_ssp_passthru(arg); + else if (cmd == CC_CSMI_SAS_FIRMWARE_DOWNLOAD) +- ret = csmisas_firmware_download(arg); ++ ret = mptctl_csmi_sas_firmware_download(arg); + else if (cmd == CC_CSMI_SAS_GET_RAID_INFO) +- ret = csmisas_get_raid_info(arg); ++ ret = mptctl_csmi_sas_get_raid_info(arg); + else if (cmd == CC_CSMI_SAS_GET_RAID_CONFIG) +- ret = csmisas_get_raid_config(arg); +- else if (cmd == CC_CSMI_SAS_GET_RAID_FEATURES) +- ret = csmisas_get_raid_features(arg); +- else if (cmd == CC_CSMI_SAS_SET_RAID_CONTROL) +- ret = csmisas_set_raid_control(arg); +- else if (cmd == CC_CSMI_SAS_GET_RAID_ELEMENT) +- ret = csmisas_get_raid_element(arg); +- else if (cmd == CC_CSMI_SAS_SET_RAID_OPERATION) +- ret = csmisas_set_raid_operation(arg); ++ ret = mptctl_csmi_sas_get_raid_config(arg); ++ else if (cmd == CC_CSMI_SAS_GET_RAID_FEATURES) ++ ret = mptctl_csmi_sas_get_raid_features(arg); ++ else if (cmd == CC_CSMI_SAS_SET_RAID_CONTROL) ++ ret = mptctl_csmi_sas_get_raid_control(arg); + else if (cmd == CC_CSMI_SAS_SET_PHY_INFO) +- ret = csmisas_set_phy_info(arg); ++ ret = mptctl_csmi_sas_set_phy_info(arg); + else if (cmd == CC_CSMI_SAS_STP_PASSTHRU) +- ret = csmisas_stp_passthru(arg); ++ ret = mptctl_csmi_sas_stp_passthru(arg); + else if (cmd == CC_CSMI_SAS_TASK_MANAGEMENT) +- ret = csmisas_task_managment(arg); ++ ret = mptctl_csmi_sas_task_managment(arg); + else if (cmd == CC_CSMI_SAS_PHY_CONTROL) +- ret = csmisas_phy_control(arg); ++ ret = mptctl_csmi_sas_phy_control(arg); + else if (cmd == CC_CSMI_SAS_GET_CONNECTOR_INFO) +- ret = csmisas_get_connector_info(arg); ++ ret = mptctl_csmi_sas_get_connector_info(arg); + else if (cmd == CC_CSMI_SAS_GET_LOCATION) +- ret = csmisas_get_location(arg); ++ ret = mptctl_csmi_sas_get_location(arg); + #endif // CPQ_CIM + else { + dctlprintk(("mptctl_ioctl() cmd=%x not found\n", cmd)); +@@ -788,7 +756,6 @@ __mptctl_ioctl(struct file *file, unsign + + up(&iocp->ioctl->sem_ioc); + +- dctlprintk(("mptctl_ioctl() called with cmd=%x ret=%d, up completed\n", cmd, ret)); + return ret; + } + +@@ -813,7 +780,7 @@ static int mptctl_do_reset(unsigned long + dctlprintk(("mptctl_do_reset called.\n")); + + if (copy_from_user(&krinfo, urinfo, sizeof(struct mpt_ioctl_diag_reset))) { +- printk(KERN_ERR "%s@%d: mptctl_do_reset - " ++ printk(KERN_ERR "%s@%d::mptctl_do_reset - " + "Unable to copy mpt_ioctl_diag_reset struct @ %p\n", + __FILE__, __LINE__, urinfo); + return -EFAULT; +@@ -858,7 +825,7 @@ mptctl_fw_download(unsigned long arg) + + dctlprintk(("mptctl_fwdl called. mptctl_id = %xh\n", mptctl_id)); //tc + if (copy_from_user(&kfwdl, ufwdl, sizeof(struct mpt_fw_xfer))) { +- printk(KERN_ERR "%s@%d: _ioctl_fwdl - " ++ printk(KERN_ERR "%s@%d::_ioctl_fwdl - " + "Unable to copy mpt_fw_xfer struct @ %p\n", + __FILE__, __LINE__, ufwdl); + return -EFAULT; +@@ -1014,7 +981,7 @@ mptctl_do_fw_download(int ioc, char __us + mpt_add_sge(sgOut, sgIn->FlagsLength, sgIn->Address); + n++; + if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) { +- printk(KERN_ERR "%s@%d: _ioctl_fwdl - " ++ printk(KERN_ERR "%s@%d::_ioctl_fwdl - " + "Unable to copy f/w buffer hunk#%d @ %p\n", + __FILE__, __LINE__, n, ufwbuf); + goto fwdl_out; +@@ -1040,9 +1007,6 @@ mptctl_do_fw_download(int ioc, char __us + * Finally, perform firmware download. + */ + ReplyMsg = NULL; +- iocp->ioctl->wait_done = 0; +- INITIALIZE_IOCTL_STATUS(iocp->ioctl->status) +- + mpt_put_msg_frame(mptctl_id, iocp, mf); + + /* Now wait for the command to complete */ +@@ -1075,7 +1039,7 @@ mptctl_do_fw_download(int ioc, char __us + printk(KERN_WARNING MYNAM ": (try again later?)\n"); + return -EBUSY; + } else { +- printk(KERN_WARNING MYNAM ": ioctl_fwdl() ERROR! %s returned [bad] status = %04xh\n", ++ printk(KERN_WARNING MYNAM "::ioctl_fwdl() ERROR! %s returned [bad] status = %04xh\n", + iocp->name, iocstat); + printk(KERN_WARNING MYNAM ": (bad VooDoo)\n"); + return -ENOMSG; +@@ -1111,7 +1075,7 @@ mptctl_fw_downloadboot(unsigned long arg + + dctlprintk(("mptctl_fwdlboot called. mptctl_id = %xh\n", mptctl_id)); //tc + if (copy_from_user(&kfwdl, ufwdl, sizeof(struct mpt_fw_xfer))) { +- printk(KERN_ERR "%s@%d: _ioctl_fwdl - " ++ printk(KERN_ERR "%s@%d::_ioctl_fwdl - " + "Unable to copy mpt_fw_xfer struct @ %p\n", + __FILE__, __LINE__, ufwdl); + return -EFAULT; +@@ -1149,20 +1113,11 @@ mptctl_do_fw_downloadboot(int ioc_num, c + return -ENODEV; /* (-6) No such device or address */ + } + +- pbuf = (char *)__get_free_pages(GFP_KERNEL, get_order(fwlen)); +- if (pbuf==NULL) { +- printk(KERN_ERR "%s@%d: _ioctl_fwdlboot - " +- "Unable to allocate memory\n", +- __FILE__, __LINE__); +- return -ENOMEM; +- } +- +- +-if (copy_from_user(pbuf, ufwbuf, fwlen)) { +- printk(KERN_ERR "%s@%d: _ioctl_fwdlboot - " ++ pbuf = kmalloc(fwlen, GFP_KERNEL); ++ if (copy_from_user(pbuf, ufwbuf, fwlen)) { ++ printk(KERN_ERR "%s@%d::_ioctl_fwdlboot - " + "Unable to copy mpt_fw @ %p\n", + __FILE__, __LINE__, (void*)ufwbuf); +-free_pages((unsigned long)pbuf, get_order(fwlen)); + return -EFAULT; + } + +@@ -1171,10 +1126,7 @@ free_pages((unsigned long)pbuf, get_orde + + rc = mpt_downloadboot(ioc, (MpiFwHeader_t *)pbuf, CAN_SLEEP); + ddlprintk((MYIOC_s_INFO_FMT "mptctl_do_fw_downloadboot rc=%x\n", +- + ioc->name, rc)); +-#if 0 +- + if ( (rc == 0) && (ioc->bus_type == SAS) ) { + /* if ((rc = mptctl_syscall_down(ioc, nonblock)) != 0) + return rc; */ +@@ -1194,12 +1146,10 @@ free_pages((unsigned long)pbuf, get_orde + ioc->name)); + } */ + } +-#endif +-free_pages((unsigned long)pbuf, get_order(fwlen)); ++ kfree(pbuf); + return rc; + } + +- + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + /* + * SGE Allocation routine +@@ -1278,9 +1228,9 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, i + if (buflist[buflist_ent].kptr == NULL) { + alloc_sz = alloc_sz / 2; + if (alloc_sz == 0) { +- printk(KERN_WARNING MYNAM ": -SG: No can do - " ++ printk(KERN_WARNING MYNAM "-SG: No can do - " + "not enough memory! :-(\n"); +- printk(KERN_WARNING MYNAM ": -SG: (freeing %d frags)\n", ++ printk(KERN_WARNING MYNAM "-SG: (freeing %d frags)\n", + numfrags); + goto free_and_fail; + } +@@ -1304,17 +1254,17 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, i + + /* Need to chain? */ + if (fragcnt == sg_spill) { +- printk(KERN_WARNING MYNAM ": -SG: No can do - " "Chain required! :-(\n"); +- printk(KERN_WARNING MYNAM ": (freeing %d frags)\n", numfrags); ++ printk(KERN_WARNING MYNAM "-SG: No can do - " "Chain required! :-(\n"); ++ printk(KERN_WARNING MYNAM "(freeing %d frags)\n", numfrags); + goto free_and_fail; + } + + /* overflow check... */ + if (numfrags*8 > MAX_SGL_BYTES){ + /* GRRRRR... */ +- printk(KERN_WARNING MYNAM ": -SG: No can do - " ++ printk(KERN_WARNING MYNAM "-SG: No can do - " + "too many SG frags! :-(\n"); +- printk(KERN_WARNING MYNAM ": -SG: (freeing %d frags)\n", ++ printk(KERN_WARNING MYNAM "-SG: (freeing %d frags)\n", + numfrags); + goto free_and_fail; + } +@@ -1435,16 +1385,18 @@ mptctl_getiocinfo (unsigned long arg, un + struct mpt_ioctl_iocinfo __user *uarg = (void __user *) arg; + struct mpt_ioctl_iocinfo *karg; + MPT_ADAPTER *ioc; +- struct _MPT_DEVICE *pMptTarget; +- VirtDevice *pTarget; + struct pci_dev *pdev; ++ struct Scsi_Host *sh; ++ MPT_SCSI_HOST *hd; + int iocnum; + int numDevices = 0; +- int id, bus; ++ unsigned int max_id; ++ int ii; + unsigned int port; + int cim_rev; + u8 revision; + ++ dctlprintk(("mptctl_getiocinfo called.\n")); + /* Add of PCI INFO results in unaligned access for + * IA64 and Sparc. Reset long to int. Return no PCI + * data for obsolete format. +@@ -1457,20 +1409,18 @@ mptctl_getiocinfo (unsigned long arg, un + cim_rev = 2; + else if (data_size == (sizeof(struct mpt_ioctl_iocinfo_rev0)+12)) + cim_rev = 0; /* obsolete */ +- else { +- dctlprintk(("mptctl_getiocinfo called.i Invalid data_size=%d\n", data_size)); ++ else + return -EFAULT; +- } + + karg = kmalloc(data_size, GFP_KERNEL); + if (karg == NULL) { +- printk(KERN_ERR "%s: mpt_ioctl_iocinfo() @%d - no memory available!\n", ++ printk(KERN_ERR "%s::mpt_ioctl_iocinfo() @%d - no memory available!\n", + __FILE__, __LINE__); + return -ENOMEM; + } + + if (copy_from_user(karg, uarg, data_size)) { +- printk(KERN_ERR "%s@%d: mptctl_getiocinfo - " ++ printk(KERN_ERR "%s@%d::mptctl_getiocinfo - " + "Unable to read in mpt_ioctl_iocinfo struct @ %p\n", + __FILE__, __LINE__, (void*)uarg); + kfree(karg); +@@ -1484,11 +1434,10 @@ mptctl_getiocinfo (unsigned long arg, un + kfree(karg); + return -ENODEV; + } +- dctlprintk(("ioc%d: mptctl_getiocinfo called.\n", iocnum)); + + /* Verify the data transfer size is correct. */ + if (karg->hdr.maxDataSize != data_size) { +- printk(KERN_ERR "%s@%d: mptctl_getiocinfo - " ++ printk(KERN_ERR "%s@%d::mptctl_getiocinfo - " + "Structure size mismatch. Command not completed.\n", + __FILE__, __LINE__); + kfree(karg); +@@ -1535,11 +1484,18 @@ mptctl_getiocinfo (unsigned long arg, un + + /* Get number of devices + */ +- for (bus = 0; bus < ioc->NumberOfBuses; bus++) { +- if ((pMptTarget = ioc->Target_List[bus])) { +- for (id = 0; id < ioc->DevicesPerBus; id++) { +- pTarget = pMptTarget->Target[id]; +- if (pTarget) ++ if ((sh = ioc->sh) != NULL) { ++ /* sh->max_id = maximum target ID + 1 ++ */ ++ max_id = sh->max_id - 1; ++ hd = (MPT_SCSI_HOST *) sh->hostdata; ++ ++ /* Check all of the target structures and ++ * keep a counter. ++ */ ++ if (hd && hd->Targets) { ++ for (ii = 0; ii <= max_id; ii++) { ++ if (hd->Targets[ii]) + numDevices++; + } + } +@@ -1563,7 +1519,7 @@ mptctl_getiocinfo (unsigned long arg, un + /* Copy the data from kernel memory to user memory + */ + if (copy_to_user((char __user *)arg, karg, data_size)) { +- printk(KERN_ERR "%s@%d: mptctl_getiocinfo - " ++ printk(KERN_ERR "%s@%d::mptctl_getiocinfo - " + "Unable to write out mpt_ioctl_iocinfo struct @ %p\n", + __FILE__, __LINE__, uarg); + kfree(karg); +@@ -1590,22 +1546,25 @@ mptctl_gettargetinfo (unsigned long arg) + struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg; + struct mpt_ioctl_targetinfo karg; + MPT_ADAPTER *ioc; +- struct _MPT_DEVICE *pMptTarget; +- VirtDevice *pTarget; ++ struct Scsi_Host *sh; ++ MPT_SCSI_HOST *hd; ++ VirtDevice *vdev; + char *pmem; + int *pdata; + IOCPage2_t *pIoc2; + IOCPage3_t *pIoc3; + int iocnum; + int numDevices = 0; ++ unsigned int max_id; + int id, jj, indexed_lun, lun_index; + u32 lun; + int maxWordsLeft; + int numBytes; +- u8 port, devType, bus; ++ u8 port, devType, bus_id; + ++ dctlprintk(("mptctl_gettargetinfo called.\n")); + if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) { +- printk(KERN_ERR "%s@%d: mptctl_gettargetinfo - " ++ printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - " + "Unable to read in mpt_ioctl_targetinfo struct @ %p\n", + __FILE__, __LINE__, uarg); + return -EFAULT; +@@ -1618,7 +1577,6 @@ mptctl_gettargetinfo (unsigned long arg) + return -ENODEV; + } + +- dctlprintk(("ioc%ds: mptctl_gettargetinfo called.\n", iocnum)); + /* Get the port number and set the maximum number of bytes + * in the returned structure. + * Ignore the port setting. +@@ -1628,7 +1586,7 @@ mptctl_gettargetinfo (unsigned long arg) + port = karg.hdr.port; + + if (maxWordsLeft <= 0) { +- printk(KERN_ERR "%s: mptctl_gettargetinfo() @%d - no memory available!\n", ++ printk(KERN_ERR "%s::mptctl_gettargetinfo() @%d - no memory available!\n", + __FILE__, __LINE__); + return -ENOMEM; + } +@@ -1649,7 +1607,7 @@ mptctl_gettargetinfo (unsigned long arg) + */ + pmem = kmalloc(numBytes, GFP_KERNEL); + if (pmem == NULL) { +- printk(KERN_ERR "%s: mptctl_gettargetinfo() @%d - no memory available!\n", ++ printk(KERN_ERR "%s::mptctl_gettargetinfo() @%d - no memory available!\n", + __FILE__, __LINE__); + return -ENOMEM; + } +@@ -1658,68 +1616,71 @@ mptctl_gettargetinfo (unsigned long arg) + + /* Get number of devices + */ +- /* Check all of the target structures. +- * Save the Id and increment the counter, +- * if ptr non-null. +- */ +- mpt_findImVolumes(ioc); +- pIoc2 = ioc->raid_data.pIocPg2; +- for (bus = 0; bus < ioc->NumberOfBuses; bus++) { +- for ( id = 0; id < ioc->DevicesPerBus; ) { +- if ( pIoc2 && pIoc2->NumActiveVolumes ) { +- if ( id == pIoc2->RaidVolume[0].VolumeID ) { +- if (maxWordsLeft <= 0) { +- printk(KERN_ERR "mptctl_gettargetinfo - " +- "buffer is full but volume is available on ioc %d\n, numDevices=%d", iocnum, numDevices); +- goto data_space_full; +- } +- if ( ( pIoc2->RaidVolume[0].Flags & MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE ) == 0 ) +- devType = 0x80; +- else +- devType = 0xC0; +- if ( bus == pIoc2->RaidVolume[0].VolumeBus) { +- numDevices++; +- *pdata = ( (devType << 24) | (bus<< 8) | id ); ++ if ((sh = ioc->sh) != NULL) { ++ ++ max_id = sh->max_id - 1; ++ hd = (MPT_SCSI_HOST *) sh->hostdata; ++ ++ /* Check all of the target structures. ++ * Save the Id and increment the counter, ++ * if ptr non-null. ++ * sh->max_id = maximum target ID + 1 ++ */ ++ if (hd && hd->Targets) { ++ mpt_findImVolumes(ioc); ++ pIoc2 = ioc->raid_data.pIocPg2; ++ for ( id = 0; id <= max_id; ) { ++ if ( pIoc2 && pIoc2->NumActiveVolumes ) { ++ if ( id == pIoc2->RaidVolume[0].VolumeID ) { ++ if (maxWordsLeft <= 0) { ++ printk(KERN_ERR "mptctl_gettargetinfo - " ++ "buffer is full but volume is available on ioc %d\n, numDevices=%d", iocnum, numDevices); ++ goto data_space_full; ++ } ++ if ( ( pIoc2->RaidVolume[0].Flags & MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE ) == 0 ) ++ devType = 0x80; ++ else ++ devType = 0xC0; ++ bus_id = pIoc2->RaidVolume[0].VolumeBus; ++ numDevices++; ++ *pdata = ( (devType << 24) | (bus_id << 8) | id ); + dctlprintk((KERN_ERR "mptctl_gettargetinfo - " + "volume ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata)); +- pdata++; ++ pdata++; + --maxWordsLeft; + goto next_id; +- } +- } else { +- pIoc3 = ioc->raid_data.pIocPg3; +- for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) { +- if ((pIoc3->PhysDisk[jj].PhysDiskID == id) && (pIoc3->PhysDisk[jj].PhysDiskBus == bus)) +- goto next_id; ++ } else { ++ pIoc3 = ioc->raid_data.pIocPg3; ++ for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) { ++ if ( pIoc3->PhysDisk[jj].PhysDiskID == id ) ++ goto next_id; ++ } + } + } +- } +- if ((pMptTarget = ioc->Target_List[bus])) { +- pTarget = pMptTarget->Target[id]; +- if (pTarget) { ++ if ( (vdev = hd->Targets[id]) ) { + for (jj = 0; jj <= MPT_LAST_LUN; jj++) { + lun_index = (jj >> 5); + indexed_lun = (jj % 32); + lun = (1 << indexed_lun); +- if (pTarget->luns[lun_index] & lun) { ++ if (vdev->luns[lun_index] & lun) { + if (maxWordsLeft <= 0) { + printk(KERN_ERR "mptctl_gettargetinfo - " +- "buffer is full but more targets are available on ioc %d numDevices=%d\n", iocnum, numDevices); ++ "buffer is full but more targets are available on ioc %d numDevices=%d\n", iocnum, numDevices); + goto data_space_full; + } +- bus = pTarget->bus; ++ bus_id = vdev->bus_id; + numDevices++; +- *pdata = ( (jj << 16) | (bus << 8) | id ); ++ *pdata = ( (jj << 16) | (bus_id << 8) | id ); + dctlprintk((KERN_ERR "mptctl_gettargetinfo - " +- "target ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata)); ++ "target ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata)); + pdata++; + --maxWordsLeft; + } + } + } +- } + next_id: +- id++; ++ id++; ++ } + } + } + data_space_full: +@@ -1729,7 +1690,7 @@ data_space_full: + */ + if (copy_to_user((char __user *)arg, &karg, + sizeof(struct mpt_ioctl_targetinfo))) { +- printk(KERN_ERR "%s@%d: mptctl_gettargetinfo - " ++ printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - " + "Unable to write out mpt_ioctl_targetinfo struct @ %p\n", + __FILE__, __LINE__, uarg); + kfree(pmem); +@@ -1739,7 +1700,7 @@ data_space_full: + /* Copy the remaining data from kernel memory to user memory + */ + if (copy_to_user(uarg->targetInfo, pmem, numBytes)) { +- printk(KERN_ERR "%s@%d: mptctl_gettargetinfo - " ++ printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - " + "Unable to write out mpt_ioctl_targetinfo struct @ %p\n", + __FILE__, __LINE__, pdata); + kfree(pmem); +@@ -1751,70 +1712,6 @@ data_space_full: + return 0; + } + +-#ifdef MPT_SUPPORT_FWDLB_IOCTL +-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +-/* +- * mptctl_hba_pciinfo - Obtain all mpt HBAs pci (Config Space) information. +- * @arg: User space argument +- * +- * Outputs: None. +- * Return: 0 if successful +- * -EFAULT if data unavailable +- */ +-static int +-mptctl_hba_pciinfo (unsigned long arg) +-{ +- struct mpt_ioctl_hbapciinfo *uarg = (struct mpt_ioctl_hbapciinfo *) arg; +- struct mpt_ioctl_hbapciinfo karg; +- +- MPT_ADAPTER *ioc; +- int ioc_num=0, data_size; +- u8 revision; +- +- data_size = sizeof(mpt_ioctl_header)+4; +- /* Clear the struct before filling in data. */ +- memset( &karg, 0, (uarg->hdr.maxDataSize + data_size) ); +- +- dctlprintk((KERN_INFO MYNAM ": Checking for MPT adapters...maxDataSize=%d data_size=%d\n", uarg->hdr.maxDataSize, data_size)); +- +- list_for_each_entry(ioc,&ioc_list,list) { +- data_size += sizeof (struct mpt_ioctl_mptpciinfo); +- if ( data_size >= uarg->hdr.maxDataSize ) { +- dctlprintk((KERN_INFO MYNAM ": data_size=%d >= maxDataSize=%d\n", data_size, uarg->hdr.maxDataSize)); +- break; +- } +- karg.hbapciinfo[ioc_num].iocNumber = ioc_num; +- karg.hbapciinfo[ioc_num].deviceID = ioc->deviceID; +- karg.hbapciinfo[ioc_num].vendorID = ioc->vendorID; +- +- pci_read_config_byte(ioc->pcidev, PCI_CLASS_REVISION, &revision); +- +- karg.hbapciinfo[ioc_num].subSystemVendorID = ioc->pcidev->subsystem_vendor; +- karg.hbapciinfo[ioc_num].subSystemID = ioc->pcidev->subsystem_device; +- +- karg.hbapciinfo[ioc_num].revisionID = revision; +- mpt_GetIocState(ioc, 1); +- karg.hbapciinfo[ioc_num++].iocState = (ioc->last_state >> MPI_IOC_STATE_SHIFT); +- } +- +- karg.totalIOC = ioc_num; +- +- dctlprintk((KERN_INFO MYNAM ": %d MPT adapters found, arg=%p karg=%p size=%d\n", +- karg.totalIOC, (char *)arg, &karg, (int)sizeof(struct mpt_ioctl_hbapciinfo))); +- +- /* Copy the data from kernel memory to user memory +- */ +- if (copy_to_user((char *)arg, &karg, sizeof(struct mpt_ioctl_hbapciinfo))) { +- printk(KERN_ERR "%s@%d::mptctl_eventquery - " +- "Unable to write out mpt_ioctl_eventquery struct @ %p\n", +- __FILE__, __LINE__, (void*)uarg); +- return -EFAULT; +- } +- return 0; +-} +-#endif +- +- + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + /* MPT IOCTL Test function. + * +@@ -1833,7 +1730,7 @@ mptctl_readtest (unsigned long arg) + + dctlprintk(("mptctl_readtest called.\n")); + if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_test))) { +- printk(KERN_ERR "%s@%d: mptctl_readtest - " ++ printk(KERN_ERR "%s@%d::mptctl_readtest - " + "Unable to read in mpt_ioctl_test struct @ %p\n", + __FILE__, __LINE__, uarg); + return -EFAULT; +@@ -1863,7 +1760,7 @@ mptctl_readtest (unsigned long arg) + /* Copy the data from kernel memory to user memory + */ + if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_test))) { +- printk(KERN_ERR "%s@%d: mptctl_readtest - " ++ printk(KERN_ERR "%s@%d::mptctl_readtest - " + "Unable to write out mpt_ioctl_test struct @ %p\n", + __FILE__, __LINE__, uarg); + return -EFAULT; +@@ -1893,7 +1790,7 @@ mptctl_eventquery (unsigned long arg) + + dctlprintk(("mptctl_eventquery called.\n")); + if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventquery))) { +- printk(KERN_ERR "%s@%d: mptctl_eventquery - " ++ printk(KERN_ERR "%s@%d::mptctl_eventquery - " + "Unable to read in mpt_ioctl_eventquery struct @ %p\n", + __FILE__, __LINE__, uarg); + return -EFAULT; +@@ -1912,7 +1809,7 @@ mptctl_eventquery (unsigned long arg) + /* Copy the data from kernel memory to user memory + */ + if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_eventquery))) { +- printk(KERN_ERR "%s@%d: mptctl_eventquery - " ++ printk(KERN_ERR "%s@%d::mptctl_eventquery - " + "Unable to write out mpt_ioctl_eventquery struct @ %p\n", + __FILE__, __LINE__, uarg); + return -EFAULT; +@@ -1931,7 +1828,7 @@ mptctl_eventenable (unsigned long arg) + + dctlprintk(("mptctl_eventenable called.\n")); + if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventenable))) { +- printk(KERN_ERR "%s@%d: mptctl_eventenable - " ++ printk(KERN_ERR "%s@%d::mptctl_eventenable - " + "Unable to read in mpt_ioctl_eventenable struct @ %p\n", + __FILE__, __LINE__, uarg); + return -EFAULT; +@@ -1978,7 +1875,7 @@ mptctl_eventreport (unsigned long arg) + + dctlprintk(("mptctl_eventreport called.\n")); + if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventreport))) { +- printk(KERN_ERR "%s@%d: mptctl_eventreport - " ++ printk(KERN_ERR "%s@%d::mptctl_eventreport - " + "Unable to read in mpt_ioctl_eventreport struct @ %p\n", + __FILE__, __LINE__, uarg); + return -EFAULT; +@@ -2010,7 +1907,7 @@ mptctl_eventreport (unsigned long arg) + */ + numBytes = max * sizeof(MPT_IOCTL_EVENTS); + if (copy_to_user(uarg->eventData, ioc->events, numBytes)) { +- printk(KERN_ERR "%s@%d: mptctl_eventreport - " ++ printk(KERN_ERR "%s@%d::mptctl_eventreport - " + "Unable to write out mpt_ioctl_eventreport struct @ %p\n", + __FILE__, __LINE__, ioc->events); + return -EFAULT; +@@ -2031,7 +1928,7 @@ mptctl_replace_fw (unsigned long arg) + + dctlprintk(("mptctl_replace_fw called.\n")); + if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_replace_fw))) { +- printk(KERN_ERR "%s@%d: mptctl_replace_fw - " ++ printk(KERN_ERR "%s@%d::mptctl_replace_fw - " + "Unable to read in mpt_ioctl_replace_fw struct @ %p\n", + __FILE__, __LINE__, uarg); + return -EFAULT; +@@ -2067,7 +1964,7 @@ mptctl_replace_fw (unsigned long arg) + /* Copy the data from user memory to kernel space + */ + if (copy_from_user(ioc->cached_fw, uarg->newImage, newFwSize)) { +- printk(KERN_ERR "%s@%d: mptctl_replace_fw - " ++ printk(KERN_ERR "%s@%d::mptctl_replace_fw - " + "Unable to read in mpt_ioctl_replace_fw image @ %p\n", + __FILE__, __LINE__, uarg); + mpt_free_fw_memory(ioc); +@@ -2104,7 +2001,7 @@ mptctl_mpt_command (unsigned long arg) + dctlprintk(("mptctl_command called.\n")); + + if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_command))) { +- printk(KERN_ERR "%s@%d: mptctl_mpt_command - " ++ printk(KERN_ERR "%s@%d::mptctl_mpt_command - " + "Unable to read in mpt_ioctl_command struct @ %p\n", + __FILE__, __LINE__, uarg); + return -EFAULT; +@@ -2149,11 +2046,10 @@ mptctl_do_mpt_command (struct mpt_ioctl_ + int iocnum, flagsLength; + int sz, rc = 0; + int msgContext; +- u16 req_idx=0; ++ u16 req_idx; + ulong timeout; +- MPT_FRAME_HDR *SAS_handshake_mf=NULL; +- char *SAS_handshake_reply=NULL; +- u16 msgSize=0; ++ ++ dctlprintk(("mptctl_do_mpt_command called.\n")); + bufIn.kptr = bufOut.kptr = NULL; + + if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || +@@ -2162,14 +2058,13 @@ mptctl_do_mpt_command (struct mpt_ioctl_ + iocnum)); + return -ENODEV; + } +- dctlprintk(("ioc%d: mptctl_do_mpt_command called.\n", iocnum)); + if (!ioc->ioctl) { +- printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - " ++ printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + "No memory available during driver init.\n", + __FILE__, __LINE__); + return -ENOMEM; + } else if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) { +- printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - " ++ printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + "Busy with IOC Reset \n", __FILE__, __LINE__); + return -EBUSY; + } +@@ -2183,7 +2078,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_ + sz += sizeof(dma_addr_t) + sizeof(u32); + + if (sz > ioc->req_sz) { +- printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - " ++ printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + "Request frame too large (%d) maximum (%d)\n", + __FILE__, __LINE__, sz, ioc->req_sz); + return -EFAULT; +@@ -2191,44 +2086,18 @@ mptctl_do_mpt_command (struct mpt_ioctl_ + + /* Get a free request frame and save the message context. + */ +- if (((MPIHeader_t *)(mfPtr))->MsgContext == 0x02012020) { +- msgSize = karg.hdr.port >> 16; +- if ( (mf = (MPT_FRAME_HDR *)kmalloc(msgSize, GFP_KERNEL)) == NULL) { +- dfailprintk(("%s: mptctl_do_mpt_command, Unable to kmalloc msgSize=%d for SAS_handshake!!\n", +- ioc->name, msgSize)); +- return -ENOMEM; +- } +- SAS_handshake_mf = mf; +- if (karg.maxReplyBytes) { +- if ( (SAS_handshake_reply = (char *)kmalloc(karg.maxReplyBytes, GFP_KERNEL)) == NULL) { +- kfree(SAS_handshake_mf); +- dfailprintk(("%s: mptctl_do_mpt_command, Unable to kmalloc maxReplyBytes=%d for SAS_handshake!!\n", +- ioc->name, karg.maxReplyBytes)); +- return -ENOMEM; +- } +- } +- hdr = (MPIHeader_t *) mf; +- msgContext = le32_to_cpu(0x02012020); +- karg.hdr.port &= 0x0000ffff; +- } else { +- if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) { +- dfailprintk((MYIOC_s_WARN_FMT "%s: no msg frames!!\n", +- ioc->name,__FUNCTION__)); +- return -EAGAIN; +- } else { +- hdr = (MPIHeader_t *) mf; +- msgContext = le32_to_cpu(hdr->MsgContext); +- req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); +- } +- } ++ if ((mf = mpt_get_msg_frame(mptctl_id, ioc)) == NULL) ++ return -EAGAIN; + ++ hdr = (MPIHeader_t *) mf; ++ msgContext = le32_to_cpu(hdr->MsgContext); ++ req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); + +-//@@@@@ + /* Copy the request frame + * Reset the saved message context. + */ + if (copy_from_user(mf, mfPtr, karg.dataSgeOffset * 4)) { +- printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - " ++ printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + "Unable to read MF from mpt_ioctl_command struct @ %p\n", + __FILE__, __LINE__, mfPtr); + rc = -EFAULT; +@@ -2259,34 +2128,17 @@ mptctl_do_mpt_command (struct mpt_ioctl_ + case MPI_FUNCTION_SCSI_IO_REQUEST: + if (ioc->sh) { + SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf; +- struct _MPT_DEVICE *pMptTarget; + VirtDevice *pTarget = NULL; + MPT_SCSI_HOST *hd = NULL; + int qtag = MPI_SCSIIO_CONTROL_UNTAGGED; + int scsidir = 0; +- int id = (int) pScsiReq->TargetID; +- int bus = (int) pScsiReq->Bus; ++ int target = (int) pScsiReq->TargetID; + int dataSize; + +- if ((id < 0) || (id > ioc->DevicesPerBus)) { +- printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - " +- "Target ID=%d out of bounds. DevicesPerBus=%d\n", +- __FILE__, __LINE__, id, ioc->DevicesPerBus); +- rc = -ENODEV; +- goto done_free_mem; +- } +- +- if ((bus < 0) || (bus >= ioc->NumberOfBuses)) { +- printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - " +- "Target Bus=%d out of bounds. NumberOfBuses=%d\n", +- __FILE__, __LINE__, bus, ioc->NumberOfBuses); +- rc = -ENODEV; +- goto done_free_mem; +- } +- if ((pMptTarget = ioc->Target_List[bus]) == NULL) { +- printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - " +- "Target_List=NULL for %s bus=%d\n", +- __FILE__, __LINE__, ioc->name, bus); ++ if ((target < 0) || (target >= ioc->sh->max_id)) { ++ printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " ++ "Target ID out of bounds. \n", ++ __FILE__, __LINE__); + rc = -ENODEV; + goto done_free_mem; + } +@@ -2310,7 +2162,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_ + + (req_idx * MPT_SENSE_BUFFER_ALLOC)); + + if ((hd = (MPT_SCSI_HOST *) ioc->sh->hostdata)) { +- pTarget = pMptTarget->Target[id]; ++ if (hd->Targets) ++ pTarget = hd->Targets[target]; + } + + if (pTarget &&(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) +@@ -2331,10 +2184,10 @@ mptctl_do_mpt_command (struct mpt_ioctl_ + pScsiReq->DataLength = cpu_to_le32(dataSize); + + ioc->ioctl->reset = MPTCTL_RESET_OK; +- ioc->ioctl->id = id; ++ ioc->ioctl->target = target; + + } else { +- printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - " ++ printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + "SCSI driver is not loaded. \n", + __FILE__, __LINE__); + rc = -EFAULT; +@@ -2353,7 +2206,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_ + + case MPI_FUNCTION_SATA_PASSTHROUGH: + if (!ioc->sh) { +- printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - " ++ printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + "SCSI driver is not loaded. \n", + __FILE__, __LINE__); + rc = -EFAULT; +@@ -2409,10 +2262,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_ + pScsiReq->DataLength = cpu_to_le32(dataSize); + + ioc->ioctl->reset = MPTCTL_RESET_OK; +- ioc->ioctl->id = pScsiReq->TargetID; +- ioc->ioctl->bus = pScsiReq->Bus; ++ ioc->ioctl->target = pScsiReq->TargetID; + } else { +- printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - " ++ printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + "SCSI driver is not loaded. \n", + __FILE__, __LINE__); + rc = -EFAULT; +@@ -2424,7 +2276,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_ + { + MPT_SCSI_HOST *hd = NULL; + if ((ioc->sh == NULL) || ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) { +- printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - " ++ printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + "SCSI driver not loaded or SCSI host not found. \n", + __FILE__, __LINE__); + rc = -EFAULT; +@@ -2457,7 +2309,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_ + (pInit->ReplyFrameSize != cpu_to_le16(ioc->reply_sz)) || + (pInit->HostMfaHighAddr != high_addr) || + (pInit->SenseBufferHighAddr != sense_high)) { +- printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - " ++ printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + "IOC_INIT issued with 1 or more incorrect parameters. Rejected.\n", + __FILE__, __LINE__); + rc = -EFAULT; +@@ -2490,7 +2342,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_ + MPI_FUNCTION_LAN_RESET + */ + +- printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - " ++ printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + "Illegal request (function 0x%x) \n", + __FILE__, __LINE__, hdr->Function); + rc = -EFAULT; +@@ -2550,7 +2402,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_ + karg.dataOutBufPtr, + bufOut.len)) { + printk(KERN_ERR +- "%s@%d: mptctl_do_mpt_command - Unable " ++ "%s@%d::mptctl_do_mpt_command - Unable " + "to read user data " + "struct @ %p\n", + __FILE__, __LINE__,karg.dataOutBufPtr); +@@ -2561,7 +2413,16 @@ mptctl_do_mpt_command (struct mpt_ioctl_ + } + + if (karg.dataInSize > 0) { +- flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ; ++ if ((karg.dataOutSize > 0) && ++ (hdr->Function == MPI_FUNCTION_SMP_PASSTHROUGH)){ ++ flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT | ++ MPI_SGE_FLAGS_END_OF_BUFFER | ++ MPI_SGE_FLAGS_DIRECTION | ++ mpt_addr_size() ) ++ << MPI_SGE_FLAGS_SHIFT; ++ } else { ++ flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ; ++ } + flagsLength |= karg.dataInSize; + + bufIn.len = karg.dataInSize; +@@ -2585,14 +2446,13 @@ mptctl_do_mpt_command (struct mpt_ioctl_ + } + + ioc->ioctl->wait_done = 0; +- INITIALIZE_IOCTL_STATUS(ioc->ioctl->status) +- + if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) { + + DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf); + + if (mpt_send_handshake_request(mptctl_id, ioc, +- sizeof(SCSITaskMgmt_t), (u32*)mf,10, CAN_SLEEP) != 0) { ++ sizeof(SCSITaskMgmt_t), (u32*)mf, ++ CAN_SLEEP) != 0) { + dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!" + " (ioc %p, mf %p) \n", ioc->name, + ioc, mf)); +@@ -2600,73 +2460,27 @@ mptctl_do_mpt_command (struct mpt_ioctl_ + rc = -ENODATA; + goto done_free_mem; + } +-timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT; +-timeout = wait_event_timeout(mptctl_wait,ioc->ioctl->wait_done == 1,HZ*timeout); + +- if(timeout <=0 && (ioc->ioctl->wait_done != 1 )) { +- /* Now we need to reset the board */ +- mptctl_free_tm_flags(ioc); +- mptctl_timeout_expired(ioc->ioctl); +- rc = -ENODATA; +- goto done_free_mem; +- } +-} else { +- if ( SAS_handshake_mf ) { +- dctlprintk(("SAS_handshake_message Function=%x\n", +- hdr->Function)); +- +- timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT; +- rc = mpt_handshake_req_reply_wait(ioc, +- msgSize, +- (u32*)SAS_handshake_mf, +- karg.maxReplyBytes, +- (u16*)SAS_handshake_reply, timeout /*seconds*/, +- CAN_SLEEP); +- kfree(SAS_handshake_mf); +- SAS_handshake_mf = NULL; +- if (rc == 0) { +- dctlprintk(("SAS_handshake_message Function=%x completed successfully\n", +- hdr->Function)); +- sz = karg.maxReplyBytes; +- if (sz > 0) { +- if (copy_to_user((char *)karg.replyFrameBufPtr,SAS_handshake_reply, sz)){ +-printk(KERN_ERR "%s@%d::mptctl_do_mpt_command -" "Unable to write out reply frame %p\n",__FILE__, __LINE__, (void*)karg.replyFrameBufPtr); +- rc = -ENODATA; +- } +- }else { +- +- rc = -ENODATA; +- dctlprintk(("SAS_handshake_message failed sz=%d\n", sz)); +- } +- kfree(SAS_handshake_reply); +- SAS_handshake_reply = NULL; +- goto done_free_mem; +- } +- else +- { +- rc = -ENODATA; +- kfree(SAS_handshake_reply); +- SAS_handshake_reply = NULL; +- goto done_free_mem; +- } +- }else { +- mpt_put_msg_frame(mptctl_id, ioc, mf); +- /* Now wait for the command to complete */ +- timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT; +- timeout = wait_event_timeout(mptctl_wait, +- ioc->ioctl->wait_done == 1, +- HZ*timeout); ++ } else ++ mpt_put_msg_frame(mptctl_id, ioc, mf); + +- if(timeout <=0 && (ioc->ioctl->wait_done != 1 )) { ++ /* Now wait for the command to complete */ ++ timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT; ++ timeout = wait_event_timeout(mptctl_wait, ++ ioc->ioctl->wait_done == 1, ++ HZ*timeout); + ++ if(timeout <=0 && (ioc->ioctl->wait_done != 1 )) { + /* Now we need to reset the board */ + ++ if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) ++ mptctl_free_tm_flags(ioc); ++ + mptctl_timeout_expired(ioc->ioctl); + rc = -ENODATA; + goto done_free_mem; +- } +- } +-} ++ } ++ + + mf = NULL; + +@@ -2684,7 +2498,7 @@ printk(KERN_ERR "%s@%d::mptctl_do_mpt_co + if (copy_to_user(karg.replyFrameBufPtr, + &ioc->ioctl->ReplyFrame, sz)){ + +- printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - " ++ printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + "Unable to write out reply frame %p\n", + __FILE__, __LINE__, karg.replyFrameBufPtr); + rc = -ENODATA; +@@ -2699,7 +2513,7 @@ printk(KERN_ERR "%s@%d::mptctl_do_mpt_co + sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE); + if (sz > 0) { + if (copy_to_user(karg.senseDataPtr, ioc->ioctl->sense, sz)) { +- printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - " ++ printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + "Unable to write sense data to user %p\n", + __FILE__, __LINE__, + karg.senseDataPtr); +@@ -2716,7 +2530,7 @@ printk(KERN_ERR "%s@%d::mptctl_do_mpt_co + (karg.dataInSize > 0) && (bufIn.kptr)) { + if (copy_to_user(karg.dataInBufPtr, + bufIn.kptr, karg.dataInSize)) { +- printk(KERN_ERR "%s@%d: mptctl_do_mpt_command - " ++ printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + "Unable to write data to user %p\n", + __FILE__, __LINE__, + karg.dataInBufPtr); +@@ -2726,6 +2540,10 @@ printk(KERN_ERR "%s@%d::mptctl_do_mpt_co + + done_free_mem: + ++ ioc->ioctl->status &= ~(MPT_IOCTL_STATUS_COMMAND_GOOD | ++ MPT_IOCTL_STATUS_SENSE_VALID | ++ MPT_IOCTL_STATUS_RF_VALID ); ++ + /* Free the allocated memory. + */ + if (bufOut.kptr != NULL) { +@@ -2738,14 +2556,6 @@ done_free_mem: + bufIn.len, (void *) bufIn.kptr, dma_addr_in); + } + +-if (SAS_handshake_mf) { +- kfree(SAS_handshake_mf); +- mf=NULL; +- } +-if (SAS_handshake_reply) +- kfree(SAS_handshake_reply); +- +- + /* mf is null if command issued successfully + * otherwise, failure occured after mf acquired. + */ +@@ -2792,7 +2602,7 @@ mptctl_hp_hostinfo(unsigned long arg, un + return -EFAULT; + + if (copy_from_user(&karg, uarg, sizeof(hp_host_info_t))) { +- printk(KERN_ERR "%s@%d: mptctl_hp_host_info - " ++ printk(KERN_ERR "%s@%d::mptctl_hp_host_info - " + "Unable to read in hp_host_info struct @ %p\n", + __FILE__, __LINE__, uarg); + return -EFAULT; +@@ -2914,8 +2724,6 @@ mptctl_hp_hostinfo(unsigned long arg, un + (MPT_SGE_FLAGS_SSIMPLE_READ|4), buf_dma); + + ioc->ioctl->wait_done = 0; +- INITIALIZE_IOCTL_STATUS(ioc->ioctl->status) +- + mpt_put_msg_frame(mptctl_id, ioc, mf); + + rc = wait_event_timeout(mptctl_wait, +@@ -2947,7 +2755,7 @@ mptctl_hp_hostinfo(unsigned long arg, un + /* Copy the data from kernel memory to user memory + */ + if (copy_to_user((char __user *)arg, &karg, sizeof(hp_host_info_t))) { +- printk(KERN_ERR "%s@%d: mptctl_hpgethostinfo - " ++ printk(KERN_ERR "%s@%d::mptctl_hpgethostinfo - " + "Unable to write out hp_host_info @ %p\n", + __FILE__, __LINE__, uarg); + return -EFAULT; +@@ -2986,7 +2794,7 @@ mptctl_hp_targetinfo(unsigned long arg) + + dctlprintk(("mptctl_hp_targetinfo called.\n")); + if (copy_from_user(&karg, uarg, sizeof(hp_target_info_t))) { +- printk(KERN_ERR "%s@%d: mptctl_hp_targetinfo - " ++ printk(KERN_ERR "%s@%d::mptctl_hp_targetinfo - " + "Unable to read in hp_host_targetinfo struct @ %p\n", + __FILE__, __LINE__, uarg); + return -EFAULT; +@@ -3097,7 +2905,7 @@ mptctl_hp_targetinfo(unsigned long arg) + /* Copy the data from kernel memory to user memory + */ + if (copy_to_user((char __user *)arg, &karg, sizeof(hp_target_info_t))) { +- printk(KERN_ERR "%s@%d: mptctl_hp_target_info - " ++ printk(KERN_ERR "%s@%d::mptctl_hp_target_info - " + "Unable to write out mpt_ioctl_targetinfo struct @ %p\n", + __FILE__, __LINE__, uarg); + return -EFAULT; +@@ -3231,8 +3039,6 @@ allocDiagBuffer: + DiagBufferPostRequest->BufferAddress.Low = cpu_to_le32(tmp); + + ioc->ioctl->wait_done = 0; +- INITIALIZE_IOCTL_STATUS(ioc->ioctl->status) +- + mpt_put_msg_frame(mptctl_id, ioc, mf); + + /* Now wait for the command to complete */ +@@ -3275,6 +3081,10 @@ allocDiagBuffer: + + mptctl_register_diag_buffer_out: + ++ ioc->ioctl->status &= ~( MPT_IOCTL_STATUS_TM_FAILED | ++ MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID | ++ MPT_IOCTL_STATUS_RF_VALID ); ++ + if ( rc ) { + pci_free_consistent(ioc->pcidev, request_data_sz, + request_data, +@@ -3371,8 +3181,6 @@ mptctl_release_diag_buffer (unsigned lon + DiagRelease->MsgFlags = 0; + + ioc->ioctl->wait_done = 0; +- INITIALIZE_IOCTL_STATUS(ioc->ioctl->status) +- + mpt_put_msg_frame(mptctl_id, ioc, mf); + + /* Now wait for the command to complete */ +@@ -3410,6 +3218,10 @@ mptctl_release_diag_buffer (unsigned lon + + mptctl_release_diag_buffer_out: + ++ ioc->ioctl->status &= ~( MPT_IOCTL_STATUS_TM_FAILED | ++ MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID | ++ MPT_IOCTL_STATUS_RF_VALID); ++ + return rc; + } + +@@ -3706,8 +3518,6 @@ mptctl_read_diag_buffer (unsigned long a + DiagBufferPostRequest->BufferAddress.Low = cpu_to_le32(tmp); + + ioc->ioctl->wait_done = 0; +- INITIALIZE_IOCTL_STATUS(ioc->ioctl->status) +- + mpt_put_msg_frame(mptctl_id, ioc, mf); + + /* Now wait for the command to complete */ +@@ -3746,8 +3556,14 @@ mptctl_read_diag_buffer (unsigned long a + ioc->ioctl->status)); + rc = -EFAULT; + } +- } ++ + mptctl_read_diag_buffer_out: ++ ++ ioc->ioctl->status &= ~( MPT_IOCTL_STATUS_TM_FAILED | ++ MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID | ++ MPT_IOCTL_STATUS_RF_VALID); ++ ++ } + return rc; + } + +@@ -3796,7 +3612,7 @@ compat_mptctl_ioctl(unsigned int fd, uns + int ret; + + lock_kernel(); +- dctlprintk((KERN_INFO MYNAM ": compat_mptctl_ioctl() called\n")); ++ dctlprintk((KERN_INFO MYNAM "::compat_mptctl_ioctl() called\n")); + ret = mptctl_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); + unlock_kernel(); + return ret; +@@ -3820,7 +3636,7 @@ compat_mptfwxfer_ioctl(struct file *filp + int nonblock = (filp->f_flags & O_NONBLOCK); + int ret; + +- dctlprintk((KERN_INFO MYNAM ": compat_mptfwxfer_ioctl() called\n")); ++ dctlprintk((KERN_INFO MYNAM "::compat_mptfwxfer_ioctl() called\n")); + + if (copy_from_user(&kfw32, (char __user *)arg, sizeof(kfw32))) + return -EFAULT; +@@ -3829,7 +3645,7 @@ compat_mptfwxfer_ioctl(struct file *filp + iocnumX = kfw32.iocnum & 0xFF; + if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) || + (iocp == NULL)) { +- dctlprintk((KERN_ERR MYNAM ": compat_mptfwxfer_ioctl @%d - ioc%d not found!\n", ++ dctlprintk((KERN_ERR MYNAM "::compat_mptfwxfer_ioctl @%d - ioc%d not found!\n", + __LINE__, iocnumX)); + return -ENODEV; + } +@@ -3866,7 +3682,7 @@ compat_mpt_command(struct file *filp, un + int nonblock = (filp->f_flags & O_NONBLOCK); + int ret; + +- dctlprintk((KERN_INFO MYNAM ": compat_mpt_command() called\n")); ++ dctlprintk((KERN_INFO MYNAM "::compat_mpt_command() called\n")); + + if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32))) + return -EFAULT; +@@ -3875,7 +3691,7 @@ compat_mpt_command(struct file *filp, un + iocnumX = karg32.hdr.iocnum & 0xFF; + if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) || + (iocp == NULL)) { +- dctlprintk((KERN_ERR MYNAM ": compat_mpt_command @%d - ioc%d not found!\n", ++ dctlprintk((KERN_ERR MYNAM "::compat_mpt_command @%d - ioc%d not found!\n", + __LINE__, iocnumX)); + return -ENODEV; + } +@@ -4087,14 +3903,6 @@ static int __init mptctl_init(void) + if (++where && err) goto out_fail; + err = register_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_CONFIG, compat_mptctl_ioctl); + if (++where && err) goto out_fail; +- err = register_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_FEATURES, compat_mptctl_ioctl); +- if (++where && err) goto out_fail; +- err = register_ioctl32_conversion(CC_CSMI_SAS_SET_RAID_CONTROL, compat_mptctl_ioctl); +- if (++where && err) goto out_fail; +- err = register_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_ELEMENT, compat_mptctl_ioctl); +- if (++where && err) goto out_fail; +- err = register_ioctl32_conversion(CC_CSMI_SAS_SET_RAID_OPERATION, compat_mptctl_ioctl); +- if (++where && err) goto out_fail; + err = register_ioctl32_conversion(CC_CSMI_SAS_SET_PHY_INFO, compat_mptctl_ioctl); + if (++where && err) goto out_fail; + err = register_ioctl32_conversion(CC_CSMI_SAS_STP_PASSTHRU, compat_mptctl_ioctl); +@@ -4185,10 +3993,6 @@ out_fail: + unregister_ioctl32_conversion(CC_CSMI_SAS_FIRMWARE_DOWNLOAD); + unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_INFO); + unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_CONFIG); +- unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_FEATURES); +- unregister_ioctl32_conversion(CC_CSMI_SAS_SET_RAID_CONTROL); +- unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_ELEMENT); +- unregister_ioctl32_conversion(CC_CSMI_SAS_SET_RAID_OPERATION); + unregister_ioctl32_conversion(CC_CSMI_SAS_SET_PHY_INFO); + unregister_ioctl32_conversion(CC_CSMI_SAS_STP_PASSTHRU); + unregister_ioctl32_conversion(CC_CSMI_SAS_TASK_MANAGEMENT); +@@ -4260,10 +4064,6 @@ static void mptctl_exit(void) + unregister_ioctl32_conversion(CC_CSMI_SAS_FIRMWARE_DOWNLOAD); + unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_INFO); + unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_CONFIG); +- unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_FEATURES); +- unregister_ioctl32_conversion(CC_CSMI_SAS_SET_RAID_CONTROL); +- unregister_ioctl32_conversion(CC_CSMI_SAS_GET_RAID_ELEMENT); +- unregister_ioctl32_conversion(CC_CSMI_SAS_SET_RAID_OPERATION); + unregister_ioctl32_conversion(CC_CSMI_SAS_SET_PHY_INFO); + unregister_ioctl32_conversion(CC_CSMI_SAS_STP_PASSTHRU); + unregister_ioctl32_conversion(CC_CSMI_SAS_TASK_MANAGEMENT); +@@ -4277,7 +4077,7 @@ static void mptctl_exit(void) + } + + #if defined(CPQ_CIM) +-#include "csmi/csmisas.c" ++#include "csmisas.c" + #endif // CPQ_CIM + + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptctl.h linux-2.6.9-55.0.12/drivers/message/fusion/mptctl.h +--- linux-2.6.9-67.0.1/drivers/message/fusion/mptctl.h 2007-12-21 11:40:54.000000000 +0100 ++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptctl.h 2007-11-02 09:10:23.000000000 +0100 +@@ -5,8 +5,8 @@ + * LSIFC9xx/LSI409xx Fibre Channel + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * +- * Copyright (c) 1999-2007 LSI Logic Corporation +- * (mailto:mpt_linux_developer@lsi.com) ++ * Copyright (c) 1999-2005 LSI Logic Corporation ++ * (mailto:mpt_linux_developer@lsil.com) + * + * $Id: mptctl.h,v 1.14 2003/03/18 22:49:51 Exp $ + */ +@@ -59,6 +59,7 @@ + */ + #define MPT_MISCDEV_BASENAME "mptctl" + #define MPT_MISCDEV_PATHNAME "/dev/" MPT_MISCDEV_BASENAME ++#define MPT_CSMI_DESCRIPTION "LSI Logic Corporation: Fusion MPT Driver "MPT_LINUX_VERSION_COMMON + + #define MPT_PRODUCT_LENGTH 12 + +@@ -94,16 +95,6 @@ + #define MPTDIAGQUERY _IOWR(MPT_MAGIC_NUMBER,29,mpt_diag_query_t) + #define MPTDIAGREADBUFFER _IOWR(MPT_MAGIC_NUMBER,30,mpt_diag_read_buffer_t) + +-#ifdef MPT_SUPPORT_FWDLB_IOCTL +-#define MPTHBAPCIINFO _IOWR(MPT_MAGIC_NUMBER,31,struct mpt_ioctl_hbapciinfo) +-#endif +- +- +-#define INITIALIZE_IOCTL_STATUS(status) \ +- status &= ~( MPT_IOCTL_STATUS_COMMAND_GOOD \ +- | MPT_IOCTL_STATUS_SENSE_VALID \ +- | MPT_IOCTL_STATUS_RF_VALID); +- + /* + * SPARC PLATFORM REMARKS: + * IOCTL data structures that contain pointers +@@ -314,28 +305,6 @@ typedef struct mpt_ioctl_replace_fw { + u8 newImage[1]; + } mpt_ioctl_replace_fw_t; + +-#ifdef MPT_SUPPORT_FWDLB_IOCTL +-struct mpt_ioctl_mptpciinfo { +- U8 iocNumber; +- U8 iocState; +- U8 revisionID; +- U8 reserved1; +- U16 vendorID; +- U16 deviceID; +- U16 subSystemVendorID; +- U16 subSystemID; +-}; +- +- +-struct mpt_ioctl_hbapciinfo { +- mpt_ioctl_header hdr; +- U8 totalIOC; +- U8 reserved[3]; +- struct mpt_ioctl_mptpciinfo hbapciinfo[18]; +-}; +-#endif +- +- + /* General MPT Pass through data strucutre + * + * iocnum +diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptfc.c linux-2.6.9-55.0.12/drivers/message/fusion/mptfc.c +--- linux-2.6.9-67.0.1/drivers/message/fusion/mptfc.c 2007-12-21 11:40:54.000000000 +0100 ++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptfc.c 2007-11-02 09:10:23.000000000 +0100 +@@ -3,8 +3,8 @@ + * For use with LSI Logic PCI chip/adapter(s) + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * +- * Copyright (c) 1999-2007 LSI Logic Corporation +- * (mailto:mpt_linux_developer@lsi.com) ++ * Copyright (c) 1999-2005 LSI Logic Corporation ++ * (mailto:mpt_linux_developer@lsil.com) + * + */ + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +@@ -74,7 +74,6 @@ + MODULE_AUTHOR(MODULEAUTHOR); + MODULE_DESCRIPTION(my_NAME); + MODULE_LICENSE("GPL"); +-MODULE_VERSION(my_VERSION); + + /* Command line args */ + static int mpt_pq_filter = 0; +@@ -131,7 +130,7 @@ static struct scsi_host_template mptfc_d + .bios_param = mptscsih_bios_param, + .can_queue = MPT_FC_CAN_QUEUE, + .this_id = -1, +- .sg_tablesize = CONFIG_FUSION_MAX_SGE, ++ .sg_tablesize = MPT_SCSI_SG_DEPTH, + .max_sectors = 8192, + .cmd_per_lun = 7, + .use_clustering = ENABLE_CLUSTERING, +@@ -161,8 +160,6 @@ static struct pci_device_id mptfc_pci_ta + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949E, + PCI_ANY_ID, PCI_ANY_ID }, +- { 0x1657, MPI_MANUFACTPAGE_DEVICEID_FC949E, +- PCI_ANY_ID, PCI_ANY_ID }, + {0} /* Terminating entry */ + }; + MODULE_DEVICE_TABLE(pci, mptfc_pci_table); +@@ -184,6 +181,8 @@ mptfc_probe(struct pci_dev *pdev, const + MPT_ADAPTER *ioc; + unsigned long flags; + int sz, ii; ++ int numSGE = 0; ++ int scale; + int ioc_cap; + u8 *mem; + int error=0; +@@ -262,16 +261,46 @@ mptfc_probe(struct pci_dev *pdev, const + ioc->name, mpt_can_queue, ioc->req_depth, + sh->can_queue)); + +- sh->max_id = ioc->DevicesPerBus; ++ sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255; + + sh->max_lun = MPT_LAST_LUN + 1; +- sh->max_channel = ioc->NumberOfBuses - 1; ++ sh->max_channel = 0; + sh->this_id = ioc->pfacts[0].PortSCSIID; + ++ + /* Required entry. + */ + sh->unique_id = ioc->id; +- sh->sg_tablesize = ioc->sg_tablesize; ++ ++ /* Verify that we won't exceed the maximum ++ * number of chain buffers ++ * We can optimize: ZZ = req_sz/sizeof(SGE) ++ * For 32bit SGE's: ++ * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ ++ * + (req_sz - 64)/sizeof(SGE) ++ * A slightly different algorithm is required for ++ * 64bit SGEs. ++ */ ++ scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); ++ if (sizeof(dma_addr_t) == sizeof(u64)) { ++ numSGE = (scale - 1) * ++ (ioc->facts.MaxChainDepth-1) + scale + ++ (ioc->req_sz - 60) / (sizeof(dma_addr_t) + ++ sizeof(u32)); ++ } else { ++ numSGE = 1 + (scale - 1) * ++ (ioc->facts.MaxChainDepth-1) + scale + ++ (ioc->req_sz - 64) / (sizeof(dma_addr_t) + ++ sizeof(u32)); ++ } ++ ++ if (numSGE < sh->sg_tablesize) { ++ /* Reset this value */ ++ dprintk((MYIOC_s_INFO_FMT ++ "Resetting sg_tablesize to %d from %d\n", ++ ioc->name, numSGE, sh->sg_tablesize)); ++ sh->sg_tablesize = numSGE; ++ } + + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)) + /* Set the pci device pointer in Scsi_Host structure. +@@ -300,24 +329,23 @@ mptfc_probe(struct pci_dev *pdev, const + dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", + ioc->name, hd->ScsiLookup, sz)); + +- for (ii=0; ii < ioc->NumberOfBuses; ii++) { +- /* Allocate memory for the device structures. +- * A non-Null pointer at an offset +- * indicates a device exists. +- */ +- sz = ioc->DevicesPerBus * sizeof(void *); +- mem = kmalloc(sz, GFP_ATOMIC); +- if (mem == NULL) { +- error = -ENOMEM; +- goto out_mptfc_probe; +- } ++ /* Allocate memory for the device structures. ++ * A non-Null pointer at an offset ++ * indicates a device exists. ++ * max_id = 1 + maximum id (hosts.h) ++ */ ++ sz = sh->max_id * sizeof(void *); ++ mem = kmalloc(sz, GFP_ATOMIC); ++ if (mem == NULL) { ++ error = -ENOMEM; ++ goto out_mptfc_probe; ++ } + +- memset(mem, 0, sz); +- ioc->Target_List[ii] = (struct _MPT_DEVICE *) mem; ++ memset(mem, 0, sz); ++ hd->Targets = (VirtDevice **) mem; + +- dinitprintk((KERN_INFO +- " For Bus=%d, Target_List=%p sz=%d\n", ii, mem, sz)); +- } ++ dprintk((KERN_INFO ++ " Targets @ %p, sz=%d\n", hd->Targets, sz)); + + /* Clear the TM flags + */ +@@ -333,17 +361,13 @@ mptfc_probe(struct pci_dev *pdev, const + */ + hd->cmdPtr = NULL; + +- /* Initialize this IOC's timers ++ /* Initialize this SCSI Hosts' timers + * To use, set the timer expires field +- * and add_timer. Used for internally +- * generated commands. ++ * and add_timer + */ +- init_timer(&hd->InternalCmdTimer); +- hd->InternalCmdTimer.data = (unsigned long) hd; +- hd->InternalCmdTimer.function = mptscsih_InternalCmdTimer_expired; +- init_timer(&ioc->TMtimer); +- ioc->TMtimer.data = (unsigned long) ioc; +- ioc->TMtimer.function = mptscsih_TM_timeout; ++ init_timer(&hd->timer); ++ hd->timer.data = (unsigned long) hd; ++ hd->timer.function = mptscsih_timer_expired; + + hd->mpt_pq_filter = mpt_pq_filter; + +@@ -356,9 +380,6 @@ mptfc_probe(struct pci_dev *pdev, const + hd->scandv_wait_done = 0; + hd->last_queue_full = 0; + +- init_waitqueue_head(&hd->TM_waitq); +- hd->TM_wait_done = 0; +- + error = scsi_add_host (sh, &ioc->pcidev->dev); + if(error) { + dprintk((KERN_ERR MYNAM +@@ -394,60 +415,6 @@ static struct pci_driver mptfc_driver = + }; + + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +-int +-mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) +-{ +- MPT_SCSI_HOST *hd; +- u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; +- +- devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to FC host driver!\n", +- ioc->name, event)); +- +- if (ioc->sh == NULL || +- ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) +- return 1; +- +- switch (event) { +- case MPI_EVENT_UNIT_ATTENTION: /* 03 */ +- /* FIXME! */ +- break; +- case MPI_EVENT_IOC_BUS_RESET: /* 04 */ +- case MPI_EVENT_EXT_BUS_RESET: /* 05 */ +- if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1)) +- hd->soft_resets++; +- break; +- case MPI_EVENT_LOGOUT: /* 09 */ +- /* FIXME! */ +- break; +- +- /* +- * CHECKME! Don't think we need to do +- * anything for these, but... +- */ +- case MPI_EVENT_RESCAN: /* 06 */ +- case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */ +- case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */ +- /* +- * CHECKME! Falling thru... +- */ +- break; +- +- case MPI_EVENT_NONE: /* 00 */ +- case MPI_EVENT_LOG_DATA: /* 01 */ +- case MPI_EVENT_STATE_CHANGE: /* 02 */ +- case MPI_EVENT_EVENT_CHANGE: /* 0A */ +- case MPI_EVENT_INTEGRATED_RAID: /* 0B */ +- default: +- devtprintk((KERN_INFO "%s: Ignoring event (=%02Xh)\n", +- __FUNCTION__, event)); +- break; +- } +- +- return 1; /* currently means nothing really */ +-} +- +- +-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + /** + * mptfc_init - Register MPT adapter(s) as SCSI host(s) with + * linux scsi mid-layer. +@@ -464,9 +431,9 @@ mptfc_init(void) + mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER); + mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER); + +- if (mpt_event_register(mptfcDoneCtx, mptfc_event_process) == 0) { ++ if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) { + devtprintk((KERN_INFO MYNAM +- ": mptfc_event_process Registered for IOC event notifications\n")); ++ ": Registered for IOC event notifications\n")); + } + + if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) { +@@ -488,7 +455,6 @@ mptfc_exit(void) + { + pci_unregister_driver(&mptfc_driver); + +- + mpt_reset_deregister(mptfcDoneCtx); + dprintk((KERN_INFO MYNAM + ": Deregistered for IOC reset notifications\n")); +diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptlan.c linux-2.6.9-55.0.12/drivers/message/fusion/mptlan.c +--- linux-2.6.9-67.0.1/drivers/message/fusion/mptlan.c 2007-12-21 11:40:54.000000000 +0100 ++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptlan.c 2007-11-02 09:10:23.000000000 +0100 +@@ -4,7 +4,7 @@ + * For use with LSI Logic Fibre Channel PCI chip/adapters + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * +- * Copyright (c) 2000-2007 LSI Logic Corporation ++ * Copyright (c) 2000-2005 LSI Logic Corporation + * + * $Id: mptlan.c,v 1.55 2003/05/07 14:08:32 Exp $ + */ +@@ -57,11 +57,9 @@ + #include <linux/module.h> + #include <linux/fs.h> + +-#define my_VERSION MPT_LINUX_VERSION_COMMON + #define MYNAM "mptlan" + + MODULE_LICENSE("GPL"); +-MODULE_VERSION(my_VERSION); + + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + /* +@@ -185,16 +183,16 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_H + struct net_device *dev = ioc->netdev; + int FreeReqFrame = 0; + +- dlioprintk((KERN_INFO MYNAM ": %s/%s: Got reply.\n", ++ dioprintk((KERN_INFO MYNAM ": %s/%s: Got reply.\n", + IOC_AND_NETDEV_NAMES_s_s(dev))); + +-// dlioprintk((KERN_INFO MYNAM "@lan_reply: mf = %p, reply = %p\n", ++// dioprintk((KERN_INFO MYNAM "@lan_reply: mf = %p, reply = %p\n", + // mf, reply)); + + if (mf == NULL) { + u32 tmsg = CAST_PTR_TO_U32(reply); + +- dlioprintk((KERN_INFO MYNAM ": %s/%s: @lan_reply, tmsg %08x\n", ++ dioprintk((KERN_INFO MYNAM ": %s/%s: @lan_reply, tmsg %08x\n", + IOC_AND_NETDEV_NAMES_s_s(dev), + tmsg)); + +@@ -204,14 +202,14 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_H + // mptbase.c::mpt_interrupt() routine and callcack here + #if 0 + case LAN_REPLY_FORM_MESSAGE_CONTEXT: +-// dlioprintk((KERN_INFO MYNAM "/lan_reply: " ++// dioprintk((KERN_INFO MYNAM "/lan_reply: " + // "MessageContext turbo reply received\n")); + FreeReqFrame = 1; + break; + #endif + + case LAN_REPLY_FORM_SEND_SINGLE: +-// dlioprintk((MYNAM "/lan_reply: " ++// dioprintk((MYNAM "/lan_reply: " + // "calling mpt_lan_send_reply (turbo)\n")); + + // FreeReqFrame = mpt_lan_send_turbo(dev, tmsg); +@@ -230,7 +228,7 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_H + break; + + case LAN_REPLY_FORM_RECEIVE_SINGLE: +-// dlioprintk((KERN_INFO MYNAM "@lan_reply: " ++// dioprintk((KERN_INFO MYNAM "@lan_reply: " + // "rcv-Turbo = %08x\n", tmsg)); + mpt_lan_receive_post_turbo(dev, tmsg); + break; +@@ -248,10 +246,10 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_H + } + + // msg = (u32 *) reply; +-// dlioprintk((KERN_INFO MYNAM "@lan_reply: msg = %08x %08x %08x %08x\n", ++// dioprintk((KERN_INFO MYNAM "@lan_reply: msg = %08x %08x %08x %08x\n", + // le32_to_cpu(msg[0]), le32_to_cpu(msg[1]), + // le32_to_cpu(msg[2]), le32_to_cpu(msg[3]))); +-// dlioprintk((KERN_INFO MYNAM "@lan_reply: Function = %02xh\n", ++// dioprintk((KERN_INFO MYNAM "@lan_reply: Function = %02xh\n", + // reply->u.hdr.Function)); + + switch (reply->u.hdr.Function) { +@@ -275,7 +273,7 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_H + if (!(pRecvRep->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) + FreeReqFrame = 1; + } else +- dlioprintk((KERN_INFO MYNAM "@lan_reply: zero context " ++ dioprintk((KERN_INFO MYNAM "@lan_reply: zero context " + "ReceivePostReply received.\n")); + break; + } +@@ -617,7 +615,7 @@ mpt_lan_send_turbo(struct net_device *de + priv->stats.tx_packets++; + priv->stats.tx_bytes += sent->len; + +- dlioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n", ++ dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n", + IOC_AND_NETDEV_NAMES_s_s(dev), + __FUNCTION__, sent)); + +@@ -649,7 +647,7 @@ mpt_lan_send_reply(struct net_device *de + + count = pSendRep->NumberOfContexts; + +- dlioprintk((KERN_INFO MYNAM ": send_reply: IOCStatus: %04x\n", ++ dioprintk((KERN_INFO MYNAM ": send_reply: IOCStatus: %04x\n", + le16_to_cpu(pSendRep->IOCStatus))); + + /* Add check for Loginfo Flag in IOCStatus */ +@@ -683,7 +681,7 @@ mpt_lan_send_reply(struct net_device *de + sent = priv->SendCtl[ctx].skb; + priv->stats.tx_bytes += sent->len; + +- dlioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n", ++ dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n", + IOC_AND_NETDEV_NAMES_s_s(dev), + __FUNCTION__, sent)); + +@@ -722,7 +720,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, s + int ctx; + u16 cur_naa = 0x1000; + +- dlioprintk((KERN_INFO MYNAM ": %s called, skb_addr = %p\n", ++ dioprintk((KERN_INFO MYNAM ": %s called, skb_addr = %p\n", + __FUNCTION__, skb)); + + spin_lock_irqsave(&priv->txfidx_lock, flags); +@@ -748,7 +746,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, s + ctx = priv->mpt_txfidx[priv->mpt_txfidx_tail--]; + spin_unlock_irqrestore(&priv->txfidx_lock, flags); + +-// dlioprintk((KERN_INFO MYNAM ": %s/%s: Creating new msg frame (send).\n", ++// dioprintk((KERN_INFO MYNAM ": %s/%s: Creating new msg frame (send).\n", + // IOC_AND_NETDEV_NAMES_s_s(dev))); + + pSendReq = (LANSendRequest_t *) mf; +@@ -783,7 +781,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, s + pTrans->Flags = 0; + pTrans->TransactionContext[0] = cpu_to_le32(ctx); + +-// dlioprintk((KERN_INFO MYNAM ": %s/%s: BC = %08x, skb = %p, buff = %p\n", ++// dioprintk((KERN_INFO MYNAM ": %s/%s: BC = %08x, skb = %p, buff = %p\n", + // IOC_AND_NETDEV_NAMES_s_s(dev), + // ctx, skb, skb->data)); + +@@ -843,7 +841,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, s + mpt_put_msg_frame (LanCtx, mpt_dev, mf); + dev->trans_start = jiffies; + +- dlioprintk((KERN_INFO MYNAM ": %s/%s: Sending packet. FlagsLength = %08x.\n", ++ dioprintk((KERN_INFO MYNAM ": %s/%s: Sending packet. FlagsLength = %08x.\n", + IOC_AND_NETDEV_NAMES_s_s(dev), + le32_to_cpu(pSimple->FlagsLength))); + +@@ -864,10 +862,10 @@ mpt_lan_wake_post_buckets_task(struct ne + schedule_work(&priv->post_buckets_task); + } else { + schedule_delayed_work(&priv->post_buckets_task, 1); +- dlioprintk((KERN_INFO MYNAM ": post_buckets queued on " ++ dioprintk((KERN_INFO MYNAM ": post_buckets queued on " + "timer.\n")); + } +- dlioprintk((KERN_INFO MYNAM ": %s/%s: Queued post_buckets task.\n", ++ dioprintk((KERN_INFO MYNAM ": %s/%s: Queued post_buckets task.\n", + IOC_AND_NETDEV_NAMES_s_s(dev) )); + } + } +@@ -880,7 +878,7 @@ mpt_lan_receive_skb(struct net_device *d + + skb->protocol = mpt_lan_type_trans(skb, dev); + +- dlioprintk((KERN_INFO MYNAM ": %s/%s: Incoming packet (%d bytes) " ++ dioprintk((KERN_INFO MYNAM ": %s/%s: Incoming packet (%d bytes) " + "delivered to upper level.\n", + IOC_AND_NETDEV_NAMES_s_s(dev), skb->len)); + +@@ -890,13 +888,13 @@ mpt_lan_receive_skb(struct net_device *d + skb->dev = dev; + netif_rx(skb); + +- dlioprintk((MYNAM "/receive_skb: %d buckets remaining\n", ++ dioprintk((MYNAM "/receive_skb: %d buckets remaining\n", + atomic_read(&priv->buckets_out))); + + if (atomic_read(&priv->buckets_out) < priv->bucketthresh) + mpt_lan_wake_post_buckets_task(dev, 1); + +- dlioprintk((KERN_INFO MYNAM "/receive_post_reply: %d buckets " ++ dioprintk((KERN_INFO MYNAM "/receive_post_reply: %d buckets " + "remaining, %d received back since sod\n", + atomic_read(&priv->buckets_out), priv->total_received)); + +@@ -1027,8 +1025,8 @@ mpt_lan_receive_post_reply(struct net_de + int count; + int i, l; + +- dlioprintk((KERN_INFO MYNAM ": mpt_lan_receive_post_reply called\n")); +- dlioprintk((KERN_INFO MYNAM ": receive_post_reply: IOCStatus: %04x\n", ++ dioprintk((KERN_INFO MYNAM ": mpt_lan_receive_post_reply called\n")); ++ dioprintk((KERN_INFO MYNAM ": receive_post_reply: IOCStatus: %04x\n", + le16_to_cpu(pRecvRep->IOCStatus))); + + if ((le16_to_cpu(pRecvRep->IOCStatus) & MPI_IOCSTATUS_MASK) == +@@ -1057,14 +1055,14 @@ mpt_lan_receive_post_reply(struct net_de + // offset); + // } + +- dlioprintk((KERN_INFO MYNAM ": %s/%s: @rpr, offset = %d, len = %d\n", ++ dioprintk((KERN_INFO MYNAM ": %s/%s: @rpr, offset = %d, len = %d\n", + IOC_AND_NETDEV_NAMES_s_s(dev), + offset, len)); + + if (count > 1) { + int szrem = len; + +-// dlioprintk((KERN_INFO MYNAM ": %s/%s: Multiple buckets returned " ++// dioprintk((KERN_INFO MYNAM ": %s/%s: Multiple buckets returned " + // "for single packet, concatenating...\n", + // IOC_AND_NETDEV_NAMES_s_s(dev))); + +@@ -1086,7 +1084,7 @@ mpt_lan_receive_post_reply(struct net_de + if (szrem < l) + l = szrem; + +-// dlioprintk((KERN_INFO MYNAM ": %s/%s: Buckets = %d, len = %u\n", ++// dioprintk((KERN_INFO MYNAM ": %s/%s: Buckets = %d, len = %u\n", + // IOC_AND_NETDEV_NAMES_s_s(dev), + // i, l)); + +@@ -1214,7 +1212,7 @@ mpt_lan_post_receive_buckets(void *dev_i + curr = atomic_read(&priv->buckets_out); + buckets = (priv->max_buckets_out - curr); + +- dlioprintk((KERN_INFO MYNAM ": %s/%s: @%s, Start_buckets = %u, buckets_out = %u\n", ++ dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, Start_buckets = %u, buckets_out = %u\n", + IOC_AND_NETDEV_NAMES_s_s(dev), + __FUNCTION__, buckets, curr)); + +@@ -1226,7 +1224,7 @@ mpt_lan_post_receive_buckets(void *dev_i + if (mf == NULL) { + printk (KERN_ERR "%s: Unable to alloc request frame\n", + __FUNCTION__); +- dlioprintk((KERN_ERR "%s: %u buckets remaining\n", ++ dioprintk((KERN_ERR "%s: %u buckets remaining\n", + __FUNCTION__, buckets)); + goto out; + } +@@ -1337,9 +1335,9 @@ mpt_lan_post_receive_buckets(void *dev_i + } + + out: +- dlioprintk((KERN_INFO MYNAM "/%s: End_buckets = %u, priv->buckets_out = %u\n", ++ dioprintk((KERN_INFO MYNAM "/%s: End_buckets = %u, priv->buckets_out = %u\n", + __FUNCTION__, buckets, atomic_read(&priv->buckets_out))); +- dlioprintk((KERN_INFO MYNAM "/%s: Posted %u buckets and received %u back\n", ++ dioprintk((KERN_INFO MYNAM "/%s: Posted %u buckets and received %u back\n", + __FUNCTION__, priv->total_posted, priv->total_received)); + + clear_bit(0, &priv->post_buckets_active); +diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptlan.h linux-2.6.9-55.0.12/drivers/message/fusion/mptlan.h +--- linux-2.6.9-67.0.1/drivers/message/fusion/mptlan.h 2007-12-21 11:40:54.000000000 +0100 ++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptlan.h 2007-11-02 09:10:23.000000000 +0100 +@@ -65,9 +65,9 @@ MODULE_DESCRIPTION(LANAME); + + /*****************************************************************************/ + #ifdef MPT_LAN_IO_DEBUG +-#define dlioprintk(x) printk x ++#define dioprintk(x) printk x + #else +-#define dlioprintk(x) ++#define dioprintk(x) + #endif + + #ifdef MPT_LAN_DEBUG +diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptsas.c linux-2.6.9-55.0.12/drivers/message/fusion/mptsas.c +--- linux-2.6.9-67.0.1/drivers/message/fusion/mptsas.c 2007-12-21 11:40:54.000000000 +0100 ++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptsas.c 2007-11-02 09:10:23.000000000 +0100 +@@ -3,8 +3,8 @@ + * For use with LSI Logic PCI chip/adapter(s) + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * +- * Copyright (c) 1999-2007 LSI Logic Corporation +- * (mailto:mpt_linux_developer@lsi.com) ++ * Copyright (c) 1999-2005 LSI Logic Corporation ++ * (mailto:mpt_linux_developer@lsil.com) + * + */ + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +@@ -64,7 +64,6 @@ + + #include "mptbase.h" + #include "mptscsih.h" +-#include "mptsas.h" + + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + #define my_NAME "Fusion MPT SAS Host driver" +@@ -74,10 +73,8 @@ + MODULE_AUTHOR(MODULEAUTHOR); + MODULE_DESCRIPTION(my_NAME); + MODULE_LICENSE("GPL"); +-MODULE_VERSION(my_VERSION); + + /* Command line args */ +- + static int mpt_pq_filter = 0; + module_param(mpt_pq_filter, int, 0); + MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)"); +@@ -90,627 +87,40 @@ static int mpt_sas_hot_plug_enable = 1; + module_param(mpt_sas_hot_plug_enable, int, 0); + MODULE_PARM_DESC(mpt_sas_hot_plug_enable, " Enable SAS Hot Plug Support: enable=1 (default=1)"); + +-static int mpt_cmd_retry_count = 144; +-module_param(mpt_cmd_retry_count, int, 0); +-MODULE_PARM_DESC(mpt_cmd_retry_count, " Device discovery TUR command retry count: default=144"); +- +-extern int mpt_enable_deadioc_detect; +- +-extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 bus, u8 id, u8 lun, int ctx2abort, ulong timeout); ++extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); + static int mptsasDoneCtx = -1; + static int mptsasTaskCtx = -1; + static int mptsasInternalCtx = -1; /* Used only for internal commands */ + +-static void mptsas_hotplug_work(void *arg); +- +-#if defined(CPQ_CIM) +-/** +- * mptsas_sas_io_unit_pg0 +- * +- * obtaining SAS_IO_UNIT page 0 +- * +- * @ioc +- * @port_info +- * +- **/ +-static int +-mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) +-{ +- ConfigExtendedPageHeader_t hdr; +- CONFIGPARMS cfg; +- SasIOUnitPage0_t *buffer; +- dma_addr_t dma_handle; +- int error, i; +- +- hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION; +- hdr.ExtPageLength = 0; +- hdr.PageNumber = 0; +- hdr.Reserved1 = 0; +- hdr.Reserved2 = 0; +- hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; +- hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; +- +- cfg.cfghdr.ehdr = &hdr; +- cfg.physAddr = -1; +- cfg.pageAddr = 0; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.dir = 0; /* read */ +- cfg.timeout = 10; +- +- error = mpt_config(ioc, &cfg); +- if (error) +- goto out; +- if (!hdr.ExtPageLength) { +- error = -ENXIO; +- goto out; +- } +- +- buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, +- &dma_handle); +- if (!buffer) { +- error = -ENOMEM; +- goto out; +- } +- +- cfg.physAddr = dma_handle; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- +- error = mpt_config(ioc, &cfg); +- if (error) +- goto out_free_consistent; +- +- port_info->num_phys = buffer->NumPhys; +- port_info->phy_info = kmalloc(port_info->num_phys * +- sizeof(*port_info->phy_info),GFP_KERNEL); +- if (!port_info->phy_info) { +- error = -ENOMEM; +- goto out_free_consistent; +- } +- +- if (port_info->num_phys) +- port_info->handle = +- le16_to_cpu(buffer->PhyData[0].ControllerDevHandle); +- for (i = 0; i < port_info->num_phys; i++) { +- port_info->phy_info[i].phy_id = i; +- port_info->phy_info[i].port_id = +- buffer->PhyData[i].Port; +- port_info->phy_info[i].negotiated_link_rate = +- buffer->PhyData[i].NegotiatedLinkRate; +- port_info->phy_info[i].portinfo = port_info; +- port_info->phy_info[i].port_flags = +- buffer->PhyData[i].PortFlags; +- } +- +- out_free_consistent: +- pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, +- buffer, dma_handle); +- out: +- return error; +-} +- +-/** +- * mptsas_sas_device_pg0 +- * +- * obtaining SAS_DEVICE page 0 +- * +- * @ioc +- * device_info +- * +- **/ +-static int +-mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, +- u32 form, u32 form_specific) +-{ +- ConfigExtendedPageHeader_t hdr; +- CONFIGPARMS cfg; +- SasDevicePage0_t *buffer; +- dma_addr_t dma_handle; +- u64 sas_address; +- int error=0; +- +- hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION; +- hdr.ExtPageLength = 0; +- hdr.PageNumber = 0; +- hdr.Reserved1 = 0; +- hdr.Reserved2 = 0; +- hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; +- hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE; +- +- cfg.cfghdr.ehdr = &hdr; +- cfg.pageAddr = form + form_specific; +- cfg.physAddr = -1; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.dir = 0; /* read */ +- cfg.timeout = 10; +- +- memset(device_info, 0, sizeof(struct mptsas_devinfo)); +- error = mpt_config(ioc, &cfg); +- if (error) +- goto out; +- if (!hdr.ExtPageLength) { +- error = -ENXIO; +- goto out; +- } +- +- buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, +- &dma_handle); +- if (!buffer) { +- error = -ENOMEM; +- goto out; +- } +- +- cfg.physAddr = dma_handle; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- +- error = mpt_config(ioc, &cfg); +- if (error) +- goto out_free_consistent; +- +- device_info->handle = le16_to_cpu(buffer->DevHandle); +- device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle); +- device_info->handle_enclosure = +- le16_to_cpu(buffer->EnclosureHandle); +- device_info->slot = le16_to_cpu(buffer->Slot); +- device_info->phy_id = buffer->PhyNum; +- device_info->port_id = buffer->PhysicalPort; +- device_info->id = buffer->TargetID; +- device_info->channel = buffer->Bus; +- memcpy(&sas_address, &buffer->SASAddress, sizeof(u64)); +- device_info->sas_address = le64_to_cpu(sas_address); +- device_info->device_info = +- le32_to_cpu(buffer->DeviceInfo); +- +- out_free_consistent: +- pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, +- buffer, dma_handle); +- out: +- return error; +-} +- +-/** +- * mptsas_get_number_hotspares - returns num hot spares in this ioc +- * @ioc: Pointer to MPT_ADAPTER structure +- * +- * Return: number of hotspares +- * +- **/ +-static int +-mptsas_get_number_hotspares(MPT_ADAPTER *ioc) +-{ +- ConfigPageHeader_t hdr; +- CONFIGPARMS cfg; +- IOCPage5_t *buffer = NULL; +- dma_addr_t dma_handle; +- int data_sz=0; +- int rc; +- +- memset(&hdr, 0, sizeof(ConfigPageHeader_t)); +- memset(&cfg, 0, sizeof(CONFIGPARMS)); +- +- rc = 0; +- hdr.PageNumber = 5; +- hdr.PageType = MPI_CONFIG_PAGETYPE_IOC; +- cfg.cfghdr.hdr = &hdr; +- cfg.physAddr = -1; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.timeout = 10; +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) +- goto get_ioc_pg5; +- +- if (hdr.PageLength == 0) +- goto get_ioc_pg5; +- +- data_sz = hdr.PageLength * 4; +- buffer = (IOCPage5_t *) pci_alloc_consistent(ioc->pcidev, +- data_sz, &dma_handle); +- if (!buffer) +- goto get_ioc_pg5; +- +- memset((u8 *)buffer, 0, data_sz); +- cfg.physAddr = dma_handle; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) +- goto get_ioc_pg5; +- +- rc = buffer->NumHotSpares; +- +- get_ioc_pg5: +- +- if (buffer) +- pci_free_consistent(ioc->pcidev, data_sz, +- (u8 *) buffer, dma_handle); +- +- return rc; +-} +- +-/** +- * mptsas_get_ioc_pg5 - ioc Page 5 hot spares +- * @ioc: Pointer to MPT_ADAPTER structure +- * @pIocPage5: ioc page 5 +- * +- * Return: 0 for success +- * -ENOMEM if no memory available +- * -EPERM if not allowed due to ISR context +- * -EAGAIN if no msg frames currently available +- * -EFAULT for non-successful reply or no reply (timeout) +- **/ +-static int +-mptsas_get_ioc_pg5(MPT_ADAPTER *ioc, IOCPage5_t *iocPage5) +-{ +- ConfigPageHeader_t hdr; +- CONFIGPARMS cfg; +- IOCPage5_t *buffer = NULL; +- dma_addr_t dma_handle; +- int data_sz=0; +- int rc; +- +- memset(&hdr, 0, sizeof(ConfigPageHeader_t)); +- memset(&cfg, 0, sizeof(CONFIGPARMS)); +- +- rc = 0; +- hdr.PageNumber = 5; +- hdr.PageType = MPI_CONFIG_PAGETYPE_IOC; +- cfg.cfghdr.hdr = &hdr; +- cfg.physAddr = -1; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- cfg.timeout = 10; +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) +- goto get_ioc_pg5; +- +- if (hdr.PageLength == 0) { +- rc = -EFAULT; +- goto get_ioc_pg5; +- } +- +- data_sz = hdr.PageLength * 4; +- buffer = (IOCPage5_t *) pci_alloc_consistent(ioc->pcidev, +- data_sz, &dma_handle); +- if (!buffer) { +- rc = -ENOMEM; +- goto get_ioc_pg5; +- } +- +- memset((u8 *)buffer, 0, data_sz); +- cfg.physAddr = dma_handle; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- +- if ((rc = mpt_config(ioc, &cfg)) != 0) +- goto get_ioc_pg5; +- +- memcpy(iocPage5, buffer, sizeof(*iocPage5)); +- +- get_ioc_pg5: +- +- if (buffer) +- pci_free_consistent(ioc->pcidev, data_sz, +- (u8 *) buffer, dma_handle); +- +- return rc; +-} +- +-/** +- * mptsas_add_device_component +- * +- * @ioc +- * @channel - fw mapped id's +- * @id +- * @sas_address +- * @device_info +- * +- **/ +-static void +-mptsas_add_device_component(MPT_ADAPTER *ioc, u8 channel, u8 id, +- u64 sas_address, u32 device_info) +-{ +- struct sas_device_info *sas_info, *next; +- +- down(&ioc->sas_device_info_mutex); +- +- /* +- * Delete all matching sas_address's out of tree +- */ +- list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list, list) { +- if (sas_info->sas_address != sas_address) +- continue; +- list_del(&sas_info->list); +- kfree(sas_info); +- } +- +- /* +- * If there is a matching channel/id, then swap out with new target info +- */ +- list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) { +- if (sas_info->fw.channel == channel && sas_info->fw.id == id) +- goto initialize_data; +- } +- +- if (!(sas_info = kmalloc(sizeof(*sas_info), GFP_KERNEL))) +- goto out; +- memset(sas_info, 0, sizeof(*sas_info)); +- +- /* +- * mapping - is for compatibility with drivers supporting sas transport layer +- */ +- sas_info->fw.id = id; +- sas_info->fw.channel = channel; +- sas_info->os.id = id; +- sas_info->os.channel = channel; +- list_add_tail(&sas_info->list, &ioc->sas_device_info_list); +- +- initialize_data: +- +- sas_info->sas_address = sas_address; +- sas_info->device_info = device_info; +- sas_info->is_cached = 0; +- sas_info->is_logical_volume = 0; +- devtprintk((KERN_INFO "%s: adding channel=%d id=%d " +- "sas_address=0x%llX\n", __FUNCTION__, channel, id, sas_address)); +- +- out: +- up(&ioc->sas_device_info_mutex); +- return; +-} +- +-/** +- * mptsas_add_device_component_single +- * +- * @ioc +- * @channel +- * @id +- * +- **/ +-static void +-mptsas_add_device_component_single(MPT_ADAPTER *ioc, u8 channel, u8 id) +-{ +- struct mptsas_devinfo sas_device; +- int rc; +- +- rc = mptsas_sas_device_pg0(ioc, &sas_device, +- (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << +- MPI_SAS_DEVICE_PGAD_FORM_SHIFT), +- (channel << 8) + id); +- if (rc) +- return; +- +- mptsas_add_device_component(ioc, sas_device.channel, +- sas_device.id, sas_device.sas_address, sas_device.device_info); +-} +- +-/** +- * mptsas_add_device_component_hotspare +- * +- * Handle adding hotspares into the list +- * +- * @ioc +- * +- **/ +-static void +-mptsas_add_device_component_hotspare(MPT_ADAPTER *ioc) +-{ +- int num_hotspares; +- IOCPage5_t *iocPage5; +- RaidPhysDiskPage0_t phys_disk; +- int i; +- +- iocPage5 = NULL; +- num_hotspares = mptsas_get_number_hotspares(ioc); +- if (!num_hotspares) +- goto out; +- +- iocPage5 = kmalloc(offsetof(IOCPage5_t,HotSpare) + +- num_hotspares * sizeof(IOC_5_HOT_SPARE), GFP_KERNEL); +- if (!iocPage5) +- goto out; +- memset(iocPage5, 0, sizeof(*iocPage5)); +- if (mptsas_get_ioc_pg5(ioc, iocPage5) != 0) +- goto out; +- for(i = 0; i < num_hotspares; i++) { +- mpt_raid_phys_disk_pg0(ioc, +- iocPage5->HotSpare[i].PhysDiskNum, &phys_disk ); +- mptsas_add_device_component_single(ioc, +- phys_disk.PhysDiskBus, phys_disk.PhysDiskID); +- } +- out: +- kfree(iocPage5); +- +-} +- +-/** +- * mptsas_add_device_component_ir +- * +- * Handle Integrated RAID, adding each individual device to list +- * +- * @ioc +- * @channel +- * @id +- * +- **/ +-static void +-mptsas_add_device_component_ir(MPT_ADAPTER *ioc, u8 channel, u8 id) +-{ +- CONFIGPARMS cfg; +- ConfigPageHeader_t hdr; +- dma_addr_t dma_handle; +- pRaidVolumePage0_t buffer = NULL; +- int i; +- RaidPhysDiskPage0_t phys_disk; +- struct sas_device_info *sas_info; +- +- memset(&cfg, 0 , sizeof(CONFIGPARMS)); +- memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); +- hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME; +- cfg.pageAddr = (channel << 8) + id; +- cfg.cfghdr.hdr = &hdr; +- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +- +- if (mpt_config(ioc, &cfg) != 0) +- goto out; +- +- if (!hdr.PageLength) +- goto out; +- +- buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, +- &dma_handle); +- +- if (!buffer) +- goto out; +- +- cfg.physAddr = dma_handle; +- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; +- +- if (mpt_config(ioc, &cfg) != 0) +- goto out; +- +- if (!buffer->NumPhysDisks) +- goto out; +- +- /* +- * Adding entry for hidden components +- */ +- for (i = 0; i < buffer->NumPhysDisks; i++) { +- +- if(mpt_raid_phys_disk_pg0(ioc, +- buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0) +- continue; + +- mptsas_add_device_component_single(ioc, phys_disk.PhysDiskBus, +- phys_disk.PhysDiskID); +- } +- +- /* +- * Adding entry for logical volume in list +- */ +- list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) { +- if (sas_info->fw.channel == channel && sas_info->fw.id == id) +- goto initialize_data; +- } +- +- if (!(sas_info = kmalloc(sizeof(*sas_info), GFP_KERNEL))) +- goto out; +- memset(sas_info, 0, sizeof(*sas_info)); +- +- sas_info->fw.id = id; +- sas_info->fw.channel = channel; /* channel zero */ +- down(&ioc->sas_device_info_mutex); +- list_add_tail(&sas_info->list, &ioc->sas_device_info_list); +- up(&ioc->sas_device_info_mutex); +- +- initialize_data: +- +- sas_info->os.id = id; +- sas_info->os.channel = channel; +- sas_info->sas_address = 0; +- sas_info->device_info = 0; +- sas_info->is_logical_volume = 1; +- sas_info->is_cached = 0; +- +- devtprintk((KERN_INFO "%s: adding volume at channel=%d id=%d\n", +- __FUNCTION__, channel, id)); +- +- mptsas_add_device_component_hotspare(ioc); +- out: +- if (buffer) +- pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, +- dma_handle); +-} +- +- +-/** +- * mptsas_del_device_component +- * +- * Once a device has been removed, we mark the +- * entry in the list as being cached +- * +- * @ioc +- * @channel - os mapped id's +- * @id +- * +- **/ +-static void +-mptsas_del_device_component(MPT_ADAPTER *ioc, u8 channel, u8 id) +-{ +- struct sas_device_info *sas_info, *next; +- +- /* +- * Set is_cached flag +- */ +- list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list, list) { +- if (sas_info->os.channel == channel && sas_info->os.id == id) { +- sas_info->is_cached = 1; +- devtprintk((KERN_INFO +- "%s: deleting channel=%d id=%d " +- "sas_address=0x%llX\n", __FUNCTION__, channel, id, +- sas_info->sas_address)); +- } +- } +-} +- +-/** +- * mptsas_del_device_components +- * +- * Cleaning the list +- * +- * @ioc +- * +- **/ +-static void +-mptsas_del_device_components(MPT_ADAPTER *ioc) +-{ +- struct sas_device_info *sas_info, *next; +- +- down(&ioc->sas_device_info_mutex); +- list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list, list) { +- list_del(&sas_info->list); +- kfree(sas_info); +- } +- up(&ioc->sas_device_info_mutex); +-} +-#endif +- +-/** +- * mptsas_find_vdevice +- * +- * @ioc +- * @channel +- * @id +- * +- **/ +-static VirtDevice * +-mptsas_find_vdevice(MPT_ADAPTER *ioc, u8 channel, u8 id) +-{ +- struct _MPT_DEVICE *pMptTarget; +- +- if (id >= ioc->DevicesPerBus || channel >= ioc->NumberOfBuses) +- return NULL; ++enum mptsas_hotplug_action { ++ MPTSAS_ADD_DEVICE, ++ MPTSAS_DEL_DEVICE, ++}; + +- pMptTarget = ioc->Target_List[channel]; +- return pMptTarget->Target[id]; +-} ++struct mptsas_hotplug_event { ++ struct work_struct work; ++ MPT_ADAPTER *ioc; ++ enum mptsas_hotplug_action event_type; ++ u64 sas_address; ++ u32 channel; ++ u32 id; ++ u32 device_info; ++ u16 handle; ++ u16 parent_handle; ++ u8 phy_id; ++ u8 isRaid; ++}; + +-/** +- * mptsas_qcmd +- * +- * receiving a scsi_cmnd from upper layers +- * +- * @SCpnt +- * @done +- * +- **/ + static int + mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) + { + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata; +- MPT_ADAPTER *ioc = hd->ioc; +- static VirtDevice *pTarget; +- int id = SCpnt->device->id; +- int channel = SCpnt->device->channel; +- +- /* If Device has been removed, inhibit any more IO */ +- pTarget = mptsas_find_vdevice(ioc, channel, id); +- if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_DELETED)) { ++ int id = SCpnt->device->id; ++ ++ /* Device has been removed, so inhibit any more IO */ ++ if (hd->Targets[id] && ++ hd->Targets[id]->tflags & MPT_TARGET_FLAGS_DELETED) { + SCpnt->result = DID_NO_CONNECT << 16; + done(SCpnt); + return 0; +@@ -719,32 +129,6 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, voi + return mptscsih_qcmd(SCpnt,done); + } + +-/** +- * mptsas_slave_configure +- * +- * +- * @sdev +- * +- **/ +-static int +-mptsas_slave_configure(struct scsi_device *sdev) +-{ +-#if defined(CPQ_CIM) +- MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata; +- MPT_ADAPTER *ioc = hd->ioc; +- int channel; +- int id; +- +- channel = sdev->channel; +- id = sdev->id; +- +- if ((ioc->raid_data.isRaid & (1 << id)) == 0) +- mptsas_add_device_component_single(ioc, channel, id); +-#endif +- return mptscsih_slave_configure(sdev); +-} +- +- + /* Show the ioc state for this card */ + static ssize_t + mptsas_show_iocstate(struct class_device *class_dev, char *buf) +@@ -778,300 +162,49 @@ static struct scsi_host_template mptsas_ + .info = mptscsih_info, + .queuecommand = mptsas_qcmd, + .slave_alloc = mptscsih_slave_alloc, +- .slave_configure = mptsas_slave_configure, +- .slave_destroy = mptscsih_slave_destroy, +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)) +- .change_queue_depth = mptscsih_change_queue_depth, +-#endif +- .eh_abort_handler = mptscsih_abort, +- .eh_device_reset_handler = mptscsih_dev_reset, +- .eh_bus_reset_handler = mptscsih_bus_reset, +- .eh_host_reset_handler = mptscsih_host_reset, +- .bios_param = mptscsih_bios_param, +- .can_queue = MPT_FC_CAN_QUEUE, +- .this_id = -1, +- .sg_tablesize = CONFIG_FUSION_MAX_SGE, +- .max_sectors = 8192, +- .cmd_per_lun = 7, +- .use_clustering = ENABLE_CLUSTERING, +- .shost_attrs = mptsas_host_attrs, +- .dump_sanity_check = mptscsih_sanity_check, +- .dump_poll = mptscsih_poll, +-}; +- +-/** +- * mptsas_remove +- * +- * +- * @pdev +- * +- **/ +-static void __devexit mptsas_remove(struct pci_dev *pdev) +-{ +-#if defined(CPQ_CIM) +- MPT_ADAPTER *ioc = pci_get_drvdata(pdev); +- if(ioc->sh != NULL) +- mptsas_del_device_components(ioc); +-#endif +- +- flush_scheduled_work(); +- mptscsih_remove(pdev); +-} +- +-/** +- * mptsas_target_reset +- * +- * Issues TARGET_RESET to end device using handshaking method +- * +- * @ioc +- * @channel +- * @id +- * +- * Returns (1) success +- * (0) failure +- * +- **/ +-static int +-mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id) +-{ +- MPT_FRAME_HDR *mf; +- SCSITaskMgmt_t *pScsiTm; +- +- if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) { +- dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n", +- ioc->name,__FUNCTION__, __LINE__)); +- return 0; +- } +- +- /* Format the Request +- */ +- pScsiTm = (SCSITaskMgmt_t *) mf; +- memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t)); +- pScsiTm->TargetID = id; +- pScsiTm->Bus = channel; +- pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; +- pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET; +- pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION; +- +-// EDM printk("tm target reset : issue : channel=%d id=%d\n", channel, id); +- DBG_DUMP_TM_REQUEST_FRAME(mf); +- +- if (mpt_send_handshake_request(ioc->TaskCtx, ioc, +- sizeof(SCSITaskMgmt_t), (u32 *)mf, 10,NO_SLEEP)) { +- mpt_free_msg_frame(ioc, mf); +- dfailprintk((MYIOC_s_WARN_FMT "%s, tm handshake failed @%d!!\n", +- ioc->name,__FUNCTION__, __LINE__)); +- return 0; +- } +- +- return 1; +-} +- +-/** +- * mptsas_target_reset_queue +- * +- * Receive request for TARGET_RESET after recieving an firmware +- * event NOT_RESPONDING_EVENT, then put command in link list +- * and queue if task_queue already in use. +- * +- * @ioc +- * @sas_event_data +- * +- **/ +-static void +-mptsas_target_reset_queue(MPT_ADAPTER *ioc, +- EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data) +-{ +- MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; +- VirtDevice *vdevice = NULL; +- struct mptscsih_target_reset *target_reset_list; +- u8 id, channel; +- +- id = sas_event_data->TargetID; +- channel = sas_event_data->Bus; +- +- if (!(vdevice = mptsas_find_vdevice(ioc, channel, id))) +- return; +- +- vdevice->tflags |= MPT_TARGET_FLAGS_DELETED; +- +- target_reset_list = kmalloc(sizeof(*target_reset_list), +- GFP_ATOMIC); +- if (!target_reset_list) { +- dfailprintk((MYIOC_s_WARN_FMT +- "%s, failed to allocate mem @%d..!!\n", +- ioc->name,__FUNCTION__, __LINE__)); +- return; +- } +- +- memset(target_reset_list, 0, sizeof(*target_reset_list)); +-// EDM printk("tm target reset : queue : channel=%d id=%d\n", channel, id); +- +- memcpy(&target_reset_list->sas_event_data, sas_event_data, +- sizeof(*sas_event_data)); +- list_add_tail(&target_reset_list->list, &hd->target_reset_list); +- +- if (hd->resetPending) +- return; +- +- if (mptsas_target_reset(ioc, channel, id)) { +- target_reset_list->target_reset_issued = 1; +- hd->resetPending = 1; +- } +-} +- +-/** +- * mptsas_dev_reset_complete +- * +- * Completion for TARGET_RESET after NOT_RESPONDING_EVENT, +- * enable work queue to finish off removing device from upper layers. +- * then send next TARGET_RESET in the queue. +- * +- * @ioc +- * +- **/ +-static void +-mptsas_dev_reset_complete(MPT_ADAPTER *ioc) +-{ +- MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; +- struct list_head *head = &hd->target_reset_list; +- struct mptscsih_target_reset *target_reset_list; +- struct mptsas_hotplug_event *ev; +- EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data; +- u8 id, channel; +- u64 sas_address; +- +- if (list_empty(head)) +- return; +- +- target_reset_list = list_entry(head->next, +- struct mptscsih_target_reset, list); +- +- sas_event_data = &target_reset_list->sas_event_data; +- id = sas_event_data->TargetID; +- channel = sas_event_data->Bus; +- hd->resetPending = 0; +- +- /* +- * retry target reset +- */ +- if (!target_reset_list->target_reset_issued) { +- if (mptsas_target_reset(ioc, channel, id)) { +- target_reset_list->target_reset_issued = 1; +- hd->resetPending = 1; +- } +- return; +- } +- +-// EDM printk("tm target reset : complete : channel=%d id=%d\n", channel, id); +- +- /* +- * enable work queue to remove device from upper layers +- */ +- list_del(&target_reset_list->list); +- +- ev = kmalloc(sizeof(*ev), GFP_ATOMIC); +- if (!ev) { +- dfailprintk((MYIOC_s_WARN_FMT +- "%s, failed to allocate mem @%d..!!\n", +- ioc->name,__FUNCTION__, __LINE__)); +- return; +- } +- +- memset(ev, 0, sizeof(*ev)); +- INIT_WORK(&ev->work, mptsas_hotplug_work, ev); +- ev->ioc = ioc; +- ev->handle = le16_to_cpu(sas_event_data->DevHandle); +- ev->parent_handle = le16_to_cpu(sas_event_data->ParentDevHandle); +- ev->channel = channel; +- ev->id = id; +- ev->phy_id = sas_event_data->PhyNum; +- memcpy(&sas_address, &sas_event_data->SASAddress, sizeof(u64)); +- ev->sas_address = le64_to_cpu(sas_address); +- ev->device_info = le32_to_cpu(sas_event_data->DeviceInfo); +- ev->event_type = MPTSAS_DEL_DEVICE; +- schedule_work(&ev->work); +- kfree(target_reset_list); +- +- /* +- * issue target reset to next device in the queue +- */ +- +- head = &hd->target_reset_list; +- if (list_empty(head)) +- return; +- +- target_reset_list = list_entry(head->next, struct mptscsih_target_reset, +- list); +- +- sas_event_data = &target_reset_list->sas_event_data; +- id = sas_event_data->TargetID; +- channel = sas_event_data->Bus; +- +- if (mptsas_target_reset(ioc, channel, id)) { +- target_reset_list->target_reset_issued = 1; +- hd->resetPending = 1; +- } +-} ++ .slave_configure = mptscsih_slave_configure, ++ .slave_destroy = mptscsih_slave_destroy, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)) ++ .change_queue_depth = mptscsih_change_queue_depth, ++#endif ++ .eh_abort_handler = mptscsih_abort, ++ .eh_device_reset_handler = mptscsih_dev_reset, ++ .eh_bus_reset_handler = mptscsih_bus_reset, ++ .eh_host_reset_handler = mptscsih_host_reset, ++ .bios_param = mptscsih_bios_param, ++ .can_queue = MPT_FC_CAN_QUEUE, ++ .this_id = -1, ++ .sg_tablesize = MPT_SCSI_SG_DEPTH, ++ .max_sectors = 8192, ++ .cmd_per_lun = 7, ++ .use_clustering = ENABLE_CLUSTERING, ++ .shost_attrs = mptsas_host_attrs, ++ .dump_sanity_check = mptscsih_sanity_check, ++ .dump_poll = mptscsih_poll, ++}; + +-/** +- * mptsas_taskmgmt_complete +- * +- * @ioc +- * @mf +- * @mr +- * +- **/ +-static int +-mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) ++static void __devexit mptsas_remove(struct pci_dev *pdev) + { +- mptsas_dev_reset_complete(ioc); +- return mptscsih_taskmgmt_complete(ioc, mf, mr); ++ flush_scheduled_work(); ++ mptscsih_remove(pdev); + } + +-/** +- * mptscsih_ioc_reset +- * +- * @ioc +- * @reset_phase +- * +- **/ +-static int +-mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) ++static void ++mptsas_target_reset(MPT_ADAPTER *ioc, VirtDevice * vdevice) + { +- MPT_SCSI_HOST *hd =NULL; +- struct mptscsih_target_reset *target_reset_list, *n; +- int rc; +- +- if ((ioc->sh != NULL) && (ioc->sh->hostdata != NULL)) +- hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; +- +- rc = mptscsih_ioc_reset(ioc, reset_phase); ++ MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; + +- if (reset_phase != MPT_IOC_POST_RESET) +- goto out; +- +- if (ioc->bus_type != SAS) +- goto out; +- if(hd == NULL) +- goto out; +- +- +- if (list_empty(&hd->target_reset_list)) +- goto out; +- +- /* flush the target_reset_list */ +- list_for_each_entry_safe(target_reset_list, n, +- &hd->target_reset_list, list) { +- list_del(&target_reset_list->list); +- kfree(target_reset_list); ++ if (mptscsih_TMHandler(hd, ++ MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, ++ vdevice->bus_id, vdevice->target_id, 0, 0, 5) < 0) { ++ hd->tmPending = 0; ++ hd->tmState = TM_STATE_NONE; ++ printk(MYIOC_s_WARN_FMT ++ "Error processing TaskMgmt id=%d TARGET_RESET\n", ++ ioc->name, vdevice->target_id); + } +- +- out: +- return rc; + } + +- + /**************************************************************************** + * Supported hardware + */ +@@ -1092,13 +225,6 @@ static struct pci_device_id mptsas_pci_t + MODULE_DEVICE_TABLE(pci, mptsas_pci_table); + + +-/** +- * mptscsih_sas_persist_clear_table +- * +- * +- * @ioc +- * +- **/ + static void + mptscsih_sas_persist_clear_table(void * arg) + { +@@ -1107,52 +233,76 @@ mptscsih_sas_persist_clear_table(void * + mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT); + } + +-/** +- * mptsas_hotplug_print +- * +- * +- * @ioc +- * @hot_plug_info +- * @msg_string +- * +- **/ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* mptbase_sas_update_device_list - ++ * This is called from the work queue. ++ * Purpose is to called when a logical volume has been created, deleted, ++ * or status change. ++ * Since in SAS the phydisk can be moved to different location, we will need ++ * to refresh the device list by recreating it. ++ */ ++static void ++mptscsih_sas_update_device_list(MPT_ADAPTER *ioc ) ++{ ++ sas_device_info_t *sasDevice, *pNext; ++ ++ /* ++ * Kill everything in the device list, then rediscover ++ */ ++ list_for_each_entry_safe(sasDevice, pNext, &ioc->sasDeviceList, list) { ++ list_del(&sasDevice->list); ++ kfree(sasDevice); ++ ioc->alloc_total -= sizeof (sas_device_info_t); ++ } ++ ++ if (ioc->sasPhyInfo != NULL) { ++ kfree(ioc->sasPhyInfo); ++ ioc->sasPhyInfo = NULL; ++ ioc->alloc_total -= ++ ioc->numPhys * sizeof (sas_phy_info_t); ++ } ++ ioc->numPhys = 0; ++ ++ /* ++ * Rescsan list ++ */ ++ mpt_sas_get_info(ioc); ++} ++ + static void + mptsas_hotplug_print(MPT_ADAPTER *ioc, struct mptsas_hotplug_event *hot_plug_info, u32 lun, u8 * msg_string) + { +- char *ds; ++ char *ds = NULL; + u32 id = hot_plug_info->id; +- u32 channel = hot_plug_info->channel; + +- if ( id >= ioc->DevicesPerBus ) { +- printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, DevicesPerBus=%d\n", +- ioc->name, __FUNCTION__, id, ioc->DevicesPerBus); ++ if ( id > ioc->pfacts->MaxDevices ) { ++ printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, MaxDevices=%d\n", ++ ioc->name, __FUNCTION__, id, ioc->pfacts->MaxDevices); + return; + } + +- if ( channel >= ioc->NumberOfBuses ) { +- printk(MYIOC_s_WARN_FMT +- "%s: Invalid channel=%d, NumberOfBuses=%d\n", +- ioc->name, __FUNCTION__, channel, ioc->NumberOfBuses); +- return; ++ if (hot_plug_info->isRaid) { ++ printk(MYIOC_s_INFO_FMT ++ "%s device, channel %d, id %d, lun %d\n", ++ ioc->name, msg_string, ++ hot_plug_info->channel, ++ id, lun); ++ } else { ++ if (hot_plug_info->device_info & ++ MPI_SAS_DEVICE_INFO_SSP_TARGET) ++ ds = "sas"; ++ if (hot_plug_info->device_info & ++ MPI_SAS_DEVICE_INFO_STP_TARGET) ++ ds = "stp"; ++ if (hot_plug_info->device_info & ++ MPI_SAS_DEVICE_INFO_SATA_DEVICE) ++ ds = "sata"; ++ printk(MYIOC_s_INFO_FMT ++ "%s %s device, channel %d, id %d, lun %d," ++ " phy %d\n", ioc->name, msg_string, ds, ++ hot_plug_info->channel, id, lun, ++ hot_plug_info->phy_id); + } +- +- if (hot_plug_info->device_info & +- MPI_SAS_DEVICE_INFO_SSP_TARGET) +- ds = "sas "; +- else if (hot_plug_info->device_info & +- MPI_SAS_DEVICE_INFO_STP_TARGET) +- ds = "stp "; +- else if (hot_plug_info->device_info & +- MPI_SAS_DEVICE_INFO_SATA_DEVICE) +- ds = "sata "; +- else +- ds = ""; +- +- printk(MYIOC_s_INFO_FMT +- "%s %sdevice, channel %d, id %d, lun %d," +- " phy %d\n", ioc->name, msg_string, ds, +- channel, id, lun, +- hot_plug_info->phy_id); + } + + /* +@@ -1167,32 +317,20 @@ mptsas_remove_target(MPT_ADAPTER *ioc, s + struct Scsi_Host *shost = ioc->sh; + unsigned long flags; + struct scsi_device *sdev; +- static VirtDevice *pTarget; + u32 channel, id; ++ MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; + + id = hot_plug_info->id; +- channel = hot_plug_info->channel; +- +- if ( id >= ioc->DevicesPerBus ) { +- printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, DevicesPerBus=%d\n", +- ioc->name, __FUNCTION__, id, ioc->DevicesPerBus); +- return; +- } + +- if ( channel >= ioc->NumberOfBuses ) { +- printk(MYIOC_s_WARN_FMT +- "%s: Invalid channel=%d, NumberOfBuses=%d\n", +- ioc->name, __FUNCTION__, channel, ioc->NumberOfBuses); ++ if ( id > ioc->pfacts->MaxDevices ) { ++ printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, MaxDevices=%d\n", ++ ioc->name, __FUNCTION__, id, ioc->pfacts->MaxDevices); + return; + } + +- pTarget = mptsas_find_vdevice(ioc, channel, id); +- if (!pTarget) +- return; +- +- pTarget->tflags &= ~MPT_TARGET_FLAGS_TLR_DONE; +- ++ mptsas_target_reset(ioc, hd->Targets[id]); + ++ channel = hot_plug_info->channel; + spin_lock_irqsave(shost->host_lock, flags); + restart: + list_for_each_entry(sdev, &shost->__devices, siblings) { +@@ -1208,46 +346,26 @@ mptsas_remove_target(MPT_ADAPTER *ioc, s + spin_unlock_irqrestore(shost->host_lock, flags); + } + +-/** +- * mptsas_add_device +- * +- * +- * @ioc +- * @hot_plug_info +- * +- **/ + static void + mptsas_add_device(MPT_ADAPTER *ioc, struct mptsas_hotplug_event *hot_plug_info, + u32 lun) + { + u32 channel, id; ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)) + struct scsi_device *sdev; ++#else ++ int error; ++#endif + + id = hot_plug_info->id; + +- if ( id >= ioc->DevicesPerBus ) { +- printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, DevicesPerBus=%d\n", +- ioc->name, __FUNCTION__, id, ioc->DevicesPerBus); ++ if ( id > ioc->pfacts->MaxDevices ) { ++ printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, MaxDevices=%d\n", ++ ioc->name, __FUNCTION__, id, ioc->pfacts->MaxDevices); + return; + } + + channel = hot_plug_info->channel; +- if ( channel >= ioc->NumberOfBuses ) { +- printk(MYIOC_s_WARN_FMT +- "%s: Invalid channel=%d, NumberOfBuses=%d\n", +- ioc->name, __FUNCTION__, channel, ioc->NumberOfBuses); +- return; +- } +- +- /* +- * avoid adding a device that is already present +- */ +- sdev = scsi_device_lookup(ioc->sh, channel, id, lun); +- if (sdev) { +- scsi_device_put(sdev); +- return; +- } +- + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)) + sdev = scsi_add_device(ioc->sh, channel, id, lun); + if (!IS_ERR(sdev)) +@@ -1261,13 +379,6 @@ mptsas_add_device(MPT_ADAPTER *ioc, stru + #endif + } + +-/** +- * scsilun_to_int +- * +- * +- * @scsilun +- * +- **/ + static int scsilun_to_int(struct scsi_lun *scsilun) + { + int i; +@@ -1298,170 +409,56 @@ mptsas_scan_target(MPT_ADAPTER *ioc, str + u32 length, channel, id, lun, num_luns; + u8 *data; + u32 retries; +- int rc; ++ int completion_code; + + id = hot_plug_info->id; +- channel = hot_plug_info->channel; + +- if ( id > ioc->DevicesPerBus ) { +- printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, DevicesPerBus=%d\n", +- ioc->name, __FUNCTION__, id, ioc->DevicesPerBus); +- return; +- } +- +- if ( channel >= ioc->NumberOfBuses ) { +- printk(MYIOC_s_WARN_FMT +- "%s: Invalid channel=%d, NumberOfBuses=%d\n", +- ioc->name, __FUNCTION__, channel, ioc->NumberOfBuses); +- return; +- } +- +- /* +- * Integrated RAID doesn't support REPORT_LUNS, it will timeout +- */ +- if (ioc->raid_data.isRaid & (1 << id)) { +- mptsas_add_device(ioc, hot_plug_info, 0); ++ if ( id > ioc->pfacts->MaxDevices ) { ++ printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, MaxDevices=%d\n", ++ ioc->name, __FUNCTION__, id, ioc->pfacts->MaxDevices); + return; + } + +- /* initialize REPORT_LUN params */ ++ channel = hot_plug_info->channel; + lun = 0; +- lun_data_len = 0; +- lun_data = NULL; +- lunp = NULL; + + /* +- * Test Unit Ready ++ * Integrated RAID doesn't support luns greater than 0 + */ +- iocmd.cmd = TEST_UNIT_READY; +- iocmd.bus = channel; +- iocmd.id = id; +- iocmd.lun = lun; +- iocmd.flags = 0; +- iocmd.data_dma = -1; +- iocmd.data = NULL; +- iocmd.size = 0; +- dinitprintk((MYIOC_s_INFO_FMT "Sending TURs to channel=%d id=%d \n", +- ioc->name, channel, id)); +- for (retries = 0; retries < mpt_cmd_retry_count; retries++) { +- if (mptscsih_do_cmd(hd, &iocmd) < 0) { +- dinitprintk((MYIOC_s_INFO_FMT +- "TUR: mptscsih_do_cmd failed\n", +- ioc->name)); +- goto tur_done; +- } +- +- if (hd->pLocal == NULL) { +- dinitprintk((MYIOC_s_INFO_FMT "TUR: no pLocal\n", +- ioc->name)); +- goto tur_done; +- } +- +- rc = hd->pLocal->completion; +- if (rc == MPT_SCANDV_GOOD) { +- dinitprintk((MYIOC_s_INFO_FMT "TUR: succeeded\n", +- ioc->name)); +- goto tur_done; +- } else if (rc == MPT_SCANDV_BUSY) { +- dinitprintk((MYIOC_s_INFO_FMT "TUR: BUSY\n", +- ioc->name)); +- msleep(1000); /* sleep 1 second */ +- continue; +- } else if (rc == MPT_SCANDV_SENSE) { +- u8 skey = hd->pLocal->sense[2] & 0x0F; +- u8 asc = hd->pLocal->sense[12]; +- u8 ascq = hd->pLocal->sense[13]; +- dinitprintk((MYIOC_s_INFO_FMT +- "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", +- ioc->name, skey, asc, ascq)); +- +- if (skey == UNIT_ATTENTION) { +- dinitprintk((MYIOC_s_INFO_FMT +- "TUR: UNIT ATTENTION\n", +- ioc->name)); +- continue; +- } else if ((skey == NOT_READY) && +- (asc == 0x04)&&(ascq == 0x01)) { +- dinitprintk((MYIOC_s_INFO_FMT +- "TUR: Becoming Ready\n", +- ioc->name)); +- msleep(1000); /* sleep 1 second */ +- continue; +- } +- } ++ if (hot_plug_info->isRaid) { ++ mptsas_add_device(ioc, hot_plug_info, lun); ++ return; + } + +- tur_done: +- + lun_data_len = (MPT_LAST_LUN + 1) * sizeof(struct scsi_lun); + lun_data = pci_alloc_consistent(ioc->pcidev, lun_data_len, + &lun_data_dma); + if (!lun_data) +- goto report_luns_done; ++ goto out; + +- /* +- * Report Luns +- */ + iocmd.cmd = REPORT_LUNS; + iocmd.data_dma = lun_data_dma; + iocmd.data = (u8 *)lun_data; + iocmd.size = lun_data_len; ++ iocmd.bus = channel; ++ iocmd.id = id; ++ iocmd.lun = lun; + iocmd.flags = 0; + + /* +- * While loop for 10 sec retrying REPORT_LUNS, this is done ++ * While loop for 3 sec retrying REPORT_LUNS, this is done + * because some devices return MPI_SCSI_STATUS_BUSY for several + * seconds. + */ +- dinitprintk((MYIOC_s_INFO_FMT +- "Sending REPORT_LUNS to channel=%d id=%d \n", +- ioc->name, channel, id)); ++// for (retries = 0; retries < 3; retries++) { /* EDM - TRY 10 */ + for (retries = 0; retries < 10; retries++) { + memset(lun_data, 0, lun_data_len); +- if (mptscsih_do_cmd(hd, &iocmd) < 0) { +- dinitprintk((MYIOC_s_INFO_FMT +- "RL: mptscsih_do_cmd failed\n", ioc->name)); +- goto report_luns_done; +- } +- +- if (hd->pLocal == NULL) { +- dinitprintk((MYIOC_s_INFO_FMT "RL: no pLocal\n", +- ioc->name)); +- goto report_luns_done; +- } +- +- rc = hd->pLocal->completion; +- if (rc == MPT_SCANDV_GOOD) { +- dinitprintk((MYIOC_s_INFO_FMT "RL: succeeded\n", +- ioc->name)); +- goto report_luns_done; +- } else if (rc == MPT_SCANDV_BUSY) { +- dinitprintk((MYIOC_s_INFO_FMT "RL: BUSY\n", ioc->name)); +- msleep(1000); +- continue; +- } else if (rc == MPT_SCANDV_SENSE) { +- u8 skey = hd->pLocal->sense[2] & 0x0F; +- u8 asc = hd->pLocal->sense[12]; +- u8 ascq = hd->pLocal->sense[13]; +- dinitprintk((MYIOC_s_INFO_FMT +- "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, +- skey, asc, ascq)); +- +- if (skey == UNIT_ATTENTION) { +- dinitprintk((MYIOC_s_INFO_FMT +- "RL: UNIT ATTENTION\n", ioc->name)); +- continue; +- } else if ((skey == NOT_READY) && +- (asc == 0x04)&&(ascq == 0x01)) { +- dinitprintk((MYIOC_s_INFO_FMT +- "RL: Becoming Ready\n", ioc->name)); +- msleep(1000); +- continue; +- } +- } ++ completion_code = mptscsih_do_cmd(hd, &iocmd); ++ if (!completion_code) ++ break; ++ msleep(1000); + } + +- report_luns_done: + /* + * Attaching lun=0 + */ +@@ -1470,8 +467,6 @@ mptsas_scan_target(MPT_ADAPTER *ioc, str + /* + * Get the length from the first four bytes of lun_data. + */ +- if (!lun_data) +- goto out; + data = (u8 *)lun_data; + length = ((data[0] << 24) | (data[1] << 16) | + (data[2] << 8) | (data[3] << 0)); +@@ -1501,91 +496,93 @@ mptsas_scan_target(MPT_ADAPTER *ioc, str + lun_data_dma); + } + +-/** +- * mptsas_hotplug_work +- * +- * +- * @hot_plug_info +- * +- **/ + static void + mptsas_hotplug_work(void *arg) + { + struct mptsas_hotplug_event *hot_plug_info = arg; + MPT_ADAPTER *ioc = hot_plug_info->ioc; +- u32 id, channel; ++ MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; ++ VirtDevice *pTarget; ++ u32 id = hot_plug_info->id; + +- id = hot_plug_info->id; +- channel = hot_plug_info->channel; + + dhotpprintk((MYIOC_s_WARN_FMT "Entering %s for channel=%d id=%d\n", +- ioc->name,__FUNCTION__, channel, id)); ++ ioc->name,__FUNCTION__, ++ hot_plug_info->channel, id)); ++ ++ ++ if ( id > ioc->pfacts->MaxDevices ) { ++ printk(MYIOC_s_WARN_FMT "%s: Invalid id=%d, MaxDevices=%d\n", ++ ioc->name, __FUNCTION__, id, ioc->pfacts->MaxDevices); ++ return; ++ } + + down(&ioc->hot_plug_semaphore); + +- /* If there has been a change to raid, then we need to +- * refresh the config raid data +- */ +- if (hot_plug_info->refresh_raid_config_pages) +- mpt_findImVolumes(ioc); ++ pTarget = hd->Targets[id]; ++ dhotpprintk((MYIOC_s_WARN_FMT "hot_plug_info=%p ioc=%p hd=%p pTarget=%p\n", ++ ioc->name, hot_plug_info, ioc, hd, pTarget)); + + switch (hot_plug_info->event_type) { + case MPTSAS_DEL_DEVICE: +-#if defined(CPQ_CIM) +- mptsas_del_device_component(ioc, channel, id); +- if (hot_plug_info->refresh_raid_config_pages) +- mptsas_add_device_component_hotspare(ioc); +-#endif + dhotpprintk((MYIOC_s_WARN_FMT + "MPTSAS_DEL_DEVICE: channel=%d id=%d\n", +- ioc->name, channel, id)); ++ ioc->name, ++ hot_plug_info->channel, ++ id)); ++ if (pTarget == NULL) { ++ dhotpprintk((MYIOC_s_WARN_FMT ++ "hot_plug id=%d not found in Targets array", ++ ioc->name, ++ id)); ++ goto out; ++ } ++ pTarget->tflags &= ~MPT_TARGET_FLAGS_TLR_DONE; ++ pTarget->tflags |= MPT_TARGET_FLAGS_DELETED; + mptsas_remove_target(ioc, hot_plug_info); + break; + + case MPTSAS_ADD_DEVICE: +-#if defined(CPQ_CIM) +- if (ioc->raid_data.isRaid & (1 << id)) +- mptsas_add_device_component_ir(ioc, channel, id); +-#endif + dhotpprintk((MYIOC_s_WARN_FMT + "MPTSAS_ADD_DEVICE: channel=%d id=%d\n", +- ioc->name, channel, id)); ++ ioc->name, ++ hot_plug_info->channel, ++ id)); ++ if (pTarget) { ++ dhotpprintk((MYIOC_s_WARN_FMT ++ "hot_plug id=%d already in Targets array", ++ ioc->name, ++ id)); ++ goto out; ++ } + mptsas_scan_target(ioc, hot_plug_info); + break; +-#if defined(CPQ_CIM) +- case MPTSAS_ADD_INACTIVE_VOLUME: +- dhotpprintk((MYIOC_s_WARN_FMT +- "MPTSAS_ADD_INACTIVE_VOLUME: channel=%d id=%d\n", +- ioc->name, channel, id)); +- mptsas_add_device_component_ir(ioc, channel, id); +- break; +- case MPTSAS_PHYSDISK_ADD: +- mptsas_add_device_component_single(ioc, channel, id); +- break; +-#endif + default: + dhotpprintk((MYIOC_s_WARN_FMT +- "Unknown hot_plug event_type=%x: channel=%d id=%d " +- " skipping\n", ioc->name, hot_plug_info->event_type, +- channel, id)); +- goto out; ++ "Unknown hot_plug event_type=%x: channel=%d id=%d\n", ++ ioc->name, ++ hot_plug_info->event_type, ++ hot_plug_info->channel, ++ id)); ++ break; ++ } ++ ++ /* If there has been a change to raid, then we need to ++ * refresh the config raid data, and sas device link list ++ */ ++ if (hot_plug_info->isRaid) { ++ mpt_findImVolumes(ioc); ++ mptscsih_sas_update_device_list(ioc); + } + + out: + dhotpprintk((MYIOC_s_WARN_FMT "%s: kfree hot_plug_info=%p\n", +- ioc->name,__FUNCTION__, hot_plug_info)); ++ ioc->name,__FUNCTION__, hot_plug_info)); + kfree(hot_plug_info); + up(&ioc->hot_plug_semaphore); + } + +-/** +- * mptsas_send_sas_event +- * +- * +- * @ioc +- * @sas_event_data +- * +- **/ ++ + static void + mptsas_send_sas_event(MPT_ADAPTER *ioc, + EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data) +@@ -1610,11 +607,8 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc, + } + + switch (sas_event_data->ReasonCode) { +- case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: +- mptsas_target_reset_queue(ioc, sas_event_data); +- break; +- + case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: ++ case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: + ev = kmalloc(sizeof(*ev), GFP_ATOMIC); + if (!ev) { + printk(KERN_WARNING "mptsas: lost hotplug event\n"); +@@ -1642,7 +636,6 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc, + ev->event_type = MPTSAS_DEL_DEVICE; + schedule_work(&ev->work); + break; +- + case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED: + /* + * Persistent table is full. +@@ -1652,7 +645,6 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc, + (void *)ioc); + schedule_work(&ioc->mptscsih_persistTask); + break; +- + case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: + /* TODO */ + case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: +@@ -1662,21 +654,12 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc, + } + } + +-/** +- * mptsas_send_raid_event +- * +- * +- * @ioc +- * @raid_event_data +- * +- **/ + static void + mptsas_send_raid_event(MPT_ADAPTER *ioc, + EVENT_DATA_RAID *raid_event_data) + { + struct mptsas_hotplug_event *ev; +- int status = le32_to_cpu(raid_event_data->SettingsStatus); +- int state = (status >> 8) & 0xff; ++ RAID_VOL0_STATUS * volumeStatus; + + if (ioc->bus_type != SAS) + return; +@@ -1688,13 +671,11 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc, + } + + memset(ev,0,sizeof(struct mptsas_hotplug_event)); ++ INIT_WORK(&ev->work, mptsas_hotplug_work, ev); + ev->ioc = ioc; + ev->id = raid_event_data->VolumeID; +- ev->channel = raid_event_data->VolumeBus; +- ev->refresh_raid_config_pages = 1; ++ ev->isRaid=1; + +- devtprintk((KERN_INFO MYNAM ": VolumeID=%d Reason=%x received\n", +- ev->id, raid_event_data->ReasonCode)); + switch (raid_event_data->ReasonCode) { + case MPI_EVENT_RAID_RC_PHYSDISK_DELETED: + ev->event_type = MPTSAS_ADD_DEVICE; +@@ -1702,24 +683,6 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc, + case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: + ev->event_type = MPTSAS_DEL_DEVICE; + break; +- case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED: +- switch (state) { +- case MPI_PD_STATE_ONLINE: +- case MPI_PD_STATE_NOT_COMPATIBLE: +- ev->event_type = MPTSAS_PHYSDISK_ADD; +- break; +- case MPI_PD_STATE_MISSING: +- case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST: +- case MPI_PD_STATE_FAILED_AT_HOST_REQUEST: +- case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON: +- ev->event_type = MPTSAS_DEL_DEVICE; +- break; +- default: +- devtprintk((KERN_INFO MYNAM +- ": ignoring this event! %d\n", __LINE__)); +- return; +- } +- break; + case MPI_EVENT_RAID_RC_VOLUME_DELETED: + ev->event_type = MPTSAS_DEL_DEVICE; + break; +@@ -1727,68 +690,18 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc, + ev->event_type = MPTSAS_ADD_DEVICE; + break; + case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED: +- switch (state) { +- case MPI_RAIDVOL0_STATUS_STATE_FAILED: +- case MPI_RAIDVOL0_STATUS_STATE_MISSING: +- ev->event_type = MPTSAS_DEL_DEVICE; +- break; +- case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL: +- case MPI_RAIDVOL0_STATUS_STATE_DEGRADED: +- ev->event_type = MPTSAS_ADD_DEVICE; +- break; +- default: +- devtprintk((KERN_INFO MYNAM +- ": ignoring this event! %d\n", __LINE__)); +- return; +- } ++ volumeStatus = (RAID_VOL0_STATUS *) & ++ raid_event_data->SettingsStatus; ++ ev->event_type = (volumeStatus->State == ++ MPI_RAIDVOL0_STATUS_STATE_FAILED) ? ++ MPTSAS_DEL_DEVICE : MPTSAS_ADD_DEVICE; + break; + default: +- devtprintk((KERN_INFO MYNAM +- ": ignoring this event! %d\n", __LINE__)); +- return; ++ break; + } +- INIT_WORK(&ev->work, mptsas_hotplug_work, ev); + schedule_work(&ev->work); + } + +-#if defined(CPQ_CIM) +-/* +- * mptsas_send_ir2_event +- * +- * This handle exposing hidden disk when an inactive raid volume is added +- */ +-static void +-mptsas_send_ir2_event(MPT_ADAPTER *ioc, PTR_MPI_EVENT_DATA_IR2 ir2_data) +-{ +- struct mptsas_hotplug_event *ev; +- +- if (ir2_data->ReasonCode != +- MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED) +- return; +- +- ev = kmalloc(sizeof(*ev), GFP_ATOMIC); +- if (!ev) +- return; +- memset(ev, 0, sizeof(*ev)); +- ev->ioc = ioc; +- ev->id = ir2_data->TargetID; +- ev->channel = ir2_data->Bus; +- ev->refresh_raid_config_pages = 1; +- ev->event_type = MPTSAS_ADD_INACTIVE_VOLUME; +- +- INIT_WORK(&ev->work, mptsas_hotplug_work, ev); +- schedule_work(&ev->work); +-}; +-#endif +- +-/** +- * mptsas_event_process +- * +- * +- * @ioc +- * @reply +- * +- **/ + static int + mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) + { +@@ -1803,16 +716,10 @@ mptsas_event_process(MPT_ADAPTER *ioc, E + + switch (event) { + case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: +-#if defined(CPQ_CIM) +- ioc->csmi_change_count++; +-#endif + mptsas_send_sas_event(ioc, + (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data); + break; + case MPI_EVENT_INTEGRATED_RAID: +-#if defined(CPQ_CIM) +- ioc->csmi_change_count++; +-#endif + mptsas_send_raid_event(ioc, + (EVENT_DATA_RAID *)reply->Data); + break; +@@ -1822,13 +729,6 @@ mptsas_event_process(MPT_ADAPTER *ioc, E + (void *)ioc); + schedule_work(&ioc->mptscsih_persistTask); + break; +-#if defined(CPQ_CIM) +- case MPI_EVENT_IR2: +- ioc->csmi_change_count++; +- mptsas_send_ir2_event(ioc, +- (PTR_MPI_EVENT_DATA_IR2)reply->Data); +- break; +-#endif + default: + rc = mptscsih_event_process(ioc, reply); + break; +@@ -1855,13 +755,12 @@ mptsas_probe(struct pci_dev *pdev, const + MPT_ADAPTER *ioc; + unsigned long flags; + int sz, ii; ++ int numSGE = 0; ++ int scale; + int ioc_cap; + u8 *mem; + int error=0; + int r; +-#if defined(CPQ_CIM) +- struct mptsas_portinfo *port_info; +-#endif + + if ((r = mpt_attach(pdev,id)) != 0) + return r; +@@ -1874,27 +773,19 @@ mptsas_probe(struct pci_dev *pdev, const + /* Added sanity check on readiness of the MPT adapter. + */ + if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) { +- if(mpt_enable_deadioc_detect) +- return 0; +- else { +- printk(MYIOC_s_WARN_FMT +- "Skipping because it's not operational!\n", ioc->name); +- error = -ENODEV; +- goto out_mptsas_probe; +- } ++ printk(MYIOC_s_WARN_FMT ++ "Skipping because it's not operational!\n", ++ ioc->name); ++ error = -ENODEV; ++ goto out_mptsas_probe; + } + + if (!ioc->active) { +- if(mpt_enable_deadioc_detect) +- return 0; +- else { +- +- printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n", ++ printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n", + ioc->name); + error = -ENODEV; + goto out_mptsas_probe; + } +- } + + /* Sanity check - ensure at least 1 port is INITIATOR capable + */ +@@ -1906,8 +797,9 @@ mptsas_probe(struct pci_dev *pdev, const + } + + if (!ioc_cap) { +- printk(MYIOC_s_WARN_FMT "Skipping ioc=%p because SCSI " +- "Initiator mode is NOT enabled!\n", ioc->name, ioc); ++ printk(MYIOC_s_WARN_FMT ++ "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n", ++ ioc->name, ioc); + return 0; + } + +@@ -1915,8 +807,8 @@ mptsas_probe(struct pci_dev *pdev, const + + if (!sh) { + printk(MYIOC_s_WARN_FMT +- "Unable to register controller with SCSI subsystem\n", +- ioc->name); ++ "Unable to register controller with SCSI subsystem\n", ++ ioc->name); + error = -1; + goto out_mptsas_probe; + } +@@ -1939,19 +831,49 @@ mptsas_probe(struct pci_dev *pdev, const + else + sh->can_queue = ioc->req_depth; + dinitprintk((MYIOC_s_INFO_FMT +- "mpt_can_queue=%d req_depth=%d can_queue=%d\n", +- ioc->name, mpt_can_queue, ioc->req_depth, sh->can_queue)); ++ "mpt_can_queue=%d req_depth=%d can_queue=%d\n", ++ ioc->name, mpt_can_queue, ioc->req_depth, ++ sh->can_queue)); + +- sh->max_id = ioc->DevicesPerBus; ++ sh->max_id = ioc->pfacts->MaxDevices + 1; + + sh->max_lun = MPT_LAST_LUN + 1; +- sh->max_channel = ioc->NumberOfBuses - 1; ++ sh->max_channel = 0; + sh->this_id = ioc->pfacts[0].PortSCSIID; + + /* Required entry. + */ + sh->unique_id = ioc->id; +- sh->sg_tablesize = ioc->sg_tablesize; ++ ++ /* Verify that we won't exceed the maximum ++ * number of chain buffers ++ * We can optimize: ZZ = req_sz/sizeof(SGE) ++ * For 32bit SGE's: ++ * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ ++ * + (req_sz - 64)/sizeof(SGE) ++ * A slightly different algorithm is required for ++ * 64bit SGEs. ++ */ ++ scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); ++ if (sizeof(dma_addr_t) == sizeof(u64)) { ++ numSGE = (scale - 1) * ++ (ioc->facts.MaxChainDepth-1) + scale + ++ (ioc->req_sz - 60) / (sizeof(dma_addr_t) + ++ sizeof(u32)); ++ } else { ++ numSGE = 1 + (scale - 1) * ++ (ioc->facts.MaxChainDepth-1) + scale + ++ (ioc->req_sz - 64) / (sizeof(dma_addr_t) + ++ sizeof(u32)); ++ } ++ ++ if (numSGE < sh->sg_tablesize) { ++ /* Reset this value */ ++ dprintk((MYIOC_s_INFO_FMT ++ "Resetting sg_tablesize to %d from %d\n", ++ ioc->name, numSGE, sh->sg_tablesize)); ++ sh->sg_tablesize = numSGE; ++ } + + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)) + /* Set the pci device pointer in Scsi_Host structure. +@@ -1968,7 +890,7 @@ mptsas_probe(struct pci_dev *pdev, const + * (with size equal to req_depth*PtrSz!) + */ + sz = ioc->req_depth * sizeof(void *); +- mem = kmalloc(sz, GFP_KERNEL); ++ mem = kmalloc(sz, GFP_ATOMIC); + if (mem == NULL) { + error = -ENOMEM; + goto out_mptsas_probe; +@@ -1978,26 +900,25 @@ mptsas_probe(struct pci_dev *pdev, const + hd->ScsiLookup = (struct scsi_cmnd **) mem; + + dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", +- ioc->name, hd->ScsiLookup, sz)); ++ ioc->name, hd->ScsiLookup, sz)); + +- for (ii=0; ii < ioc->NumberOfBuses; ii++) { +- /* Allocate memory for the device structures. +- * A non-Null pointer at an offset +- * indicates a device exists. +- */ +- sz = ioc->DevicesPerBus * sizeof(void *); +- mem = kmalloc(sz, GFP_KERNEL); +- if (mem == NULL) { +- error = -ENOMEM; +- goto out_mptsas_probe; +- } ++ /* Allocate memory for the device structures. ++ * A non-Null pointer at an offset ++ * indicates a device exists. ++ * max_id = 1 + maximum id (hosts.h) ++ */ ++ sz = sh->max_id * sizeof(void *); ++ mem = kmalloc(sz, GFP_ATOMIC); ++ if (mem == NULL) { ++ error = -ENOMEM; ++ goto out_mptsas_probe; ++ } + +- memset(mem, 0, sz); +- ioc->Target_List[ii] = (struct _MPT_DEVICE *) mem; ++ memset(mem, 0, sz); ++ hd->Targets = (VirtDevice **) mem; + +- dinitprintk((KERN_INFO " For Bus=%d, Target_List=%p sz=%d\n", +- ii, mem, sz)); +- } ++ dprintk((KERN_INFO ++ " Targets @ %p, sz=%d\n", hd->Targets, sz)); + + /* Clear the TM flags + */ +@@ -2013,18 +934,13 @@ mptsas_probe(struct pci_dev *pdev, const + */ + hd->cmdPtr = NULL; + +- /* Initialize this IOC's timers ++ /* Initialize this SCSI Hosts' timers + * To use, set the timer expires field +- * and add_timer. Used for internally +- * generated commands. ++ * and add_timer + */ +- init_timer(&hd->InternalCmdTimer); +- hd->InternalCmdTimer.data = (unsigned long) hd; +- hd->InternalCmdTimer.function = mptscsih_InternalCmdTimer_expired; +- +- init_timer(&ioc->TMtimer); +- ioc->TMtimer.data = (unsigned long) ioc; +- ioc->TMtimer.function = mptscsih_TM_timeout; ++ init_timer(&hd->timer); ++ hd->timer.data = (unsigned long) hd; ++ hd->timer.function = mptscsih_timer_expired; + + init_MUTEX(&ioc->hot_plug_semaphore); + +@@ -2038,50 +954,24 @@ mptsas_probe(struct pci_dev *pdev, const + ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT); + } + +- ddvprintk((MYIOC_s_INFO_FMT "mpt_pq_filter %x mpt_pq_filter %x\n", +- ioc->name, mpt_pq_filter, mpt_pq_filter)); ++ ddvprintk((MYIOC_s_INFO_FMT ++ "mpt_pq_filter %x mpt_pq_filter %x\n", ++ ioc->name, ++ mpt_pq_filter, ++ mpt_pq_filter)); + + init_waitqueue_head(&hd->scandv_waitq); + hd->scandv_wait_done = 0; + hd->last_queue_full = 0; + +- init_waitqueue_head(&hd->TM_waitq); +- hd->TM_wait_done = 0; +- +- INIT_LIST_HEAD(&hd->target_reset_list); +- +-#if defined(CPQ_CIM) +- INIT_LIST_HEAD(&ioc->sas_device_info_list); +- init_MUTEX(&ioc->sas_device_info_mutex); +- port_info = kmalloc(sizeof(*port_info), GFP_KERNEL); +- if (port_info && !mptsas_sas_io_unit_pg0(ioc, port_info)) +- ioc->num_ports = port_info->num_phys; +- kfree(port_info); +-#endif +- + error = scsi_add_host (sh, &ioc->pcidev->dev); + if(error) { +- dprintk((KERN_ERR MYNAM "scsi_add_host failed\n")); ++ dprintk((KERN_ERR MYNAM ++ "scsi_add_host failed\n")); + goto out_mptsas_probe; + } + + scsi_scan_host(sh); +- +-#if defined(CPQ_CIM) +- /* +- * Handling Inactive Volumes +- */ +- if (!ioc->ir_firmware || +- !ioc->raid_data.pIocPg2 || +- !ioc->raid_data.pIocPg2->NumActiveVolumes) +- return 0; +- +- for (ii = 0; ii < ioc->raid_data.pIocPg2->NumActiveVolumes; ii++) +- mptsas_add_device_component_ir(ioc, +- ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeBus, +- ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID); +-#endif +- + return 0; + + out_mptsas_probe: +@@ -2122,17 +1012,17 @@ mptsas_init(void) + show_mptmod_ver(my_NAME, my_VERSION); + + mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER); +- mptsasTaskCtx = mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER); ++ mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER); + mptsasInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER); + + if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) { + devtprintk((KERN_INFO MYNAM +- ": Registered for sas IOC event notifications\n")); ++ ": Registered for sas IOC event notifications\n")); + } + +- if (mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset) == 0) { ++ if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) { + dprintk((KERN_INFO MYNAM +- ": Registered for IOC reset notifications\n")); ++ ": Registered for IOC reset notifications\n")); + } + + return pci_register_driver(&mptsas_driver); +@@ -2151,11 +1041,11 @@ mptsas_exit(void) + + mpt_reset_deregister(mptsasDoneCtx); + dprintk((KERN_INFO MYNAM +- ": Deregistered for IOC reset notifications\n")); ++ ": Deregistered for IOC reset notifications\n")); + + mpt_event_deregister(mptsasDoneCtx); + dprintk((KERN_INFO MYNAM +- ": Deregistered for IOC event notifications\n")); ++ ": Deregistered for IOC event notifications\n")); + + mpt_deregister(mptsasInternalCtx); + mpt_deregister(mptsasTaskCtx); +diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptsas.h linux-2.6.9-55.0.12/drivers/message/fusion/mptsas.h +--- linux-2.6.9-67.0.1/drivers/message/fusion/mptsas.h 2007-12-21 11:40:54.000000000 +0100 ++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptsas.h 1970-01-01 01:00:00.000000000 +0100 +@@ -1,166 +0,0 @@ +-/* +- * linux/drivers/message/fusion/mptsas.h +- * High performance SCSI + LAN / Fibre Channel device drivers. +- * For use with PCI chip/adapter(s): +- * LSIFC9xx/LSI409xx Fibre Channel +- * running LSI Logic Fusion MPT (Message Passing Technology) firmware. +- * +- * Copyright (c) 1999-2007 LSI Logic Corporation +- * (mailto:mpt_linux_developer@lsi.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 +- the Free Software Foundation; version 2 of the License. +- +- This program is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- GNU General Public License for more details. +- +- NO WARRANTY +- THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR +- CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT +- LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, +- MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is +- solely responsible for determining the appropriateness of using and +- distributing the Program and assumes all risks associated with its +- exercise of rights under this Agreement, including but not limited to +- the risks and costs of program errors, damage to or loss of data, +- programs or equipment, and unavailability or interruption of operations. +- +- DISCLAIMER OF LIABILITY +- NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY +- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +- DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND +- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +- TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +- USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED +- HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES +- +- You should have received a copy of the GNU General Public License +- along with this program; if not, write to the Free Software +- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-*/ +- +-#ifndef MPTSAS_H_INCLUDED +-#define MPTSAS_H_INCLUDED +-/*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +- +-struct mptscsih_target_reset { +- struct list_head list; +- EVENT_DATA_SAS_DEVICE_STATUS_CHANGE sas_event_data; +- u8 target_reset_issued; +-}; +- +-enum mptsas_hotplug_action { +- MPTSAS_ADD_DEVICE, +- MPTSAS_DEL_DEVICE, +- MPTSAS_ADD_INACTIVE_VOLUME, +- MPTSAS_PHYSDISK_ADD, +-}; +- +-struct mptsas_hotplug_event { +- struct work_struct work; +- MPT_ADAPTER *ioc; +- enum mptsas_hotplug_action event_type; +- u64 sas_address; +- u32 channel; +- u32 id; +- u32 device_info; +- u16 handle; +- u16 parent_handle; +- u8 phy_id; +- u8 refresh_raid_config_pages; +-}; +- +-/* +- * SAS topology structures +- * +- * The MPT Fusion firmware interface spreads information about the +- * SAS topology over many manufacture pages, thus we need some data +- * structure to collect it and process it for the SAS transport class. +- */ +- +-struct mptsas_devinfo { +- u16 handle; /* unique id to address this device */ +- u16 handle_parent; /* unique id to address parent device */ +- u16 handle_enclosure; /* enclosure identifier of the enclosure */ +- u16 slot; /* physical slot in enclosure */ +- u8 phy_id; /* phy number of parent device */ +- u8 port_id; /* sas physical port this device +- is assoc'd with */ +- u8 id; /* logical target id of this device */ +- u32 phys_disk_num; /* phys disk id, for csmi-ioctls */ +- u8 channel; /* logical bus number of this device */ +- u64 sas_address; /* WWN of this device, +- SATA is assigned by HBA,expander */ +- u32 device_info; /* bitfield detailed info about this device */ +-#if !defined(MPT_WIDE_PORT_API) +- u8 wide_port_enable; /* when set, this is part of wide port*/ +-#endif +-}; +- +-/* +- * Specific details on ports, wide/narrow +- */ +-struct mptsas_portinfo_details{ +-#if !defined(MPT_WIDE_PORT_API) +- u8 port_id; /* port number provided to transport */ +- u8 rphy_id; /* phy index used for reporting end device*/ +- u32 device_info; /* bitfield detailed info about this device */ +-#endif +- u16 num_phys; /* number of phys beloing to this port */ +- u64 phy_bitmask; /* this needs extending to support 128 phys */ +- struct sas_rphy *rphy; /* rphy for end devices */ +-#if defined(MPT_WIDE_PORT_API) +- struct sas_port *port; /* transport layer port object */ +-#endif +- struct scsi_target *starget; +- struct mptsas_portinfo *port_info; +-}; +- +-struct mptsas_phyinfo { +- u8 phy_id; /* phy index */ +- u8 port_id; /* port number this phy is part of */ +- u8 negotiated_link_rate; /* nego'd link rate for this phy */ +- u8 hw_link_rate; /* hardware max/min phys link rate */ +- u8 programmed_link_rate; /* programmed max/min phy link rate */ +-#if defined(MPT_WIDE_PORT_API) +- u8 sas_port_add_phy; /* flag to request sas_port_add_phy*/ +-#endif +-#if defined(CPQ_CIM) +- u8 change_count; /* change count of the phy */ +- u8 port_flags; /* info wrt host sas ports */ +-#endif +- u32 phy_info; /* various info wrt the phy */ +- struct mptsas_devinfo identify; /* point to phy device info */ +- struct mptsas_devinfo attached; /* point to attached device info */ +- struct sas_phy *phy; +- struct mptsas_portinfo *portinfo; +- struct mptsas_portinfo_details * port_details; +-}; +- +-struct mptsas_portinfo { +- struct list_head list; +- u16 handle; /* unique id to address this */ +- u16 num_phys; /* number of phys */ +- struct mptsas_phyinfo *phy_info; +-}; +- +-struct mptsas_enclosure { +- u64 enclosure_logical_id; /* The WWN for the enclosure */ +- u16 enclosure_handle; /* unique id to address this */ +- u16 flags; /* details enclosure management */ +- u16 num_slot; /* num slots */ +- u16 start_slot; /* first slot */ +- u8 start_id; /* starting logical target id */ +- u8 start_channel; /* starting logical channel id */ +- u8 sep_id; /* SEP device logical target id */ +- u8 sep_channel; /* SEP channel logical channel id */ +-}; +- +-/*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +-#endif +diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptscsi.c linux-2.6.9-55.0.12/drivers/message/fusion/mptscsi.c +--- linux-2.6.9-67.0.1/drivers/message/fusion/mptscsi.c 2007-12-21 11:40:54.000000000 +0100 ++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptscsi.c 2007-11-02 09:10:23.000000000 +0100 +@@ -3,8 +3,8 @@ + * For use with LSI Logic PCI chip/adapter(s) + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * +- * Copyright (c) 1999-2007 LSI Logic Corporation +- * (mailto:mpt_linux_developer@lsi.com) ++ * Copyright (c) 1999-2005 LSI Logic Corporation ++ * (mailto:mpt_linux_developer@lsil.com) + * + * $Id: mptscsih.c,v 1.1.2.4 2003/05/07 14:08:34 Exp $ + */ +@@ -74,7 +74,6 @@ + MODULE_AUTHOR(MODULEAUTHOR); + MODULE_DESCRIPTION(my_NAME); + MODULE_LICENSE("GPL"); +-MODULE_VERSION(my_VERSION); + + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + +@@ -83,6 +82,13 @@ typedef struct _BIG_SENSE_BUF { + } BIG_SENSE_BUF; + + #define OEM_TLR_COMMAND 0xC2 ++#define MPT_SCANDV_GOOD (0x00000000) /* must be 0 */ ++#define MPT_SCANDV_DID_RESET (0x00000001) ++#define MPT_SCANDV_SENSE (0x00000002) ++#define MPT_SCANDV_SOME_ERROR (0x00000004) ++#define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008) ++#define MPT_SCANDV_ISSUE_SENSE (0x00000010) ++#define MPT_SCANDV_FALLBACK (0x00000020) + + #define MPT_SCANDV_MAX_RETRIES (10) + +@@ -116,37 +122,44 @@ typedef struct _dv_parameters { + int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); + static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq); + int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); ++ + static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt, + SCSIIORequest_t *pReq, int req_idx); + static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx); + static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply); + static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd); +-static int SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc); +-int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, u8 lun, int ctx2abort, ulong timeout); +-static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, u8 lun, int ctx2abort, ulong timeout); ++static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ); ++static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc); ++ ++int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); ++static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); + + int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); + int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); +-static void mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus, int id, u8 lun, char *data, int dlen); +-static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *pTarget, char byte56); +-static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int id); +-static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int id, int bus); ++ ++static void mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen); ++static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56); ++static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq); ++static void mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags); ++static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id); ++static int mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags); ++static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus); + int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); +-void mptscsih_InternalCmdTimer_expired(unsigned long data); ++void mptscsih_timer_expired(unsigned long data); + static int mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum); + + #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION + static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io); + static void mptscsih_domainValidation(void *hd); +-static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int channel, int id); ++static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id); + static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id); +-static int mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int id); +-static void mptscsih_post_PendingMF_command(MPT_ADAPTER *ioc); ++static int mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target); + static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage); +-static MPT_FRAME_HDR * mptscsih_search_PendingMF(MPT_ADAPTER *ioc, struct scsi_cmnd * sc); + static void mptscsih_fillbuf(char *buffer, int size, int index, int width); ++static void mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id); + #endif +-static void mpt_IssueTLR(MPT_SCSI_HOST *hd, VirtDevice *pTarget); ++static void ++mpt_IssueTLR(MPT_SCSI_HOST *hd, VirtDevice *pTarget); + + void mptscsih_remove(struct pci_dev *); + // This was changed in the 2.6.13 kernel +@@ -169,6 +182,8 @@ int mptscsih_resume(struct pci_dev *pdev + */ + static spinlock_t dvtaskQ_lock = SPIN_LOCK_UNLOCKED; + static int dvtaskQ_active = 0; ++static int dvtaskQ_release = 0; ++static struct work_struct dvTaskQ_task; + #endif + + +@@ -560,7 +575,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F + } + + sc = hd->ScsiLookup[req_idx]; +- hd->ScsiLookup[req_idx] = NULL; + if (sc == NULL) { + MPIHeader_t *hdr = (MPIHeader_t *)mf; + +@@ -575,10 +589,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F + mptscsih_freeChainBuffers(ioc, req_idx); + return 1; + } +- if ((unsigned char *)mf != sc->host_scribble) { +- mptscsih_freeChainBuffers(ioc, req_idx); +- return 1; +- } + + sc->result = DID_OK << 16; /* Set default reply as OK */ + pScsiReq = (SCSIIORequest_t *) mf; +@@ -601,12 +611,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F + u32 xfer_cnt; + u16 ioc_status; + u8 scsi_state, scsi_status; +-#ifdef MPT_DEBUG_ERROR +- u8 ii, skey, asc, ascq; +-#endif +- struct _MPT_DEVICE *pMptTarget; +- VirtDevice *pTarget; +- int bus, id; ++ VirtDevice *pTarget; ++ int target; + + ioc_status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK; + scsi_state = pScsiReply->SCSIState; +@@ -627,35 +633,18 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F + ioc_status = MPI_IOCSTATUS_SUCCESS; + } + +-#ifdef MPT_DEBUG_ERR +- if (ioc_status != MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE) { /* 0x0043 */ +- derrprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n" +- "IOCStatus=%04x SCSIState=%02x SCSIStatus=%02x\n" +- "resid=%d bufflen=%d xfer_cnt=%d\n", +- ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1], +- ioc_status, scsi_state, scsi_status, sc->resid, +- sc->request_bufflen, xfer_cnt)); +- } +-#endif ++ dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n" ++ "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n" ++ "resid=%d bufflen=%d xfer_cnt=%d\n", ++ ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1], ++ ioc_status, scsi_state, scsi_status, sc->resid, ++ sc->request_bufflen, xfer_cnt)); + +- if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID){ ++ if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) + mptscsih_copy_sense_data(sc, hd, mf, pScsiReply); + +-#ifdef MPT_DEBUG_ERROR +- skey = sc->sense_buffer[2]; +- asc = sc->sense_buffer[12]; +- ascq = sc->sense_buffer[13]; +- derrprintk((MYIOC_s_WARN_FMT +- "id=%d SenseKey:ASC:ASCQ = (%x:%02x:%02x) CDB:\n", +- ioc->name, pScsiReq->TargetID, +- skey, asc, ascq)); +- +- for (ii=0; ii<pScsiReq->CDBLength; ii++) { +- printk("%02x ", pScsiReq->CDB[ii]); +- } +- printk("\n"); +-#endif +- } else if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID && pScsiReply->ResponseInfo) { ++ if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID && ++ pScsiReply->ResponseInfo) { + printk(KERN_NOTICE "ha=%d id=%d lun=%d: " + "FCP_ResponseInfo=%08xh\n", + ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1], +@@ -670,13 +659,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F + * killing interrupt handler:-( + */ + sc->result = SAM_STAT_BUSY; +-#ifdef MPT_DEBUG_FAIL +- derrprintk((MYIOC_s_ERR_FMT +- "id=%d MPI_IOCSTATUS_BUSY\n", +- ioc->name, pScsiReq->TargetID)); +-// panic ("IOCSTATUS_BUSY!!!!!\n"); +-#endif +- + break; + + case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */ +@@ -688,15 +670,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F + /* Spoof to SCSI Selection Timeout! */ + sc->result = DID_NO_CONNECT << 16; + +- bus = pScsiReq->Bus; +- id = pScsiReq->TargetID; +- if ( ioc->bus_type == SPI ) { +- if (hd->sel_timeout[id] < 0xFFFF) +- hd->sel_timeout[pScsiReq->TargetID]++; +- } ++ target = pScsiReq->TargetID; ++ if (hd->sel_timeout[target] < 0xFFFF) ++ hd->sel_timeout[pScsiReq->TargetID]++; + +- pMptTarget = ioc->Target_List[bus]; +- pTarget = (VirtDevice *)pMptTarget->Target[id]; ++ pTarget = hd->Targets[target]; + + if ( pTarget ) { + if (pTarget->tflags & MPT_TARGET_FLAGS_LED_ON) { +@@ -710,8 +688,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F + } else { + SEPMsg = (SEPRequest_t *)mf; + SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR; +- SEPMsg->Bus = pTarget->bus; +- SEPMsg->TargetID = pTarget->id; ++ SEPMsg->Bus = pTarget->bus_id; ++ SEPMsg->TargetID = pTarget->target_id; + SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS; + SEPMsg->SlotStatus = MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED; + pTarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON; +@@ -726,24 +704,24 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F + case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ + if ( ioc->bus_type == SAS ) { + u16 status = le16_to_cpu(pScsiReply->IOCStatus); +- u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo); +-// sc->result = DID_RESET << 16; +- sc->result = DID_SOFT_ERROR << 16; + if (status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { +- if ((log_info & 0xFFFF0000) == +- SAS_LOGINFO_NEXUS_LOSS) { ++ u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo); ++ log_info &= 0xFFFF0000; /* mask subcodes */ ++ dreplyprintk((KERN_NOTICE "IOC_TERMINATED: ha=%d id=%d lun=%d:\n" ++ "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh " ++ "loginfo=%08x\n" ++ ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1], ++ status, scsi_state, scsi_status, log_info)); ++ if (log_info == SAS_LOGINFO_NEXUS_LOSS) { + sc->result = (DID_BUS_BUSY << 16); ++ break; + } ++ } else { ++ dreplyprintk((KERN_NOTICE "IOC_TERMINATED: ha=%d id=%d lun=%d:\n" ++ "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n", ++ ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1], ++ status, scsi_state, scsi_status)); + } +- derrprintk((KERN_NOTICE "IOC_TERMINATED: " +- "ha=%d id=%d lun=%d " +- "IOCStatus=%04x SCSIState=%02x\n" +- "SCSIStatus=%02x LogInfo=%08x " +- "sc->result=%08x sc=%p\n", +- ioc->id, pScsiReq->TargetID, +- pScsiReq->LUN[1], status, scsi_state, +- scsi_status, log_info, sc->result, sc)); +- break; + } /* allow non-SAS & non-NEXUS_LOSS to drop into below code */ + + case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ +@@ -775,7 +753,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F + } else { + sc->result = DID_SOFT_ERROR << 16; + } +-// derrprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target)); ++// dreplyprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target)); + printk("RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id); + break; + #else +@@ -784,7 +762,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F + sc->result=DID_SOFT_ERROR << 16; + else /* Sufficient data transfer occurred */ + sc->result = (DID_OK << 16) | scsi_status; +- derrprintk((KERN_NOTICE ++ dreplyprintk((KERN_NOTICE + "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id)); + break; + #endif +@@ -804,9 +782,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F + sc->result = SAM_STAT_BUSY; + else + sc->result = DID_SOFT_ERROR << 16; +- derrprintk((KERN_NOTICE " xfer_cnt=%d < sc->underflow=%d result=%08x\n",xfer_cnt, sc->underflow, sc->result)); +- +- } ++ } + if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) { + /* What to do? + */ +@@ -818,6 +794,9 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F + } + } + ++ dreplyprintk((KERN_NOTICE " sc->underflow={report ERR if < %02xh bytes xfer'd}\n", ++ sc->underflow)); ++ dreplyprintk((KERN_NOTICE " ActBytesXferd=%02xh\n", xfer_cnt)); + /* Report Queue Full + */ + if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL) +@@ -896,18 +875,9 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F + break; + + } /* switch(ioc_status) */ +- if (ioc_status != MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) { +- derrprintk((KERN_NOTICE "ha=%d id=%d lun=%d " +- "IOCStatus=%04x SCSIState=%02x\n" +- "SCSIStatus=%02x " +- "sc->result=%08x sc=%p\n", +- ioc->id, pScsiReq->TargetID, +- pScsiReq->LUN[1], ioc_status, +- scsi_state, scsi_status, sc->result, +- sc)); +- } + +- } /* end of address reply case */ ++ dreplyprintk((KERN_NOTICE " sc->result is %08xh\n", sc->result)); ++ } /* end of address reply case */ + + /* Unmap the DMA buffers, if any. */ + if (sc->use_sg) { +@@ -918,7 +888,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F + sc->request_bufflen, sc->sc_data_direction); + } + +- sc->host_scribble = NULL; ++ hd->ScsiLookup[req_idx] = NULL; ++ + sc->scsi_done(sc); /* Issue the command callback */ + + /* Free Chain buffers */ +@@ -945,9 +916,7 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOS + int ii; + int max = ioc->req_depth; + +- +-drsprintk((MYIOC_s_WARN_FMT ": %s entered\n",ioc->name, __FUNCTION__)); +- ++ dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n")); + for (ii= 0; ii < max; ii++) { + if ((SCpnt = hd->ScsiLookup[ii]) != NULL) { + +@@ -959,24 +928,8 @@ drsprintk((MYIOC_s_WARN_FMT ": %s entere + hd->ScsiLookup[ii] = NULL; + + mf = MPT_INDEX_2_MFPTR(ioc, ii); +- +-/* drsprintk((MYIOC_s_WARN_FMT "flush mf=%p sc=%p\n", +- ioc->name, mf, SCpnt)); +- DBG_DUMP_RESET_REQUEST_FRAME(ioc, mf) */ +- +- +- /* Free Chain buffers */ +- mptscsih_freeChainBuffers(ioc, ii); +- +- /* Free Message frames */ +- mpt_free_msg_frame(ioc, mf); +- +- if ((unsigned char *)mf != SCpnt->host_scribble) { +- drsprintk(( "%s Skipping scsi_done mf=%p host_scribble=%p\n", +- __FUNCTION__, mf, SCpnt->host_scribble)); +- +- continue; +- } ++ dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n", ++ mf, SCpnt)); + + /* Set status, free OS resources (SG DMA buffers) + * Do OS callback +@@ -993,14 +946,20 @@ drsprintk((MYIOC_s_WARN_FMT ": %s entere + SCpnt->request_bufflen, + SCpnt->sc_data_direction); + } +- SCpnt->result = (DID_BUS_BUSY << 16); ++ SCpnt->result = DID_RESET << 16; + SCpnt->host_scribble = NULL; ++ ++ /* Free Chain buffers */ ++ mptscsih_freeChainBuffers(ioc, ii); ++ ++ /* Free Message frames */ ++ mpt_free_msg_frame(ioc, mf); ++ + SCpnt->scsi_done(SCpnt); /* Issue the command callback */ + } + } + +-drsprintk((MYIOC_s_WARN_FMT ": %s exiting\n", ioc->name, __FUNCTION__)); +- ++ return; + } + + /* +@@ -1010,7 +969,7 @@ drsprintk((MYIOC_s_WARN_FMT ": %s exitin + * Do NOT access the referenced scsi_cmnd structure or + * members. Will cause either a paging or NULL ptr error. + * @hd: Pointer to a SCSI HOST structure +- * @id: target id ++ * @target: target id + * @lun: lun + * + * Returns: None. +@@ -1018,47 +977,43 @@ drsprintk((MYIOC_s_WARN_FMT ": %s exitin + * Called from slave_destroy. + */ + static void +-mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint id, uint lun) ++mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun) + { +- MPT_ADAPTER *ioc = hd->ioc; + SCSIIORequest_t *mf = NULL; + int ii; +- int max = ioc->req_depth; ++ int max = hd->ioc->req_depth; + struct scsi_cmnd *sc; + +- dsprintk((KERN_INFO MYNAM ": search_running id %d lun %d max %d\n", +- id, lun, max)); ++ dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n", ++ target, lun, max)); + + for (ii=0; ii < max; ii++) { + if ((sc = hd->ScsiLookup[ii]) != NULL) { + +- mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii); ++ mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii); + + dsprintk(( "search_running: found (sc=%p, mf = %p)\n", + hd->ScsiLookup[ii], mf)); + if (mf == NULL) + continue; +- dsprintk(( "search_running: found (sc=%p, mf = %p) id %d, lun %d \n", ++ dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n", + hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1])); + +- if ((mf->TargetID != ((u8)id)) || (mf->LUN[1] != ((u8) lun))) ++ if ((mf->TargetID != ((u8)target)) || (mf->LUN[1] != ((u8) lun))) + continue; + + /* Cleanup + */ + hd->ScsiLookup[ii] = NULL; +- mptscsih_freeChainBuffers(ioc, ii); +- mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf); +- if ((unsigned char *)mf != sc->host_scribble) { +- continue; +- } ++ mptscsih_freeChainBuffers(hd->ioc, ii); ++ mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf); + if (sc->use_sg) { +- pci_unmap_sg(ioc->pcidev, ++ pci_unmap_sg(hd->ioc->pcidev, + (struct scatterlist *) sc->request_buffer, + sc->use_sg, + sc->sc_data_direction); + } else if (sc->request_bufflen) { +- pci_unmap_single(ioc->pcidev, ++ pci_unmap_single(hd->ioc->pcidev, + sc->SCp.dma_handle, + sc->request_bufflen, + sc->sc_data_direction); +@@ -1068,8 +1023,8 @@ mptscsih_search_running_cmds(MPT_SCSI_HO + sc->scsi_done(sc); + } + } +- dsprintk((KERN_INFO MYNAM ": search_running id %d lun %d completed\n", +- id, lun)); ++ dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d completed\n", ++ target, lun)); + return; + } + +@@ -1169,66 +1124,9 @@ mptscsih_sendIOCInit(MPT_SCSI_HOST *hd) + } + + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +-/* mptscsih_TM_timeout - Call back for timeout on a +- * task management request. +- * @data: Pointer to MPT_ADAPTER recast as an unsigned long +- * +- */ +-void mptscsih_TM_timeout(unsigned long data) +-{ +- MPT_ADAPTER *ioc=(MPT_ADAPTER *)data; +- MPT_SCSI_HOST *hd =(MPT_SCSI_HOST *)ioc->sh->hostdata; +- int retval; +- u32 ioc_state; +- +- dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_TM_timeout: " +- "TM request timed out!\n", ioc->name)); +- +- /* Delete the timer that triggered this callback. +- * Remark: DEL_TIMER checks to make sure timer is active +- * before deleting. +- */ +- del_timer(&ioc->TMtimer); +- +- mpt_free_msg_frame(ioc, ioc->tmPtr); +- +- ioc->tmPtr = NULL; +- +- dtmprintk((MYIOC_s_WARN_FMT "%s: Calling mpt_SendIocReset MUR!\n", +- ioc->name, __FUNCTION__)); +- if ((retval = mpt_SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, NO_SLEEP)) != 0) { +- ioc_state = mpt_GetIocState(ioc, 0); +- dfailprintk((MYIOC_s_WARN_FMT "%s: IOC MUR failed! ioc_state=%08x\n", +- ioc->name, __FUNCTION__, ioc_state)); +-// panic ("IOC MUR Failed"); +- ioc->IOCResetInProgress = 0; +- +- if ((retval = mpt_HardResetHandler(ioc, NO_SLEEP)) < 0){ +- printk(KERN_WARNING "%s: %s: HardResetHandler FAILED!!\n", +- ioc->name, __FUNCTION__); +- } else { +- dtmprintk((MYIOC_s_WARN_FMT "%s: HardResetHandler succeeded!!\n", +- ioc->name, __FUNCTION__)); +- } +- } else { +- dtmprintk((MYIOC_s_WARN_FMT "IOC MUR succeeded\n", ioc->name)); +- mptscsih_flush_running_cmds(hd); +- dtmprintk((MYIOC_s_WARN_FMT "Calling do_ioc_recovery! \n", ioc->name)); +- if ((retval = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, NO_SLEEP)) != 0) { +- dfailprintk((MYIOC_s_ERR_FMT "%s: (%d) ioc_recovery failed\n", ioc->name, __FUNCTION__, retval)); +- } else { +- dtmprintk((MYIOC_s_WARN_FMT "%s:Successful do_ioc_recovery! \n", ioc->name, __FUNCTION__)); +- } +- } +- hd->TM_wait_done = 1; +- wake_up(&hd->TM_waitq); +-} +- +-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + /* mptscsih_writeFCPortPage3 - write FC Port Page 3 + * @hd: Pointer to a SCSI Host Structure +- * @bus: write FC Port Page 3 for this bus +- * @id: write FC Port Page 3 for this target ID ++ * @target_id: write FC Port Page 3 for this target ID + * + * Return: -EAGAIN if unable to obtain a Message Frame + * or 0 if success. +@@ -1236,7 +1134,7 @@ void mptscsih_TM_timeout(unsigned long d + * Remark: We do not wait for a return, write pages sequentially. + */ + static int +-mptscsih_writeFCPortPage3(MPT_SCSI_HOST *hd, int bus, int id) ++mptscsih_writeFCPortPage3(MPT_SCSI_HOST *hd, int target_id) + { + MPT_ADAPTER *ioc = hd->ioc; + Config_t *pReq; +@@ -1247,7 +1145,6 @@ mptscsih_writeFCPortPage3(MPT_SCSI_HOST + u32 frameOffset; + u32 flagsLength; + int ii; +- struct _MPT_DEVICE *pMptTarget; + VirtDevice *pTarget; + + /* Get a MF for this command. +@@ -1287,10 +1184,9 @@ mptscsih_writeFCPortPage3(MPT_SCSI_HOST + pReq->Header.PageType = MPI_CONFIG_PAGETYPE_FC_PORT | + MPI_CONFIG_PAGEATTR_PERSISTENT; + pReq->PageAddress = cpu_to_le32(MPI_FC_PORT_PGAD_FORM_INDEX | +- id); ++ target_id); + +- pMptTarget = ioc->Target_List[bus]; +- pTarget = pMptTarget->Target[id]; ++ pTarget = hd->Targets[target_id]; + + FCPort3->Header.PageVersion = MPI_FCPORTPAGE3_PAGEVERSION; + FCPort3->Header.PageLength = sizeof(FCPortPage3_t) / 4; +@@ -1299,8 +1195,8 @@ mptscsih_writeFCPortPage3(MPT_SCSI_HOST + MPI_CONFIG_PAGEATTR_PERSISTENT; + FCPort3->Entry[0].PhysicalIdentifier.WWN.WWPN = pTarget->WWPN; + FCPort3->Entry[0].PhysicalIdentifier.WWN.WWNN = pTarget->WWNN; +- FCPort3->Entry[0].TargetID = id; +- FCPort3->Entry[0].Bus = bus; ++ FCPort3->Entry[0].TargetID = pTarget->target_id; ++ FCPort3->Entry[0].Bus = pTarget->bus_id; + FCPort3->Entry[0].Flags = cpu_to_le16(MPI_PERSISTENT_FLAGS_ENTRY_VALID); + + /* Add a SGE to the config request. +@@ -1308,7 +1204,7 @@ mptscsih_writeFCPortPage3(MPT_SCSI_HOST + flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sizeof(FCPortPage3_t); + mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma); + +- drsprintk((MYIOC_s_INFO_FMT "writeFCPortPage3: bus=%d id=%d\n", ioc->name, , bus, id)); ++ drsprintk((MYIOC_s_INFO_FMT "writeFCPortPage3: target=%d\n", ioc->name, target_id)); + + mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); + +@@ -1320,7 +1216,7 @@ mptscsih_writeFCPortPage3(MPT_SCSI_HOST + * mptscsih_readFCDevicePage0 - returns FC Device Page 0 data + * @ioc: Pointer to MPT_ADAPTER structure + * @bus: bus id +- * @id: target id ++ * @targetId: target id + * @fcDevicePage: FC Device Page 0 data + * + * Returns count of number bytes copied into @fcDevicePage +@@ -1328,7 +1224,7 @@ mptscsih_writeFCPortPage3(MPT_SCSI_HOST + */ + + int +-mptscsih_readFCDevicePage0(MPT_ADAPTER *ioc, u8 bus, u8 id, pFCDevicePage0_t fcDevicePage) ++mptscsih_readFCDevicePage0(MPT_ADAPTER *ioc, u8 bus, u8 targetId, pFCDevicePage0_t fcDevicePage) + { + ConfigPageHeader_t hdr; + CONFIGPARMS cfg; +@@ -1348,7 +1244,7 @@ mptscsih_readFCDevicePage0(MPT_ADAPTER * + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.dir = 0; + +- cfg.pageAddr = (bus << 8) + id + MPI_FC_DEVICE_PGAD_FORM_BUS_TID; ++ cfg.pageAddr = (bus << 8) + targetId + MPI_FC_DEVICE_PGAD_FORM_BUS_TID; + cfg.timeout = 0; + + if ((rc = mpt_config(ioc, &cfg)) != 0) +@@ -1436,16 +1332,15 @@ mptscsih_remove(struct pci_dev *pdev) + spin_unlock_irqrestore(&dvtaskQ_lock, flags); + } + if (!count) +- printk(KERN_ERR MYNAM ": %s: ERROR - DV thread still active!\n", +- ioc->name); +-#ifdef MPT_DEBUG_DV ++ printk(KERN_ERR MYNAM ": ERROR - DV thread still active!\n"); ++#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY) + else +- printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", ioc->name,10 * HZ, count); ++ printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", 10 * HZ, count); + #endif + #endif + +- dexitprintk((KERN_INFO MYNAM ": %s ioc=%p hd=%p MaxDevices=%d\n", +- ioc->name, ioc, hd, ioc->facts.MaxDevices)); ++ dexitprintk((KERN_INFO MYNAM ": %s ioc=%p hd=%p Targets=%p MaxDevices=%d\n", ++ ioc->name, ioc, hd, hd->Targets, ioc->facts.MaxDevices)); + // This was changed in the 2.6.13 kernel + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)) + mptscsih_shutdown(&pdev->dev); +@@ -1453,19 +1348,19 @@ mptscsih_remove(struct pci_dev *pdev) + mptscsih_shutdown(pdev); + #endif + +- dexitprintk((KERN_INFO MYNAM ": %s: calling scsi_remove_host ioc=%p host=%p\n", ++ dexitprintk((KERN_INFO MYNAM ": %s: calling scsi_remove_host ioc=%p host=%p\n", + ioc->name, ioc, host)); + + scsi_remove_host(host); + dexitprintk((KERN_INFO MYNAM ": %s: scsi_remove_host completed\n", ioc->name)); + + if (hd->ScsiLookup != NULL) { +- sz1 = ioc->req_depth * sizeof(void *); ++ sz1 = hd->ioc->req_depth * sizeof(void *); + kfree(hd->ScsiLookup); + hd->ScsiLookup = NULL; + dprintk((MYIOC_s_INFO_FMT + "Free'd ScsiLookup (%d) memory\n", +- ioc->name, sz1)); ++ hd->ioc->name, sz1)); + } + + if (hd->info_kbuf != NULL) +@@ -1473,7 +1368,7 @@ mptscsih_remove(struct pci_dev *pdev) + + /* NULL the Scsi_Host pointer + */ +- ioc->sh = NULL; ++ hd->ioc->sh = NULL; + + scsi_host_put(host); + +@@ -1498,36 +1393,25 @@ mptscsih_shutdown(struct pci_dev *pdev) + { + MPT_ADAPTER *ioc = pci_get_drvdata(pdev); + #endif +- struct Scsi_Host *host; ++ struct Scsi_Host *host = ioc->sh; + MPT_SCSI_HOST *hd; + +- host = ioc->sh; +- + if(!host) + return; + + hd = (MPT_SCSI_HOST *)host->hostdata; + +- dexitprintk((KERN_INFO MYNAM ": %s: ioc=%p hd=%p\n", +- __FUNCTION__, ioc, hd)); +- + /* Flush the cache of this adapter + */ +- if(hd != NULL) { +- dexitprintk((KERN_INFO MYNAM ": Calling mptscsih_synchronize_cache for %s\n", +- ioc->name)); ++ if(hd != NULL) + mptscsih_synchronize_cache(hd, 0); +- dexitprintk((KERN_INFO MYNAM ": mptscsih_synchronize_cache for %s completed\n", +- ioc->name)); +- } +- dexitprintk((KERN_INFO MYNAM ": %s done: ioc=%p hd=%p\n", +- __FUNCTION__, ioc, hd)); ++ + } + + #ifdef CONFIG_PM + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + /* +- * mptscsih_suspend - Fusion MPT scsi driver suspend routine. ++ * mptscsih_suspend - Fusion MPT scsie driver suspend routine. + * + * + */ +@@ -1566,7 +1450,7 @@ mptscsih_resume(struct pci_dev *pdev) + return 0; + + #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION +-/* { ++ { + unsigned long lflags; + spin_lock_irqsave(&dvtaskQ_lock, lflags); + if (!dvtaskQ_active) { +@@ -1578,7 +1462,7 @@ mptscsih_resume(struct pci_dev *pdev) + } else { + spin_unlock_irqrestore(&dvtaskQ_lock, lflags); + } +- } */ ++ } + #endif + return 0; + } +@@ -1732,13 +1616,10 @@ int + mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) + { + MPT_SCSI_HOST *hd; +- MPT_ADAPTER *ioc; + MPT_FRAME_HDR *mf; + SCSIIORequest_t *pScsiReq; +- struct _MPT_DEVICE *pMptTarget; + VirtDevice *pTarget; +- unsigned long flags; +- int bus, id; ++ int target; + int lun; + u32 datalen; + u32 scsictl; +@@ -1746,34 +1627,18 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, v + int my_idx; + int ii; + +- /* EDM Debug */ +-// mptscsih_scsi_print_command(SCpnt); +- + hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata; +- ioc = hd->ioc; +- bus = SCpnt->device->channel; +- id = SCpnt->device->id; ++ target = SCpnt->device->id; + lun = SCpnt->device->lun; + SCpnt->scsi_done = done; + +- spin_lock_irqsave(&ioc->diagLock, flags); +- if (ioc->IOCResetInProgress) { +- dfailprintk((MYIOC_s_WARN_FMT "qcmd, SCpnt=%p IOCResetInProgress!!\n", +- ioc->name, SCpnt)); +- spin_unlock_irqrestore(&ioc->diagLock, flags); +- goto fail; +- } +- spin_unlock_irqrestore(&ioc->diagLock, flags); +- +- +- pMptTarget = ioc->Target_List[bus]; +- pTarget = pMptTarget->Target[id]; ++ pTarget = hd->Targets[target]; + + if ( pTarget ) { + if ( lun > pTarget->last_lun ) { + dsprintk((MYIOC_s_INFO_FMT + "qcmd: lun=%d > last_lun=%d on id=%d\n", +- ioc->name, lun, pTarget->last_lun, id)); ++ hd->ioc->name, lun, pTarget->last_lun, target)); + SCpnt->result = DID_BAD_TARGET << 16; + SCpnt->scsi_done(SCpnt); + return 0; +@@ -1782,31 +1647,32 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, v + * allocated, use the Inquiry data to determine if device + * supports tagged. + */ +- if ( pTarget->tflags & MPT_TARGET_FLAGS_Q_YES) ++ if ( (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES) ++ && (SCpnt->device->tagged_supported)) { + scsictl = MPI_SCSIIO_CONTROL_SIMPLEQ; +- else ++ } else { + scsictl = MPI_SCSIIO_CONTROL_UNTAGGED; ++ } + +- } else { ++ } else + scsictl = MPI_SCSIIO_CONTROL_UNTAGGED; +-dioprintk((MYIOC_s_WARN_FMT "qcmd: CDB=%02x id=%d lun=%d Null pTarget, sending Untagged\n", +- ioc->name, SCpnt->cmnd[0], id, lun)); +- if (ioc->bus_type == SPI) { +- dnegoprintk(("writeSDP1: id=%d Async/Narrow\n", +- id)); +- mpt_writeSDP1(ioc, 0, id, 0); +- } ++ dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n", ++ (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done)); + +- } ++ if (hd->resetPending) { ++ dfailprintk((MYIOC_s_INFO_FMT "QueueCmd, SCpnt=%p resetPending!!\n", ++ hd->ioc->name, SCpnt)); ++ return SCSI_MLQUEUE_HOST_BUSY; ++ } + + /* + * Put together a MPT SCSI request... + */ +- if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) { ++ if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) { + dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n", +- ioc->name,__FUNCTION__)); +- goto fail; +- } ++ hd->ioc->name,__FUNCTION__)); ++ return SCSI_MLQUEUE_HOST_BUSY; ++ } + + pScsiReq = (SCSIIORequest_t *) mf; + +@@ -1831,8 +1697,8 @@ dioprintk((MYIOC_s_WARN_FMT "qcmd: CDB=% + + /* Use the above information to set up the message frame + */ +- pScsiReq->TargetID = (u8) id; +- pScsiReq->Bus = (u8) bus; ++ pScsiReq->TargetID = (u8) target; ++ pScsiReq->Bus = (u8) SCpnt->device->channel; + pScsiReq->ChainOffset = 0; + pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; + pScsiReq->CDBLength = SCpnt->cmd_len; +@@ -1863,7 +1729,7 @@ dioprintk((MYIOC_s_WARN_FMT "qcmd: CDB=% + pScsiReq->DataLength = cpu_to_le32(datalen); + + /* SenseBuffer low address */ +- pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma ++ pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma + + (my_idx * MPT_SENSE_BUFFER_ALLOC)); + + /* Now add the SG list +@@ -1875,39 +1741,67 @@ dioprintk((MYIOC_s_WARN_FMT "qcmd: CDB=% + (dma_addr_t) -1); + } else { + /* Add a 32 or 64 bit SGE */ +- if (mptscsih_AddSGE(ioc, SCpnt, pScsiReq, my_idx) != SUCCESS){ +- mptscsih_freeChainBuffers(ioc, my_idx); +- mpt_free_msg_frame(ioc, mf); ++ if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS) + goto fail; +- } + } + +- SCpnt->host_scribble = (unsigned char *)mf; +- +- if (ioc->bus_type == SPI && +- ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_IN_PROGRESS) { +- spin_lock_irqsave(&ioc->PendingMFlock, flags); +- ioc->PendingMF = mf; +- ioc->PendingSCpnt = SCpnt; +- spin_unlock_irqrestore(&ioc->PendingMFlock, flags); +- dpendprintk((KERN_INFO " qcmd: %s: DV In Progress id=%d mf=%p sc=%p into PendingMF\n", +- ioc->name, id, mf, SCpnt)); +- DBG_DUMP_REQUEST_FRAME(ioc, mf) +-// mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ); +- return 0; +-} + hd->ScsiLookup[my_idx] = SCpnt; ++ SCpnt->host_scribble = NULL; + +- mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); ++#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION ++ if (hd->ioc->bus_type == SPI) { ++ int dvStatus = hd->ioc->spi_data.dvStatus[target]; ++ int issueCmd = 1; ++ ++ if (dvStatus || hd->ioc->spi_data.forceDv) { ++ ++ if ((dvStatus & MPT_SCSICFG_NEED_DV) || ++ (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) { ++ unsigned long lflags; ++ /* Schedule DV if necessary */ ++ spin_lock_irqsave(&dvtaskQ_lock, lflags); ++ if (!dvtaskQ_active) { ++ dvtaskQ_active = 1; ++ spin_unlock_irqrestore(&dvtaskQ_lock, lflags); ++ INIT_WORK(&dvTaskQ_task, mptscsih_domainValidation, (void *) hd); ++ ++ schedule_work(&dvTaskQ_task); ++ } else { ++ spin_unlock_irqrestore(&dvtaskQ_lock, lflags); ++ } ++ hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV; ++ } ++ ++ /* Trying to do DV to this target, extend timeout. ++ * Wait to issue until flag is clear ++ */ ++ if (dvStatus & MPT_SCSICFG_DV_PENDING) { ++ mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ); ++ issueCmd = 0; ++ } ++ ++ /* Set the DV flags. ++ */ ++ if (dvStatus & MPT_SCSICFG_DV_NOT_DONE) ++ mptscsih_set_dvflags(hd, pScsiReq); ++ ++ if (!issueCmd) ++ goto fail; ++ } ++ } ++#endif ++ ++ mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf); + dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n", +- ioc->name, SCpnt, mf, my_idx)); +- DBG_DUMP_REQUEST_FRAME(ioc,mf) ++ hd->ioc->name, SCpnt, mf, my_idx)); ++ DBG_DUMP_REQUEST_FRAME(mf) + return 0; + + fail: +- SCpnt->result = DID_BUS_BUSY << 16; +- SCpnt->scsi_done(SCpnt); +- return 0; ++ hd->ScsiLookup[my_idx] = NULL; ++ mptscsih_freeChainBuffers(hd->ioc, my_idx); ++ mpt_free_msg_frame(hd->ioc, mf); ++ return SCSI_MLQUEUE_HOST_BUSY; + } + + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +@@ -1972,8 +1866,7 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *i + * + * @ioc: Pointer to MPT_ADAPTER structure + * @type: Task Management type +- * @bus: Logical Bus for reset (if appropriate) +- * @id: Logical Target ID for reset (if appropriate) ++ * @target: Logical Target ID for reset (if appropriate) + * @lun: Logical Unit for reset (if appropriate) + * @ctx2abort: Context for the task to be aborted (if appropriate) + * +@@ -1982,10 +1875,10 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *i + * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC + * will be active. + * +- * Returns 0 for SUCCESS. ++ * Returns 0 for SUCCESS or -1 if FAILED. + */ + int +-mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 bus, u8 id, u8 lun, int ctx2abort, ulong timeout) ++mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout) + { + MPT_ADAPTER *ioc; + int rc = -1; +@@ -2000,15 +1893,16 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 + return 0; + + ioc = hd->ioc; +- ++ if (ioc == NULL) { ++ printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n"); ++ return FAILED; ++ } + dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name)); + + // SJR - CHECKME - Can we avoid this here? + // (mpt_HardResetHandler has this check...) + spin_lock_irqsave(&ioc->diagLock, flags); +- if (ioc->IOCResetInProgress) { +- dtmprintk((KERN_INFO MYNAM ": %s: TMHandler failing: " +- "IOCResetInProgress\n", ioc->name)); ++ if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) { + spin_unlock_irqrestore(&ioc->diagLock, flags); + return FAILED; + } +@@ -2023,54 +1917,52 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 + if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { + dtmprintk((KERN_INFO MYNAM ": %s: TMHandler abort: " + "Timed out waiting for last TM (%d) to complete! \n", +- ioc->name, hd->tmPending)); ++ hd->ioc->name, hd->tmPending)); + return FAILED; + } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { + dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: " + "Timed out waiting for last TM (%d) to complete! \n", +- ioc->name, hd->tmPending)); ++ hd->ioc->name, hd->tmPending)); + return FAILED; + } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { + dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: " + "Timed out waiting for last TM (%d) to complete! \n", +- ioc->name, hd->tmPending)); ++ hd->ioc->name, hd->tmPending)); + if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)) + return FAILED; + + doTask = 0; + } + } else { +- spin_lock_irqsave(&ioc->FreeQlock, flags); ++ spin_lock_irqsave(&hd->ioc->FreeQlock, flags); + hd->tmPending |= (1 << type); +- spin_unlock_irqrestore(&ioc->FreeQlock, flags); ++ spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + } + + /* Is operational? + */ +- ioc_raw_state = mpt_GetIocState(ioc, 0); ++ ioc_raw_state = mpt_GetIocState(hd->ioc, 0); + + #ifdef MPT_DEBUG_RESET + if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) { + printk(MYIOC_s_WARN_FMT + "TM Handler: IOC Not operational(0x%x)!\n", +- ioc->name, ioc_raw_state); +- return FAILED; +-// panic ( "TMHandler: IOC Not operational!"); ++ hd->ioc->name, ioc_raw_state); + } + #endif + + if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) + && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) { + +- /* Issue the Task Mgmt request. ++ /* Isse the Task Mgmt request. + */ + if (hd->hard_resets < -1) + hd->hard_resets++; +- rc = mptscsih_IssueTaskMgmt(hd, type, bus, id, lun, ctx2abort, timeout); ++ rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout); + if (rc) { +- printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", ioc->name); ++ printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name); + } else { +- dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", ioc->name)); ++ dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name)); + } + } + +@@ -2079,21 +1971,11 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 + if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc || + ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) { + dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", +- ioc->name)); +- rc = mpt_HardResetHandler(ioc, CAN_SLEEP); ++ hd->ioc->name)); ++ rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP); + } + +- /* +- * Check IOCStatus from TM reply message +- */ +- if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS || +- hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED || +- hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED) +- rc = 0; +- else +- rc = FAILED; +- +- dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", ioc->name, rc)); ++ dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc)); + + return rc; + } +@@ -2104,7 +1986,7 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 + * mptscsih_IssueTaskMgmt - Generic send Task Management function. + * @hd: Pointer to MPT_SCSI_HOST structure + * @type: Task Management type +- * @id: Logical Target ID for reset (if appropriate) ++ * @target: Logical Target ID for reset (if appropriate) + * @lun: Logical Unit for reset (if appropriate) + * @ctx2abort: Context for the task to be aborted (if appropriate) + * +@@ -2117,31 +1999,28 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 + * else other non-zero value returned. + */ + static int +-mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 bus, u8 id, u8 lun, int ctx2abort, ulong timeout) ++mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout) + { +- MPT_ADAPTER *ioc = hd->ioc; + MPT_FRAME_HDR *mf; + SCSITaskMgmt_t *pScsiTm; + int ii; + int retval; +- u32 ioc_state; +- unsigned long flags; + + /* Return Fail to calling function if no message frames available. + */ +- if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) { ++ if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) { + dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n", +- ioc->name,__FUNCTION__)); ++ hd->ioc->name,__FUNCTION__)); + return FAILED; + } +- dtmprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt request @ %p\n", +- ioc->name, mf)); ++ dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n", ++ hd->ioc->name, mf)); + + /* Format the Request + */ + pScsiTm = (SCSITaskMgmt_t *) mf; +- pScsiTm->TargetID = id; +- pScsiTm->Bus = bus; ++ pScsiTm->TargetID = target; ++ pScsiTm->Bus = channel; + pScsiTm->ChainOffset = 0; + pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; + +@@ -2161,52 +2040,31 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd + + pScsiTm->TaskMsgContext = ctx2abort; + +- dtmprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n", +- ioc->name, ctx2abort, type)); ++ dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n", ++ hd->ioc->name, ctx2abort, type)); + + DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm); + +- hd->TM_wait_done = 0; +- if ((retval = mpt_send_handshake_request(ioc->TaskCtx, ioc, +- sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, timeout, CAN_SLEEP)) != 0) { +- dfailprintk((MYIOC_s_WARN_FMT "%s: send_handshake FAILED!\n", +- ioc->name, __FUNCTION__)); +- mpt_free_msg_frame(ioc, mf); +- +- dtmprintk((MYIOC_s_WARN_FMT "Calling mpt_SendIocReset MUR!\n", +- ioc->name)); +- if ((retval = mpt_SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) != 0) { +- ioc_state = mpt_GetIocState(ioc, 0); +- dfailprintk((MYIOC_s_WARN_FMT "IOC MUR failed! ioc_state=%08x\n", ioc->name, ioc_state)); +-// panic ("IOC MUR Failed"); +- ioc->IOCResetInProgress = 0; ++ if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc, ++ sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, ++ CAN_SLEEP)) != 0) { ++ dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!" ++ " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, ++ hd->ioc, mf)); ++ mpt_free_msg_frame(hd->ioc, mf); ++ return retval; ++ } + +- if ((retval = mpt_HardResetHandler(ioc, CAN_SLEEP)) < 0){ +- printk((KERN_WARNING " HardResetHandler FAILED!!\n")); } +- else { +- dtmprintk((MYIOC_s_WARN_FMT " HardResetHandler succeeded!!\n", ioc->name)); +- } +- } else { +- dtmprintk((MYIOC_s_WARN_FMT "IOC MUR succeeded\n", ioc->name)); +- mptscsih_flush_running_cmds(hd); +- dtmprintk((MYIOC_s_WARN_FMT "Calling do_ioc_recovery! \n", ioc->name)); +- if ((retval = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, CAN_SLEEP)) != 0) { +- dfailprintk((MYIOC_s_ERR_FMT "- (%d) ioc_recovery failed\n", ioc->name, retval)); +- } else { +- dtmprintk((MYIOC_s_WARN_FMT "Successful do_ioc_recovery! \n", ioc->name)); +- } +- } +- } else { +- dtmprintk((MYIOC_s_WARN_FMT "%s: send_handshake SUCCESS!\n", +- ioc->name, __FUNCTION__)); +- if (hd->TM_wait_done == 0) { +- wait_event(hd->TM_waitq, hd->TM_wait_done); +- } ++ if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) { ++ dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!" ++ " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, ++ hd->ioc, mf)); ++ mpt_free_msg_frame(hd->ioc, mf); ++ dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", ++ hd->ioc->name)); ++ retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP); + } +- spin_lock_irqsave(&ioc->FreeQlock, flags); +- hd->tmPending = 0; +- hd->tmState = TM_STATE_NONE; +- spin_unlock_irqrestore(&ioc->FreeQlock, flags); ++ + return retval; + } + +@@ -2229,8 +2087,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) + int scpnt_idx; + int retval; + int tm_timeout; +- unsigned long flags; +- unsigned long sn = SCpnt->serial_number; + + /* From the 2.6.13 kernels, they have removed calling + * eh_threads with the host_lock in locked state +@@ -2251,57 +2107,30 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) + } + + ioc = hd->ioc; +- spin_lock_irqsave(&ioc->diagLock, flags); +- if (ioc->IOCResetInProgress) { +- dtmprintk((KERN_INFO ": %s: abort: " +- "IOCResetInProgress (sc=%p)\n", +- ioc->name, SCpnt)); +- spin_unlock_irqrestore(&ioc->diagLock, flags); +- +- ++ if (hd->resetPending) { + return FAILED; + } + +-spin_unlock_irqrestore(&ioc->diagLock, flags); +- + if (hd->timeouts < -1) +- + hd->timeouts++; + +- printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n", +- ioc->name, SCpnt); +- scsi_print_command(SCpnt); +- +-// printk(KERN_WARNING MYNAM ": %s: Delaying 30 seconds\n", ioc->name); +-// mdelay (30000); +- /* If this command is pended, then timeout/hang occurred +- * during DV. Post command and flush pending Q +- * and then following up with the reset request. +- */ +- if ( (mf = mptscsih_search_PendingMF(ioc, SCpnt)) != NULL) { +- /* Cmd was in PendingMF. +- */ +- dpendprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: " +- "Command was in PendingMF! (sc=%p)\n", +- ioc->name, SCpnt)); +- return SUCCESS; +- } +- +- +- + /* Find this command + */ + if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) { + /* Cmd not found in ScsiLookup. + * Do OS callback. + */ +-// SCpnt->result = DID_RESET << 16; ++ SCpnt->result = DID_RESET << 16; + dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: " + "Command not in the active list! (sc=%p)\n", +- ioc->name, SCpnt)); ++ hd->ioc->name, SCpnt)); + return SUCCESS; + } + ++ printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n", ++ hd->ioc->name, SCpnt); ++ scsi_print_command(SCpnt); ++ + /* Most important! Set TaskMsgContext to SCpnt's MsgContext! + * (the IO to be ABORT'd) + * +@@ -2309,7 +2138,7 @@ spin_unlock_irqrestore(&ioc->diagLock, f + * swap it here either. It is an opaque cookie to + * the controller, so it does not matter. -DaveM + */ +- mf = MPT_INDEX_2_MFPTR(ioc, scpnt_idx); ++ mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx); + ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext; + + hd->abortSCpnt = SCpnt; +@@ -2318,7 +2147,7 @@ spin_unlock_irqrestore(&ioc->diagLock, f + spin_unlock_irq(host_lock); + #endif + /* set timeout in seconds */ +- switch (ioc->bus_type) { ++ switch (hd->ioc->bus_type) { + case FC: + tm_timeout=40; + break; +@@ -2327,7 +2156,7 @@ spin_unlock_irqrestore(&ioc->diagLock, f + break; + case SPI: + default: +- tm_timeout=10; ++ tm_timeout=2; + break; + } + retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, +@@ -2337,30 +2166,17 @@ spin_unlock_irqrestore(&ioc->diagLock, f + spin_lock_irq(host_lock); + #endif + +-if (ioc->bus_type == FC) { +- if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx && +- SCpnt->serial_number == sn) { +- dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: " +- "scpnt_idx=%08x sn=%lx (sc=%p)\n", +- ioc->name, scpnt_idx, sn, SCpnt)); +- retval = FAILED; +- } +-} +- + printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n", +- ioc->name, ++ hd->ioc->name, + ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); +- hd->ScsiLookup[scpnt_idx] = NULL; +-//panic ("Task Abort completed"); +- spin_lock_irqsave(&hd->ioc->FreeQlock, flags); +- hd->tmPending = 0; +- hd->tmState = TM_STATE_NONE; +- spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); +- + + if (retval == 0) + return SUCCESS; + ++ if(retval != FAILED ) { ++ hd->tmPending = 0; ++ hd->tmState = TM_STATE_NONE; ++ } + return FAILED; + } + +@@ -2377,10 +2193,8 @@ int + mptscsih_dev_reset(struct scsi_cmnd * SCpnt) + { + MPT_SCSI_HOST *hd; +- MPT_ADAPTER *ioc; +- int id,retval; ++ int retval; + int tm_timeout; +- unsigned long flags; + + /* From the 2.6.13 kernels, they have removed calling + * eh_threads with the host_lock in locked state +@@ -2398,27 +2212,17 @@ mptscsih_dev_reset(struct scsi_cmnd * SC + return FAILED; + } + +- ioc = hd->ioc; +- id = SCpnt->device->id; +- spin_lock_irqsave(&ioc->diagLock, flags); +- if (ioc->IOCResetInProgress) { +- dtmprintk((KERN_INFO ": %s: target reset: " +- "IOCResetInProgress (sc=%p)\n", +- ioc->name, SCpnt)); +- spin_unlock_irqrestore(&ioc->diagLock, flags); +- +- return FAILED; +-} +-spin_unlock_irqrestore(&ioc->diagLock, flags); ++ if (hd->resetPending) ++ return FAILED; + + printk(KERN_WARNING MYNAM ": %s: attempting target reset! (sc=%p)\n", +- ioc->name, SCpnt); ++ hd->ioc->name, SCpnt); + scsi_print_command(SCpnt); + + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)) + spin_unlock_irq(host_lock); + #endif +- switch (ioc->bus_type) { ++ switch (hd->ioc->bus_type) { + case FC: + tm_timeout=40; + break; +@@ -2427,29 +2231,25 @@ spin_unlock_irqrestore(&ioc->diagLock, f + break; + case SPI: + default: +- tm_timeout=10; ++ tm_timeout=5; + break; + } + retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, +- SCpnt->device->channel, id, 0, 0, tm_timeout); ++ SCpnt->device->channel, SCpnt->device->id, ++ 0, 0, tm_timeout); + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)) + spin_lock_irq(host_lock); + #endif + printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n", +- ioc->name, ++ hd->ioc->name, + ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); +- spin_lock_irqsave(&hd->ioc->FreeQlock, flags); +- hd->tmPending = 0; +- hd->tmState = TM_STATE_NONE; +- spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); +- +- if (retval == 0) { +- if (ioc->bus_type == SPI) { +- dnegoprintk(("writeSDP1: id=%d USE_NVRAM\n", +- id)); +- mpt_writeSDP1(ioc, 0, id, MPT_SCSICFG_USE_NVRAM); +- } +- return SUCCESS; ++ ++ if (retval == 0) ++ return SUCCESS; ++ ++ if(retval != FAILED ) { ++ hd->tmPending = 0; ++ hd->tmState = TM_STATE_NONE; + } + return FAILED; + } +@@ -2467,10 +2267,8 @@ int + mptscsih_bus_reset(struct scsi_cmnd * SCpnt) + { + MPT_SCSI_HOST *hd; +- MPT_ADAPTER *ioc; + int retval; + int tm_timeout; +- unsigned long flags; + + /* From the 2.6.13 kernels, they have removed calling + * eh_threads with the host_lock in locked state +@@ -2488,9 +2286,8 @@ mptscsih_bus_reset(struct scsi_cmnd * SC + return FAILED; + } + +- ioc = hd->ioc; + printk(KERN_WARNING MYNAM ": %s: attempting bus reset! (sc=%p)\n", +- ioc->name, SCpnt); ++ hd->ioc->name, SCpnt); + scsi_print_command(SCpnt); + + if (hd->timeouts < -1) +@@ -2500,7 +2297,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SC + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)) + spin_unlock_irq(host_lock); + #endif +- switch (ioc->bus_type) { ++ switch (hd->ioc->bus_type) { + case FC: + tm_timeout=40; + break; +@@ -2509,7 +2306,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SC + break; + case SPI: + default: +- tm_timeout=10; ++ tm_timeout=5; + break; + } + retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, +@@ -2519,20 +2316,17 @@ mptscsih_bus_reset(struct scsi_cmnd * SC + #endif + + printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n", +- ioc->name, ++ hd->ioc->name, + ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); + +- spin_lock_irqsave(&hd->ioc->FreeQlock, flags); +- hd->tmPending = 0; +- hd->tmState = TM_STATE_NONE; +- spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); +- +- +- + if (retval == 0) + return SUCCESS; + +- return FAILED; ++ if(retval != FAILED ) { ++ hd->tmPending = 0; ++ hd->tmState = TM_STATE_NONE; ++ } ++ return FAILED; + } + + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +@@ -2549,10 +2343,8 @@ int + mptscsih_host_reset(struct scsi_cmnd *SCpnt) + { + MPT_SCSI_HOST * hd; +- MPT_ADAPTER *ioc; + int status = SUCCESS; +- unsigned long flags; +- ++ int can_sleep; + /* From the 2.6.13 kernels, they have removed calling + * eh_threads with the host_lock in locked state + */ +@@ -2560,6 +2352,8 @@ mptscsih_host_reset(struct scsi_cmnd *SC + spinlock_t *host_lock = SCpnt->device->host->host_lock; + #endif + ++ can_sleep = crashdump_mode() ? NO_SLEEP : CAN_SLEEP; ++ + /* If we can't locate the host to reset, then we failed. */ + if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){ + dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: " +@@ -2568,9 +2362,8 @@ mptscsih_host_reset(struct scsi_cmnd *SC + return FAILED; + } + +- ioc = hd->ioc; + printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n", +- ioc->name, SCpnt); ++ hd->ioc->name, SCpnt); + + /* If our attempts to reset the host failed, then return a failed + * status. The host will be taken off line by the SCSI mid-layer. +@@ -2578,78 +2371,26 @@ mptscsih_host_reset(struct scsi_cmnd *SC + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)) + MPT_HOST_UNLOCK(host_lock); + #endif +- if (mpt_HardResetHandler(ioc, +- crashdump_mode() ? NO_SLEEP : CAN_SLEEP) < 0) { +-dfailprintk((MYIOC_s_ERR_FMT "host reset: HardResetHandler failed\n", ioc->name)); +- ++ if (mpt_HardResetHandler(hd->ioc, can_sleep) < 0){ + status = FAILED; + } else { +- +-dtmprintk((MYIOC_s_ERR_FMT "host reset: HardResetHandler succeeded\n", ioc->name)); +- status = SUCCESS; +- ++ /* Make sure TM pending is cleared and TM state is set to ++ * NONE. ++ */ ++ hd->tmPending = 0; ++ hd->tmState = TM_STATE_NONE; + } +- + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)) + MPT_HOST_LOCK(host_lock); + #endif +- spin_lock_irqsave(&hd->ioc->FreeQlock, flags); +- hd->tmPending = 0; +- hd->tmState = TM_STATE_NONE; +- spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); +- +- return status; +-} +- +-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +-/* Search the pendingMF for a command with specific index. +- * If found, delete and return mf pointer +- * If not found, return NULL +- */ +-static MPT_FRAME_HDR * +-mptscsih_search_PendingMF(MPT_ADAPTER *ioc, struct scsi_cmnd * sc) +-{ +- MPT_SCSI_HOST *hd=(MPT_SCSI_HOST *) ioc->sh->hostdata; +- MPT_FRAME_HDR *mf; +- unsigned long flags; +- u16 req_idx; + +- dpendprintk((MYIOC_s_WARN_FMT "%s entered\n", +- ioc->name, __FUNCTION__)); +- +- spin_lock_irqsave(&ioc->PendingMFlock, flags); +- if ((mf=ioc->PendingMF) == NULL) { +- spin_unlock_irqrestore(&ioc->PendingMFlock, flags); +- return NULL; +- } ++ dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: " ++ "Status = %s\n", ++ (status == SUCCESS) ? "SUCCESS" : "FAILED" ) ); + +- req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); +- if (sc == hd->ScsiLookup[req_idx]) { +- ioc->PendingMF = NULL; +- spin_unlock_irqrestore(&ioc->PendingMFlock, flags); +- +- dpendprintk((MYIOC_s_WARN_FMT "%s: found mf=%p\n", +- ioc->name, __FUNCTION__, mf)); +- DBG_DUMP_PENDING_REQUEST_FRAME(ioc, mf) +- /* Free Chain buffers */ +- mptscsih_freeChainBuffers(ioc, req_idx); +- /* Free Message frames */ +- mpt_free_msg_frame(ioc, mf); +- hd->ScsiLookup[req_idx] = NULL; +- sc->result = (DID_RESET << 16); +- sc->host_scribble = NULL; +- sc->scsi_done(sc); /* Issue the command callback */ +- dpendprintk(( "%s Executed scsi_done mf=%p sc=%p\n", +- __FUNCTION__, mf, sc)); +- return mf; +- } +- spin_unlock_irqrestore(&ioc->PendingMFlock, flags); +- dpendprintk((MYIOC_s_WARN_FMT "%s exiting mf=%p not in ScsiLookup\n", +- ioc->name, __FUNCTION__, mf)); +- return NULL; ++ return status; + } + +- + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + /** + * mptscsih_tm_pending_wait - wait for pending task management request to +@@ -2661,21 +2402,20 @@ mptscsih_search_PendingMF(MPT_ADAPTER *i + static int + mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd) + { +- MPT_ADAPTER *ioc = hd->ioc; + unsigned long flags; + int loop_count = 4 * 10; /* Wait 10 seconds */ + int status = FAILED; + + do { +- spin_lock_irqsave(&ioc->FreeQlock, flags); ++ spin_lock_irqsave(&hd->ioc->FreeQlock, flags); + if (hd->tmState == TM_STATE_NONE) { + hd->tmState = TM_STATE_IN_PROGRESS; + hd->tmPending = 1; +- spin_unlock_irqrestore(&ioc->FreeQlock, flags); ++ spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + status = SUCCESS; + break; + } +- spin_unlock_irqrestore(&ioc->FreeQlock, flags); ++ spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + msleep(250); + } while (--loop_count); + +@@ -2683,6 +2423,34 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * + } + + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/** ++ * mptscsih_tm_wait_for_completion - wait for completion of TM task ++ * @hd: Pointer to MPT host structure. ++ * ++ * Returns {SUCCESS,FAILED}. ++ */ ++static int ++mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ) ++{ ++ unsigned long flags; ++ int loop_count = 4 * timeout; ++ int status = FAILED; ++ ++ do { ++ spin_lock_irqsave(&hd->ioc->FreeQlock, flags); ++ if(hd->tmPending == 0) { ++ status = SUCCESS; ++ spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); ++ break; ++ } ++ spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); ++ msleep_interruptible(250); ++ } while (--loop_count); ++ ++ return status; ++} ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + static void + mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code) + { +@@ -2720,17 +2488,17 @@ mptscsih_taskmgmt_response_code(MPT_ADAP + + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + /** +- * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver +- * @ioc: Pointer to MPT_ADAPTER structure +- * @mf: Pointer to SCSI task mgmt request frame +- * @mr: Pointer to SCSI task mgmt reply frame +- * +- * This routine is called from mptbase.c::mpt_interrupt() at the completion +- * of any SCSI task management request. +- * This routine is registered with the MPT (base) driver at driver +- * load/init time via the mpt_register() API call. ++ * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver ++ * @ioc: Pointer to MPT_ADAPTER structure ++ * @mf: Pointer to SCSI task mgmt request frame ++ * @mr: Pointer to SCSI task mgmt reply frame + * +- * Returns 1 indicating alloc'd request frame ptr should be freed. ++ * This routine is called from mptbase.c::mpt_interrupt() at the completion ++ * of any SCSI task management request. ++ * This routine is registered with the MPT (base) driver at driver ++ * load/init time via the mpt_register() API call. ++ * ++ * Returns 1 indicating alloc'd request frame ptr should be freed. + */ + int + mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) +@@ -2739,26 +2507,27 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER * + SCSITaskMgmt_t *pScsiTmReq; + MPT_SCSI_HOST *hd; + unsigned long flags; +- u16 iocstatus = MPI_IOCSTATUS_SUCCESS; ++ u16 iocstatus; + u8 tmType; +- u32 termination_count; + + dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n", + ioc->name, mf, mr)); ++ if (ioc->sh) { + /* Depending on the thread, a timer is activated for + * the TM request. Delete this timer on completion of TM. + * Decrement count of outstanding TM requests. + */ +- hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; +- if (ioc->tmPtr) { +- del_timer(&ioc->TMtimer); +- mpt_free_msg_frame(ioc, ioc->tmPtr); +- ioc->tmPtr = NULL; ++ hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; ++ } else { ++ dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n", ++ ioc->name)); ++ return 1; + } + + if (mr == NULL) { +- dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Turbo Reply: Request %p\n", ++ dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n", + ioc->name, mf)); ++ return 1; + } else { + pScsiTmReply = (SCSITaskMgmtReply_t*)mr; + pScsiTmReq = (SCSITaskMgmt_t*)mf; +@@ -2771,40 +2540,31 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER * + mptscsih_taskmgmt_response_code(ioc, + pScsiTmReply->ResponseCode); + +- termination_count = le32_to_cpu(pScsiTmReply->TerminationCount); +- +- iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; +- dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x TerminationCount=%d\n", +- ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo), termination_count)); ++ dtmprintk((MYIOC_s_WARN_FMT " TaskType = %d, TerminationCount=%d\n", ++ ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount))); + DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply); + ++ iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; ++ dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n", ++ ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo))); + /* Error? (anything non-zero?) */ + if (iocstatus) { + + /* clear flags and continue. + */ +- if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { +- if (termination_count == 1) { +- iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED; +- dtmprintk((MYIOC_s_WARN_FMT " SCSI Abort Task IOCStatus is now %04x\n", +- ioc->name, iocstatus)); +- } ++ if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) + hd->abortSCpnt = NULL; +- } + + /* If an internal command is present + * or the TM failed - reload the FW. + * FC FW may respond FAILED to an ABORT + */ +- else if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { ++ if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { + if ((hd->cmdPtr) || + (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) { + if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) { + printk((KERN_WARNING + " Firmware Reload FAILED!!\n")); +- dfailprintk((MYIOC_s_ERR_FMT "taskmgmt_complete: HardReset failed\n", ioc->name)); +- } else { +- dtmprintk((MYIOC_s_ERR_FMT "taskmgmt_complete: HardReset succeeded\n", ioc->name)); + } + } + } +@@ -2818,16 +2578,12 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER * + + spin_lock_irqsave(&ioc->FreeQlock, flags); + hd->tmPending = 0; +- hd->tm_iocstatus = iocstatus; +- hd->tmState = TM_STATE_NONE; + spin_unlock_irqrestore(&ioc->FreeQlock, flags); ++ hd->tmState = TM_STATE_NONE; + +- hd->TM_wait_done = 1; +- wake_up(&hd->TM_waitq); + return 1; + } + +- + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + /* + * This is anyones guess quite frankly. +@@ -2884,48 +2640,38 @@ mptscsih_slave_alloc(struct scsi_device + { + struct Scsi_Host *host = device->host; + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; +- MPT_ADAPTER *ioc = hd->ioc; +- struct _MPT_DEVICE *pMptTarget; + VirtDevice *pTarget; +- SpiCfgData *pSpi; +- uint bus=device->channel, id=device->id, lun=device->lun; ++ uint target = device->id, lun = device->lun; + int indexed_lun, lun_index; + ++ if (hd == NULL) ++ return -ENODEV; + +- pMptTarget = ioc->Target_List[bus]; +- pTarget = pMptTarget->Target[id]; +- dinitprintk((MYIOC_s_INFO_FMT "mptscsih_slave_alloc: bus=%d id=%d lun=%d hd=%p pMptTarget=%p pTarget=%p\n", +- ioc->name, bus, id, lun, hd, pMptTarget, pTarget)); +- +- if (pTarget) { +- dinitprintk((MYIOC_s_ERR_FMT "slave_alloc: pTarget=%p already allocated!\n", +- ioc->name, pTarget)); ++ if ((pTarget = hd->Targets[target])) + goto out; +- } + + pTarget = kmalloc(sizeof(VirtDevice), GFP_KERNEL); + if (!pTarget) { + printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", +- ioc->name, sizeof(VirtDevice)); ++ hd->ioc->name, sizeof(VirtDevice)); + return -ENOMEM; + } + ++ dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_alloc target=%d lun=%d pTarget=%p\n", ++ hd->ioc->name, target, lun, pTarget)); + memset(pTarget, 0, sizeof(VirtDevice)); +-if (ioc->bus_type != SPI) +- pTarget->tflags = MPT_TARGET_FLAGS_Q_YES; +- pTarget->ioc = ioc; +- pTarget->id = id; +- pTarget->bus = bus; ++ pTarget->tflags = MPT_TARGET_FLAGS_Q_YES; ++ pTarget->ioc_id = hd->ioc->id; ++ pTarget->target_id = device->id; ++ pTarget->bus_id = device->channel; + pTarget->last_lun = MPT_LAST_LUN; +- pMptTarget->Target[id] = pTarget; +- if (ioc->bus_type == SPI) { +- pSpi = &ioc->spi_data; +- pSpi->dvStatus[id] |= (MPT_SCSICFG_NEED_DV | +- MPT_SCSICFG_DV_NOT_DONE); +- +- if (ioc->raid_data.isRaid & (1 << device->id)) { ++ pTarget->raidVolume = 0; ++ pTarget->device = device; ++ hd->Targets[target] = pTarget; ++ if (hd->ioc->bus_type == SPI) { ++ if (hd->ioc->raid_data.isRaid & (1 << device->id)) { + pTarget->raidVolume = 1; +- ddvprintk((KERN_INFO ++ ddvtprintk((KERN_INFO + "RAID Volume @ id %d\n", device->id)); + } + } +@@ -2937,8 +2683,8 @@ out: + indexed_lun = (lun % 32); + pTarget->luns[lun_index] |= (1 << indexed_lun); + +- dinitprintk((MYIOC_s_WARN_FMT "mptscsih_slave_alloc: bus=%d id=%d lun=%d pTarget=%p num_luns=%d\n", +- ioc->name, bus, id, lun, pTarget, pTarget->num_luns)); ++ dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_alloc target=%d lun=%d pTarget=%p num_luns=%d\n", ++ hd->ioc->name, target, lun, pTarget, pTarget->num_luns)); + return 0; + } + +@@ -2951,24 +2697,20 @@ mptscsih_slave_destroy(struct scsi_devic + { + struct Scsi_Host *host = device->host; + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; +- MPT_ADAPTER *ioc = hd->ioc; +- struct _MPT_DEVICE *pMptTarget; + VirtDevice *pTarget; +- uint bus=device->channel, id=device->id, lun=device->lun; ++ uint target = device->id, lun = device->lun; + int indexed_lun, lun_index; + +- pMptTarget = ioc->Target_List[bus]; +- pTarget = pMptTarget->Target[id]; +- if (pTarget == NULL) { +- printk(MYIOC_s_WARN_FMT " mptscsih_slave_destroy bus=%d id=%d lun=%d pTarget=%p is NULL\n", +- ioc->name, bus, id, lun, pTarget); ++ if ((pTarget = hd->Targets[target]) == NULL) { ++ printk(MYIOC_s_WARN_FMT " mptscsih_slave_destroy target=%d lun=%d pTarget=%p is NULL\n", ++ hd->ioc->name, target, lun, pTarget); + return; + } +- dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy bus=%d id=%d lun=%d type=%x pTarget=%p\n", +- ioc->name, bus, id, lun, pTarget->inq_data[0], pTarget)); ++ dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy target=%d lun=%d type=%x pTarget=%p\n", ++ hd->ioc->name, target, lun, pTarget->inq_data[0], pTarget)); + +- if((ioc->bus_type == SPI) && +- mptscsih_is_phys_disk(ioc, bus, id)) { ++ if((hd->ioc->bus_type == SPI) && ++ mptscsih_is_phys_disk(hd->ioc, target)) { + ; /* this target reset shouldn't be issued to hidden + * phys disk in a raid volume. The result would + * kill domain validation on that disk; e.g. disk +@@ -2984,41 +2726,38 @@ mptscsih_slave_destroy(struct scsi_devic + */ + } + +- mptscsih_search_running_cmds(hd, id, lun); ++ mptscsih_search_running_cmds(hd, target, lun); + + lun_index = (lun >> 5); /* 32 luns per lun_index */ + indexed_lun = (lun % 32); + pTarget->luns[lun_index] &= ~(1 << indexed_lun); + + if (--pTarget->num_luns) { +- dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy bus=%d id=%d lun=%d pTarget=%p num_luns=%d luns[0]=%x returning\n", +- ioc->name, bus, id, lun, pTarget, pTarget->num_luns, pTarget->luns[0])); ++ dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy target=%d lun=%d pTarget=%p num_luns=%d luns[0]=%x returning\n", ++ hd->ioc->name, target, lun, pTarget, pTarget->num_luns, pTarget->luns[0])); + return; + } + +- dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy bus=%d id=%d lun=%d freeing pTarget=%p\n", +- ioc->name, bus, id, lun, pTarget)); +- +- if (ioc->bus_type == SPI) { +- if (mptscsih_is_phys_disk(ioc, bus, id)) { +- ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3; +- dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy PhysDisk bus=%d id=% d lun=%d pTarget=%p retained\n",ioc->name, bus, id, lun, pTarget)); +- +- ++ dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy target=%d lun=%d freeing pTarget=%p\n", ++ hd->ioc->name, target, lun, pTarget)); ++ kfree(pTarget); ++ hd->Targets[target] = NULL; ++ ++ if (hd->ioc->bus_type == SPI) { ++ if (mptscsih_is_phys_disk(hd->ioc, target)) { ++ hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3; + } else { +- ioc->spi_data.dvStatus[id] = +- (MPT_SCSICFG_NEGOTIATE | MPT_SCSICFG_DV_NOT_DONE); +- kfree(pTarget); +- pMptTarget->Target[id] = NULL; +- dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy bus=%d id=%d lun=%d pTarget=%p completed\n",ioc->name, bus, id, lun, pTarget)); ++ hd->ioc->spi_data.dvStatus[target] = ++ MPT_SCSICFG_NEGOTIATE; + ++ if (!hd->negoNvram) { ++ hd->ioc->spi_data.dvStatus[target] |= ++ MPT_SCSICFG_DV_NOT_DONE; ++ } + } +-}else { +-kfree(pTarget); +-pMptTarget->Target[id] = NULL; +-dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy bus=%d id=%d lun=%d pTarget=%p completed\n", +-ioc->name, bus, id, lun, pTarget)); +- } ++ } ++ dsprintk((MYIOC_s_INFO_FMT " mptscsih_slave_destroy target=%d lun=%d pTarget=%p completed\n", ++ hd->ioc->name, target, lun, pTarget)); + } + + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +@@ -3033,34 +2772,29 @@ int + mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth) + { + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata; +- MPT_ADAPTER *ioc = hd->ioc; +- struct _MPT_DEVICE *pMptTarget; + VirtDevice *pTarget; + int max_depth; + int tagged; + +- pMptTarget = ioc->Target_List[sdev->channel]; +- pTarget = pMptTarget->Target[sdev->id]; +- if (pTarget == NULL) ++ if (!(pTarget = hd->Targets[sdev->id])) + return 0; + +- +- if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) { +- if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) +- max_depth = 1; +- else if (ioc->bus_type == SPI) { +- if (((pTarget->inq_data[0] & 0x1f) == 0x00) && +- (pTarget->minSyncFactor <= MPT_ULTRA160 )) ++ if (hd->ioc->bus_type == SPI) { ++ if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) { ++ if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) ++ max_depth = 1; ++ else if (((pTarget->inq_data[0] & 0x1f) == 0x00) && ++ (pTarget->minSyncFactor <= MPT_ULTRA160 )) + max_depth = MPT_SCSI_CMD_PER_DEV_HIGH; + else +- max_depth = MPT_SCSI_CMD_PER_DEV_LOW; ++ max_depth = MPT_SCSI_CMD_PER_DEV_LOW; ++ } else { ++ /* error case - No Inq. Data */ ++ max_depth = 1; ++ } ++ } else ++ max_depth = MPT_SCSI_CMD_PER_DEV_HIGH; + +- } else +- max_depth = MPT_SCSI_CMD_PER_DEV_HIGH; +- } else { +- /* error case - No Inq. Data */ +- max_depth = 1; +- } + if (qdepth > max_depth) + qdepth = max_depth; + if (qdepth == 1) +@@ -3082,29 +2816,25 @@ int + mptscsih_slave_configure(struct scsi_device *device) + { + struct Scsi_Host *sh = device->host; +- struct _MPT_DEVICE *pMptTarget; + VirtDevice *pTarget; + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata; +- MPT_ADAPTER *ioc = hd->ioc; + int rc; + +- dinitprintk((MYIOC_s_INFO_FMT +- "%s: device @ %p, id=%d, LUN=%d, channel=%d\n", +- ioc->name, __FUNCTION__, device, device->id, device->lun, +- device->channel)); +- dinitprintk((MYIOC_s_INFO_FMT +- "sdtr %d wdtr %d ppr %d inq length=%d\n", +- ioc->name, device->sdtr, device->wdtr, ++ dsprintk((MYIOC_s_INFO_FMT ++ "device @ %p, id=%d, LUN=%d, channel=%d\n", ++ hd->ioc->name, device, device->id, device->lun, device->channel)); ++ dsprintk((MYIOC_s_INFO_FMT ++ "sdtr %d wdtr %d ppr %d inq length=%d\n", ++ hd->ioc->name, device->sdtr, device->wdtr, + device->ppr, device->inquiry_len)); + +- if (device->id >= ioc->DevicesPerBus) { ++ if (device->id > sh->max_id) { + /* error case, should never happen */ + scsi_adjust_queue_depth(device, 0, 1); + goto slave_configure_exit; + } + +- pMptTarget = ioc->Target_List[device->channel]; +- pTarget = pMptTarget->Target[device->id]; ++ pTarget = hd->Targets[device->id]; + + if (pTarget == NULL) { + /* Driver doesn't know about this device. +@@ -3122,19 +2852,19 @@ mptscsih_slave_configure(struct scsi_dev + pTarget->configured_lun=1; + + /* LUN persistancy support */ +- if (ioc->bus_type == FC) { ++ if (hd->ioc->bus_type == FC) { + FCDevicePage0_t fcDevicePage; + +- rc = mptscsih_readFCDevicePage0(ioc, +- pTarget->bus, pTarget->id, &fcDevicePage); ++ rc = mptscsih_readFCDevicePage0(hd->ioc, ++ pTarget->bus_id, pTarget->target_id, &fcDevicePage); + + if (rc > offsetof(FCDevicePage0_t,PortIdentifier)) { + pTarget->WWPN = fcDevicePage.WWPN; + pTarget->WWNN = fcDevicePage.WWNN; + + dsprintk((MYIOC_s_INFO_FMT +- " bus=%d id=%d is WWPN = %08x%08x, WWNN = %08x%08x\n", +- ioc->name, pTarget->bus, pTarget->id, ++ " target %d is WWPN = %08x%08x, WWNN = %08x%08x\n", ++ hd->ioc->name, pTarget->target_id, + le32_to_cpu(fcDevicePage.WWPN.High), + le32_to_cpu(fcDevicePage.WWPN.Low), + le32_to_cpu(fcDevicePage.WWNN.High), +@@ -3147,19 +2877,19 @@ mptscsih_slave_configure(struct scsi_dev + device->inquiry, device->inquiry_len ); + mptscsih_change_queue_depth(device, MPT_SCSI_CMD_PER_DEV_HIGH); + +- dinitprintk((MYIOC_s_INFO_FMT ++ dsprintk((MYIOC_s_INFO_FMT + "Queue depth=%d, tflags=%x\n", +- ioc->name, device->queue_depth, pTarget->tflags)); ++ hd->ioc->name, device->queue_depth, pTarget->tflags)); + +- dinitprintk((MYIOC_s_INFO_FMT ++ dsprintk((MYIOC_s_INFO_FMT + "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n", +- ioc->name, pTarget->negoFlags, pTarget->maxOffset, pTarget->minSyncFactor)); ++ hd->ioc->name, pTarget->negoFlags, pTarget->maxOffset, pTarget->minSyncFactor)); + + slave_configure_exit: + +- dinitprintk((MYIOC_s_INFO_FMT ++ dsprintk((MYIOC_s_INFO_FMT + "tagged %d, simple %d, ordered %d\n", +- ioc->name,device->tagged_supported, device->simple_tags, ++ hd->ioc->name,device->tagged_supported, device->simple_tags, + device->ordered_tags)); + + return 0; +@@ -3220,20 +2950,16 @@ mptscsih_poll(struct scsi_device *sdev) + static void + mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply) + { +- MPT_ADAPTER *ioc = hd->ioc; +- struct _MPT_DEVICE *pMptTarget; + VirtDevice *pTarget; + SCSIIORequest_t *pReq; + u32 sense_count = le32_to_cpu(pScsiReply->SenseCount); +- int bus, id; ++ int target; + + /* Get target structure + */ + pReq = (SCSIIORequest_t *) mf; +- bus = (int) pReq->Bus; +- id = (int) pReq->TargetID; +- pMptTarget = ioc->Target_List[bus]; +- pTarget = pMptTarget->Target[id]; ++ target = (int) pReq->TargetID; ++ pTarget = hd->Targets[target]; + + if (sense_count) { + u8 *sense_data; +@@ -3241,15 +2967,15 @@ mptscsih_copy_sense_data(struct scsi_cmn + + /* Copy the sense received into the scsi command block. */ + req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); +- sense_data = ((u8 *)ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC)); ++ sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC)); + memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc)); +- DBG_DUMP_SENSE_DATA(sense_data); + + /* Log SMART data (asc = 0x5D, non-IM case only) if required. + */ +- if ((ioc->events) && (ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) { ++ if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) { + if ((sense_data[12] == 0x5D) && (pTarget->raidVolume == 0)) { + int idx; ++ MPT_ADAPTER *ioc = hd->ioc; + + idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE; + ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE; +@@ -3287,21 +3013,19 @@ mptscsih_copy_sense_data(struct scsi_cmn + } + } else { + dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n", +- ioc->name)); ++ hd->ioc->name)); + } + } + +-static int ++static u32 + SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc) + { + MPT_SCSI_HOST *hd; +- MPT_ADAPTER *ioc; + int i; + + hd = (MPT_SCSI_HOST *) sc->device->host->hostdata; + +- ioc = hd->ioc; +- for (i = 0; i < ioc->req_depth; i++) { ++ for (i = 0; i < hd->ioc->req_depth; i++) { + if (hd->ScsiLookup[i] == sc) { + return i; + } +@@ -3315,10 +3039,8 @@ int + mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) + { + MPT_SCSI_HOST *hd; +- struct _MPT_DEVICE *pMptTarget; +- VirtDevice *pTarget; + unsigned long flags; +- int bus, id, ii; ++ int ii; + int n; + + dtmprintk((KERN_INFO MYNAM +@@ -3338,8 +3060,11 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int + if (reset_phase == MPT_IOC_SETUP_RESET) { + dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name)); + +- mptscsih_flush_running_cmds(hd); +- dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Complete\n", ioc->name)); ++ /* Clean Up: ++ * 1. Set Hard Reset Pending Flag ++ * All new commands go to doneQ ++ */ ++ hd->resetPending = 1; + + } else if (reset_phase == MPT_IOC_PRE_RESET) { + dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name)); +@@ -3358,41 +3083,28 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int + * free these resources. + */ + if (hd->cmdPtr) { +- del_timer(&hd->InternalCmdTimer); ++ del_timer(&hd->timer); + mpt_free_msg_frame(ioc, hd->cmdPtr); +- hd->cmdPtr = NULL; + } +- /* 2d. If a task management has not completed, +- * free resources associated with this request. +- */ +- if (ioc->tmPtr) { +- del_timer(&ioc->TMtimer); +- mpt_free_msg_frame(ioc, ioc->tmPtr); +- ioc->tmPtr = NULL; +- } + +- dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name)); ++ dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name)); + + } else { + dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name)); + + if (ioc->bus_type == FC) { + n = 0; +- for (bus = 0; bus < ioc->NumberOfBuses; bus++) { +- pMptTarget = ioc->Target_List[bus]; +- for (id=0; id < ioc->DevicesPerBus; id++) { +- pTarget = pMptTarget->Target[id]; +- if (pTarget) { +- dsprintk((MYIOC_s_INFO_FMT +- "bus=%d id=%d is known to be WWPN %08x%08x, WWNN %08x%08x\n", +- ioc->name, bus, id, +- le32_to_cpu(pTarget->WWPN.High), +- le32_to_cpu(pTarget->WWPN.Low), +- le32_to_cpu(pTarget->WWNN.High), +- le32_to_cpu(pTarget->WWNN.Low))); +- mptscsih_writeFCPortPage3(hd, bus, id); +- n++; +- } ++ for (ii=0; ii < ioc->sh->max_id; ii++) { ++ if (hd->Targets && hd->Targets[ii]) { ++ dsprintk((MYIOC_s_INFO_FMT ++ "target %d is known to be WWPN %08x%08x, WWNN %08x%08x\n", ++ ioc->name, ii, ++ le32_to_cpu(hd->Targets[ii]->WWPN.High), ++ le32_to_cpu(hd->Targets[ii]->WWPN.Low), ++ le32_to_cpu(hd->Targets[ii]->WWNN.High), ++ le32_to_cpu(hd->Targets[ii]->WWNN.Low))); ++ mptscsih_writeFCPortPage3(hd, ii); ++ n++; + } + } + +@@ -3408,7 +3120,7 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int + + /* ScsiLookup initialization + */ +- for (ii=0; ii < ioc->req_depth; ii++) ++ for (ii=0; ii < hd->ioc->req_depth; ii++) + hd->ScsiLookup[ii] = NULL; + + /* 2. Chain Buffer initialization +@@ -3417,19 +3129,17 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int + /* 4. Renegotiate to all devices, if SPI + */ + if (ioc->bus_type == SPI) { +- dnegoprintk((MYIOC_s_WARN_FMT "%s: writeSDP1: ALL_IDS USE_NVRAM\n", +- ioc->name, __FUNCTION__)); +- mpt_writeSDP1(ioc, 0, 0, (MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM)); +- ++ dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n")); ++ mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM); + } + + /* 5. Enable new commands to be posted + */ + spin_lock_irqsave(&ioc->FreeQlock, flags); + hd->tmPending = 0; ++ spin_unlock_irqrestore(&ioc->FreeQlock, flags); ++ hd->resetPending = 0; + hd->tmState = TM_STATE_NONE; +- spin_unlock_irqrestore(&ioc->FreeQlock, flags); +- + + /* 6. If there was an internal command, + * wake this process up. +@@ -3448,9 +3158,8 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int + /* 7. Set flag to force DV and re-read IOC Page 3 + */ + if (ioc->bus_type == SPI) { +-ioc->spi_data.forceDv = MPT_SCSICFG_RELOAD_IOC_PG3; +-ddvprintk(("Set reload IOC Pg3 Flag\n")); +- ++ ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; ++ ddvtprintk(("Set reload IOC Pg3 Flag\n")); + } + + dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name)); +@@ -3468,13 +3177,9 @@ mptscsih_event_process(MPT_ADAPTER *ioc, + { + MPT_SCSI_HOST *hd; + u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; +- struct _MPT_DEVICE *pMptTarget; +- VirtDevice *pTarget; +- int physDiskNum, bus, id; +- +- devtprintk((MYIOC_s_WARN_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", +- ioc->name, event)); + ++ devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", ++ ioc->name, event)); + + if (ioc->sh == NULL || + ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) +@@ -3508,53 +3213,16 @@ mptscsih_event_process(MPT_ADAPTER *ioc, + #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION + case MPI_EVENT_INTEGRATED_RAID: /* 0B */ + { ++ pMpiEventDataRaid_t pRaidEventData = ++ (pMpiEventDataRaid_t) pEvReply->Data; + +-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION +- pMpiEventDataRaid_t pRaidEventData = +- (pMpiEventDataRaid_t) &pEvReply->Data; +- +-/* Domain Validation Needed */ ++ /* Domain Validation Needed */ + if (ioc->bus_type == SPI && + pRaidEventData->ReasonCode == + MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) { +- SpiCfgData *pSpi; +- physDiskNum = pRaidEventData->PhysDiskNum; +- if (ioc->raid_data.pIocPg3) { +- id = ioc->raid_data.pIocPg3->PhysDisk[physDiskNum].PhysDiskID; +- bus = ioc->raid_data.pIocPg3->PhysDisk[physDiskNum].PhysDiskBus; +- pMptTarget = ioc->Target_List[bus]; +- pTarget = (VirtDevice *)pMptTarget->Target[id]; +- ddvprintk((KERN_WARNING "%s: Raid Event: DV Requested for PhysDiskNum=%d bus=%d id=%d pTarget=%p\n", +- ioc->name, physDiskNum, bus, id, pTarget)); +- } else { +- ddvprintk((KERN_WARNING "%s: Raid Event: DV Requested for PhysDiskNum=%d but raid_data.pIocPg3 is NULL\n", +- ioc->name, physDiskNum)); +- break; +- } +- pSpi = &ioc->spi_data; +- pSpi->dvStatus[id] |= (MPT_SCSICFG_PHYSDISK_DV_ONLY | +- MPT_SCSICFG_NEED_DV | +- MPT_SCSICFG_DV_NOT_DONE); +- +- if (pTarget == NULL) { +- ddvprintk((KERN_WARNING " Raid Event: DV Requested for PhysDiskNum=%d bus=%d id=%d but pTarget is NULL\n", +- physDiskNum, bus, id)); +- mptscsih_initTarget(hd, bus, id, 0, +- NULL, 0 ); +- pTarget = (VirtDevice *)pMptTarget->Target[id]; +- ddvprintk((KERN_WARNING "%s: Raid Event: DV Requested for PhysDiskNum=%d bus=%d id=%d pTarget%p now\n", +- ioc->name, physDiskNum, bus, id, pTarget)); +- } +- pSpi->forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3; +- ddvprintk((KERN_WARNING "%s: Raid Event: Scheduling DV for PhysDiskNum=%d bus=%d id=%d pTarget=%p\n", +- ioc->name, physDiskNum, bus, id, pTarget)); +- INIT_WORK(&pTarget->dvTask, mptscsih_domainValidation, (void *) pTarget); +- schedule_work(&pTarget->dvTask); +- ddvprintk((KERN_WARNING "%s: Raid Event: DV Scheduled for PhysDiskNum=%d bus=%d id=%d pTarget=%p\n", +- ioc->name, physDiskNum, bus, id, pTarget)); +-#endif + +- } ++ mptscsih_set_dvflags_raid(hd, pRaidEventData->PhysDiskNum); ++ } + break; + } + #endif +@@ -3575,8 +3243,8 @@ mptscsih_event_process(MPT_ADAPTER *ioc, + /* + * mptscsih_initTarget - Target, LUN alloc/free functionality. + * @hd: Pointer to MPT_SCSI_HOST structure +- * @bus: Bus number (?) +- * @id: SCSI target id ++ * @bus_id: Bus number (?) ++ * @target_id: SCSI target id + * @lun: SCSI LUN id + * @data: Pointer to data + * @dlen: Number of INQUIRY bytes +@@ -3589,17 +3257,16 @@ mptscsih_event_process(MPT_ADAPTER *ioc, + * + */ + static void +-mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus, int id, u8 lun, char *data, int dlen) ++mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen) + { + int indexed_lun, lun_index; + MPT_ADAPTER *ioc = hd->ioc; +- struct _MPT_DEVICE *pMptTarget; + VirtDevice *pTarget; + SpiCfgData *pSpi; + char data_56; + +- dinitprintk((MYIOC_s_WARN_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n", +- ioc->name, bus, id, lun, hd)); ++ dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n", ++ ioc->name, bus_id, target_id, lun, hd)); + + /* + * If the peripheral qualifier filter is enabled then if the target reports a 0x1 +@@ -3610,71 +3277,29 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, i + * around a bug in th emid-layer in some distributions in which the mid-layer will + * continue to try to communicate to the LUN and evntually create a dummy LUN. + */ +- if (hd->mpt_pq_filter && dlen && (data[0] & 0x20)) ++ if (hd->mpt_pq_filter && dlen && (data[0] & 0xE0)) + data[0] |= 0x40; + + /* Is LUN supported? If so, upper 2 bits will be 0 + * in first byte of inquiry data. + */ ++ if (data[0] & 0xe0) ++ return; + +- if (dlen && (data[0] & 0xe0)) +- return; +- +- pMptTarget = ioc->Target_List[bus]; +- pTarget = pMptTarget->Target[id]; +- if (pTarget == NULL) { +- dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d pTarget is NULL\n" +-, +- ioc->name, bus, id, lun)); +- pTarget = kmalloc(sizeof(VirtDevice), GFP_KERNEL); +- if (!pTarget) { +- printk(MYIOC_s_ERR_FMT "initTarget kmalloc(%zd) FAILED!\n", +- ioc->name, sizeof(VirtDevice)); +- return; +- } +- +- memset(pTarget, 0, sizeof(VirtDevice)); +- if (ioc->bus_type != SPI) +- pTarget->tflags = MPT_TARGET_FLAGS_Q_YES; +- pTarget->ioc = ioc; +- pTarget->id = id; +- pTarget->bus = bus; +- pTarget->last_lun = MPT_LAST_LUN; +- pTarget->raidVolume = 0; +- pMptTarget->Target[id] = pTarget; +- if (ioc->bus_type == SPI) { +- if (ioc->raid_data.isRaid & (1 << id)) { +- pTarget->raidVolume = 1; +- ddvprintk((KERN_INFO +- "RAID Volume @ id %d\n", id)); +- } +- } +- ++ if ((pTarget = hd->Targets[target_id]) == NULL) { + return; +-} +- dinitprintk((MYIOC_s_WARN_FMT "initTarget bus=%d id=%d lun=%d pTarget=%p\n", +- ioc->name, bus, id, lun, pTarget)); +- pSpi = &ioc->spi_data; +- pTarget->ioc = ioc; +- pTarget->tflags &= ~MPT_TARGET_FLAGS_DELETED; ++ } + + lun_index = (lun >> 5); /* 32 luns per lun_index */ + indexed_lun = (lun % 32); + pTarget->luns[lun_index] |= (1 << indexed_lun); + +- if (!(pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) { +- if ( dlen > 8 ) { +- memcpy (pTarget->inq_data, data, 8); +- } else { +- memcpy (pTarget->inq_data, data, dlen); +- } +- } + if (ioc->bus_type == SPI) { + if ((data[0] == TYPE_PROCESSOR) && (ioc->spi_data.Saf_Te)) { + /* Treat all Processors as SAF-TE if + * command line option is set */ + pTarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; +- mptscsih_writeIOCPage4(hd, id, bus); ++ mptscsih_writeIOCPage4(hd, target_id, bus_id); + }else if ((data[0] == TYPE_PROCESSOR) && + !(pTarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) { + if ( dlen > 49 ) { +@@ -3686,17 +3311,29 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, i + data[48] == 'T' && + data[49] == 'E' ) { + pTarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED; +- mptscsih_writeIOCPage4(hd, id, bus); ++ mptscsih_writeIOCPage4(hd, target_id, bus_id); + } + } + } +-data_56 = 0x00; /* Default to no Ultra 160 or 320 capabilities if Inq data length is < 57 */ +- +- + if (!(pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) { ++ if ( dlen > 8 ) { ++ memcpy (pTarget->inq_data, data, 8); ++ } else { ++ memcpy (pTarget->inq_data, data, dlen); ++ } ++ ++ /* If have not done DV, set the DV flag. ++ */ ++ pSpi = &ioc->spi_data; ++ if ((data[0] == TYPE_TAPE) || (data[0] == TYPE_PROCESSOR)) { ++ if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE) ++ pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV; ++ } + + pTarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY; + ++ ++ data_56 = 0x00; /* Default to no Ultra 160 or 320 capabilities if Inq data length is < 57 */ + if (dlen > 56) { + if ( (!(pTarget->tflags & MPT_TARGET_FLAGS_VALID_56))) { + /* Update the target capabilities +@@ -3705,6 +3342,7 @@ data_56 = 0x00; /* Default to no Ultra + pTarget->tflags |= MPT_TARGET_FLAGS_VALID_56; + } + } ++ mptscsih_setTargetNegoParms(hd, pTarget, data_56); + } else { + /* Initial Inquiry may not request enough data bytes to + * obtain byte 57. DV will; if target doesn't return +@@ -3715,40 +3353,25 @@ data_56 = 0x00; /* Default to no Ultra + */ + data_56 = data[56]; + pTarget->tflags |= MPT_TARGET_FLAGS_VALID_56; ++ mptscsih_setTargetNegoParms(hd, pTarget, data_56); + } + } + } +- +-mptscsih_setTargetNegoParms(hd, pTarget, data_56); +-if (pSpi->dvStatus[id] & MPT_SCSICFG_NEED_DV) { +- ddvprintk((MYIOC_s_WARN_FMT "%s: DV Scheduled for non-PhysDisk id %d\n", +- ioc->name, __FUNCTION__, id)); +-INIT_WORK(&pTarget->dvTask, mptscsih_domainValidation, (void *) pTarget); +-schedule_work(&pTarget->dvTask); +- } +- } else { +- pTarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY; +- if (ioc->bus_type == SAS) { +- if ( (pTarget->inq_data[7] & 0x02) == 0) { +- pTarget->tflags &= ~MPT_TARGET_FLAGS_Q_YES; +- } +- if ((data[0] == TYPE_TAPE)) { +- if (ioc->facts.IOCCapabilities & +- MPI_IOCFACTS_CAPABILITY_TLR ) { +- if ((pTarget->tflags & MPT_TARGET_FLAGS_TLR_DONE) == 0){ +- if ( data[8] == 'H' && +- data[9] == 'P' && +- data[10] == ' ' && +- data[11] == ' ' && +- data[12] == ' ' && +- data[13] == ' ' && +- data[14] == ' ' && +- data[15] == ' ' ) { +- mpt_IssueTLR(hd, pTarget); +- pTarget->tflags |= MPT_TARGET_FLAGS_TLR_DONE; +- +- } +- ++ } else if (ioc->bus_type == SAS) { ++ if ((data[0] == TYPE_TAPE)) { ++ if (ioc->facts.IOCCapabilities & ++ MPI_IOCFACTS_CAPABILITY_TLR ) { ++ if ((pTarget->tflags & MPT_TARGET_FLAGS_TLR_DONE) == 0) { ++ if ( data[8] == 'H' && ++ data[9] == 'P' && ++ data[10] == ' ' && ++ data[11] == ' ' && ++ data[12] == ' ' && ++ data[13] == ' ' && ++ data[14] == ' ' && ++ data[15] == ' ' ) { ++ mpt_IssueTLR(hd, pTarget); ++ pTarget->tflags |= MPT_TARGET_FLAGS_TLR_DONE; + } + } + } +@@ -3760,12 +3383,11 @@ schedule_work(&pTarget->dvTask); + static void + mpt_IssueTLR(MPT_SCSI_HOST *hd, VirtDevice *pTarget) + { +- MPT_ADAPTER *ioc = hd->ioc; + INTERNAL_CMD iocmd; + int lun, indexed_lun, lun_index; + +- iocmd.id = pTarget->id; +- iocmd.bus = pTarget->bus; ++ iocmd.id = pTarget->target_id; ++ iocmd.bus = pTarget->bus_id; + for (lun=0; lun <= MPT_LAST_LUN; lun++) { + /* If LUN present, issue the command + */ +@@ -3777,7 +3399,7 @@ mpt_IssueTLR(MPT_SCSI_HOST *hd, VirtDevi + } + } + printk(MYIOC_s_INFO_FMT "mpt_IssueTLR: Unable find a lun on id=%d\n", +- ioc->name, iocmd.id); ++ hd->ioc->name, iocmd.id); + return; + issueTLR: + iocmd.flags = 0; +@@ -3790,7 +3412,7 @@ issueTLR: + if (mptscsih_do_cmd(hd, &iocmd) < 0) { + if (mptscsih_do_cmd(hd, &iocmd) < 0) { + printk(MYIOC_s_INFO_FMT "Unable to set TLR on id=%d\n", +- ioc->name, iocmd.id); ++ hd->ioc->name, iocmd.id); + } + } + } +@@ -3802,14 +3424,12 @@ issueTLR: + * + */ + static void +-mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *pTarget, char byte56) ++mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56) + { +- MPT_ADAPTER *ioc = hd->ioc; +- SpiCfgData *pspi_data = &ioc->spi_data; +- int id = (int) pTarget->id; ++ SpiCfgData *pspi_data = &hd->ioc->spi_data; ++ int id = (int) target->target_id; + int nvram; +- struct _MPT_DEVICE *pMptTarget; +- VirtDevice *loop_pTarget; ++ VirtDevice *pTarget; + int ii; + u8 width = MPT_NARROW; + u8 factor = MPT_ASYNC; +@@ -3817,36 +3437,31 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOS + u8 version, nfactor; + u8 noQas = 1; + +- pTarget->negoFlags = pspi_data->noQas; +-ddvprintk((KERN_INFO "Command-line QAS setting sets noQas=%02x on id=%d!\n", +- pspi_data->noQas, id)); ++ target->negoFlags = pspi_data->noQas; + +-/* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine ++ ddvtprintk((KERN_INFO "Command-line QAS setting sets noQas=%02x on id=%d!\n", ++ pspi_data->noQas, id)); ++ /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine + * support. If available, default QAS to off and allow enabling. + * If not available, default QAS to on, turn off for non-disks. + */ + + /* Set flags based on Inquiry data + */ +- version = pTarget->inq_data[2] & 0x07; ++ version = target->inq_data[2] & 0x07; + if (version < 2) { + width = 0; + factor = MPT_ULTRA2; + offset = pspi_data->maxSyncOffset; +- pTarget->tflags &= ~MPT_TARGET_FLAGS_Q_YES; ++ target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; + } else { +- if (pTarget->inq_data[7] & 0x20) { ++ if (target->inq_data[7] & 0x20) { + width = 1; + } + +- if (pTarget->inq_data[7] & 0x02) +- pTarget->tflags |= MPT_TARGET_FLAGS_Q_YES; +- else +- pTarget->tflags &= ~MPT_TARGET_FLAGS_Q_YES; +- +- if (pTarget->inq_data[7] & 0x10) { ++ if (target->inq_data[7] & 0x10) { + factor = pspi_data->minSyncFactor; +- if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_56) { ++ if (target->tflags & MPT_TARGET_FLAGS_VALID_56) { + /* bits 2 & 3 show Clocking support */ + if ((byte56 & 0x0C) == 0) + factor = MPT_ULTRA2; +@@ -3857,17 +3472,17 @@ ddvprintk((KERN_INFO "Command-line QAS s + factor = MPT_ULTRA320; + if (byte56 & 0x02) + { +- ddvprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id)); ++ ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id)); + noQas = 0; + } +- if (pTarget->inq_data[0] == TYPE_TAPE) { ++ if (target->inq_data[0] == TYPE_TAPE) { + if (byte56 & 0x01) +- pTarget->negoFlags |= MPT_TAPE_NEGO_IDP; ++ target->negoFlags |= MPT_TAPE_NEGO_IDP; + } + } + } + } else { +- ddvprintk((KERN_INFO "Ultra 80 on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id)); ++ ddvtprintk((KERN_INFO "Ultra 80 on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id)); + factor = MPT_ULTRA2; + } + +@@ -3879,7 +3494,7 @@ ddvprintk((KERN_INFO "Command-line QAS s + * bit 1 QAS support, non-raid only + * bit 0 IU support + */ +- if (pTarget->raidVolume == 1) { ++ if (target->raidVolume == 1) { + noQas = 0; + } + } else { +@@ -3888,6 +3503,9 @@ ddvprintk((KERN_INFO "Command-line QAS s + } + } + ++ if ( (target->inq_data[7] & 0x02) == 0) { ++ target->tflags &= ~MPT_TARGET_FLAGS_Q_YES; ++ } + + /* Update tflags based on NVRAM settings. (SCSI only) + */ +@@ -3926,43 +3544,41 @@ ddvprintk((KERN_INFO "Command-line QAS s + + /* Save the data to the target structure. + */ +- pTarget->minSyncFactor = factor; +- pTarget->maxOffset = offset; +- pTarget->maxWidth = width; ++ target->minSyncFactor = factor; ++ target->maxOffset = offset; ++ target->maxWidth = width; + +- pTarget->tflags |= MPT_TARGET_FLAGS_VALID_NEGO; ++ target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO; + + /* Disable unused features. + */ + if (!width) +- pTarget->negoFlags |= MPT_TARGET_NO_NEGO_WIDE; ++ target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE; + + if (!offset) +- pTarget->negoFlags |= MPT_TARGET_NO_NEGO_SYNC; ++ target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC; + + if ( factor > MPT_ULTRA320 ) + noQas = 0; + + /* GEM, processor WORKAROUND + */ +- if ((pTarget->inq_data[0] == TYPE_PROCESSOR) || (pTarget->inq_data[0] > 0x08)) { +- pTarget->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC); ++ if ((target->inq_data[0] == TYPE_PROCESSOR) || (target->inq_data[0] > 0x08)) { ++ target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC); + pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO; + } else { + if (noQas && (pspi_data->noQas == 0)) { + pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS; +- pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS; ++ target->negoFlags |= MPT_TARGET_NO_NEGO_QAS; + + /* Disable QAS in a mixed configuration case + */ +-ddvprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id)); + +- pMptTarget = ioc->Target_List[0]; ++ ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id)); + for (ii = 0; ii < id; ii++) { +- loop_pTarget = pMptTarget->Target[id]; +- if ((loop_pTarget)) { +- loop_pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS; +- mpt_writeSDP1(ioc, 0, ii, loop_pTarget->negoFlags); ++ if ( (pTarget = hd->Targets[ii]) ) { ++ pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS; ++ mptscsih_writeSDP1(hd, 0, ii, pTarget->negoFlags); + } + } + } +@@ -3970,33 +3586,115 @@ ddvprintk((KERN_INFO "Disabling QAS due + + /* Write SDP1 on this I/O to this target */ + if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) { +- dnegoprintk((KERN_INFO "MPT_SCSICFG_NEGOTIATE on id=%d!\n", id)); +- /* First IO to this device; NEED_DV will cause async/narrow */ +- mpt_writeSDP1(ioc, 0, id, 0); ++ ddvtprintk((KERN_INFO "MPT_SCSICFG_NEGOTIATE on id=%d!\n", id)); ++ mptscsih_writeSDP1(hd, 0, id, hd->negoNvram); + pspi_data->dvStatus[id] &= ~MPT_SCSICFG_NEGOTIATE; + } else if (pspi_data->dvStatus[id] & MPT_SCSICFG_BLK_NEGO) { +- dnegoprintk((KERN_INFO "MPT_SCSICFG_BLK_NEGO on id=%d!\n", id)); +- mpt_writeSDP1(ioc, 0, id, MPT_SCSICFG_BLK_NEGO); ++ ddvtprintk((KERN_INFO "MPT_SCSICFG_BLK_NEGO on id=%d!\n", id)); ++ mptscsih_writeSDP1(hd, 0, id, MPT_SCSICFG_BLK_NEGO); + pspi_data->dvStatus[id] &= ~MPT_SCSICFG_BLK_NEGO; + } + } + + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return. ++ * Else set the NEED_DV flag after Read Capacity Issued (disks) ++ * or Mode Sense (cdroms). ++ * ++ * Tapes, initTarget will set this flag on completion of Inquiry command. ++ * Called only if DV_NOT_DONE flag is set ++ */ ++static void ++mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq) ++{ ++ MPT_ADAPTER *ioc = hd->ioc; ++ u8 cmd; ++ SpiCfgData *pSpi; ++ ++ ddvtprintk((MYIOC_s_NOTE_FMT ++ " set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n", ++ hd->ioc->name, pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0])); ++ ++ if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0)) ++ return; ++ ++ cmd = pReq->CDB[0]; ++ ++ if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) { ++ pSpi = &ioc->spi_data; ++ if ((ioc->raid_data.isRaid & (1 << pReq->TargetID)) && ioc->raid_data.pIocPg3) { ++ /* Set NEED_DV for all hidden disks ++ */ ++ Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk; ++ int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; ++ ++ while (numPDisk) { ++ pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV; ++ ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID)); ++ pPDisk++; ++ numPDisk--; ++ } ++ } ++ pSpi->dvStatus[pReq->TargetID] |= MPT_SCSICFG_NEED_DV; ++ ddvtprintk(("NEED_DV set for visible disk id %d\n", pReq->TargetID)); ++ } ++} ++ ++/* mptscsih_raid_set_dv_flags() ++ * ++ * New or replaced disk. Set DV flag and schedule DV. ++ */ ++static void ++mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id) ++{ ++ MPT_ADAPTER *ioc = hd->ioc; ++ SpiCfgData *pSpi = &ioc->spi_data; ++ Ioc3PhysDisk_t *pPDisk; ++ int numPDisk; ++ ++ if (hd->negoNvram != 0) ++ return; ++ ++ ddvtprintk(("DV requested for phys disk id %d\n", id)); ++ if (ioc->raid_data.pIocPg3) { ++ pPDisk = ioc->raid_data.pIocPg3->PhysDisk; ++ numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; ++ while (numPDisk) { ++ if (id == pPDisk->PhysDiskNum) { ++ pSpi->dvStatus[pPDisk->PhysDiskID] = ++ (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE); ++ pSpi->forceDv = MPT_SCSICFG_NEED_DV; ++ ddvtprintk(("NEED_DV set for phys disk id %d\n", ++ pPDisk->PhysDiskID)); ++ break; ++ } ++ pPDisk++; ++ numPDisk--; ++ } ++ ++ if (numPDisk == 0) { ++ /* The physical disk that needs DV was not found ++ * in the stored IOC Page 3. The driver must reload ++ * this page. DV routine will set the NEED_DV flag for ++ * all phys disks that have DV_NOT_DONE set. ++ */ ++ pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; ++ ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n",id)); ++ } ++ } ++} ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + /* + * If no Target, bus reset on 1st I/O. Set the flag to + * prevent any future negotiations to this device. + */ + static void +-mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int id) ++mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id) + { +- MPT_ADAPTER *ioc = hd->ioc; +- struct _MPT_DEVICE *pMptTarget; +- VirtDevice *pTarget; + +- pMptTarget = ioc->Target_List[0]; +- pTarget = pMptTarget->Target[id]; +- if (pTarget == NULL) +- ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_BLK_NEGO; ++ if (hd->Targets[target_id] == NULL) ++ hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO; + + return; + } +@@ -4006,9 +3704,266 @@ mptscsih_no_negotiate(MPT_SCSI_HOST *hd, + * SCSI Config Page functionality ... + */ + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* mptscsih_setDevicePage1Flags - add Requested and Configuration fields flags ++ * based on width, factor and offset parameters. ++ * @width: bus width ++ * @factor: sync factor ++ * @offset: sync offset ++ * @requestedPtr: pointer to requested values (updated) ++ * @configurationPtr: pointer to configuration values (updated) ++ * @flags: flags to block WDTR or SDTR negotiation ++ * ++ * Return: None. ++ * ++ * Remark: Called by writeSDP1 and _dv_params ++ */ ++static void ++mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags) ++{ ++ u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE; ++ u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC; ++ ++ *configurationPtr = 0; ++ *requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0; ++ *requestedPtr |= (offset << 16) | (factor << 8); ++ ++ if (width && offset && !nowide && !nosync) { ++ if (factor < MPT_ULTRA160) { ++ *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT); ++ if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0) ++ *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS; ++ if (flags & MPT_TAPE_NEGO_IDP) ++ *requestedPtr |= 0x08000000; ++ } else if (factor < MPT_ULTRA2) { ++ *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT; ++ } ++ } ++ ++ if (nowide) ++ *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED; ++ ++ if (nosync) ++ *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED; ++ ++ return; ++} ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ ++/* mptscsih_writeSDP1 - write SCSI Device Page 1 ++ * @hd: Pointer to a SCSI Host Strucutre ++ * @portnum: IOC port number ++ * @target_id: writeSDP1 for single ID ++ * @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO ++ * ++ * Return: -EFAULT if read of config page header fails ++ * or 0 if success. ++ * ++ * Remark: If a target has been found, the settings from the ++ * target structure are used, else the device is set ++ * to async/narrow. ++ * ++ * Remark: Called during init and after a FW reload. ++ * Remark: We do not wait for a return, write pages sequentially. ++ */ ++static int ++mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags) ++{ ++ MPT_ADAPTER *ioc = hd->ioc; ++ Config_t *pReq; ++ SCSIDevicePage1_t *pData; ++ VirtDevice *pTarget; ++ MPT_FRAME_HDR *mf; ++ dma_addr_t dataDma; ++ u16 req_idx; ++ u32 frameOffset; ++ u32 requested, configuration, flagsLength; ++ int ii, nvram; ++ int id = 0, maxid = 0; ++ u8 width; ++ u8 factor; ++ u8 offset; ++ u8 bus = 0; ++ u8 negoFlags; ++ u8 maxwidth, maxoffset, maxfactor; ++ ++ if (ioc->spi_data.sdp1length == 0) ++ return 0; ++ ++ if (flags & MPT_SCSICFG_ALL_IDS) { ++ id = 0; ++ maxid = ioc->sh->max_id - 1; ++ } else if (ioc->sh) { ++ id = target_id; ++ maxid = min_t(int, id, ioc->sh->max_id - 1); ++ } ++ ++ for (; id <= maxid; id++) { ++ ++ if (id == ioc->pfacts[portnum].PortSCSIID) ++ continue; ++ ++ /* Use NVRAM to get adapter and target maximums ++ * Data over-riden by target structure information, if present ++ */ ++ maxwidth = ioc->spi_data.maxBusWidth; ++ maxoffset = ioc->spi_data.maxSyncOffset; ++ maxfactor = ioc->spi_data.minSyncFactor; ++ if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) { ++ nvram = ioc->spi_data.nvram[id]; ++ ++ if (maxwidth) ++ maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; ++ ++ if (maxoffset > 0) { ++ maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8; ++ if (maxfactor == 0) { ++ /* Key for async */ ++ maxfactor = MPT_ASYNC; ++ maxoffset = 0; ++ } else if (maxfactor < ioc->spi_data.minSyncFactor) { ++ maxfactor = ioc->spi_data.minSyncFactor; ++ } ++ } else ++ maxfactor = MPT_ASYNC; ++ } ++ ++ /* Set the negotiation flags. ++ */ ++ negoFlags = ioc->spi_data.noQas; ++ if (!maxwidth) ++ negoFlags |= MPT_TARGET_NO_NEGO_WIDE; ++ ++ if (!maxoffset) ++ negoFlags |= MPT_TARGET_NO_NEGO_SYNC; ++ ++ if (flags & MPT_SCSICFG_USE_NVRAM) { ++ width = maxwidth; ++ factor = maxfactor; ++ offset = maxoffset; ++ } else { ++ width = 0; ++ factor = MPT_ASYNC; ++ offset = 0; ++ //negoFlags = 0; ++ //negoFlags = MPT_TARGET_NO_NEGO_SYNC; ++ } ++ ++ /* If id is not a raid volume, get the updated ++ * transmission settings from the target structure. ++ */ ++ if ( (pTarget = hd->Targets[id]) && !pTarget->raidVolume) { ++ width = pTarget->maxWidth; ++ factor = pTarget->minSyncFactor; ++ offset = pTarget->maxOffset; ++ negoFlags |= pTarget->negoFlags; ++ } ++ ++#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION ++ /* Force to async and narrow if DV has not been executed ++ * for this ID ++ */ ++ if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) { ++ width = 0; ++ factor = MPT_ASYNC; ++ offset = 0; ++ } ++#endif ++ ++ if (flags & MPT_SCSICFG_BLK_NEGO) ++ negoFlags |= MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC; ++ ++ mptscsih_setDevicePage1Flags(width, factor, offset, ++ &requested, &configuration, negoFlags); ++ dnegoprintk(("writeSDP1: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n", ++ target_id, width, factor, offset, negoFlags, requested, configuration)); ++ ++ /* Get a MF for this command. ++ */ ++ if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) { ++ dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n", ++ ioc->name,__FUNCTION__)); ++ return -EAGAIN; ++ } ++ ++ ddvprintk((MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n", ++ hd->ioc->name, mf, id, requested, configuration)); ++ ++ ++ /* Set the request and the data pointers. ++ * Request takes: 36 bytes (32 bit SGE) ++ * SCSI Device Page 1 requires 16 bytes ++ * 40 + 16 <= size of SCSI IO Request = 56 bytes ++ * and MF size >= 64 bytes. ++ * Place data at end of MF. ++ */ ++ pReq = (Config_t *)mf; ++ ++ req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); ++ frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t); ++ ++ pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset); ++ dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset; ++ ++ /* Complete the request frame (same for all requests). ++ */ ++ pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; ++ pReq->Reserved = 0; ++ pReq->ChainOffset = 0; ++ pReq->Function = MPI_FUNCTION_CONFIG; ++ pReq->ExtPageLength = 0; ++ pReq->ExtPageType = 0; ++ pReq->MsgFlags = 0; ++ for (ii=0; ii < 8; ii++) { ++ pReq->Reserved2[ii] = 0; ++ } ++ pReq->Header.PageVersion = ioc->spi_data.sdp1version; ++ pReq->Header.PageLength = ioc->spi_data.sdp1length; ++ pReq->Header.PageNumber = 1; ++ pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; ++ pReq->PageAddress = cpu_to_le32(id | (bus << 8 )); ++ ++ /* Add a SGE to the config request. ++ */ ++ flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4; ++ ++ mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma); ++ ++ /* Set up the common data portion ++ */ ++ pData->Header.PageVersion = pReq->Header.PageVersion; ++ pData->Header.PageLength = pReq->Header.PageLength; ++ pData->Header.PageNumber = pReq->Header.PageNumber; ++ pData->Header.PageType = pReq->Header.PageType; ++ pData->RequestedParameters = cpu_to_le32(requested); ++ pData->Reserved = 0; ++ pData->Configuration = cpu_to_le32(configuration); ++ ++ if ( pTarget ) { ++ if ( requested & MPI_SCSIDEVPAGE1_RP_IU ) { ++ pTarget->last_lun = MPT_LAST_LUN; ++ } else { ++ pTarget->last_lun = MPT_NON_IU_LAST_LUN; ++ } ++ dsprintk((MYIOC_s_INFO_FMT ++ "writeSDP1: last_lun=%d on id=%d\n", ++ ioc->name, pTarget->last_lun, id)); ++ } ++ ++ dprintk((MYIOC_s_INFO_FMT ++ "write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n", ++ ioc->name, id, (id | (bus<<8)), ++ requested, configuration)); ++ ++ mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); ++ } ++ ++ return 0; ++} ++ ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + /* mptscsih_writeIOCPage4 - write IOC Page 4 + * @hd: Pointer to a SCSI Host Structure +- * @id: write IOC Page4 for this ID & Bus ++ * @target_id: write IOC Page4 for this ID & Bus + * + * Return: -EAGAIN if unable to obtain a Message Frame + * or 0 if success. +@@ -4016,7 +3971,7 @@ mptscsih_no_negotiate(MPT_SCSI_HOST *hd, + * Remark: We do not wait for a return, write pages sequentially. + */ + static int +-mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int id, int bus) ++mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus) + { + MPT_ADAPTER *ioc = hd->ioc; + Config_t *pReq; +@@ -4060,10 +4015,10 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd + IOCPage4Ptr = ioc->spi_data.pIocPg4; + dataDma = ioc->spi_data.IocPg4_dma; + ii = IOCPage4Ptr->ActiveSEP++; +- IOCPage4Ptr->SEP[ii].SEPTargetID = id; ++ IOCPage4Ptr->SEP[ii].SEPTargetID = target_id; + IOCPage4Ptr->SEP[ii].SEPBus = bus; + pReq->Header = IOCPage4Ptr->Header; +- pReq->PageAddress = cpu_to_le32(id | (bus << 8 )); ++ pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 )); + + /* Add a SGE to the config request. + */ +@@ -4074,7 +4029,7 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd + + dinitprintk((MYIOC_s_INFO_FMT + "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n", +- ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, id, bus)); ++ ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus)); + + mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); + +@@ -4116,9 +4071,6 @@ mptscsih_scandv_complete(MPT_ADAPTER *io + + hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; + +- del_timer(&hd->InternalCmdTimer); +- +- + if ((mf == NULL) || + (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) { + printk(MYIOC_s_ERR_FMT +@@ -4127,18 +4079,19 @@ mptscsih_scandv_complete(MPT_ADAPTER *io + goto wakeup; + } + ++ del_timer(&hd->timer); + req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); + hd->ScsiLookup[req_idx] = NULL; + pReq = (SCSIIORequest_t *) mf; + + if (mf != hd->cmdPtr) { +- printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p,!= cmdPtr=%p, idx=%d)\n", +- ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx); ++ printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n", ++ hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx); + } + hd->cmdPtr = NULL; + +- ddvprintk((MYIOC_s_WARN_FMT "ScanDvComplete mf=%p,mr=%p,idx=%d\n", +- ioc->name, mf, mr, req_idx)); ++ ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n", ++ hd->ioc->name, mf, mr, req_idx)); + + hd->pLocal = &hd->localReply; + hd->pLocal->scsiStatus = 0; +@@ -4156,9 +4109,10 @@ mptscsih_scandv_complete(MPT_ADAPTER *io + + status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK; + scsi_status = pReply->SCSIStatus; +- ddvprintk((MYIOC_s_WARN_FMT "%s: IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh IOCLogInfo=%08xh\n", +- ioc->name, __FUNCTION__, status, pReply->SCSIState, scsi_status, +- le32_to_cpu(pReply->IOCLogInfo))); ++ ++ ddvtprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n", ++ status, pReply->SCSIState, scsi_status, ++ le32_to_cpu(pReply->IOCLogInfo))); + + switch(status) { + +@@ -4203,14 +4157,13 @@ mptscsih_scandv_complete(MPT_ADAPTER *io + */ + completionCode = MPT_SCANDV_SENSE; + hd->pLocal->scsiStatus = scsi_status; +- sense_data = ((u8 *)ioc->sense_buf_pool + ++ sense_data = ((u8 *)hd->ioc->sense_buf_pool + + (req_idx * MPT_SENSE_BUFFER_ALLOC)); + + sz = min_t(int, pReq->SenseBufferLength, + SCSI_STD_SENSE_BYTES); + memcpy(hd->pLocal->sense, sense_data, sz); + +- DBG_DUMP_SENSE_DATA(sense_data); + ddvprintk((KERN_NOTICE " Check Condition, sense ptr %p\n", + sense_data)); + } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) { +@@ -4224,7 +4177,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *io + else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED) + completionCode = MPT_SCANDV_DID_RESET; + else if (scsi_status == MPI_SCSI_STATUS_BUSY) +- completionCode = MPT_SCANDV_BUSY; ++ completionCode = MPT_SCANDV_SOME_ERROR; + else { + completionCode = MPT_SCANDV_GOOD; + hd->pLocal->scsiStatus = scsi_status; +@@ -4243,9 +4196,9 @@ mptscsih_scandv_complete(MPT_ADAPTER *io + break; + + } /* switch(status) */ +- ddvprintk((MYIOC_s_WARN_FMT ": completionCode=%08xh\n", +- ioc->name, completionCode)); + ++ ddvtprintk((KERN_NOTICE " completionCode set to %08xh\n", ++ completionCode)); + } /* end of address reply case */ + + hd->pLocal->completion = completionCode; +@@ -4266,53 +4219,48 @@ wakeup: + } + + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +-/* mptscsih_InternalCmdTimer_expired - Call back for DV timer process. ++/* mptscsih_timer_expired - Call back for timer process. + * Used only for dv functionality. + * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long + * + */ +-void mptscsih_InternalCmdTimer_expired(unsigned long data) ++void ++mptscsih_timer_expired(unsigned long data) + { + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data; +- MPT_ADAPTER *ioc=hd->ioc; +- MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr; + +- ddvprintk((MYIOC_s_WARN_FMT "InternalCmdTimer_expired! cmdPtr=%p\n", +- ioc->name, cmd)); ++ ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr)); + +- hd->cmdPtr = NULL; +- if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) { +-#ifdef MPT_DEBUG_DV +- SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) cmd; +- int id = pScsiReq->TargetID; +- +- /* Desire to issue a task management request here. +- * TM requests MUST be single threaded. +- * If old eh code and no TM current, issue request. +- * If new eh code, do nothing. Wait for OS cmd timeout +- * for bus reset. +- */ +- ddvprintk((MYIOC_s_WARN_FMT "DV Cmd Timeout: id=%d CDB=%02x\n", +- ioc->name, id, pScsiReq->CDB[0])); +-#endif ++ if (hd->cmdPtr) { ++ MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr; + +- /* +- * Wake up the original calling thread +- */ +- hd->pLocal = &hd->localReply; +- hd->pLocal->completion = MPT_SCANDV_FALLBACK; +- hd->scandv_wait_done = 1; +- wake_up(&hd->scandv_waitq); +- } else { +- /* Perform a FW reload */ +- if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) { +- printk(MYIOC_s_WARN_FMT "InternalCmdTimer_expired: HardReset FAILED!\n", ioc->name); +- dfailprintk((MYIOC_s_ERR_FMT "InternalCmdTimer_expired: HardReset failed\n", ioc->name)); ++ if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) { ++ /* Desire to issue a task management request here. ++ * TM requests MUST be single threaded. ++ * If old eh code and no TM current, issue request. ++ * If new eh code, do nothing. Wait for OS cmd timeout ++ * for bus reset. ++ */ ++ ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name)); + } else { +- ddvprintk((MYIOC_s_ERR_FMT "InternalCmdTimer_expired: HardReset succeeded\n", ioc->name)); ++ /* Perform a FW reload */ ++ if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) { ++ printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name); ++ } + } ++ } else { ++ /* This should NEVER happen */ ++ printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name); + } +- ddvprintk((MYIOC_s_WARN_FMT "InternalCmdTimer_expired Complete!\n", ioc->name)); ++ ++ /* No more processing. ++ * TM call will generate an interrupt for SCSI TM Management. ++ * The FW will reply to all outstanding commands, callback will finish cleanup. ++ * Hard reset clean-up will free all resources. ++ */ ++ ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name)); ++ ++ return; + } + + #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION +@@ -4331,23 +4279,22 @@ void mptscsih_InternalCmdTimer_expired(u + static int + mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io) + { +- MPT_ADAPTER *ioc = hd->ioc; + MpiRaidActionRequest_t *pReq; + MPT_FRAME_HDR *mf; + int in_isr; + + in_isr = in_interrupt(); + if (in_isr) { +- dfailprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n", +- ioc->name)); ++ dprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n", ++ hd->ioc->name)); + return -EPERM; + } + + /* Get and Populate a free Frame + */ +- if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) { ++ if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) { + dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n", +- ioc->name,__FUNCTION__)); ++ hd->ioc->name,__FUNCTION__)); + return -EAGAIN; + } + pReq = (MpiRaidActionRequest_t *)mf; +@@ -4367,11 +4314,10 @@ mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 a + MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); + + ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n", +- ioc->name, action, io->id)); ++ hd->ioc->name, action, io->id)); + + hd->pLocal = NULL; +- hd->InternalCmdTimer.data = (unsigned long) hd; +- hd->InternalCmdTimer.expires = jiffies + HZ*10; /* 10 second timeout */ ++ hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */ + hd->scandv_wait_done = 0; + + /* Save cmd pointer, for resource free if timeout or +@@ -4379,8 +4325,8 @@ mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 a + */ + hd->cmdPtr = mf; + +- add_timer(&hd->InternalCmdTimer); +- mpt_put_msg_frame(ioc->InternalCtx, ioc, mf); ++ add_timer(&hd->timer); ++ mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf); + wait_event(hd->scandv_waitq, hd->scandv_wait_done); + + if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD)) +@@ -4413,7 +4359,6 @@ mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 a + int + mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) + { +- MPT_ADAPTER *ioc = hd->ioc; + MPT_FRAME_HDR *mf; + SCSIIORequest_t *pScsiReq; + SCSIIORequest_t ReqCopy; +@@ -4426,8 +4371,8 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER + + in_isr = in_interrupt(); + if (in_isr) { +- dfailprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n", +- ioc->name)); ++ dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n", ++ hd->ioc->name)); + return -EPERM; + } + +@@ -4542,16 +4487,14 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER + + default: + /* Error Case */ +- dfailprintk((MYIOC_s_WARN_FMT "%s,Unknown cmd=%02x!!\n", +- ioc->name,__FUNCTION__, cmd)); + return -EFAULT; + } + + /* Get and Populate a free Frame + */ +- if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) { ++ if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) { + dfailprintk((MYIOC_s_WARN_FMT "%s, no msg frames!!\n", +- ioc->name,__FUNCTION__)); ++ hd->ioc->name,__FUNCTION__)); + return -EBUSY; + } + +@@ -4593,18 +4536,18 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER + if (cmd == REQUEST_SENSE) { + pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED); + ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n", +- ioc->name, cmd)); ++ hd->ioc->name, cmd)); + } + + for (ii=0; ii < 16; ii++) + pScsiReq->CDB[ii] = CDB[ii]; + + pScsiReq->DataLength = cpu_to_le32(io->size); +- pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma ++ pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma + + (my_idx * MPT_SENSE_BUFFER_ALLOC)); + +- ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d) mf=%p\n", +- ioc->name, cmd, io->bus, io->id, io->lun, pScsiReq)); ++ ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n", ++ hd->ioc->name, cmd, io->bus, io->id, io->lun)); + + if (dir == MPI_SCSIIO_CONTROL_READ) { + mpt_add_sge((char *) &pScsiReq->SGL, +@@ -4630,8 +4573,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER + * set scandv_wait_done and call wake_up + */ + hd->pLocal = NULL; +- hd->InternalCmdTimer.data = (unsigned long) hd; +- hd->InternalCmdTimer.expires = jiffies + HZ*cmdTimeout; ++ hd->timer.expires = jiffies + HZ*cmdTimeout; + hd->scandv_wait_done = 0; + + /* Save cmd pointer, for resource free if timeout or +@@ -4639,8 +4581,8 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER + */ + hd->cmdPtr = mf; + +- add_timer(&hd->InternalCmdTimer); +- mpt_put_msg_frame(ioc->InternalCtx, ioc, mf); ++ add_timer(&hd->timer); ++ mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf); + wait_event(hd->scandv_waitq, hd->scandv_wait_done); + + if (hd->pLocal) { +@@ -4657,7 +4599,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER + rc = -EFAULT; + /* This should never happen. */ + ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n", +- ioc->name)); ++ hd->ioc->name)); + } + + return rc; +@@ -4678,7 +4620,6 @@ static int + mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum) + { + MPT_ADAPTER *ioc= hd->ioc; +- struct _MPT_DEVICE *pMptTarget; + VirtDevice *pTarget; + SCSIDevicePage1_t *pcfg1Data = NULL; + INTERNAL_CMD iocmd; +@@ -4690,6 +4631,7 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST + int lun; + int indexed_lun, lun_index; + int hostId = ioc->pfacts[portnum].PortSCSIID; ++ int max_id; + int requested, configuration, data; + int doConfig = 0; + u8 flags, factor; +@@ -4697,6 +4639,8 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST + dexitprintk((KERN_INFO MYNAM ": %s called\n", + __FUNCTION__)); + ++ max_id = ioc->sh->max_id - 1; ++ + /* Following parameters will not change + * in this routine. + */ +@@ -4733,11 +4677,10 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST + + /* loop through all devices on this port + */ +- while (bus < ioc->NumberOfBuses) { ++ while (bus < MPT_MAX_BUS) { + iocmd.bus = bus; + iocmd.id = id; +- pMptTarget = ioc->Target_List[bus]; +- pTarget = pMptTarget->Target[id]; ++ pTarget = hd->Targets[(int)id]; + + if (doConfig) { + +@@ -4745,9 +4688,9 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST + if (pTarget && !pTarget->raidVolume) { + flags = pTarget->negoFlags; + } else { +- flags = ioc->spi_data.noQas; +- if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) { +- data = ioc->spi_data.nvram[id]; ++ flags = hd->ioc->spi_data.noQas; ++ if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) { ++ data = hd->ioc->spi_data.nvram[id]; + + if (data & MPT_NVRAM_WIDE_DISABLE) + flags |= MPT_TARGET_NO_NEGO_WIDE; +@@ -4759,16 +4702,16 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST + } + + /* Force to async, narrow */ +- mpt_setSDP1parameters(0, MPT_ASYNC, 0, flags, +- &requested, &configuration); +- dnegoprintk(("%s: syncronize cache: id=%d width=0 factor=MPT_ASYNC " +- "offset=0 negoFlags=%x requested=%x configuration=%x\n", +- ioc->name, id, flags, requested, configuration)); ++ mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested, ++ &configuration, flags); ++ dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC " ++ "offset=0 negoFlags=%x request=%x config=%x\n", ++ id, flags, requested, configuration)); + pcfg1Data->RequestedParameters = cpu_to_le32(requested); + pcfg1Data->Reserved = 0; + pcfg1Data->Configuration = cpu_to_le32(configuration); + cfg.pageAddr = (bus<<8) | id; +- mpt_config(ioc, &cfg); ++ mpt_config(hd->ioc, &cfg); + } + + /* If target Ptr NULL or if this target is NOT a disk, skip. +@@ -4780,9 +4723,6 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST + lun_index = (lun >> 5); /* 32 luns per lun_index */ + indexed_lun = (lun % 32); + if (pTarget->luns[lun_index] & (1<<indexed_lun)) { +- dexitprintk((KERN_INFO MYNAM ": %s: synchronize_cache for bus=%d id=%d lun=%d\n", +- ioc->name, bus, id, lun)); +- + iocmd.lun = lun; + (void) mptscsih_do_cmd(hd, &iocmd); + } +@@ -4795,27 +4735,21 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST + if (id == hostId) + id++; + +- if (id >= ioc->DevicesPerBus) { ++ if (id > max_id) { + id = 0; + bus++; + } + } + +- dexitprintk((KERN_INFO MYNAM ": %s: synchronize_cache commands done\n", +- ioc->name)); +- + if (pcfg1Data) { +- dexitprintk((KERN_INFO MYNAM ": %s: free pcfg1Data=%p\n", +- ioc->name, pcfg1Data)); + pci_free_consistent(ioc->pcidev, header1.PageLength * 4, pcfg1Data, cfg1_dma_addr); + } + +- dexitprintk((KERN_INFO MYNAM ": %s: synchronize_cache done\n", +- ioc->name)); + return 0; + } + + #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION ++/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + /** + * mptscsih_domainValidation - Top level handler for domain validation. + * @hd: Pointer to MPT_SCSI_HOST structure. +@@ -4829,209 +4763,163 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST + static void + mptscsih_domainValidation(void *arg) + { +- VirtDevice *pTarget=(VirtDevice *)arg; +- MPT_SCSI_HOST *hd; +- MPT_ADAPTER *ioc; +- unsigned long flags; +- int id, dvStatus; +- int ii; ++ MPT_SCSI_HOST *hd; ++ MPT_ADAPTER *ioc; ++ unsigned long flags; ++ int id, maxid, dvStatus, did; ++ int ii, isPhysDisk; + + spin_lock_irqsave(&dvtaskQ_lock, flags); + dvtaskQ_active = 1; ++ if (dvtaskQ_release) { ++ dvtaskQ_active = 0; ++ spin_unlock_irqrestore(&dvtaskQ_lock, flags); ++ return; ++ } + spin_unlock_irqrestore(&dvtaskQ_lock, flags); + +- if (pTarget == NULL) { +- ddvprintk((KERN_WARNING "domainValidation called with NULL pTarget\n")); +- goto mptscsih_domainValidation_exit; +- } +- id = pTarget->id; +- ioc = pTarget->ioc; +- if (ioc == NULL) { +- ddvprintk((KERN_WARNING "domainValidation called with NULL pTarget->ioc id=%d\n", id)); +- goto mptscsih_domainValidation_exit; +- } +-// set_current_state(TASK_INTERRUPTIBLE); +-// schedule_timeout(MPT_HZ/4); ++ if (crashdump_mode()) ++ return; + +- hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; ++ /* For this ioc, loop through all devices and do dv to each device. ++ * When complete with this ioc, search through the ioc list, and ++ * for each scsi ioc found, do dv for all devices. Exit when no ++ * device needs dv. ++ */ ++ did = 1; ++ while (did) { ++ did = 0; ++ list_for_each_entry(ioc, &ioc_list, list) { ++ spin_lock_irqsave(&dvtaskQ_lock, flags); ++ if (dvtaskQ_release) { ++ dvtaskQ_active = 0; ++ spin_unlock_irqrestore(&dvtaskQ_lock, flags); ++ return; ++ } ++ spin_unlock_irqrestore(&dvtaskQ_lock, flags); + +- ddvprintk((KERN_WARNING "domainValidation pTarget=%p ioc=%p hd=%p id=%d\n", +- pTarget, ioc, hd, id)); +- if (hd == NULL) { +- ddvprintk((KERN_WARNING "domainValidation called with NULL hd id=%d\n", id)); +- goto mptscsih_domainValidation_exit; +- } ++ msleep(250); + +- if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) { +- mpt_read_ioc_pg_3(ioc); +- if (ioc->spi_data.dvStatus[id] & MPT_SCSICFG_PHYSDISK_DV_ONLY) { +- ddvprintk((KERN_WARNING "PHYSDISK_DV_ONLY id=%d\n", id)); +- ioc->spi_data.dvStatus[id] &= +- ~MPT_SCSICFG_PHYSDISK_DV_ONLY; +- if (mptscsih_doDv(hd, 0, id) == 1) { +- /* Untagged device was busy, try again +- */ +- ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV; +- } else { +- /* DV is complete. Clear flags. +- */ +- ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE; +- } +- goto mptscsih_domainValidation_exit; +- } ++ /* DV only to SPI adapters */ ++ if (ioc->bus_type != SPI) ++ continue; + +- if (ioc->raid_data.pIocPg3) { +- Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk; +- int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; ++ /* Make sure everything looks ok */ ++ if (ioc->sh == NULL) ++ continue; + +- while (numPDisk) { +- if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE) +- ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV; ++ hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; ++ if (hd == NULL) ++ continue; + +- pPDisk++; +- numPDisk--; ++ if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) { ++ mpt_read_ioc_pg_3(ioc); ++ if (ioc->raid_data.pIocPg3) { ++ Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk; ++ int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; ++ ++ while (numPDisk) { ++ if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE) ++ ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV; ++ ++ pPDisk++; ++ numPDisk--; ++ } ++ } ++ ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3; + } +- } +- ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3; +- } + +- dvStatus = ioc->spi_data.dvStatus[id]; ++ maxid = min_t(int, ioc->sh->max_id, MPT_MAX_SCSI_DEVICES); + +- if (dvStatus & MPT_SCSICFG_NEED_DV) { +- ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_IN_PROGRESS; +- ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV; ++ for (id = 0; id < maxid; id++) { ++ spin_lock_irqsave(&dvtaskQ_lock, flags); ++ if (dvtaskQ_release) { ++ dvtaskQ_active = 0; ++ spin_unlock_irqrestore(&dvtaskQ_lock, flags); ++ return; ++ } ++ spin_unlock_irqrestore(&dvtaskQ_lock, flags); ++ dvStatus = hd->ioc->spi_data.dvStatus[id]; + +-// set_current_state(TASK_INTERRUPTIBLE); +-// schedule_timeout(MPT_HZ/4); ++ if (dvStatus & MPT_SCSICFG_NEED_DV) { ++ did++; ++ hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING; ++ hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV; ++ ++ msleep(250); ++ ++ /* If hidden phys disk, block IO's to all ++ * raid volumes ++ * else, process normally ++ */ ++ isPhysDisk = mptscsih_is_phys_disk(hd->ioc, id); ++ if (isPhysDisk) { ++ for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { ++ if (hd->ioc->raid_data.isRaid & (1 << ii)) { ++ hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING; ++ } ++ } ++ } + +- /* If hidden phys disk, block IO's to all +- * raid volumes +- * else, process normally +- */ +- if (ioc->raid_data.isRaid & (1 << id)) { +- Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk; +- int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; +- while (numPDisk) { +- ii = pPDisk->PhysDiskID; +- if ( ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) { +- ddvprintk((KERN_WARNING "doDv for PhysDiskNum=%d PhysDiskID=%d numPDisk=%d\n", +- pPDisk->PhysDiskNum, ii, numPDisk)); +- if (mptscsih_doDv(hd, 0, ii) == 1) { ++ if(mpt_alt_ioc_wait(hd->ioc)!=0) { ++ ddvprintk((MYIOC_s_WARN_FMT "alt_ioc busy!\n", ++ hd->ioc->name)); ++ continue; ++ } ++ ++ if (mptscsih_doDv(hd, 0, id) == 1) { + /* Untagged device was busy, try again + */ +- ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_NEED_DV; ++ hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV; ++ hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING; + } else { +- ddvprintk((KERN_WARNING "doDv successful for PhysDiskNum=%d PhysDiskID=%d\n", +- pPDisk->PhysDiskNum, ii)); + /* DV is complete. Clear flags. + */ +- ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_NOT_DONE; ++ hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING); ++ } ++ ++ spin_lock(&hd->ioc->initializing_hba_lock); ++ hd->ioc->initializing_hba_lock_flag=0; ++ spin_unlock(&hd->ioc->initializing_hba_lock); ++ ++ if (isPhysDisk) { ++ for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { ++ if (hd->ioc->raid_data.isRaid & (1 << ii)) { ++ hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING; ++ } ++ } + } ++ ++ if (hd->ioc->spi_data.noQas) ++ mptscsih_qas_check(hd, id); + } +- pPDisk++; +- numPDisk--; +- } +- } else { +- ddvprintk((KERN_WARNING "doDv for id=%d\n", +- id)); +- if (mptscsih_doDv(hd, 0, id) == 1) { +- /* Untagged device was busy, try again +- */ +- ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV; +- } else { +- ddvprintk((KERN_WARNING "doDv successful for id=%d\n", +- id)); +- /* DV is complete. Clear flags. +- */ +- ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE; + } + } +- +- if (ioc->spi_data.noQas) +- mptscsih_qas_check(hd, id); +- } else { +- ddvprintk((KERN_INFO "~NEED_DV dvStatus=%x for id %d\n", +- dvStatus, id)); +-// panic( "~NEED_DV"); + } +-mptscsih_domainValidation_exit: ++ + spin_lock_irqsave(&dvtaskQ_lock, flags); + dvtaskQ_active = 0; + spin_unlock_irqrestore(&dvtaskQ_lock, flags); +-} +- + +-/* Post command on the PendingMF to the FW. +- */ +-void +-mptscsih_post_PendingMF_command(MPT_ADAPTER *ioc) +-{ +- MPT_SCSI_HOST *hd; +- MPT_FRAME_HDR *mf; +- struct scsi_cmnd *SCpnt; +- unsigned long flags; +- u16 req_idx; +- +- spin_lock_irqsave(&ioc->PendingMFlock, flags); +- if ((mf=ioc->PendingMF) == NULL) { +- spin_unlock_irqrestore(&ioc->PendingMFlock, flags); +- dpendprintk((MYIOC_s_INFO_FMT "%s: PendingMF is empty\n", +- ioc->name, __FUNCTION__)); +- return; +- } +- +- mf = ioc->PendingMF; +- SCpnt = ioc->PendingSCpnt; +- ioc->PendingMF = NULL; +- spin_unlock_irqrestore(&ioc->PendingMFlock, flags); +- +- dpendprintk((MYIOC_s_INFO_FMT "mptscsih_post_PendingMF_command: mf=%p\n", +- ioc->name, mf)); +- DBG_DUMP_PENDING_REQUEST_FRAME(ioc, mf) +- +- hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; +- req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); +- hd->ScsiLookup[req_idx] = SCpnt; +- mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); ++ return; + } + +- + /* Search IOC page 3 to determine if this is hidden physical disk + */ + static int +-mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int channel, int id) ++mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) + { +- struct inactive_raid_component_info *component_info; + int i; +- int rc = 0; +- +- if (!ioc->raid_data.pIocPg3) +- goto out; +- for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { +- if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) && +- (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) { +- rc = 1; +- goto out; +- } +- } + +- /* +- * Check inactive list for matching phys disks +- */ +- if (list_empty(&ioc->raid_data.inactive_list)) +- goto out; ++ if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3) ++ return 0; + +- down(&ioc->raid_data.inactive_list_mutex); +- list_for_each_entry(component_info, +- &ioc->raid_data.inactive_list, list) { +- if ((component_info->d.PhysDiskID == id) && +- (component_info->d.PhysDiskBus == channel)) +- rc = 1; ++ for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { ++ if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) ++ return 1; + } +- up(&ioc->raid_data.inactive_list_mutex); + +- out: +- return rc; ++ return 0; + } + + /* Write SDP1 if no QAS has been enabled +@@ -5039,37 +4927,32 @@ mptscsih_is_phys_disk(MPT_ADAPTER *ioc, + static void + mptscsih_qas_check(MPT_SCSI_HOST *hd, int id) + { +- MPT_ADAPTER *ioc = hd->ioc; +- struct _MPT_DEVICE *pMptTarget; + VirtDevice *pTarget; + int ii; + +- pMptTarget = ioc->Target_List[0]; + for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { + if (ii == id) + continue; + +- if ((ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0) ++ if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0) + continue; + +- pTarget = pMptTarget->Target[ii]; +- +- if (pTarget) { +- if (!pTarget->raidVolume) { +- if ((pTarget->negoFlags & ioc->spi_data.noQas) == 0) { +- pTarget->negoFlags |= ioc->spi_data.noQas; +- dnegoprintk(("mptscsih_qas_check: writeSDP1: id=%d negoFlags=%d\n", ii, pTarget->negoFlags)); +- mpt_writeSDP1(ioc, 0, ii, MPT_SCSICFG_USE_NVRAM); +- } +- } else { +- if (mptscsih_is_phys_disk(ioc, 0, ii) == 1) { +- dnegoprintk(("mptscsih_qas_check: is_phys_disk writeSDP1: id=%d SCSICFG_USE_NVRAM\n", ii)); +- mpt_writeSDP1(ioc, 0, ii, MPT_SCSICFG_USE_NVRAM); ++ pTarget = hd->Targets[ii]; + +- } ++ if (pTarget && (!pTarget->raidVolume)) { ++ if ((pTarget->negoFlags & hd->ioc->spi_data.noQas) == 0) { ++ pTarget->negoFlags |= hd->ioc->spi_data.noQas; ++ dnegoprintk(("writeSDP1: id=%d negoFlags=%d\n", id, pTarget->negoFlags)); ++ mptscsih_writeSDP1(hd, 0, ii, 0); ++ } ++ } else { ++ if (mptscsih_is_phys_disk(hd->ioc, ii) == 1) { ++ dnegoprintk(("writeSDP1: id=%d SCSICFG_USE_NVRAM\n", id)); ++ mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM); + } + } + } ++ return; + } + + +@@ -5094,16 +4977,15 @@ mptscsih_qas_check(MPT_SCSI_HOST *hd, in + * Return: None. + */ + static int +-mptscsih_doDv(MPT_SCSI_HOST *hd, int bus, int id) ++mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) + { + MPT_ADAPTER *ioc = hd->ioc; +- struct _MPT_DEVICE *pMptTarget; + VirtDevice *pTarget; + SCSIDevicePage1_t *pcfg1Data; + SCSIDevicePage0_t *pcfg0Data; + u8 *pbuf1; + u8 *pbuf2; +- u8 *pDvBuf=NULL; ++ u8 *pDvBuf; + dma_addr_t dvbuf_dma = -1; + dma_addr_t buf1_dma = -1; + dma_addr_t buf2_dma = -1; +@@ -5127,7 +5009,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus + char firstPass = 1; + char doFallback = 0; + char readPage0; +- char lun; ++ char bus, lun; + char inq0 = 0; + + if (ioc->spi_data.sdp1length == 0) +@@ -5141,10 +5023,12 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus + */ + if (id == ioc->pfacts[0].PortSCSIID) + return 0; +-ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_IN_PROGRESS; + + lun = 0; +- ddvprintk((MYIOC_s_INFO_FMT "DV Started: bus=%d id=%d dv @ %p\n",ioc->name, bus, id, &dv)); ++ bus = (u8) bus_number; ++ ddvtprintk((MYIOC_s_NOTE_FMT ++ "DV Started: bus=%d id=%d dv @ %p\n", ++ ioc->name, bus, id, &dv)); + + /* Prep DV structure + */ +@@ -5167,8 +5051,7 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF + iocmd.physDiskNum = -1; + iocmd.rsvd = iocmd.rsvd2 = 0; + +- pMptTarget = ioc->Target_List[bus]; +- pTarget = pMptTarget->Target[id]; ++ pTarget = hd->Targets[id]; + + /* Use tagged commands if possible. + */ +@@ -5176,12 +5059,12 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF + if (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES) + iocmd.flags |= MPT_ICFLAG_TAGGED_CMD; + else { +- if (ioc->facts.FWVersion.Word < 0x01000600) +- goto doDv_done; ++ if (hd->ioc->facts.FWVersion.Word < 0x01000600) ++ return 0; + +- if ((ioc->facts.FWVersion.Word >= 0x01010000) && +- (ioc->facts.FWVersion.Word < 0x01010B00)) +- goto doDv_done; ++ if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) && ++ (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ++ return 0; + } + } + +@@ -5211,7 +5094,7 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF + + pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma); + if (pDvBuf == NULL) +- goto doDv_done; ++ return 0; + + sz = 0; + pbuf1 = (u8 *)pDvBuf; +@@ -5237,7 +5120,7 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF + /* Skip this ID? Set cfg.cfghdr.hdr to force config page write + */ + { +- SpiCfgData *pspi_data = &ioc->spi_data; ++ SpiCfgData *pspi_data = &hd->ioc->spi_data; + if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) { + /* Set the factor from nvram */ + nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8; +@@ -5247,7 +5130,7 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF + if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) || + (pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) { + +- ddvprintk((MYIOC_s_INFO_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n", ++ ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n", + ioc->name, bus, id, lun)); + + dv.cmd = MPT_SET_MAX; +@@ -5260,7 +5143,7 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF + cfg.physAddr = cfg1_dma_addr; + cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; + cfg.dir = 1; +- mpt_config(ioc, &cfg); ++ mpt_config(hd->ioc, &cfg); + goto target_done; + } + } +@@ -5295,7 +5178,7 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF + /* RAID Volume ID's may double for a physical device. If RAID but + * not a physical ID as well, skip DV. + */ +- if ((ioc->raid_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK)) ++ if ((hd->ioc->raid_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK)) + goto target_done; + + +@@ -5312,10 +5195,8 @@ ioc->spi_data.dvStatus[id] |= MPT_SCSICF + readPage0 = 0; + sz = SCSI_MAX_INQUIRY_BYTES; + rc = MPT_SCANDV_GOOD; +- +-start_DV: + while (1) { +- ddvprintk((MYIOC_s_INFO_FMT "DV: Start Basic test on id=%d\n", ioc->name, id)); ++ ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id)); + retcode = 0; + dv.cmd = MPT_SET_MIN; + mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); +@@ -5324,7 +5205,7 @@ start_DV: + cfg.physAddr = cfg1_dma_addr; + cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; + cfg.dir = 1; +- if (mpt_config(ioc, &cfg) != 0) ++ if (mpt_config(hd->ioc, &cfg) != 0) + goto target_done; + + /* Wide - narrow - wide workaround case +@@ -5333,9 +5214,9 @@ start_DV: + /* Send an untagged command to reset disk Qs corrupted + * when a parity error occurs on a Request Sense. + */ +- if ((ioc->facts.FWVersion.Word >= 0x01000600) || +- ((ioc->facts.FWVersion.Word >= 0x01010000) && +- (ioc->facts.FWVersion.Word < 0x01010B00)) ) { ++ if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) || ++ ((hd->ioc->facts.FWVersion.Word >= 0x01010000) && ++ (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) { + + iocmd.cmd = REQUEST_SENSE; + iocmd.data_dma = buf1_dma; +@@ -5400,6 +5281,12 @@ start_DV: + * if PROCESSOR, quit DV. + */ + if (inq0 == TYPE_PROCESSOR) { ++ mptscsih_initTarget(hd, ++ bus, ++ id, ++ lun, ++ pbuf1, ++ sz); + goto target_done; + } + +@@ -5426,8 +5313,8 @@ start_DV: + + if ((pbuf1[56] & 0x02) == 0) { + pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS; +- ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS; +- ddvprintk((MYIOC_s_INFO_FMT ++ hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS; ++ ddvprintk((MYIOC_s_NOTE_FMT + "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n", + ioc->name, id, pbuf1[56])); + } +@@ -5440,7 +5327,7 @@ start_DV: + dv.cmd = MPT_SET_MAX; + + mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); +- if (mpt_config(ioc, &cfg) != 0) ++ if (mpt_config(hd->ioc, &cfg) != 0) + goto target_done; + + if ((!dv.now.width) && (!dv.now.offset)) +@@ -5473,7 +5360,7 @@ start_DV: + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + cfg.dir = 0; + +- if (mpt_config(ioc, &cfg) != 0) ++ if (mpt_config(hd->ioc, &cfg) != 0) + goto target_done; + + sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E; +@@ -5504,7 +5391,15 @@ start_DV: + if (!firstPass) + doFallback = 1; + } else { +- ++ ddvprintk((MYIOC_s_NOTE_FMT ++ "DV:Inquiry compared id=%d, calling initTarget\n", ioc->name, id)); ++ hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE; ++ mptscsih_initTarget(hd, ++ bus, ++ id, ++ lun, ++ pbuf1, ++ sz); + break; /* test complete */ + } + } +@@ -5522,7 +5417,7 @@ start_DV: + firstPass = 0; + } + } +- ddvprintk((MYIOC_s_INFO_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id)); ++ ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id)); + + if (ioc->spi_data.mpt_dv == 0) + goto target_done; +@@ -5534,10 +5429,10 @@ start_DV: + if (inq0 != 0) + goto target_done; + +- ddvprintk((MYIOC_s_INFO_FMT "DV: bus, id, lun (%d, %d, %d) PortFlags=%x\n", ++ ddvprintk((MYIOC_s_NOTE_FMT "DV: bus, id, lun (%d, %d, %d) PortFlags=%x\n", + ioc->name, bus, id, lun, ioc->spi_data.PortFlags)); + if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY ) { +- ddvprintk((MYIOC_s_INFO_FMT "DV Basic Only: bus, id, lun (%d, %d, %d) PortFlags=%x\n", ++ ddvprintk((MYIOC_s_NOTE_FMT "DV Basic Only: bus, id, lun (%d, %d, %d) PortFlags=%x\n", + ioc->name, bus, id, lun, ioc->spi_data.PortFlags)); + goto target_done; + } +@@ -5574,7 +5469,7 @@ start_DV: + u8 skey = hd->pLocal->sense[2] & 0x0F; + u8 asc = hd->pLocal->sense[12]; + u8 ascq = hd->pLocal->sense[13]; +- ddvprintk((MYIOC_s_WARN_FMT ++ ddvprintk((MYIOC_s_INFO_FMT + "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", + ioc->name, skey, asc, ascq)); + +@@ -5646,7 +5541,7 @@ start_DV: + u8 skey = hd->pLocal->sense[2] & 0x0F; + u8 asc = hd->pLocal->sense[12]; + u8 ascq = hd->pLocal->sense[13]; +- ddvprintk((MYIOC_s_WARN_FMT ++ ddvprintk((MYIOC_s_INFO_FMT + "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", + ioc->name, skey, asc, ascq)); + if (skey == ILLEGAL_REQUEST) { +@@ -5665,11 +5560,6 @@ start_DV: + ioc->name)); + goto target_done; + } +- } else if (rc == MPT_SCANDV_FALLBACK) { +- doFallback = 1; /* set fallback flag */ +- notDone++; +- goto start_DV; +- + } else { + /* All other errors are fatal + */ +@@ -5812,7 +5702,7 @@ skip_Reserve: + dv.cmd = MPT_FALLBACK; + mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); + +- if (mpt_config(ioc, &cfg) != 0) ++ if (mpt_config(hd->ioc, &cfg) != 0) + goto target_done; + + if ((!dv.now.width) && (!dv.now.offset)) +@@ -5826,7 +5716,7 @@ skip_Reserve: + /* Restart data test if UA, else quit. + */ + u8 skey = hd->pLocal->sense[2] & 0x0F; +- ddvprintk((MYIOC_s_WARN_FMT ++ ddvprintk((MYIOC_s_INFO_FMT + "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey, + hd->pLocal->sense[12], hd->pLocal->sense[13])); + if (skey == UNIT_ATTENTION) { +@@ -5891,7 +5781,7 @@ skip_Reserve: + dv.cmd = MPT_FALLBACK; + mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); + +- if (mpt_config(ioc, &cfg) != 0) ++ if (mpt_config(hd->ioc, &cfg) != 0) + goto target_done; + + if ((!dv.now.width) && (!dv.now.offset)) +@@ -5909,7 +5799,7 @@ skip_Reserve: + dv.cmd = MPT_FALLBACK; + mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); + +- if (mpt_config(ioc, &cfg) != 0) ++ if (mpt_config(hd->ioc, &cfg) != 0) + goto target_done; + + if ((!dv.now.width) && (!dv.now.offset)) +@@ -5922,7 +5812,7 @@ skip_Reserve: + /* Restart data test if UA, else quit. + */ + u8 skey = hd->pLocal->sense[2] & 0x0F; +- ddvprintk((MYIOC_s_WARN_FMT ++ ddvprintk((MYIOC_s_INFO_FMT + "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey, + hd->pLocal->sense[12], hd->pLocal->sense[13])); + if (skey == UNIT_ATTENTION) { +@@ -5964,8 +5854,8 @@ target_done: + /* If disk, not U320, disable QAS + */ + if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) { +- ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS; +- ddvprintk((MYIOC_s_INFO_FMT ++ hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS; ++ ddvprintk((MYIOC_s_NOTE_FMT + "noQas set due to id=%d has factor=%x\n", ioc->name, id, dv.now.factor)); + } + +@@ -5980,7 +5870,7 @@ target_done: + cfg.physAddr = cfg1_dma_addr; + cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; + cfg.dir = 1; +- mpt_config(ioc, &cfg); ++ mpt_config(hd->ioc, &cfg); + */ + } + +@@ -5991,18 +5881,13 @@ target_done: + ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name)); + } + +-doDv_done: + /* Done with the DV scan of the current target + */ + if (pDvBuf) + pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma); + +- ddvprintk((MYIOC_s_WARN_FMT "DV Done id=%d\n",ioc->name, id)); +- ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_IN_PROGRESS); +- /* Post an IO that was pended while +- * DV was running. +- */ +- mptscsih_post_PendingMF_command(ioc); ++ ddvtprintk((MYIOC_s_INFO_FMT "DV Done id=%d\n", ++ ioc->name, id)); + + return retcode; + } +@@ -6017,8 +5902,6 @@ doDv_done: + static void + mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage) + { +- MPT_ADAPTER *ioc = hd->ioc; +- struct _MPT_DEVICE *pMptTarget; + VirtDevice *pTarget; + SCSIDevicePage0_t *pPage0; + SCSIDevicePage1_t *pPage1; +@@ -6032,48 +5915,49 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP + + switch (cmd) { + case MPT_GET_NVRAM_VALS: +- ddvprintk((MYIOC_s_INFO_FMT "Getting NVRAM: ", +- ioc->name)); ++ ddvprintk((MYIOC_s_NOTE_FMT "Getting NVRAM: ", ++ hd->ioc->name)); + /* Get the NVRAM values and save in tmax + * If not an LVD bus, the adapter minSyncFactor has been + * already throttled back. + */ +- negoFlags = ioc->spi_data.noQas; +- pMptTarget = ioc->Target_List[0]; +- pTarget = pMptTarget->Target[id]; +- if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) { +- data = ioc->spi_data.nvram[id]; +- width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; +- if ((offset = ioc->spi_data.maxSyncOffset) == 0) +- factor = MPT_ASYNC; +- else { +- factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT; +- if ((factor == 0) || (factor == MPT_ASYNC)){ ++ negoFlags = hd->ioc->spi_data.noQas; ++ if ((pTarget = hd->Targets[(int)id]) && !pTarget->raidVolume) { ++ width = pTarget->maxWidth; ++ offset = pTarget->maxOffset; ++ factor = pTarget->minSyncFactor; ++ negoFlags |= pTarget->negoFlags; ++ } else { ++ if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) { ++ data = hd->ioc->spi_data.nvram[id]; ++ width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; ++ if ((offset = hd->ioc->spi_data.maxSyncOffset) == 0) + factor = MPT_ASYNC; +- offset = 0; ++ else { ++ factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT; ++ if ((factor == 0) || (factor == MPT_ASYNC)){ ++ factor = MPT_ASYNC; ++ offset = 0; ++ } + } +- ddvprintk(("NVRAM id=%d width=%d factor=%x offset=%x negoFlags=%x\n", +- id, width, factor, offset, negoFlags)); ++ } else { ++ width = MPT_NARROW; ++ offset = 0; ++ factor = MPT_ASYNC; + } +- } else { +- width = MPT_NARROW; +- offset = 0; +- factor = MPT_ASYNC; +- ddvprintk(("NVRAM_INVALID id=%d width=%d factor=%x offset=%x negoFlags=%x\n", +- id, width, factor, offset, negoFlags)); +- } + +- /* Set the negotiation flags */ +- if (!width) +- negoFlags |= MPT_TARGET_NO_NEGO_WIDE; ++ /* Set the negotiation flags */ ++ if (!width) ++ negoFlags |= MPT_TARGET_NO_NEGO_WIDE; + +- if (!offset) +- negoFlags |= MPT_TARGET_NO_NEGO_SYNC; ++ if (!offset) ++ negoFlags |= MPT_TARGET_NO_NEGO_SYNC; ++ } + + /* limit by adapter capabilities */ +- width = min(width, ioc->spi_data.maxBusWidth); +- offset = min(offset, ioc->spi_data.maxSyncOffset); +- factor = max(factor, ioc->spi_data.minSyncFactor); ++ width = min(width, hd->ioc->spi_data.maxBusWidth); ++ offset = min(offset, hd->ioc->spi_data.maxSyncOffset); ++ factor = max(factor, hd->ioc->spi_data.minSyncFactor); + + /* Check Consistency */ + if (offset && (factor < MPT_ULTRA2) && !width) +@@ -6083,13 +5967,13 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP + dv->max.offset = offset; + dv->max.factor = factor; + dv->max.flags = negoFlags; +- ddvprintk(("id=%d width=%d factor=%x offset=%x negoFlags=%x\n", ++ ddvprintk((" id=%d width=%d factor=%x offset=%x negoFlags=%x\n", + id, width, factor, offset, negoFlags)); + break; + + case MPT_UPDATE_MAX: +- ddvprintk((MYIOC_s_INFO_FMT +- "Updating with SDP0 Data: ", ioc->name)); ++ ddvprintk((MYIOC_s_NOTE_FMT ++ "Updating with SDP0 Data: ", hd->ioc->name)); + /* Update tmax values with those from Device Page 0.*/ + pPage0 = (SCSIDevicePage0_t *) pPage; + if (pPage0) { +@@ -6103,10 +5987,12 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP + dv->now.offset = dv->max.offset; + dv->now.factor = dv->max.factor; + ddvprintk(("id=%d width=%d factor=%x offset=%x negoFlags=%x\n", +- id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags)); ++ id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags)); + break; + + case MPT_SET_MAX: ++ ddvprintk((MYIOC_s_NOTE_FMT "Setting Max: ", ++ hd->ioc->name)); + /* Set current to the max values. Update the config page.*/ + dv->now.width = dv->max.width; + dv->now.offset = dv->max.offset; +@@ -6115,18 +6001,22 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP + + pPage1 = (SCSIDevicePage1_t *)pPage; + if (pPage1) { +- mpt_setSDP1parameters (dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, +- &val, &configuration); ++ mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor, ++ dv->now.offset, &val, &configuration, dv->now.flags); ++ dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n", ++ id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration)); + pPage1->RequestedParameters = cpu_to_le32(val); + pPage1->Reserved = 0; + pPage1->Configuration = cpu_to_le32(configuration); + } + +- dnegoprintk(("%s: Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x requested=%08x configuration=%08x\n", +- ioc->name, id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration)); ++ ddvprintk(("id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x configuration=%x\n", ++ id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration)); + break; + + case MPT_SET_MIN: ++ ddvprintk((MYIOC_s_NOTE_FMT "Setting Min: ", ++ hd->ioc->name)); + /* Set page to asynchronous and narrow + * Do not update now, breaks fallback routine. */ + width = MPT_NARROW; +@@ -6136,20 +6026,22 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP + + pPage1 = (SCSIDevicePage1_t *)pPage; + if (pPage1) { +- mpt_setSDP1parameters (width, factor, offset, negoFlags, +- &val, &configuration); ++ mptscsih_setDevicePage1Flags (width, factor, ++ offset, &val, &configuration, negoFlags); ++ dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n", ++ id, width, factor, offset, negoFlags, val, configuration)); + pPage1->RequestedParameters = cpu_to_le32(val); + pPage1->Reserved = 0; + pPage1->Configuration = cpu_to_le32(configuration); + } +- dnegoprintk(("%s: Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x requested=%08x configuration=%08x\n", +- ioc->name, id, width, factor, offset, negoFlags, val, configuration)); ++ ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n", ++ id, width, factor, offset, val, configuration, negoFlags)); + break; + + case MPT_FALLBACK: +- ddvprintk((MYIOC_s_INFO_FMT ++ ddvprintk((MYIOC_s_NOTE_FMT + "Fallback: Start: offset %d, factor %x, width %d \n", +- ioc->name, dv->now.offset, ++ hd->ioc->name, dv->now.offset, + dv->now.factor, dv->now.width)); + width = dv->now.width; + offset = dv->now.offset; +@@ -6212,32 +6104,31 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP + + pPage1 = (SCSIDevicePage1_t *)pPage; + if (pPage1) { +- mpt_setSDP1parameters (width, factor, offset, dv->now.flags, +- &val, &configuration); ++ mptscsih_setDevicePage1Flags (width, factor, offset, &val, ++ &configuration, dv->now.flags); ++ dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x negoFlags=%x request=%x config=%x\n", ++ id, width, offset, factor, dv->now.flags, val, configuration)); + + pPage1->RequestedParameters = cpu_to_le32(val); + pPage1->Reserved = 0; + pPage1->Configuration = cpu_to_le32(configuration); + } + +- ddvprintk(("%s: Finish: id=%d width=%d offset=%d factor=%x negoFlags=%x requested=%08x configuration=%08x\n", +- ioc->name, id, width, offset, factor, dv->now.flags, val, configuration)); ++ ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n", ++ id, dv->now.offset, dv->now.factor, dv->now.width, val, configuration)); + break; + + case MPT_SAVE: +- ddvprintk((MYIOC_s_INFO_FMT +- "Saving to pTarget: " +- "id=%d width=%x factor=%x offset=%d negoFlags=%x\n", +- ioc->name, id, dv->now.width, dv->now.factor, +- dv->now.offset, dv->now.flags)); ++ ddvprintk((MYIOC_s_NOTE_FMT ++ "Saving to Target structure: ", hd->ioc->name)); ++ ddvprintk(("id=%d width=%x factor=%x offset=%d negoFlags=%x\n", ++ id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags)); + + /* Save these values to target structures + * or overwrite nvram (phys disks only). + */ + +- pMptTarget = ioc->Target_List[0]; +- pTarget = pMptTarget->Target[id]; +- if (pTarget && !pTarget->raidVolume ) { ++ if ((pTarget = hd->Targets[(int)id]) && !pTarget->raidVolume ) { + pTarget->maxWidth = dv->now.width; + pTarget->maxOffset = dv->now.offset; + pTarget->minSyncFactor = dv->now.factor; +@@ -6246,8 +6137,8 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP + /* Preserv all flags, use + * read-modify-write algorithm + */ +- if (ioc->spi_data.nvram) { +- data = ioc->spi_data.nvram[id]; ++ if (hd->ioc->spi_data.nvram) { ++ data = hd->ioc->spi_data.nvram[id]; + + if (dv->now.width) + data &= ~MPT_NVRAM_WIDE_DISABLE; +@@ -6260,14 +6151,13 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP + data &= ~MPT_NVRAM_SYNC_MASK; + data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK; + +- ioc->spi_data.nvram[id] = data; ++ hd->ioc->spi_data.nvram[id] = data; + } + } + break; + } + } + +- + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + /* mptscsih_fillbuf - fill a buffer with a special data pattern + * cleanup. For bus scan only. +@@ -6422,11 +6312,10 @@ EXPORT_SYMBOL(mptscsih_taskmgmt_complete + EXPORT_SYMBOL(mptscsih_scandv_complete); + EXPORT_SYMBOL(mptscsih_event_process); + EXPORT_SYMBOL(mptscsih_ioc_reset); +-EXPORT_SYMBOL(mptscsih_InternalCmdTimer_expired); ++EXPORT_SYMBOL(mptscsih_timer_expired); + EXPORT_SYMBOL(mptscsih_readFCDevicePage0); + EXPORT_SYMBOL(mptscsih_change_queue_depth); + EXPORT_SYMBOL(mptscsih_TMHandler); +-EXPORT_SYMBOL(mptscsih_TM_timeout); + EXPORT_SYMBOL(mptscsih_sanity_check); + EXPORT_SYMBOL(mptscsih_poll); + EXPORT_SYMBOL(mptscsih_do_cmd); +diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptscsih.h linux-2.6.9-55.0.12/drivers/message/fusion/mptscsih.h +--- linux-2.6.9-67.0.1/drivers/message/fusion/mptscsih.h 2007-12-21 11:40:54.000000000 +0100 ++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptscsih.h 2007-11-02 09:10:23.000000000 +0100 +@@ -5,8 +5,8 @@ + * LSIFC9xx/LSI409xx Fibre Channel + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * +- * Copyright (c) 1999-2007 LSI Logic Corporation +- * (mailto:mpt_linux_developer@lsi.com) ++ * Copyright (c) 1999-2005 LSI Logic Corporation ++ * (mailto:mpt_linux_developer@lsil.com) + * + * $Id: mptscsih.h,v 1.1.2.2 2003/05/07 14:08:35 Exp $ + */ +@@ -54,17 +54,7 @@ + * SCSI Public stuff... + */ + +-#define MPT_SCANDV_GOOD (0x00000000) /* must be 0 */ +-#define MPT_SCANDV_DID_RESET (0x00000001) +-#define MPT_SCANDV_SENSE (0x00000002) +-#define MPT_SCANDV_SOME_ERROR (0x00000004) +-#define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008) +-#define MPT_SCANDV_ISSUE_SENSE (0x00000010) +-#define MPT_SCANDV_FALLBACK (0x00000020) +-#define MPT_SCANDV_BUSY (0x00000040) +- +-//#define MPT_SCSI_CMD_PER_DEV_HIGH 64 +-#define MPT_SCSI_CMD_PER_DEV_HIGH 48 ++#define MPT_SCSI_CMD_PER_DEV_HIGH 64 + #define MPT_SCSI_CMD_PER_DEV_LOW 32 + + #define MPT_SCSI_CMD_PER_LUN 7 +@@ -133,7 +123,7 @@ extern int mptscsih_taskmgmt_complete(MP + extern int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); + extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); + extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); +-extern void mptscsih_InternalCmdTimer_expired(unsigned long data); ++extern void mptscsih_timer_expired(unsigned long data); + extern int mptscsih_readFCDevicePage0(MPT_ADAPTER *ioc, u8 bus, u8 targetId, pFCDevicePage0_t fcDevicePage); + extern void mptscsih_hot_plug_worker_thread(void * arg); + extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); +@@ -141,4 +131,4 @@ extern int mptscsih_change_queue_depth(s + extern int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); + extern int mptscsih_sanity_check(struct scsi_device *sdev); + extern void mptscsih_poll(struct scsi_device *sdev); +-extern void scsi_print_command(struct scsi_cmnd *cmd); ++extern void scsi_print_command(struct scsi_cmnd *cmd); +\ Pas de fin de ligne à la fin du fichier. +diff -Nrup linux-2.6.9-67.0.1/drivers/message/fusion/mptspi.c linux-2.6.9-55.0.12/drivers/message/fusion/mptspi.c +--- linux-2.6.9-67.0.1/drivers/message/fusion/mptspi.c 2007-12-21 11:40:54.000000000 +0100 ++++ linux-2.6.9-55.0.12/drivers/message/fusion/mptspi.c 2007-11-02 09:10:23.000000000 +0100 +@@ -3,8 +3,8 @@ + * For use with LSI Logic PCI chip/adapter(s) + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * +- * Copyright (c) 1999-2007 LSI Logic Corporation +- * (mailto:mpt_linux_developer@lsi.com) ++ * Copyright (c) 1999-2005 LSI Logic Corporation ++ * (mailto:mpt_linux_developer@lsil.com) + * + */ + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +@@ -73,7 +73,6 @@ + MODULE_AUTHOR(MODULEAUTHOR); + MODULE_DESCRIPTION(my_NAME); + MODULE_LICENSE("GPL"); +-MODULE_VERSION(my_VERSION); + + /* Command line args */ + #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION +@@ -146,13 +145,12 @@ static struct scsi_host_template mptspi_ + .change_queue_depth = mptscsih_change_queue_depth, + #endif + .eh_abort_handler = mptscsih_abort, +- .eh_device_reset_handler = mptscsih_dev_reset, + .eh_bus_reset_handler = mptscsih_bus_reset, + .eh_host_reset_handler = mptscsih_host_reset, + .bios_param = mptscsih_bios_param, + .can_queue = MPT_SCSI_CAN_QUEUE, + .this_id = -1, +- .sg_tablesize = CONFIG_FUSION_MAX_SGE, ++ .sg_tablesize = MPT_SCSI_SG_DEPTH, + .max_sectors = 8192, + .cmd_per_lun = 7, + .use_clustering = ENABLE_CLUSTERING, +@@ -191,6 +189,8 @@ mptspi_probe(struct pci_dev *pdev, const + MPT_ADAPTER *ioc; + unsigned long flags; + int sz, ii; ++ int numSGE = 0; ++ int scale; + int ioc_cap; + u8 *mem; + int error=0; +@@ -269,7 +269,7 @@ mptspi_probe(struct pci_dev *pdev, const + ioc->name, mpt_can_queue, ioc->req_depth, + sh->can_queue)); + +- sh->max_id = ioc->DevicesPerBus; ++ sh->max_id = MPT_MAX_SCSI_DEVICES; + + sh->max_lun = MPT_LAST_LUN + 1; + sh->max_channel = 0; +@@ -278,7 +278,36 @@ mptspi_probe(struct pci_dev *pdev, const + /* Required entry. + */ + sh->unique_id = ioc->id; +- sh->sg_tablesize = ioc->sg_tablesize; ++ ++ /* Verify that we won't exceed the maximum ++ * number of chain buffers ++ * We can optimize: ZZ = req_sz/sizeof(SGE) ++ * For 32bit SGE's: ++ * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ ++ * + (req_sz - 64)/sizeof(SGE) ++ * A slightly different algorithm is required for ++ * 64bit SGEs. ++ */ ++ scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); ++ if (sizeof(dma_addr_t) == sizeof(u64)) { ++ numSGE = (scale - 1) * ++ (ioc->facts.MaxChainDepth-1) + scale + ++ (ioc->req_sz - 60) / (sizeof(dma_addr_t) + ++ sizeof(u32)); ++ } else { ++ numSGE = 1 + (scale - 1) * ++ (ioc->facts.MaxChainDepth-1) + scale + ++ (ioc->req_sz - 64) / (sizeof(dma_addr_t) + ++ sizeof(u32)); ++ } ++ ++ if (numSGE < sh->sg_tablesize) { ++ /* Reset this value */ ++ dprintk((MYIOC_s_INFO_FMT ++ "Resetting sg_tablesize to %d from %d\n", ++ ioc->name, numSGE, sh->sg_tablesize)); ++ sh->sg_tablesize = numSGE; ++ } + + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)) + /* Set the pci device pointer in Scsi_Host structure. +@@ -307,29 +336,29 @@ mptspi_probe(struct pci_dev *pdev, const + dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", + ioc->name, hd->ScsiLookup, sz)); + +- for (ii=0; ii < ioc->NumberOfBuses; ii++) { +- /* Allocate memory for the device structures. +- * A non-Null pointer at an offset +- * indicates a device exists. +- */ +- sz = ioc->DevicesPerBus * sizeof(void *); +- mem = kmalloc(sz, GFP_ATOMIC); +- if (mem == NULL) { +- error = -ENOMEM; +- goto out_mptspi_probe; +- } ++ /* Allocate memory for the device structures. ++ * A non-Null pointer at an offset ++ * indicates a device exists. ++ * max_id = 1 + maximum id (hosts.h) ++ */ ++ sz = sh->max_id * sizeof(void *); ++ mem = kmalloc(sz, GFP_ATOMIC); ++ if (mem == NULL) { ++ error = -ENOMEM; ++ goto out_mptspi_probe; ++ } + +- memset(mem, 0, sz); +- ioc->Target_List[ii] = (struct _MPT_DEVICE *) mem; ++ memset(mem, 0, sz); ++ hd->Targets = (VirtDevice **) mem; + +- dinitprintk((KERN_INFO +- " For Bus=%d, Target_List=%p sz=%d\n", ii, mem, sz)); +- } ++ dprintk((KERN_INFO ++ " Targets @ %p, sz=%d\n", hd->Targets, sz)); + + /* Clear the TM flags + */ + hd->tmPending = 0; + hd->tmState = TM_STATE_NONE; ++ hd->resetPending = 0; + hd->abortSCpnt = NULL; + + /* Clear the pointer used to store +@@ -339,21 +368,16 @@ mptspi_probe(struct pci_dev *pdev, const + */ + hd->cmdPtr = NULL; + +- /* Initialize this IOC's timers ++ /* Initialize this SCSI Hosts' timers + * To use, set the timer expires field +- * and add_timer.Used for internally +- * generated commands. ++ * and add_timer + */ +- init_timer(&hd->InternalCmdTimer); +- hd->InternalCmdTimer.data = (unsigned long) hd; +- hd->InternalCmdTimer.function = mptscsih_InternalCmdTimer_expired; +- +- init_timer(&ioc->TMtimer); +- ioc->TMtimer.data = (unsigned long) ioc; +- ioc->TMtimer.function = mptscsih_TM_timeout; ++ init_timer(&hd->timer); ++ hd->timer.data = (unsigned long) hd; ++ hd->timer.function = mptscsih_timer_expired; + +- ioc->spi_data.Saf_Te = mpt_saf_te; +- hd->mpt_pq_filter = mpt_pq_filter; ++ ioc->spi_data.Saf_Te = mpt_saf_te; ++ hd->mpt_pq_filter = mpt_pq_filter; + + #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION + if (ioc->spi_data.maxBusWidth > mpt_width) +@@ -364,6 +388,7 @@ mptspi_probe(struct pci_dev *pdev, const + ioc->spi_data.maxSyncOffset = 0; + } + ioc->spi_data.mpt_dv = mpt_dv; ++ hd->negoNvram = 0; + + ddvprintk((MYIOC_s_INFO_FMT + "dv %x width %x factor %x saf_te %x mpt_pq_filter %x\n", +@@ -374,7 +399,7 @@ mptspi_probe(struct pci_dev *pdev, const + mpt_saf_te, + mpt_pq_filter)); + #else +- ++ hd->negoNvram = MPT_SCSICFG_USE_NVRAM; + ddvprintk((MYIOC_s_INFO_FMT + "saf_te %x mpt_pq_filter %x\n", + ioc->name, +@@ -387,18 +412,18 @@ mptspi_probe(struct pci_dev *pdev, const + ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS; + else + ioc->spi_data.noQas = 0; +-/* enable domain validation flags */ + + for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) +-ioc->spi_data.dvStatus[ii] = ++ ioc->spi_data.dvStatus[ii] = ++ MPT_SCSICFG_NEGOTIATE; + +-(MPT_SCSICFG_NEGOTIATE | MPT_SCSICFG_DV_NOT_DONE); ++ for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) ++ ioc->spi_data.dvStatus[ii] |= ++ MPT_SCSICFG_DV_NOT_DONE; + + init_waitqueue_head(&hd->scandv_waitq); + hd->scandv_wait_done = 0; + hd->last_queue_full = 0; +- init_waitqueue_head(&hd->TM_waitq); +- hd->TM_wait_done = 0; + + error = scsi_add_host (sh, &ioc->pcidev->dev); + if(error) { +@@ -414,10 +439,6 @@ ioc->spi_data.dvStatus[ii] = + 0, 0, 0, 0, 5 /* 5 second timeout */); + } + +- dnegoprintk((MYIOC_s_WARN_FMT "%s: writeSDP1: ALL_IDS\n", +- ioc->name, __FUNCTION__)); +- mpt_writeSDP1(ioc, 0, 0, MPT_SCSICFG_ALL_IDS); +- + scsi_scan_host(sh); + return 0; + +@@ -464,7 +485,7 @@ mptspi_init(void) + + if (mpt_event_register(mptspiDoneCtx, mptscsih_event_process) == 0) { + devtprintk((KERN_INFO MYNAM +- ": Registered for IOC event notifications mptspiDoneCtx=%08x\n", mptspiDoneCtx)); ++ ": Registered for IOC event notifications\n")); + } + + if (mpt_reset_register(mptspiDoneCtx, mptscsih_ioc_reset) == 0) { diff --git a/lustre/kernel_patches/series/2.6-rhel4.series b/lustre/kernel_patches/series/2.6-rhel4.series index 072df44c0c..8cdcacb5fb 100644 --- a/lustre/kernel_patches/series/2.6-rhel4.series +++ b/lustre/kernel_patches/series/2.6-rhel4.series @@ -38,3 +38,4 @@ quota-umount-race-fix.patch quota-deadlock-on-pagelock-ext3.patch vfs-keep-inode-hashed-for-clear-inode.patch modpost_external_module_updates_rhel4.patch +mpt-fusion-downgrade-to-3_02_73-rhel4.patch -- GitLab