Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a7938b0b authored by Kashyap, Desai's avatar Kashyap, Desai Committed by James Bottomley
Browse files

[SCSI] mpt fusion: RAID device handling and Dual port Raid support is added



1. Handle integrated Raid device(Add/Delete) and error condition and check
   related to Raid device. is_logical_volume will represent logical volume
   device.
2. Raid device dual port support is added. Main functions to support this
   feature are mpt_raid_phys_disk_get_num_paths and mpt_raid_phys_disk_pg1.

Signed-off-by: default avatarKashyap Desai <kadesai@lsi.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 71278192
Loading
Loading
Loading
Loading
+167 −0
Original line number Diff line number Diff line
@@ -5762,6 +5762,161 @@ mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num,
	return rc;
}

/**
 *	mpt_raid_phys_disk_get_num_paths - returns number paths associated to this phys_num
 *	@ioc: Pointer to a Adapter Structure
 *	@phys_disk_num: io unit unique phys disk num generated by the ioc
 *
 *	Return:
 *	returns number paths
 **/
int
mpt_raid_phys_disk_get_num_paths(MPT_ADAPTER *ioc, u8 phys_disk_num)
{
	CONFIGPARMS		 	cfg;
	ConfigPageHeader_t	 	hdr;
	dma_addr_t			dma_handle;
	pRaidPhysDiskPage1_t		buffer = NULL;
	int				rc;

	memset(&cfg, 0 , sizeof(CONFIGPARMS));
	memset(&hdr, 0 , sizeof(ConfigPageHeader_t));

	hdr.PageVersion = MPI_RAIDPHYSDISKPAGE1_PAGEVERSION;
	hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
	hdr.PageNumber = 1;
	cfg.cfghdr.hdr = &hdr;
	cfg.physAddr = -1;
	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;

	if (mpt_config(ioc, &cfg) != 0) {
		rc = 0;
		goto out;
	}

	if (!hdr.PageLength) {
		rc = 0;
		goto out;
	}

	buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
	    &dma_handle);

	if (!buffer) {
		rc = 0;
		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 = 0;
		goto out;
	}

	rc = buffer->NumPhysDiskPaths;
 out:

	if (buffer)
		pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
		    dma_handle);

	return rc;
}
EXPORT_SYMBOL(mpt_raid_phys_disk_get_num_paths);

/**
 *	mpt_raid_phys_disk_pg1 - returns phys disk page 1
 *	@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_pg1(MPT_ADAPTER *ioc, u8 phys_disk_num,
		RaidPhysDiskPage1_t *phys_disk)
{
	CONFIGPARMS		 	cfg;
	ConfigPageHeader_t	 	hdr;
	dma_addr_t			dma_handle;
	pRaidPhysDiskPage1_t		buffer = NULL;
	int				rc;
	int				i;
	__le64				sas_address;

	memset(&cfg, 0 , sizeof(CONFIGPARMS));
	memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
	rc = 0;

	hdr.PageVersion = MPI_RAIDPHYSDISKPAGE1_PAGEVERSION;
	hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
	hdr.PageNumber = 1;
	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;
	}

	phys_disk->NumPhysDiskPaths = buffer->NumPhysDiskPaths;
	phys_disk->PhysDiskNum = phys_disk_num;
	for (i = 0; i < phys_disk->NumPhysDiskPaths; i++) {
		phys_disk->Path[i].PhysDiskID = buffer->Path[i].PhysDiskID;
		phys_disk->Path[i].PhysDiskBus = buffer->Path[i].PhysDiskBus;
		phys_disk->Path[i].OwnerIdentifier =
				buffer->Path[i].OwnerIdentifier;
		phys_disk->Path[i].Flags = le16_to_cpu(buffer->Path[i].Flags);
		memcpy(&sas_address, &buffer->Path[i].WWID, sizeof(__le64));
		sas_address = le64_to_cpu(sas_address);
		memcpy(&phys_disk->Path[i].WWID, &sas_address, sizeof(__le64));
		memcpy(&sas_address,
				&buffer->Path[i].OwnerWWID, sizeof(__le64));
		sas_address = le64_to_cpu(sas_address);
		memcpy(&phys_disk->Path[i].OwnerWWID,
				&sas_address, sizeof(__le64));
	}

 out:

	if (buffer)
		pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
		    dma_handle);

	return rc;
}
EXPORT_SYMBOL(mpt_raid_phys_disk_pg1);


/**
 *	mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
 *	@ioc: Pointer to a Adapter Strucutre
@@ -7170,6 +7325,18 @@ mpt_display_event_info(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply)
			    "id=%d channel=%d phys_num=%d",
			    id, channel, phys_num);
			break;
		case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED:
			snprintf(evStr, EVENT_DESCR_STR_SZ,
			    "IR2: Dual Port Added: "
			    "id=%d channel=%d phys_num=%d",
			    id, channel, phys_num);
			break;
		case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED:
			snprintf(evStr, EVENT_DESCR_STR_SZ,
			    "IR2: Dual Port Removed: "
			    "id=%d channel=%d phys_num=%d",
			    id, channel, phys_num);
			break;
		default:
			ds = "IR2";
		break;
+4 −0
Original line number Diff line number Diff line
@@ -958,6 +958,10 @@ extern void mpt_free_fw_memory(MPT_ADAPTER *ioc);
extern int	 mpt_findImVolumes(MPT_ADAPTER *ioc);
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);
extern int	mpt_raid_phys_disk_pg1(MPT_ADAPTER *ioc, u8 phys_disk_num,
		pRaidPhysDiskPage1_t phys_disk);
extern int	mpt_raid_phys_disk_get_num_paths(MPT_ADAPTER *ioc,
		u8 phys_disk_num);
extern int	 mpt_set_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc);
extern void	 mpt_clear_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc);
extern void     mpt_halt_firmware(MPT_ADAPTER *ioc);
+272 −60
Original line number Diff line number Diff line
@@ -121,6 +121,7 @@ static void mptsas_expander_delete(MPT_ADAPTER *ioc,
static void mptsas_send_expander_event(struct fw_event_work *fw_event);
static void mptsas_not_responding_devices(MPT_ADAPTER *ioc);
static void mptsas_scan_sas_topology(MPT_ADAPTER *ioc);
static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id);

static void mptsas_print_phy_data(MPT_ADAPTER *ioc,
					MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
@@ -542,7 +543,8 @@ mptsas_add_device_component(MPT_ADAPTER *ioc, u8 channel, u8 id,
	mutex_lock(&ioc->sas_device_info_mutex);
	list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
	    list) {
		if ((sas_info->sas_address == sas_address ||
		if (!sas_info->is_logical_volume &&
		    (sas_info->sas_address == sas_address ||
		    (sas_info->fw.channel == channel &&
		     sas_info->fw.id == id))) {
			list_del(&sas_info->list);
@@ -616,6 +618,100 @@ mptsas_add_device_component_by_fw(MPT_ADAPTER *ioc, u8 channel, u8 id)
	    sas_device.slot, enclosure_info.enclosure_logical_id);
}

/**
 *	mptsas_add_device_component_starget_ir - Handle Integrated RAID, adding
 *	each individual device to list
 *	@ioc: Pointer to MPT_ADAPTER structure
 *	@channel: fw mapped id's
 *	@id:
 *
 **/
static void
mptsas_add_device_component_starget_ir(MPT_ADAPTER *ioc,
		struct scsi_target *starget)
{
	CONFIGPARMS			cfg;
	ConfigPageHeader_t		hdr;
	dma_addr_t			dma_handle;
	pRaidVolumePage0_t		buffer = NULL;
	int				i;
	RaidPhysDiskPage0_t 		phys_disk;
	struct mptsas_device_info	*sas_info, *next;

	memset(&cfg, 0 , sizeof(CONFIGPARMS));
	memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
	hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
	/* assumption that all volumes on channel = 0 */
	cfg.pageAddr = starget->id;
	cfg.cfghdr.hdr = &hdr;
	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
	cfg.timeout = 10;

	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_by_fw(ioc, phys_disk.PhysDiskBus,
		    phys_disk.PhysDiskID);

	}

	/*
	 * Delete all matching devices out of the list
	 */
	mutex_lock(&ioc->sas_device_info_mutex);
	list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
	    list) {
		if (sas_info->is_logical_volume && sas_info->fw.id ==
		    starget->id) {
			list_del(&sas_info->list);
			kfree(sas_info);
		}
	}

	sas_info = kzalloc(sizeof(struct mptsas_device_info), GFP_KERNEL);
	if (sas_info) {
		sas_info->fw.id = starget->id;
		sas_info->os.id = starget->id;
		sas_info->os.channel = starget->channel;
		sas_info->is_logical_volume = 1;
		INIT_LIST_HEAD(&sas_info->list);
		list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
	}
	mutex_unlock(&ioc->sas_device_info_mutex);

 out:
	if (buffer)
		pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
		    dma_handle);
}

/**
 *	mptsas_add_device_component_starget -
 *	@ioc: Pointer to MPT_ADAPTER structure
@@ -817,6 +913,10 @@ mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
		if ((vdevice == NULL) ||
			(vdevice->vtarget == NULL))
			continue;
		if ((vdevice->vtarget->tflags &
		    MPT_TARGET_FLAGS_RAID_COMPONENT ||
		    vdevice->vtarget->raidVolume))
			continue;
		if (vdevice->vtarget->id == id &&
			vdevice->vtarget->channel == channel)
			vtarget = vdevice->vtarget;
@@ -1487,9 +1587,21 @@ mptsas_slave_configure(struct scsi_device *sdev)
	struct Scsi_Host	*host = sdev->host;
	MPT_SCSI_HOST	*hd = shost_priv(host);
	MPT_ADAPTER	*ioc = hd->ioc;
	VirtDevice	*vdevice = sdev->hostdata;

	if (sdev->channel == MPTSAS_RAID_CHANNEL)
	if (vdevice->vtarget->deleted) {
		sdev_printk(KERN_INFO, sdev, "clearing deleted flag\n");
		vdevice->vtarget->deleted = 0;
	}

	/*
	 * RAID volumes placed beyond the last expected port.
	 * Ignore sending sas mode pages in that case..
	 */
	if (sdev->channel == MPTSAS_RAID_CHANNEL) {
		mptsas_add_device_component_starget_ir(ioc, scsi_target(sdev));
		goto out;
	}

	sas_read_port_mode_page(sdev);

@@ -1525,9 +1637,18 @@ mptsas_target_alloc(struct scsi_target *starget)
	 * RAID volumes placed beyond the last expected port.
	 */
	if (starget->channel == MPTSAS_RAID_CHANNEL) {
		for (i=0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
			if (id == ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID)
				channel = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus;
		if (!ioc->raid_data.pIocPg2) {
			kfree(vtarget);
			return -ENXIO;
		}
		for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
			if (id == ioc->raid_data.pIocPg2->
					RaidVolume[i].VolumeID) {
				channel = ioc->raid_data.pIocPg2->
					RaidVolume[i].VolumeBus;
			}
		}
		vtarget->raidVolume = 1;
		goto out;
	}

@@ -3277,6 +3398,7 @@ mptsas_not_responding_devices(MPT_ADAPTER *ioc)
	mutex_lock(&ioc->sas_device_info_mutex);
 redo_device_scan:
	list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) {
		if (!sas_info->is_logical_volume) {
			sas_device.handle = 0;
			retry_count = 0;
retry_page:
@@ -3297,7 +3419,8 @@ retry_page:
					ioc->name, __func__));
					spin_unlock_irqrestore
					(&ioc->taskmgmt_lock, flags);
				mutex_unlock(&ioc->sas_device_info_mutex);
					mutex_unlock(&ioc->
					sas_device_info_mutex);
					return;
				}
				spin_unlock_irqrestore(&ioc->taskmgmt_lock,
@@ -3320,16 +3443,21 @@ retry_page:
			/* delete device */
			vtarget = mptsas_find_vtarget(ioc,
				sas_info->fw.channel, sas_info->fw.id);

			if (vtarget)
				vtarget->deleted = 1;

			phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
					sas_info->sas_address);

			if (phy_info) {
				mptsas_del_end_device(ioc, phy_info);
				goto redo_device_scan;
			}
		} else
			mptsas_volume_delete(ioc, sas_info->fw.id);
	}
	mutex_unlock(&ioc->sas_device_info_mutex);
	mutex_lock(&ioc->sas_device_info_mutex);

	/* expanders */
	mutex_lock(&ioc->sas_topology_mutex);
@@ -3508,28 +3636,74 @@ mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
	return phy_info;
}


/**
 *	mptsas_find_phyinfo_by_phys_disk_num -
 *	@ioc: Pointer to MPT_ADAPTER structure
 *	@phys_disk_num:
 *	@channel:
 *	@id:
 *
 **/
static struct mptsas_phyinfo *
mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 phys_disk_num,
	u8 channel, u8 id)
{
	struct mptsas_portinfo *port_info;
	struct mptsas_phyinfo *phy_info = NULL;
	struct mptsas_portinfo *port_info;
	RaidPhysDiskPage1_t *phys_disk = NULL;
	int num_paths;
	u64 sas_address = 0;
	int i;

	phy_info = NULL;
	if (!ioc->raid_data.pIocPg3)
		return NULL;
	/* dual port support */
	num_paths = mpt_raid_phys_disk_get_num_paths(ioc, phys_disk_num);
	if (!num_paths)
		goto out;
	phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) +
	   (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
	if (!phys_disk)
		goto out;
	mpt_raid_phys_disk_pg1(ioc, phys_disk_num, phys_disk);
	for (i = 0; i < num_paths; i++) {
		if ((phys_disk->Path[i].Flags & 1) != 0)
			/* entry no longer valid */
			continue;
		if ((id == phys_disk->Path[i].PhysDiskID) &&
		    (channel == phys_disk->Path[i].PhysDiskBus)) {
			memcpy(&sas_address, &phys_disk->Path[i].WWID,
				sizeof(u64));
			phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
					sas_address);
			goto out;
		}
	}

 out:
	kfree(phys_disk);
	if (phy_info)
		return phy_info;

	/*
	 * Extra code to handle RAID0 case, where the sas_address is not updated
	 * in phys_disk_page_1 when hotswapped
	 */
	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++) {
		for (i = 0; i < port_info->num_phys && !phy_info; 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;
			if ((port_info->phy_info[i].attached.phys_disk_num ==
			    phys_disk_num) &&
			    (port_info->phy_info[i].attached.id == id) &&
			    (port_info->phy_info[i].attached.channel ==
			     channel))
				phy_info = &port_info->phy_info[i];
			break;
		}
	}
	mutex_unlock(&ioc->sas_topology_mutex);
@@ -3683,8 +3857,9 @@ mptsas_hotplug_work(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
		mpt_findImVolumes(ioc);

		phy_info = mptsas_find_phyinfo_by_phys_disk_num(
				ioc, hot_plug_info->channel,
				hot_plug_info->phys_disk_num);
				ioc, hot_plug_info->phys_disk_num,
				hot_plug_info->channel,
				hot_plug_info->id);
		mptsas_del_end_device(ioc, phy_info);
		break;

@@ -4032,6 +4207,7 @@ mptsas_send_ir2_event(struct fw_event_work *fw_event)
	struct mptsas_hotplug_event hot_plug_info;
	MPI_EVENT_DATA_IR2	*ir2_data;
	u8 reasonCode;
	RaidPhysDiskPage0_t phys_disk;

	ioc = fw_event->ioc;
	ir2_data = (MPI_EVENT_DATA_IR2 *)fw_event->event_data;
@@ -4047,6 +4223,17 @@ mptsas_send_ir2_event(struct fw_event_work *fw_event)
	case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
		hot_plug_info.event_type = MPTSAS_ADD_INACTIVE_VOLUME;
		break;
	case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED:
		hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum;
		hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK;
		break;
	case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED:
		hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum;
		mpt_raid_phys_disk_pg0(ioc,
		    ir2_data->PhysDiskNum, &phys_disk);
		hot_plug_info.id = phys_disk.PhysDiskID;
		hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK;
		break;
	default:
		mptsas_free_fw_event(ioc, fw_event);
		return;
@@ -4132,6 +4319,31 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
	return 0;
}

/* Delete a volume when no longer listed in ioc pg2
 */
static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id)
{
	struct scsi_device *sdev;
	int i;

	sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, id, 0);
	if (!sdev)
		return;
	if (!ioc->raid_data.pIocPg2)
		goto out;
	if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
		goto out;
	for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
		if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id)
			goto release_sdev;
 out:
	printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, "
	    "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL, id);
	scsi_remove_device(sdev);
 release_sdev:
	scsi_device_put(sdev);
}

static int
mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
+1 −0
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ struct mptsas_device_info {
	u32			device_info; /* specific bits for devices */
	u16			slot;		/* enclosure slot id */
	u64			enclosure_logical_id; /*enclosure address */
	u8			is_logical_volume; /* is this logical volume */
};

struct mptsas_hotplug_event {
+83 −2
Original line number Diff line number Diff line
@@ -2087,8 +2087,10 @@ int
mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
{
	struct inactive_raid_component_info *component_info;
	int i;
	int i, j;
	RaidPhysDiskPage1_t *phys_disk;
	int rc = 0;
	int num_paths;

	if (!ioc->raid_data.pIocPg3)
		goto out;
@@ -2100,6 +2102,45 @@ mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
		}
	}

	if (ioc->bus_type != SAS)
		goto out;

	/*
	 * Check if dual path
	 */
	for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
		num_paths = mpt_raid_phys_disk_get_num_paths(ioc,
		    ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum);
		if (num_paths < 2)
			continue;
		phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) +
		   (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
		if (!phys_disk)
			continue;
		if ((mpt_raid_phys_disk_pg1(ioc,
		    ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum,
		    phys_disk))) {
			kfree(phys_disk);
			continue;
		}
		for (j = 0; j < num_paths; j++) {
			if ((phys_disk->Path[j].Flags &
			    MPI_RAID_PHYSDISK1_FLAG_INVALID))
				continue;
			if ((phys_disk->Path[j].Flags &
			    MPI_RAID_PHYSDISK1_FLAG_BROKEN))
				continue;
			if ((id == phys_disk->Path[j].PhysDiskID) &&
			    (channel == phys_disk->Path[j].PhysDiskBus)) {
				rc = 1;
				kfree(phys_disk);
				goto out;
			}
		}
		kfree(phys_disk);
	}


	/*
	 * Check inactive list for matching phys disks
	 */
@@ -2124,8 +2165,10 @@ u8
mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
{
	struct inactive_raid_component_info *component_info;
	int i;
	int i, j;
	RaidPhysDiskPage1_t *phys_disk;
	int rc = -ENXIO;
	int num_paths;

	if (!ioc->raid_data.pIocPg3)
		goto out;
@@ -2137,6 +2180,44 @@ mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
		}
	}

	if (ioc->bus_type != SAS)
		goto out;

	/*
	 * Check if dual path
	 */
	for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
		num_paths = mpt_raid_phys_disk_get_num_paths(ioc,
		    ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum);
		if (num_paths < 2)
			continue;
		phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) +
		   (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
		if (!phys_disk)
			continue;
		if ((mpt_raid_phys_disk_pg1(ioc,
		    ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum,
		    phys_disk))) {
			kfree(phys_disk);
			continue;
		}
		for (j = 0; j < num_paths; j++) {
			if ((phys_disk->Path[j].Flags &
			    MPI_RAID_PHYSDISK1_FLAG_INVALID))
				continue;
			if ((phys_disk->Path[j].Flags &
			    MPI_RAID_PHYSDISK1_FLAG_BROKEN))
				continue;
			if ((id == phys_disk->Path[j].PhysDiskID) &&
			    (channel == phys_disk->Path[j].PhysDiskBus)) {
				rc = phys_disk->PhysDiskNum;
				kfree(phys_disk);
				goto out;
			}
		}
		kfree(phys_disk);
	}

	/*
	 * Check inactive list for matching phys disks
	 */