mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 16:54:21 +00:00 
			
		
		
		
	[SCSI] fusion - inactive raid support, and raid event bug fix's
inactive raid support, e.g. exposing hidden raid components belonging to a volume that are inactive. Also misc bug fix's for various raid asyn events. Signed-off-by: Eric Moore <Eric.Moore@lsi.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
		
							parent
							
								
									c6c727a1a0
								
							
						
					
					
						commit
						b506ade9f3
					
				
					 5 changed files with 513 additions and 97 deletions
				
			
		|  | @ -184,6 +184,7 @@ 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_spi_log_info(MPT_ADAPTER *ioc, u32 log_info); | ||||||
| static void	mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info); | static void	mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info); | ||||||
| static int	mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); | static int	mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); | ||||||
|  | static void	mpt_inactive_raid_list_free(MPT_ADAPTER *ioc); | ||||||
| 
 | 
 | ||||||
| /* module entry point */ | /* module entry point */ | ||||||
| static int  __init    fusion_init  (void); | static int  __init    fusion_init  (void); | ||||||
|  | @ -1815,6 +1816,13 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | ||||||
| 	 *	and we try GetLanConfigPages again... | 	 *	and we try GetLanConfigPages again... | ||||||
| 	 */ | 	 */ | ||||||
| 	if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) { | 	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) { | 		if (ioc->bus_type == SAS) { | ||||||
| 
 | 
 | ||||||
| 			/* clear persistency table */ | 			/* clear persistency table */ | ||||||
|  | @ -2021,6 +2029,8 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	kfree(ioc->spi_data.nvram); | 	kfree(ioc->spi_data.nvram); | ||||||
|  | 	mpt_inactive_raid_list_free(ioc); | ||||||
|  | 	kfree(ioc->raid_data.pIocPg2); | ||||||
| 	kfree(ioc->raid_data.pIocPg3); | 	kfree(ioc->raid_data.pIocPg3); | ||||||
| 	ioc->spi_data.nvram = NULL; | 	ioc->spi_data.nvram = NULL; | ||||||
| 	ioc->raid_data.pIocPg3 = NULL; | 	ioc->raid_data.pIocPg3 = NULL; | ||||||
|  | @ -2417,6 +2427,9 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) | ||||||
| 			facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word); | 			facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word); | ||||||
| 
 | 
 | ||||||
| 		facts->ProductID = le16_to_cpu(facts->ProductID); | 		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 = | 		facts->CurrentHostMfaHighAddr = | ||||||
| 				le32_to_cpu(facts->CurrentHostMfaHighAddr); | 				le32_to_cpu(facts->CurrentHostMfaHighAddr); | ||||||
| 		facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits); | 		facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits); | ||||||
|  | @ -2735,9 +2748,7 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag) | ||||||
| 
 | 
 | ||||||
| 	/* RAID FW may take a long time to enable
 | 	/* RAID FW may take a long time to enable
 | ||||||
| 	 */ | 	 */ | ||||||
| 	if (((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) | 	if (ioc->ir_firmware || ioc->bus_type == SAS) { | ||||||
| 	    > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) || |  | ||||||
| 	    (ioc->bus_type == SAS)) { |  | ||||||
| 		rc = mpt_handshake_req_reply_wait(ioc, req_sz, | 		rc = mpt_handshake_req_reply_wait(ioc, req_sz, | ||||||
| 		(u32*)&port_enable, reply_sz, (u16*)&reply_buf, | 		(u32*)&port_enable, reply_sz, (u16*)&reply_buf, | ||||||
| 		300 /*seconds*/, sleepFlag); | 		300 /*seconds*/, sleepFlag); | ||||||
|  | @ -4325,8 +4336,8 @@ mptbase_raid_process_event_data(MPT_ADAPTER *ioc, | ||||||
| 	if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED && | 	if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED && | ||||||
| 	     reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) || | 	     reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) || | ||||||
| 	    (reason == MPI_EVENT_RAID_RC_SMART_DATA)) { | 	    (reason == MPI_EVENT_RAID_RC_SMART_DATA)) { | ||||||
| 		printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d\n", | 		printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d id=%d\n", | ||||||
| 			ioc->name, disk); | 			ioc->name, disk, volume); | ||||||
| 	} else { | 	} else { | ||||||
| 		printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n", | 		printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n", | ||||||
| 			ioc->name, volume); | 			ioc->name, volume); | ||||||
|  | @ -4727,7 +4738,187 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum) | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | /**
 | ||||||
|  |  * 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_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_findImVolumes - Identify IDs of hidden disks and RAID Volumes |  *	mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes | ||||||
|  *	@ioc: Pointer to a Adapter Strucutre |  *	@ioc: Pointer to a Adapter Strucutre | ||||||
|  | @ -4737,21 +4928,27 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum) | ||||||
|  *	0 on success |  *	0 on success | ||||||
|  *	-EFAULT if read of config page header fails or data pointer not NULL |  *	-EFAULT if read of config page header fails or data pointer not NULL | ||||||
|  *	-ENOMEM if pci_alloc failed |  *	-ENOMEM if pci_alloc failed | ||||||
|  */ |  **/ | ||||||
| int | int | ||||||
| mpt_findImVolumes(MPT_ADAPTER *ioc) | mpt_findImVolumes(MPT_ADAPTER *ioc) | ||||||
| { | { | ||||||
| 	IOCPage2_t		*pIoc2; | 	IOCPage2_t		*pIoc2; | ||||||
| 	u8			*mem; | 	u8			*mem; | ||||||
| 	ConfigPageIoc2RaidVol_t	*pIocRv; |  | ||||||
| 	dma_addr_t		 ioc2_dma; | 	dma_addr_t		 ioc2_dma; | ||||||
| 	CONFIGPARMS		 cfg; | 	CONFIGPARMS		 cfg; | ||||||
| 	ConfigPageHeader_t	 header; | 	ConfigPageHeader_t	 header; | ||||||
| 	int			 jj; |  | ||||||
| 	int			 rc = 0; | 	int			 rc = 0; | ||||||
| 	int			 iocpage2sz; | 	int			 iocpage2sz; | ||||||
| 	u8			 nVols, nPhys; | 	int			 i; | ||||||
| 	u8			 vid, vbus, vioc; | 
 | ||||||
|  | 	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); | ||||||
| 
 | 
 | ||||||
| 	/* Read IOCP2 header then the page.
 | 	/* Read IOCP2 header then the page.
 | ||||||
| 	 */ | 	 */ | ||||||
|  | @ -4779,55 +4976,23 @@ mpt_findImVolumes(MPT_ADAPTER *ioc) | ||||||
| 	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | 	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||||||
| 	cfg.physAddr = ioc2_dma; | 	cfg.physAddr = ioc2_dma; | ||||||
| 	if (mpt_config(ioc, &cfg) != 0) | 	if (mpt_config(ioc, &cfg) != 0) | ||||||
| 		goto done_and_free; | 		goto out; | ||||||
|  | 
 | ||||||
|  | 	mem = kmalloc(iocpage2sz, GFP_KERNEL); | ||||||
|  | 	if (!mem) | ||||||
|  | 		goto out; | ||||||
| 
 | 
 | ||||||
| 	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); | 	memcpy(mem, (u8 *)pIoc2, iocpage2sz); | ||||||
|  | 	ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem; | ||||||
| 
 | 
 | ||||||
| 	/* Identify RAID Volume Id's */ | 	mpt_read_ioc_pg_3(ioc); | ||||||
| 	nVols = pIoc2->NumActiveVolumes; |  | ||||||
| 	if ( nVols == 0) { |  | ||||||
| 		/* No RAID Volume.
 |  | ||||||
| 		 */ |  | ||||||
| 		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
 | 	for (i = 0; i < pIoc2->NumActiveVolumes ; i++) | ||||||
| 			 */ | 		mpt_inactive_raid_volumes(ioc, | ||||||
| 			if (vbus == 0) { | 		    pIoc2->RaidVolume[i].VolumeBus, | ||||||
| 				ioc->raid_data.isRaid |= (1 << vid); | 		    pIoc2->RaidVolume[i].VolumeID); | ||||||
| 			} else { |  | ||||||
| 				/* Error! Always bus 0
 |  | ||||||
| 				 */ |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	/* Identify Hidden Physical Disk Id's */ |  out: | ||||||
| 	nPhys = pIoc2->NumActivePhysDisks; |  | ||||||
| 	if (nPhys == 0) { |  | ||||||
| 		/* No physical disks.
 |  | ||||||
| 		 */ |  | ||||||
| 	} else { |  | ||||||
| 		mpt_read_ioc_pg_3(ioc); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| done_and_free: |  | ||||||
| 	pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma); | 	pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma); | ||||||
| 
 | 
 | ||||||
| 	return rc; | 	return rc; | ||||||
|  | @ -4880,7 +5045,7 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc) | ||||||
| 	cfg.physAddr = ioc3_dma; | 	cfg.physAddr = ioc3_dma; | ||||||
| 	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | 	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||||||
| 	if (mpt_config(ioc, &cfg) == 0) { | 	if (mpt_config(ioc, &cfg) == 0) { | ||||||
| 		mem = kmalloc(iocpage3sz, GFP_ATOMIC); | 		mem = kmalloc(iocpage3sz, GFP_KERNEL); | ||||||
| 		if (mem) { | 		if (mem) { | ||||||
| 			memcpy(mem, (u8 *)pIoc3, iocpage3sz); | 			memcpy(mem, (u8 *)pIoc3, iocpage3sz); | ||||||
| 			ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem; | 			ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem; | ||||||
|  | @ -6833,6 +6998,7 @@ EXPORT_SYMBOL(mpt_findImVolumes); | ||||||
| EXPORT_SYMBOL(mpt_alloc_fw_memory); | EXPORT_SYMBOL(mpt_alloc_fw_memory); | ||||||
| EXPORT_SYMBOL(mpt_free_fw_memory); | EXPORT_SYMBOL(mpt_free_fw_memory); | ||||||
| EXPORT_SYMBOL(mptbase_sas_persist_operation); | EXPORT_SYMBOL(mptbase_sas_persist_operation); | ||||||
|  | EXPORT_SYMBOL(mpt_raid_phys_disk_pg0); | ||||||
| 
 | 
 | ||||||
| /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||||||
| /**
 | /**
 | ||||||
|  |  | ||||||
|  | @ -485,10 +485,24 @@ typedef	struct _SasCfgData { | ||||||
| 						 */ | 						 */ | ||||||
| }SasCfgData; | }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 { | typedef	struct _RaidCfgData { | ||||||
| 	IOCPage2_t	*pIocPg2;		/* table of Raid Volumes */ | 	IOCPage2_t	*pIocPg2;		/* table of Raid Volumes */ | ||||||
| 	IOCPage3_t	*pIocPg3;		/* table of physical disks */ | 	IOCPage3_t	*pIocPg3;		/* table of physical disks */ | ||||||
| 	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 */ | ||||||
| }RaidCfgData; | }RaidCfgData; | ||||||
| 
 | 
 | ||||||
| typedef struct _FcCfgData { | typedef struct _FcCfgData { | ||||||
|  | @ -611,6 +625,8 @@ typedef struct _MPT_ADAPTER | ||||||
| 	u8			 persist_reply_frame[MPT_DEFAULT_FRAME_SIZE]; /* persist reply */ | 	u8			 persist_reply_frame[MPT_DEFAULT_FRAME_SIZE]; /* persist reply */ | ||||||
| 	LANPage0_t		 lan_cnfg_page0; | 	LANPage0_t		 lan_cnfg_page0; | ||||||
| 	LANPage1_t		 lan_cnfg_page1; | 	LANPage1_t		 lan_cnfg_page1; | ||||||
|  | 
 | ||||||
|  | 	u8			 ir_firmware; /* =1 if IR firmware detected */ | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * Description: errata_flag_1064 | 	 * Description: errata_flag_1064 | ||||||
| 	 * If a PCIX read occurs within 1 or 2 cycles after the chip receives | 	 * If a PCIX read occurs within 1 or 2 cycles after the chip receives | ||||||
|  | @ -1043,6 +1059,7 @@ extern void	 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size); | ||||||
| extern void	 mpt_free_fw_memory(MPT_ADAPTER *ioc); | extern void	 mpt_free_fw_memory(MPT_ADAPTER *ioc); | ||||||
| extern int	 mpt_findImVolumes(MPT_ADAPTER *ioc); | extern int	 mpt_findImVolumes(MPT_ADAPTER *ioc); | ||||||
| extern int	 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); | extern int	 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); | ||||||
|  | extern int	 mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk); | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  *  Public data decl's... |  *  Public data decl's... | ||||||
|  |  | ||||||
|  | @ -94,12 +94,14 @@ static int	mptsasTaskCtx = -1; | ||||||
| static int	mptsasInternalCtx = -1; /* Used only for internal commands */ | static int	mptsasInternalCtx = -1; /* Used only for internal commands */ | ||||||
| static int	mptsasMgmtCtx = -1; | static int	mptsasMgmtCtx = -1; | ||||||
| 
 | 
 | ||||||
|  | static void mptsas_hotplug_work(struct work_struct *work); | ||||||
| 
 | 
 | ||||||
| enum mptsas_hotplug_action { | enum mptsas_hotplug_action { | ||||||
| 	MPTSAS_ADD_DEVICE, | 	MPTSAS_ADD_DEVICE, | ||||||
| 	MPTSAS_DEL_DEVICE, | 	MPTSAS_DEL_DEVICE, | ||||||
| 	MPTSAS_ADD_RAID, | 	MPTSAS_ADD_RAID, | ||||||
| 	MPTSAS_DEL_RAID, | 	MPTSAS_DEL_RAID, | ||||||
|  | 	MPTSAS_ADD_INACTIVE_VOLUME, | ||||||
| 	MPTSAS_IGNORE_EVENT, | 	MPTSAS_IGNORE_EVENT, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -108,14 +110,15 @@ struct mptsas_hotplug_event { | ||||||
| 	MPT_ADAPTER		*ioc; | 	MPT_ADAPTER		*ioc; | ||||||
| 	enum mptsas_hotplug_action event_type; | 	enum mptsas_hotplug_action event_type; | ||||||
| 	u64			sas_address; | 	u64			sas_address; | ||||||
| 	u32			channel; | 	u8			channel; | ||||||
| 	u32			id; | 	u8			id; | ||||||
| 	u32			device_info; | 	u32			device_info; | ||||||
| 	u16			handle; | 	u16			handle; | ||||||
| 	u16			parent_handle; | 	u16			parent_handle; | ||||||
| 	u8			phy_id; | 	u8			phy_id; | ||||||
| 	u8			phys_disk_num; | 	u8			phys_disk_num_valid;	/* hrc (hidden raid component) */ | ||||||
| 	u8			phys_disk_num_valid; | 	u8			phys_disk_num;		/* hrc - unique index*/ | ||||||
|  | 	u8			hidden_raid_component;	/* hrc - don't expose*/ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct mptsas_discovery_event { | struct mptsas_discovery_event { | ||||||
|  | @ -140,6 +143,7 @@ struct mptsas_devinfo { | ||||||
| 	u8	port_id;	/* sas physical port this device
 | 	u8	port_id;	/* sas physical port this device
 | ||||||
| 				   is assoc'd with */ | 				   is assoc'd with */ | ||||||
| 	u8	id;		/* logical target id of this device */ | 	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 */ | 	u8	channel;	/* logical bus number of this device */ | ||||||
| 	u64	sas_address;    /* WWN of this device,
 | 	u64	sas_address;    /* WWN of this device,
 | ||||||
| 				   SATA is assigned by HBA,expander */ | 				   SATA is assigned by HBA,expander */ | ||||||
|  | @ -711,6 +715,7 @@ mptsas_target_alloc(struct scsi_target *starget) | ||||||
| 						channel, id); | 						channel, id); | ||||||
| 				vtarget->tflags |= | 				vtarget->tflags |= | ||||||
| 				    MPT_TARGET_FLAGS_RAID_COMPONENT; | 				    MPT_TARGET_FLAGS_RAID_COMPONENT; | ||||||
|  | 				p->phy_info[i].attached.phys_disk_num = id; | ||||||
| 			} | 			} | ||||||
| 			mutex_unlock(&hd->ioc->sas_topology_mutex); | 			mutex_unlock(&hd->ioc->sas_topology_mutex); | ||||||
| 			goto out; | 			goto out; | ||||||
|  | @ -1272,6 +1277,7 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, | ||||||
| 	device_info->phy_id = buffer->PhyNum; | 	device_info->phy_id = buffer->PhyNum; | ||||||
| 	device_info->port_id = buffer->PhysicalPort; | 	device_info->port_id = buffer->PhysicalPort; | ||||||
| 	device_info->id = buffer->TargetID; | 	device_info->id = buffer->TargetID; | ||||||
|  | 	device_info->phys_disk_num = ~0; | ||||||
| 	device_info->channel = buffer->Bus; | 	device_info->channel = buffer->Bus; | ||||||
| 	memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64)); | 	memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64)); | ||||||
| 	device_info->sas_address = le64_to_cpu(sas_address); | 	device_info->sas_address = le64_to_cpu(sas_address); | ||||||
|  | @ -1983,6 +1989,8 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc) | ||||||
| 	/*
 | 	/*
 | ||||||
| 	  Reporting RAID volumes. | 	  Reporting RAID volumes. | ||||||
| 	*/ | 	*/ | ||||||
|  | 	if (!ioc->ir_firmware) | ||||||
|  | 		goto out; | ||||||
| 	if (!ioc->raid_data.pIocPg2) | 	if (!ioc->raid_data.pIocPg2) | ||||||
| 		goto out; | 		goto out; | ||||||
| 	if (!ioc->raid_data.pIocPg2->NumActiveVolumes) | 	if (!ioc->raid_data.pIocPg2->NumActiveVolumes) | ||||||
|  | @ -2041,12 +2049,12 @@ mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address) | ||||||
| 	mutex_lock(&ioc->sas_topology_mutex); | 	mutex_lock(&ioc->sas_topology_mutex); | ||||||
| 	list_for_each_entry(port_info, &ioc->sas_topology, list) { | 	list_for_each_entry(port_info, &ioc->sas_topology, list) { | ||||||
| 		for (i = 0; i < port_info->num_phys; i++) { | 		for (i = 0; i < port_info->num_phys; i++) { | ||||||
| 			if (port_info->phy_info[i].attached.sas_address |  | ||||||
| 			    != sas_address) |  | ||||||
| 				continue; |  | ||||||
| 			if (!mptsas_is_end_device( | 			if (!mptsas_is_end_device( | ||||||
| 				&port_info->phy_info[i].attached)) | 				&port_info->phy_info[i].attached)) | ||||||
| 				continue; | 				continue; | ||||||
|  | 			if (port_info->phy_info[i].attached.sas_address | ||||||
|  | 			    != sas_address) | ||||||
|  | 				continue; | ||||||
| 			phy_info = &port_info->phy_info[i]; | 			phy_info = &port_info->phy_info[i]; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  | @ -2056,7 +2064,7 @@ mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static struct mptsas_phyinfo * | static struct mptsas_phyinfo * | ||||||
| mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id) | mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u8 channel, u8 id) | ||||||
| { | { | ||||||
| 	struct mptsas_portinfo *port_info; | 	struct mptsas_portinfo *port_info; | ||||||
| 	struct mptsas_phyinfo *phy_info = NULL; | 	struct mptsas_phyinfo *phy_info = NULL; | ||||||
|  | @ -2065,11 +2073,40 @@ mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id) | ||||||
| 	mutex_lock(&ioc->sas_topology_mutex); | 	mutex_lock(&ioc->sas_topology_mutex); | ||||||
| 	list_for_each_entry(port_info, &ioc->sas_topology, list) { | 	list_for_each_entry(port_info, &ioc->sas_topology, list) { | ||||||
| 		for (i = 0; i < port_info->num_phys; i++) { | 		for (i = 0; i < port_info->num_phys; i++) { | ||||||
| 			if (port_info->phy_info[i].attached.id != id) |  | ||||||
| 				continue; |  | ||||||
| 			if (!mptsas_is_end_device( | 			if (!mptsas_is_end_device( | ||||||
| 				&port_info->phy_info[i].attached)) | 				&port_info->phy_info[i].attached)) | ||||||
| 				continue; | 				continue; | ||||||
|  | 			if (port_info->phy_info[i].attached.id != id) | ||||||
|  | 				continue; | ||||||
|  | 			if (port_info->phy_info[i].attached.channel != channel) | ||||||
|  | 				continue; | ||||||
|  | 			phy_info = &port_info->phy_info[i]; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	mutex_unlock(&ioc->sas_topology_mutex); | ||||||
|  | 	return phy_info; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static struct mptsas_phyinfo * | ||||||
|  | mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id) | ||||||
|  | { | ||||||
|  | 	struct mptsas_portinfo *port_info; | ||||||
|  | 	struct mptsas_phyinfo *phy_info = NULL; | ||||||
|  | 	int i; | ||||||
|  | 
 | ||||||
|  | 	mutex_lock(&ioc->sas_topology_mutex); | ||||||
|  | 	list_for_each_entry(port_info, &ioc->sas_topology, list) { | ||||||
|  | 		for (i = 0; i < port_info->num_phys; i++) { | ||||||
|  | 			if (!mptsas_is_end_device( | ||||||
|  | 				&port_info->phy_info[i].attached)) | ||||||
|  | 				continue; | ||||||
|  | 			if (port_info->phy_info[i].attached.phys_disk_num == ~0) | ||||||
|  | 				continue; | ||||||
|  | 			if (port_info->phy_info[i].attached.phys_disk_num != id) | ||||||
|  | 				continue; | ||||||
|  | 			if (port_info->phy_info[i].attached.channel != channel) | ||||||
|  | 				continue; | ||||||
| 			phy_info = &port_info->phy_info[i]; | 			phy_info = &port_info->phy_info[i]; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  | @ -2105,6 +2142,76 @@ mptsas_reprobe_target(struct scsi_target *starget, int uld_attach) | ||||||
| 			mptsas_reprobe_lun); | 			mptsas_reprobe_lun); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void | ||||||
|  | mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id) | ||||||
|  | { | ||||||
|  | 	CONFIGPARMS			cfg; | ||||||
|  | 	ConfigPageHeader_t		hdr; | ||||||
|  | 	dma_addr_t			dma_handle; | ||||||
|  | 	pRaidVolumePage0_t		buffer = NULL; | ||||||
|  | 	RaidPhysDiskPage0_t 		phys_disk; | ||||||
|  | 	int				i; | ||||||
|  | 	struct mptsas_hotplug_event 	*ev; | ||||||
|  | 
 | ||||||
|  | 	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->VolumeStatus.Flags & | ||||||
|  | 	    MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE)) | ||||||
|  | 		goto out; | ||||||
|  | 
 | ||||||
|  | 	if (!buffer->NumPhysDisks) | ||||||
|  | 		goto out; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < buffer->NumPhysDisks; i++) { | ||||||
|  | 
 | ||||||
|  | 		if (mpt_raid_phys_disk_pg0(ioc, | ||||||
|  | 		    buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		ev = kzalloc(sizeof(*ev), GFP_ATOMIC); | ||||||
|  | 		if (!ev) { | ||||||
|  | 			printk(KERN_WARNING "mptsas: lost hotplug event\n"); | ||||||
|  | 			goto out; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		INIT_WORK(&ev->work, mptsas_hotplug_work); | ||||||
|  | 		ev->ioc = ioc; | ||||||
|  | 		ev->id = phys_disk.PhysDiskID; | ||||||
|  | 		ev->channel = phys_disk.PhysDiskBus; | ||||||
|  | 		ev->phys_disk_num_valid = 1; | ||||||
|  | 		ev->phys_disk_num = phys_disk.PhysDiskNum; | ||||||
|  | 		ev->event_type = MPTSAS_ADD_DEVICE; | ||||||
|  | 		schedule_work(&ev->work); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  |  out: | ||||||
|  | 	if (buffer) | ||||||
|  | 		pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, | ||||||
|  | 		    dma_handle); | ||||||
|  | } | ||||||
| /*
 | /*
 | ||||||
|  * Work queue thread to handle SAS hotplug events |  * Work queue thread to handle SAS hotplug events | ||||||
|  */ |  */ | ||||||
|  | @ -2113,6 +2220,7 @@ mptsas_hotplug_work(struct work_struct *work) | ||||||
| { | { | ||||||
| 	struct mptsas_hotplug_event *ev = | 	struct mptsas_hotplug_event *ev = | ||||||
| 		container_of(work, struct mptsas_hotplug_event, work); | 		container_of(work, struct mptsas_hotplug_event, work); | ||||||
|  | 
 | ||||||
| 	MPT_ADAPTER *ioc = ev->ioc; | 	MPT_ADAPTER *ioc = ev->ioc; | ||||||
| 	struct mptsas_phyinfo *phy_info; | 	struct mptsas_phyinfo *phy_info; | ||||||
| 	struct sas_rphy *rphy; | 	struct sas_rphy *rphy; | ||||||
|  | @ -2125,17 +2233,43 @@ mptsas_hotplug_work(struct work_struct *work) | ||||||
| 	VirtTarget *vtarget; | 	VirtTarget *vtarget; | ||||||
| 	VirtDevice *vdevice; | 	VirtDevice *vdevice; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 	mutex_lock(&ioc->sas_discovery_mutex); | 	mutex_lock(&ioc->sas_discovery_mutex); | ||||||
| 	switch (ev->event_type) { | 	switch (ev->event_type) { | ||||||
| 	case MPTSAS_DEL_DEVICE: | 	case MPTSAS_DEL_DEVICE: | ||||||
| 
 | 
 | ||||||
| 		phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id); | 		phy_info = NULL; | ||||||
|  | 		if (ev->phys_disk_num_valid) { | ||||||
|  | 			if (ev->hidden_raid_component){ | ||||||
|  | 				if (mptsas_sas_device_pg0(ioc, &sas_device, | ||||||
|  | 				    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << | ||||||
|  | 				     MPI_SAS_DEVICE_PGAD_FORM_SHIFT), | ||||||
|  | 				    (ev->channel << 8) + ev->id)) { | ||||||
|  | 					dfailprintk((MYIOC_s_ERR_FMT | ||||||
|  | 					"%s: exit at line=%d\n", ioc->name, | ||||||
|  | 						__FUNCTION__, __LINE__)); | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 				phy_info = mptsas_find_phyinfo_by_sas_address( | ||||||
|  | 				    ioc, sas_device.sas_address); | ||||||
|  | 			}else | ||||||
|  | 				phy_info = mptsas_find_phyinfo_by_phys_disk_num( | ||||||
|  | 				    ioc, ev->channel, ev->phys_disk_num); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (!phy_info) | ||||||
|  | 			phy_info = mptsas_find_phyinfo_by_target(ioc, | ||||||
|  | 			    ev->channel, ev->id); | ||||||
| 
 | 
 | ||||||
| 		/*
 | 		/*
 | ||||||
| 		 * Sanity checks, for non-existing phys and remote rphys. | 		 * Sanity checks, for non-existing phys and remote rphys. | ||||||
| 		 */ | 		 */ | ||||||
| 		if (!phy_info || !phy_info->port_details) { | 		if (!phy_info){ | ||||||
|  | 			dfailprintk((MYIOC_s_ERR_FMT | ||||||
|  | 				"%s: exit at line=%d\n", ioc->name, | ||||||
|  | 				__FUNCTION__, __LINE__)); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		if (!phy_info->port_details) { | ||||||
| 			dfailprintk((MYIOC_s_ERR_FMT | 			dfailprintk((MYIOC_s_ERR_FMT | ||||||
| 				"%s: exit at line=%d\n", ioc->name, | 				"%s: exit at line=%d\n", ioc->name, | ||||||
| 			       	__FUNCTION__, __LINE__)); | 			       	__FUNCTION__, __LINE__)); | ||||||
|  | @ -2148,6 +2282,7 @@ mptsas_hotplug_work(struct work_struct *work) | ||||||
| 			       	__FUNCTION__, __LINE__)); | 			       	__FUNCTION__, __LINE__)); | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		port = mptsas_get_port(phy_info); | 		port = mptsas_get_port(phy_info); | ||||||
| 		if (!port) { | 		if (!port) { | ||||||
| 			dfailprintk((MYIOC_s_ERR_FMT | 			dfailprintk((MYIOC_s_ERR_FMT | ||||||
|  | @ -2170,28 +2305,38 @@ mptsas_hotplug_work(struct work_struct *work) | ||||||
| 			/*
 | 			/*
 | ||||||
| 			 * Handling  RAID components | 			 * Handling  RAID components | ||||||
| 			 */ | 			 */ | ||||||
| 			if (ev->phys_disk_num_valid) { | 			if (ev->phys_disk_num_valid && | ||||||
|  | 			    ev->hidden_raid_component) { | ||||||
|  | 				printk(MYIOC_s_INFO_FMT | ||||||
|  | 				    "RAID Hidding: channel=%d, id=%d, " | ||||||
|  | 				    "physdsk %d \n", ioc->name, ev->channel, | ||||||
|  | 				    ev->id, ev->phys_disk_num); | ||||||
| 				vtarget->id = ev->phys_disk_num; | 				vtarget->id = ev->phys_disk_num; | ||||||
| 				vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; | 				vtarget->tflags |= | ||||||
|  | 				    MPT_TARGET_FLAGS_RAID_COMPONENT; | ||||||
| 				mptsas_reprobe_target(starget, 1); | 				mptsas_reprobe_target(starget, 1); | ||||||
| 				break; | 				phy_info->attached.phys_disk_num = | ||||||
|  | 				    ev->phys_disk_num; | ||||||
|  | 			break; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			vtarget->deleted = 1; | 			vtarget->deleted = 1; | ||||||
| 			mptsas_target_reset(ioc, vtarget); | 			mptsas_target_reset(ioc, vtarget); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) | 		if (phy_info->attached.device_info & | ||||||
|  | 		    MPI_SAS_DEVICE_INFO_SSP_TARGET) | ||||||
| 			ds = "ssp"; | 			ds = "ssp"; | ||||||
| 		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET) | 		if (phy_info->attached.device_info & | ||||||
|  | 		    MPI_SAS_DEVICE_INFO_STP_TARGET) | ||||||
| 			ds = "stp"; | 			ds = "stp"; | ||||||
| 		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE) | 		if (phy_info->attached.device_info & | ||||||
|  | 		    MPI_SAS_DEVICE_INFO_SATA_DEVICE) | ||||||
| 			ds = "sata"; | 			ds = "sata"; | ||||||
| 
 | 
 | ||||||
| 		printk(MYIOC_s_INFO_FMT | 		printk(MYIOC_s_INFO_FMT | ||||||
| 		       "removing %s device, channel %d, id %d, phy %d\n", | 		       "removing %s device, channel %d, id %d, phy %d\n", | ||||||
| 		       ioc->name, ds, ev->channel, ev->id, phy_info->phy_id); | 		       ioc->name, ds, ev->channel, ev->id, phy_info->phy_id); | ||||||
| 
 |  | ||||||
| #ifdef MPT_DEBUG_SAS_WIDE | #ifdef MPT_DEBUG_SAS_WIDE | ||||||
| 		dev_printk(KERN_DEBUG, &port->dev, | 		dev_printk(KERN_DEBUG, &port->dev, | ||||||
| 		    "delete port (%d)\n", port->port_identifier); | 		    "delete port (%d)\n", port->port_identifier); | ||||||
|  | @ -2209,14 +2354,14 @@ mptsas_hotplug_work(struct work_struct *work) | ||||||
| 		 */ | 		 */ | ||||||
| 		if (mptsas_sas_device_pg0(ioc, &sas_device, | 		if (mptsas_sas_device_pg0(ioc, &sas_device, | ||||||
| 		    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << | 		    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << | ||||||
| 		     MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id)) { | 		     MPI_SAS_DEVICE_PGAD_FORM_SHIFT), | ||||||
|  | 			(ev->channel << 8) + ev->id)) { | ||||||
| 				dfailprintk((MYIOC_s_ERR_FMT | 				dfailprintk((MYIOC_s_ERR_FMT | ||||||
| 					"%s: exit at line=%d\n", ioc->name, | 					"%s: exit at line=%d\n", ioc->name, | ||||||
| 					__FUNCTION__, __LINE__)); | 					__FUNCTION__, __LINE__)); | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		ssleep(2); |  | ||||||
| 		__mptsas_discovery_work(ioc); | 		__mptsas_discovery_work(ioc); | ||||||
| 
 | 
 | ||||||
| 		phy_info = mptsas_find_phyinfo_by_sas_address(ioc, | 		phy_info = mptsas_find_phyinfo_by_sas_address(ioc, | ||||||
|  | @ -2230,7 +2375,8 @@ mptsas_hotplug_work(struct work_struct *work) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		starget = mptsas_get_starget(phy_info); | 		starget = mptsas_get_starget(phy_info); | ||||||
| 		if (starget) { | 		if (starget && (!ev->hidden_raid_component)){ | ||||||
|  | 
 | ||||||
| 			vtarget = starget->hostdata; | 			vtarget = starget->hostdata; | ||||||
| 
 | 
 | ||||||
| 			if (!vtarget) { | 			if (!vtarget) { | ||||||
|  | @ -2243,9 +2389,15 @@ mptsas_hotplug_work(struct work_struct *work) | ||||||
| 			 * Handling  RAID components | 			 * Handling  RAID components | ||||||
| 			 */ | 			 */ | ||||||
| 			if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { | 			if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { | ||||||
| 				vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT; | 				printk(MYIOC_s_INFO_FMT | ||||||
|  | 				    "RAID Exposing: channel=%d, id=%d, " | ||||||
|  | 				    "physdsk %d \n", ioc->name, ev->channel, | ||||||
|  | 				    ev->id, ev->phys_disk_num); | ||||||
|  | 				vtarget->tflags &= | ||||||
|  | 				    ~MPT_TARGET_FLAGS_RAID_COMPONENT; | ||||||
| 				vtarget->id = ev->id; | 				vtarget->id = ev->id; | ||||||
| 				mptsas_reprobe_target(starget, 0); | 				mptsas_reprobe_target(starget, 0); | ||||||
|  | 				phy_info->attached.phys_disk_num = ~0; | ||||||
| 			} | 			} | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  | @ -2254,8 +2406,10 @@ mptsas_hotplug_work(struct work_struct *work) | ||||||
| 			dfailprintk((MYIOC_s_ERR_FMT | 			dfailprintk((MYIOC_s_ERR_FMT | ||||||
| 				"%s: exit at line=%d\n", ioc->name, | 				"%s: exit at line=%d\n", ioc->name, | ||||||
| 			       	__FUNCTION__, __LINE__)); | 			       	__FUNCTION__, __LINE__)); | ||||||
|  | 			if (ev->channel) printk("%d\n", __LINE__); | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		port = mptsas_get_port(phy_info); | 		port = mptsas_get_port(phy_info); | ||||||
| 		if (!port) { | 		if (!port) { | ||||||
| 			dfailprintk((MYIOC_s_ERR_FMT | 			dfailprintk((MYIOC_s_ERR_FMT | ||||||
|  | @ -2263,15 +2417,17 @@ mptsas_hotplug_work(struct work_struct *work) | ||||||
| 			       	__FUNCTION__, __LINE__)); | 			       	__FUNCTION__, __LINE__)); | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 		memcpy(&phy_info->attached, &sas_device, | 		memcpy(&phy_info->attached, &sas_device, | ||||||
| 		    sizeof(struct mptsas_devinfo)); | 		    sizeof(struct mptsas_devinfo)); | ||||||
| 
 | 
 | ||||||
| 		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) | 		if (phy_info->attached.device_info & | ||||||
|  | 		    MPI_SAS_DEVICE_INFO_SSP_TARGET) | ||||||
| 			ds = "ssp"; | 			ds = "ssp"; | ||||||
| 		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET) | 		if (phy_info->attached.device_info & | ||||||
|  | 		    MPI_SAS_DEVICE_INFO_STP_TARGET) | ||||||
| 			ds = "stp"; | 			ds = "stp"; | ||||||
| 		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE) | 		if (phy_info->attached.device_info & | ||||||
|  | 		    MPI_SAS_DEVICE_INFO_SATA_DEVICE) | ||||||
| 			ds = "sata"; | 			ds = "sata"; | ||||||
| 
 | 
 | ||||||
| 		printk(MYIOC_s_INFO_FMT | 		printk(MYIOC_s_INFO_FMT | ||||||
|  | @ -2312,19 +2468,23 @@ mptsas_hotplug_work(struct work_struct *work) | ||||||
| 		break; | 		break; | ||||||
| 	case MPTSAS_DEL_RAID: | 	case MPTSAS_DEL_RAID: | ||||||
| 		sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, | 		sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, | ||||||
| 	    	    ev->id, 0); | 		    ev->id, 0); | ||||||
| 		if (!sdev) | 		if (!sdev) | ||||||
| 			break; | 			break; | ||||||
| 		printk(MYIOC_s_INFO_FMT | 		printk(MYIOC_s_INFO_FMT | ||||||
| 		       "removing raid volume, channel %d, id %d\n", | 		       "removing raid volume, channel %d, id %d\n", | ||||||
| 		       ioc->name, MPTSAS_RAID_CHANNEL, ev->id); | 		       ioc->name, MPTSAS_RAID_CHANNEL, ev->id); | ||||||
| 		vdevice = sdev->hostdata; |  | ||||||
| 		vdevice->vtarget->deleted = 1; | 		vdevice->vtarget->deleted = 1; | ||||||
| 		mptsas_target_reset(ioc, vdevice->vtarget); | 		mptsas_target_reset(ioc, vdevice->vtarget); | ||||||
|  | 		vdevice = sdev->hostdata; | ||||||
| 		scsi_remove_device(sdev); | 		scsi_remove_device(sdev); | ||||||
| 		scsi_device_put(sdev); | 		scsi_device_put(sdev); | ||||||
| 		mpt_findImVolumes(ioc); | 		mpt_findImVolumes(ioc); | ||||||
| 		break; | 		break; | ||||||
|  | 	case MPTSAS_ADD_INACTIVE_VOLUME: | ||||||
|  | 		mptsas_adding_inactive_raid_components(ioc, | ||||||
|  | 		    ev->channel, ev->id); | ||||||
|  | 		break; | ||||||
| 	case MPTSAS_IGNORE_EVENT: | 	case MPTSAS_IGNORE_EVENT: | ||||||
| 	default: | 	default: | ||||||
| 		break; | 		break; | ||||||
|  | @ -2332,7 +2492,6 @@ mptsas_hotplug_work(struct work_struct *work) | ||||||
| 
 | 
 | ||||||
| 	mutex_unlock(&ioc->sas_discovery_mutex); | 	mutex_unlock(&ioc->sas_discovery_mutex); | ||||||
| 	kfree(ev); | 	kfree(ev); | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -2386,15 +2545,20 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc, | ||||||
| 		    mptsas_persist_clear_table); | 		    mptsas_persist_clear_table); | ||||||
| 		schedule_work(&ioc->sas_persist_task); | 		schedule_work(&ioc->sas_persist_task); | ||||||
| 		break; | 		break; | ||||||
|  | 	/*
 | ||||||
|  | 	 * TODO, handle other events | ||||||
|  | 	 */ | ||||||
| 	case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: | 	case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: | ||||||
| 	/* TODO */ | 	case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED: | ||||||
| 	case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: | 	case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: | ||||||
| 	/* TODO */ | 	case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL: | ||||||
|  | 	case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL: | ||||||
|  | 	case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL: | ||||||
|  | 	case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL: | ||||||
| 	default: | 	default: | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 |  | ||||||
| static void | static void | ||||||
| mptsas_send_raid_event(MPT_ADAPTER *ioc, | mptsas_send_raid_event(MPT_ADAPTER *ioc, | ||||||
| 		EVENT_DATA_RAID *raid_event_data) | 		EVENT_DATA_RAID *raid_event_data) | ||||||
|  | @ -2415,31 +2579,36 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc, | ||||||
| 	INIT_WORK(&ev->work, mptsas_hotplug_work); | 	INIT_WORK(&ev->work, mptsas_hotplug_work); | ||||||
| 	ev->ioc = ioc; | 	ev->ioc = ioc; | ||||||
| 	ev->id = raid_event_data->VolumeID; | 	ev->id = raid_event_data->VolumeID; | ||||||
|  | 	ev->channel = raid_event_data->VolumeBus; | ||||||
| 	ev->event_type = MPTSAS_IGNORE_EVENT; | 	ev->event_type = MPTSAS_IGNORE_EVENT; | ||||||
| 
 | 
 | ||||||
| 	switch (raid_event_data->ReasonCode) { | 	switch (raid_event_data->ReasonCode) { | ||||||
| 	case MPI_EVENT_RAID_RC_PHYSDISK_DELETED: | 	case MPI_EVENT_RAID_RC_PHYSDISK_DELETED: | ||||||
|  | 		ev->phys_disk_num_valid = 1; | ||||||
|  | 		ev->phys_disk_num = raid_event_data->PhysDiskNum; | ||||||
| 		ev->event_type = MPTSAS_ADD_DEVICE; | 		ev->event_type = MPTSAS_ADD_DEVICE; | ||||||
| 		break; | 		break; | ||||||
| 	case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: | 	case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: | ||||||
| 		ioc->raid_data.isRaid = 1; |  | ||||||
| 		ev->phys_disk_num_valid = 1; | 		ev->phys_disk_num_valid = 1; | ||||||
| 		ev->phys_disk_num = raid_event_data->PhysDiskNum; | 		ev->phys_disk_num = raid_event_data->PhysDiskNum; | ||||||
|  | 		ev->hidden_raid_component = 1; | ||||||
| 		ev->event_type = MPTSAS_DEL_DEVICE; | 		ev->event_type = MPTSAS_DEL_DEVICE; | ||||||
| 		break; | 		break; | ||||||
| 	case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED: | 	case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED: | ||||||
| 		switch (state) { | 		switch (state) { | ||||||
| 		case MPI_PD_STATE_ONLINE: | 		case MPI_PD_STATE_ONLINE: | ||||||
| 			ioc->raid_data.isRaid = 1; | 		case MPI_PD_STATE_NOT_COMPATIBLE: | ||||||
| 			ev->phys_disk_num_valid = 1; | 			ev->phys_disk_num_valid = 1; | ||||||
| 			ev->phys_disk_num = raid_event_data->PhysDiskNum; | 			ev->phys_disk_num = raid_event_data->PhysDiskNum; | ||||||
|  | 			ev->hidden_raid_component = 1; | ||||||
| 			ev->event_type = MPTSAS_ADD_DEVICE; | 			ev->event_type = MPTSAS_ADD_DEVICE; | ||||||
| 			break; | 			break; | ||||||
| 		case MPI_PD_STATE_MISSING: | 		case MPI_PD_STATE_MISSING: | ||||||
| 		case MPI_PD_STATE_NOT_COMPATIBLE: |  | ||||||
| 		case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST: | 		case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST: | ||||||
| 		case MPI_PD_STATE_FAILED_AT_HOST_REQUEST: | 		case MPI_PD_STATE_FAILED_AT_HOST_REQUEST: | ||||||
| 		case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON: | 		case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON: | ||||||
|  | 			ev->phys_disk_num_valid = 1; | ||||||
|  | 			ev->phys_disk_num = raid_event_data->PhysDiskNum; | ||||||
| 			ev->event_type = MPTSAS_DEL_DEVICE; | 			ev->event_type = MPTSAS_DEL_DEVICE; | ||||||
| 			break; | 			break; | ||||||
| 		default: | 		default: | ||||||
|  | @ -2496,6 +2665,35 @@ mptsas_send_discovery_event(MPT_ADAPTER *ioc, | ||||||
| 	schedule_work(&ev->work); | 	schedule_work(&ev->work); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * mptsas_send_ir2_event - handle exposing hidden disk when | ||||||
|  |  * an inactive raid volume is added | ||||||
|  |  * | ||||||
|  |  * @ioc: Pointer to MPT_ADAPTER structure | ||||||
|  |  * @ir2_data | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | 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 = kzalloc(sizeof(*ev), GFP_ATOMIC); | ||||||
|  | 	if (!ev) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	INIT_WORK(&ev->work, mptsas_hotplug_work); | ||||||
|  | 	ev->ioc = ioc; | ||||||
|  | 	ev->id = ir2_data->TargetID; | ||||||
|  | 	ev->channel = ir2_data->Bus; | ||||||
|  | 	ev->event_type = MPTSAS_ADD_INACTIVE_VOLUME; | ||||||
|  | 
 | ||||||
|  | 	schedule_work(&ev->work); | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| static int | static int | ||||||
| mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) | mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) | ||||||
|  | @ -2535,6 +2733,10 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) | ||||||
| 		mptsas_send_discovery_event(ioc, | 		mptsas_send_discovery_event(ioc, | ||||||
| 			(EVENT_DATA_SAS_DISCOVERY *)reply->Data); | 			(EVENT_DATA_SAS_DISCOVERY *)reply->Data); | ||||||
| 		break; | 		break; | ||||||
|  | 	case MPI_EVENT_IR2: | ||||||
|  | 		mptsas_send_ir2_event(ioc, | ||||||
|  | 		    (PTR_MPI_EVENT_DATA_IR2)reply->Data); | ||||||
|  | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		rc = mptscsih_event_process(ioc, reply); | 		rc = mptscsih_event_process(ioc, reply); | ||||||
| 		break; | 		break; | ||||||
|  | @ -2742,7 +2944,7 @@ static void __devexit mptsas_remove(struct pci_dev *pdev) | ||||||
| 	struct mptsas_portinfo *p, *n; | 	struct mptsas_portinfo *p, *n; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	ioc->sas_discovery_ignore_events=1; | 	ioc->sas_discovery_ignore_events = 1; | ||||||
| 	sas_remove_host(ioc->sh); | 	sas_remove_host(ioc->sh); | ||||||
| 
 | 
 | ||||||
| 	mutex_lock(&ioc->sas_topology_mutex); | 	mutex_lock(&ioc->sas_topology_mutex); | ||||||
|  |  | ||||||
|  | @ -2244,6 +2244,7 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, | ||||||
| int | int | ||||||
| mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) | mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) | ||||||
| { | { | ||||||
|  | 	struct inactive_raid_component_info *component_info; | ||||||
| 	int i; | 	int i; | ||||||
| 	int rc = 0; | 	int rc = 0; | ||||||
| 
 | 
 | ||||||
|  | @ -2257,6 +2258,21 @@ mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * 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: |  out: | ||||||
| 	return rc; | 	return rc; | ||||||
| } | } | ||||||
|  | @ -2265,6 +2281,7 @@ EXPORT_SYMBOL(mptscsih_is_phys_disk); | ||||||
| u8 | u8 | ||||||
| mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) | mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) | ||||||
| { | { | ||||||
|  | 	struct inactive_raid_component_info *component_info; | ||||||
| 	int i; | 	int i; | ||||||
| 	int rc = -ENXIO; | 	int rc = -ENXIO; | ||||||
| 
 | 
 | ||||||
|  | @ -2278,6 +2295,21 @@ mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * 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: |  out: | ||||||
| 	return rc; | 	return rc; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1363,8 +1363,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * If RAID Firmware Detected, setup virtual channel | 	 * If RAID Firmware Detected, setup virtual channel | ||||||
| 	 */ | 	 */ | ||||||
| 	if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) | 	if (ioc->ir_firmware) | ||||||
| 	    > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) |  | ||||||
| 		sh->max_channel = 1; | 		sh->max_channel = 1; | ||||||
| 	else | 	else | ||||||
| 		sh->max_channel = 0; | 		sh->max_channel = 0; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Eric Moore
						Eric Moore