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

[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
......@@ -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;
......
......@@ -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);
......
This diff is collapsed.
......@@ -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 {
......
......@@ -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
*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment