[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: Kashyap Desai <kadesai@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
This commit is contained in:
Kashyap, Desai 2009-05-29 16:53:56 +05:30 committed by James Bottomley
parent 71278192a8
commit a7938b0bb3
5 changed files with 527 additions and 62 deletions

View File

@ -5762,6 +5762,161 @@ mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num,
return rc; 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 * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
* @ioc: Pointer to a Adapter Strucutre * @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=%d channel=%d phys_num=%d",
id, channel, phys_num); id, channel, phys_num);
break; 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: default:
ds = "IR2"; ds = "IR2";
break; break;

View File

@ -958,6 +958,10 @@ 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); 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 int mpt_set_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc);
extern void mpt_clear_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); extern void mpt_halt_firmware(MPT_ADAPTER *ioc);

View File

@ -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_send_expander_event(struct fw_event_work *fw_event);
static void mptsas_not_responding_devices(MPT_ADAPTER *ioc); static void mptsas_not_responding_devices(MPT_ADAPTER *ioc);
static void mptsas_scan_sas_topology(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, static void mptsas_print_phy_data(MPT_ADAPTER *ioc,
MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
@ -542,9 +543,10 @@ mptsas_add_device_component(MPT_ADAPTER *ioc, u8 channel, u8 id,
mutex_lock(&ioc->sas_device_info_mutex); mutex_lock(&ioc->sas_device_info_mutex);
list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list, list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
list) { list) {
if ((sas_info->sas_address == sas_address || if (!sas_info->is_logical_volume &&
(sas_info->fw.channel == channel && (sas_info->sas_address == sas_address ||
sas_info->fw.id == id))) { (sas_info->fw.channel == channel &&
sas_info->fw.id == id))) {
list_del(&sas_info->list); list_del(&sas_info->list);
kfree(sas_info); kfree(sas_info);
} }
@ -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); 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 - * mptsas_add_device_component_starget -
* @ioc: Pointer to MPT_ADAPTER structure * @ioc: Pointer to MPT_ADAPTER structure
@ -817,6 +913,10 @@ mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
if ((vdevice == NULL) || if ((vdevice == NULL) ||
(vdevice->vtarget == NULL)) (vdevice->vtarget == NULL))
continue; continue;
if ((vdevice->vtarget->tflags &
MPT_TARGET_FLAGS_RAID_COMPONENT ||
vdevice->vtarget->raidVolume))
continue;
if (vdevice->vtarget->id == id && if (vdevice->vtarget->id == id &&
vdevice->vtarget->channel == channel) vdevice->vtarget->channel == channel)
vtarget = vdevice->vtarget; vtarget = vdevice->vtarget;
@ -1487,9 +1587,21 @@ mptsas_slave_configure(struct scsi_device *sdev)
struct Scsi_Host *host = sdev->host; struct Scsi_Host *host = sdev->host;
MPT_SCSI_HOST *hd = shost_priv(host); MPT_SCSI_HOST *hd = shost_priv(host);
MPT_ADAPTER *ioc = hd->ioc; 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; goto out;
}
sas_read_port_mode_page(sdev); 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. * RAID volumes placed beyond the last expected port.
*/ */
if (starget->channel == MPTSAS_RAID_CHANNEL) { if (starget->channel == MPTSAS_RAID_CHANNEL) {
for (i=0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) if (!ioc->raid_data.pIocPg2) {
if (id == ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID) kfree(vtarget);
channel = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus; 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; goto out;
} }
@ -3277,59 +3398,66 @@ mptsas_not_responding_devices(MPT_ADAPTER *ioc)
mutex_lock(&ioc->sas_device_info_mutex); mutex_lock(&ioc->sas_device_info_mutex);
redo_device_scan: redo_device_scan:
list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) { list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) {
sas_device.handle = 0; if (!sas_info->is_logical_volume) {
retry_count = 0; sas_device.handle = 0;
retry_count = 0;
retry_page: retry_page:
retval = mptsas_sas_device_pg0(ioc, &sas_device, retval = 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), << MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
(sas_info->fw.channel << 8) + (sas_info->fw.channel << 8) +
sas_info->fw.id); sas_info->fw.id);
if (sas_device.handle) if (sas_device.handle)
continue; continue;
if (retval == -EBUSY) { if (retval == -EBUSY) {
spin_lock_irqsave(&ioc->taskmgmt_lock, flags); spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
if (ioc->ioc_reset_in_progress) { if (ioc->ioc_reset_in_progress) {
dfailprintk(ioc, dfailprintk(ioc,
printk(MYIOC_s_DEBUG_FMT printk(MYIOC_s_DEBUG_FMT
"%s: exiting due to reset\n", "%s: exiting due to reset\n",
ioc->name, __func__)); ioc->name, __func__));
spin_unlock_irqrestore spin_unlock_irqrestore
(&ioc->taskmgmt_lock, flags); (&ioc->taskmgmt_lock, flags);
mutex_unlock(&ioc->sas_device_info_mutex); mutex_unlock(&ioc->
return; sas_device_info_mutex);
return;
}
spin_unlock_irqrestore(&ioc->taskmgmt_lock,
flags);
} }
spin_unlock_irqrestore(&ioc->taskmgmt_lock,
flags);
}
if (retval && (retval != -ENODEV)) { if (retval && (retval != -ENODEV)) {
if (retry_count < 10) { if (retry_count < 10) {
retry_count++; retry_count++;
goto retry_page; goto retry_page;
} else { } else {
devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
"%s: Config page retry exceeded retry " "%s: Config page retry exceeded retry "
"count deleting device 0x%llx\n", "count deleting device 0x%llx\n",
ioc->name, __func__, ioc->name, __func__,
sas_info->sas_address)); sas_info->sas_address));
}
} }
}
/* delete device */ /* delete device */
vtarget = mptsas_find_vtarget(ioc, vtarget = mptsas_find_vtarget(ioc,
sas_info->fw.channel, sas_info->fw.id); sas_info->fw.channel, sas_info->fw.id);
if (vtarget)
vtarget->deleted = 1; if (vtarget)
phy_info = mptsas_find_phyinfo_by_sas_address(ioc, vtarget->deleted = 1;
sas_info->sas_address);
if (phy_info) { phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
mptsas_del_end_device(ioc, phy_info); sas_info->sas_address);
goto redo_device_scan;
} 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 */ /* expanders */
mutex_lock(&ioc->sas_topology_mutex); 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; 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 * 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_phyinfo *phy_info = NULL;
struct mptsas_portinfo *port_info;
RaidPhysDiskPage1_t *phys_disk = NULL;
int num_paths;
u64 sas_address = 0;
int i; 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); 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 && !phy_info; i++) {
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.phys_disk_num == ~0) if (port_info->phy_info[i].attached.phys_disk_num == ~0)
continue; continue;
if (port_info->phy_info[i].attached.phys_disk_num != id) if ((port_info->phy_info[i].attached.phys_disk_num ==
continue; phys_disk_num) &&
if (port_info->phy_info[i].attached.channel != channel) (port_info->phy_info[i].attached.id == id) &&
continue; (port_info->phy_info[i].attached.channel ==
phy_info = &port_info->phy_info[i]; channel))
break; phy_info = &port_info->phy_info[i];
} }
} }
mutex_unlock(&ioc->sas_topology_mutex); 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); mpt_findImVolumes(ioc);
phy_info = mptsas_find_phyinfo_by_phys_disk_num( phy_info = mptsas_find_phyinfo_by_phys_disk_num(
ioc, hot_plug_info->channel, ioc, hot_plug_info->phys_disk_num,
hot_plug_info->phys_disk_num); hot_plug_info->channel,
hot_plug_info->id);
mptsas_del_end_device(ioc, phy_info); mptsas_del_end_device(ioc, phy_info);
break; break;
@ -4032,6 +4207,7 @@ mptsas_send_ir2_event(struct fw_event_work *fw_event)
struct mptsas_hotplug_event hot_plug_info; struct mptsas_hotplug_event hot_plug_info;
MPI_EVENT_DATA_IR2 *ir2_data; MPI_EVENT_DATA_IR2 *ir2_data;
u8 reasonCode; u8 reasonCode;
RaidPhysDiskPage0_t phys_disk;
ioc = fw_event->ioc; ioc = fw_event->ioc;
ir2_data = (MPI_EVENT_DATA_IR2 *)fw_event->event_data; 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: case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
hot_plug_info.event_type = MPTSAS_ADD_INACTIVE_VOLUME; hot_plug_info.event_type = MPTSAS_ADD_INACTIVE_VOLUME;
break; 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: default:
mptsas_free_fw_event(ioc, fw_event); mptsas_free_fw_event(ioc, fw_event);
return; return;
@ -4132,6 +4319,31 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
return 0; 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 static int
mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{ {

View File

@ -82,6 +82,7 @@ struct mptsas_device_info {
u32 device_info; /* specific bits for devices */ u32 device_info; /* specific bits for devices */
u16 slot; /* enclosure slot id */ u16 slot; /* enclosure slot id */
u64 enclosure_logical_id; /*enclosure address */ u64 enclosure_logical_id; /*enclosure address */
u8 is_logical_volume; /* is this logical volume */
}; };
struct mptsas_hotplug_event { struct mptsas_hotplug_event {

View File

@ -2087,8 +2087,10 @@ 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; struct inactive_raid_component_info *component_info;
int i; int i, j;
RaidPhysDiskPage1_t *phys_disk;
int rc = 0; int rc = 0;
int num_paths;
if (!ioc->raid_data.pIocPg3) if (!ioc->raid_data.pIocPg3)
goto out; 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 * Check inactive list for matching phys disks
*/ */
@ -2124,8 +2165,10 @@ 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; struct inactive_raid_component_info *component_info;
int i; int i, j;
RaidPhysDiskPage1_t *phys_disk;
int rc = -ENXIO; int rc = -ENXIO;
int num_paths;
if (!ioc->raid_data.pIocPg3) if (!ioc->raid_data.pIocPg3)
goto out; 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 * Check inactive list for matching phys disks
*/ */