|
@@ -104,6 +104,8 @@ struct mptsas_hotplug_event {
|
|
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;
|
|
};
|
|
};
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -139,6 +141,7 @@ struct mptsas_phyinfo {
|
|
struct mptsas_devinfo attached; /* point to attached device info */
|
|
struct mptsas_devinfo attached; /* point to attached device info */
|
|
struct sas_phy *phy;
|
|
struct sas_phy *phy;
|
|
struct sas_rphy *rphy;
|
|
struct sas_rphy *rphy;
|
|
|
|
+ struct scsi_target *starget;
|
|
};
|
|
};
|
|
|
|
|
|
struct mptsas_portinfo {
|
|
struct mptsas_portinfo {
|
|
@@ -388,6 +391,17 @@ mptsas_slave_alloc(struct scsi_device *sdev)
|
|
target_id = p->phy_info[i].attached.id;
|
|
target_id = p->phy_info[i].attached.id;
|
|
vtarget->bus_id = p->phy_info[i].attached.channel;
|
|
vtarget->bus_id = p->phy_info[i].attached.channel;
|
|
vdev->lun = sdev->lun;
|
|
vdev->lun = sdev->lun;
|
|
|
|
+ p->phy_info[i].starget = sdev->sdev_target;
|
|
|
|
+ /*
|
|
|
|
+ * Exposing hidden disk (RAID)
|
|
|
|
+ */
|
|
|
|
+ if (mptscsih_is_phys_disk(hd->ioc, target_id)) {
|
|
|
|
+ target_id = mptscsih_raid_id_to_num(hd,
|
|
|
|
+ target_id);
|
|
|
|
+ vdev->vtarget->tflags |=
|
|
|
|
+ MPT_TARGET_FLAGS_RAID_COMPONENT;
|
|
|
|
+ sdev->no_uld_attach = 1;
|
|
|
|
+ }
|
|
mutex_unlock(&hd->ioc->sas_topology_mutex);
|
|
mutex_unlock(&hd->ioc->sas_topology_mutex);
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
@@ -1378,10 +1392,24 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
|
|
{
|
|
{
|
|
u32 handle = 0xFFFF;
|
|
u32 handle = 0xFFFF;
|
|
int index = 0;
|
|
int index = 0;
|
|
|
|
+ int i;
|
|
|
|
|
|
mptsas_probe_hba_phys(ioc, &index);
|
|
mptsas_probe_hba_phys(ioc, &index);
|
|
while (!mptsas_probe_expander_phys(ioc, &handle, &index))
|
|
while (!mptsas_probe_expander_phys(ioc, &handle, &index))
|
|
;
|
|
;
|
|
|
|
+ /*
|
|
|
|
+ Reporting RAID volumes.
|
|
|
|
+ */
|
|
|
|
+ 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++) {
|
|
|
|
+ scsi_add_device(ioc->sh, ioc->num_ports,
|
|
|
|
+ ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
|
|
|
|
+ }
|
|
|
|
+ out:
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
|
|
static struct mptsas_phyinfo *
|
|
static struct mptsas_phyinfo *
|
|
@@ -1460,6 +1488,20 @@ mptscsih_sas_persist_clear_table(void * arg)
|
|
mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
|
|
mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void
|
|
|
|
+mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
|
|
|
|
+{
|
|
|
|
+ sdev->no_uld_attach = data ? 1 : 0;
|
|
|
|
+ scsi_device_reprobe(sdev);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void
|
|
|
|
+mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
|
|
|
|
+{
|
|
|
|
+ starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
|
|
|
|
+ mptsas_reprobe_lun);
|
|
|
|
+}
|
|
|
|
+
|
|
static void
|
|
static void
|
|
mptsas_hotplug_work(void *arg)
|
|
mptsas_hotplug_work(void *arg)
|
|
{
|
|
{
|
|
@@ -1470,14 +1512,33 @@ mptsas_hotplug_work(void *arg)
|
|
struct scsi_device *sdev;
|
|
struct scsi_device *sdev;
|
|
char *ds = NULL;
|
|
char *ds = NULL;
|
|
struct mptsas_devinfo sas_device;
|
|
struct mptsas_devinfo sas_device;
|
|
|
|
+ VirtTarget *vtarget;
|
|
|
|
|
|
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 = mptsas_find_phyinfo_by_target(ioc, ev->id);
|
|
- if (!phy_info) {
|
|
|
|
- printk("mptsas: remove event for non-existant PHY.\n");
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Sanity checks, for non-existing phys and remote rphys.
|
|
|
|
+ */
|
|
|
|
+ if (!phy_info)
|
|
break;
|
|
break;
|
|
|
|
+ if (!phy_info->rphy)
|
|
|
|
+ break;
|
|
|
|
+ if (phy_info->starget) {
|
|
|
|
+ vtarget = phy_info->starget->hostdata;
|
|
|
|
+
|
|
|
|
+ if (!vtarget)
|
|
|
|
+ break;
|
|
|
|
+ /*
|
|
|
|
+ * Handling RAID components
|
|
|
|
+ */
|
|
|
|
+ if (ev->phys_disk_num_valid) {
|
|
|
|
+ vtarget->target_id = ev->phys_disk_num;
|
|
|
|
+ vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
|
|
|
|
+ mptsas_reprobe_target(vtarget->starget, 1);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
|
|
if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
|
|
@@ -1491,11 +1552,10 @@ mptsas_hotplug_work(void *arg)
|
|
"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);
|
|
|
|
|
|
- if (phy_info->rphy) {
|
|
|
|
- sas_rphy_delete(phy_info->rphy);
|
|
|
|
- memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
|
|
|
|
- phy_info->rphy = NULL;
|
|
|
|
- }
|
|
|
|
|
|
+ sas_rphy_delete(phy_info->rphy);
|
|
|
|
+ memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
|
|
|
|
+ phy_info->rphy = NULL;
|
|
|
|
+ phy_info->starget = NULL;
|
|
break;
|
|
break;
|
|
case MPTSAS_ADD_DEVICE:
|
|
case MPTSAS_ADD_DEVICE:
|
|
|
|
|
|
@@ -1509,16 +1569,27 @@ mptsas_hotplug_work(void *arg)
|
|
|
|
|
|
phy_info = mptsas_find_phyinfo_by_parent(ioc,
|
|
phy_info = mptsas_find_phyinfo_by_parent(ioc,
|
|
sas_device.handle_parent, sas_device.phy_id);
|
|
sas_device.handle_parent, sas_device.phy_id);
|
|
- if (!phy_info) {
|
|
|
|
- printk("mptsas: add event for non-existant PHY.\n");
|
|
|
|
|
|
+ if (!phy_info)
|
|
break;
|
|
break;
|
|
- }
|
|
|
|
|
|
+ if (phy_info->starget) {
|
|
|
|
+ vtarget = phy_info->starget->hostdata;
|
|
|
|
|
|
- if (phy_info->rphy) {
|
|
|
|
- printk("mptsas: trying to add existing device.\n");
|
|
|
|
|
|
+ if (!vtarget)
|
|
|
|
+ break;
|
|
|
|
+ /*
|
|
|
|
+ * Handling RAID components
|
|
|
|
+ */
|
|
|
|
+ if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
|
|
|
|
+ vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
|
|
|
|
+ vtarget->target_id = ev->id;
|
|
|
|
+ mptsas_reprobe_target(phy_info->starget, 0);
|
|
|
|
+ }
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (phy_info->rphy)
|
|
|
|
+ break;
|
|
|
|
+
|
|
memcpy(&phy_info->attached, &sas_device,
|
|
memcpy(&phy_info->attached, &sas_device,
|
|
sizeof(struct mptsas_devinfo));
|
|
sizeof(struct mptsas_devinfo));
|
|
|
|
|
|
@@ -1672,6 +1743,9 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc,
|
|
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 = raid_event_data->PhysDiskNum;
|
|
ev->event_type = MPTSAS_DEL_DEVICE;
|
|
ev->event_type = MPTSAS_DEL_DEVICE;
|
|
break;
|
|
break;
|
|
case MPI_EVENT_RAID_RC_VOLUME_DELETED:
|
|
case MPI_EVENT_RAID_RC_VOLUME_DELETED:
|
|
@@ -1932,20 +2006,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
|
|
|
|
mptsas_scan_sas_topology(ioc);
|
|
mptsas_scan_sas_topology(ioc);
|
|
|
|
|
|
- /*
|
|
|
|
- Reporting RAID volumes.
|
|
|
|
- */
|
|
|
|
- if (!ioc->raid_data.pIocPg2)
|
|
|
|
- return 0;
|
|
|
|
- if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
|
|
|
|
- return 0;
|
|
|
|
- for (ii=0;ii<ioc->raid_data.pIocPg2->NumActiveVolumes;ii++) {
|
|
|
|
- scsi_add_device(sh,
|
|
|
|
- ioc->num_ports,
|
|
|
|
- ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID,
|
|
|
|
- 0);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
out_mptsas_probe:
|
|
out_mptsas_probe:
|