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;iiResponseInfo);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; iraid_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 - -#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 -#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; (iiraid_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;iiResponseInfo);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; (iiraid_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; iraid_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; jNumPhysDisks; 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;iioc->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; iraid_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 + +#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 +#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; iireq_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; iiname); } @@ -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; countname, 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<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<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;iinumPhys;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; ireq_sz/4; \ - u32 *m = (u32 *)(mfp); \ - for (i=0; ireq_sz/4; - u32 *m = (u32 *)(mfp); \ - for (i=0; ireply_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 #include #include +#if defined(CPQ_CIM) +#include "csmisas.h" +#endif // CPQ_CIM #include #include @@ -67,16 +70,11 @@ #include #include -#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 #include -#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; iiCDBLength; 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<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) {