Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 19121
b: refs/heads/master
c: c73787e
h: refs/heads/master
i:
  19119: 5e3846e
v: v3
  • Loading branch information
Moore, Eric authored and James Bottomley committed Jan 31, 2006
1 parent b6fb56b commit c630ea7
Show file tree
Hide file tree
Showing 2 changed files with 174 additions and 26 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d99ca4180fe44ae7f409fc73f1a09f270b8d458a
refs/heads/master: c73787eecdbe4691d4e3f989052db8b552e1ac34
198 changes: 173 additions & 25 deletions trunk/drivers/message/fusion/mptsas.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ static int mptsasMgmtCtx = -1;
enum mptsas_hotplug_action {
MPTSAS_ADD_DEVICE,
MPTSAS_DEL_DEVICE,
MPTSAS_ADD_RAID,
MPTSAS_DEL_RAID,
};

struct mptsas_hotplug_event {
Expand All @@ -114,6 +116,7 @@ struct mptsas_hotplug_event {

struct mptsas_devinfo {
u16 handle; /* unique id to address this device */
u16 handle_parent; /* unique id to address parent device */
u8 phy_id; /* phy number of parent device */
u8 port_id; /* sas physical port this device
is assoc'd with */
Expand Down Expand Up @@ -714,6 +717,7 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
mptsas_print_device_pg0(buffer);

device_info->handle = le16_to_cpu(buffer->DevHandle);
device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
device_info->phy_id = buffer->PhyNum;
device_info->port_id = buffer->PhysicalPort;
device_info->id = buffer->TargetID;
Expand Down Expand Up @@ -863,6 +867,26 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
return error;
}

/*
* Returns true if there is a scsi end device
*/
static inline int
mptsas_is_end_device(struct mptsas_devinfo * attached)
{
if ((attached->handle) &&
(attached->device_info &
MPI_SAS_DEVICE_INFO_END_DEVICE) &&
((attached->device_info &
MPI_SAS_DEVICE_INFO_SSP_TARGET) |
(attached->device_info &
MPI_SAS_DEVICE_INFO_STP_TARGET) |
(attached->device_info &
MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
return 1;
else
return 0;
}

static void
mptsas_parse_device_info(struct sas_identify *identify,
struct mptsas_devinfo *device_info)
Expand Down Expand Up @@ -1227,7 +1251,7 @@ mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)
}

static struct mptsas_phyinfo *
mptsas_find_phyinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
{
struct mptsas_portinfo *port_info;
struct mptsas_phyinfo *phy_info = NULL;
Expand All @@ -1239,12 +1263,12 @@ mptsas_find_phyinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
*/
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 (port_info->phy_info[i].attached.handle == handle) {
phy_info = &port_info->phy_info[i];
break;
}
}
for (i = 0; i < port_info->num_phys; i++)
if (mptsas_is_end_device(&port_info->phy_info[i].attached))
if (port_info->phy_info[i].attached.id == id) {
phy_info = &port_info->phy_info[i];
break;
}
}
mutex_unlock(&ioc->sas_topology_mutex);

Expand All @@ -1258,36 +1282,58 @@ mptsas_hotplug_work(void *arg)
MPT_ADAPTER *ioc = ev->ioc;
struct mptsas_phyinfo *phy_info;
struct sas_rphy *rphy;
struct scsi_device *sdev;
char *ds = NULL;

if (ev->device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
ds = "ssp";
if (ev->device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
ds = "stp";
if (ev->device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
ds = "sata";
struct mptsas_devinfo sas_device;

switch (ev->event_type) {
case MPTSAS_DEL_DEVICE:
printk(MYIOC_s_INFO_FMT
"removing %s device, channel %d, id %d, phy %d\n",
ioc->name, ds, ev->channel, ev->id, ev->phy_id);

phy_info = mptsas_find_phyinfo_by_handle(ioc, ev->handle);
phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
if (!phy_info) {
printk("mptsas: remove event for non-existant PHY.\n");
break;
}

if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
ds = "ssp";
if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
ds = "stp";
if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
ds = "sata";

printk(MYIOC_s_INFO_FMT
"removing %s device, channel %d, id %d, phy %d\n",
ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);

if (phy_info->rphy) {
sas_rphy_delete(phy_info->rphy);
phy_info->rphy = NULL;
}
break;
case MPTSAS_ADD_DEVICE:
printk(MYIOC_s_INFO_FMT
"attaching %s device, channel %d, id %d, phy %d\n",
ioc->name, ds, ev->channel, ev->id, ev->phy_id);

/*
* When there is no sas address,
* RAID volumes are being deleted,
* and hidden phy disk are being added.
* We don't know the SAS data yet,
* so lookup sas device page to get
* pertaining info
*/
if (!ev->sas_address) {
if (mptsas_sas_device_pg0(ioc,
&sas_device, ev->id,
(MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
MPI_SAS_DEVICE_PGAD_FORM_SHIFT)))
break;
ev->handle = sas_device.handle;
ev->parent_handle = sas_device.handle_parent;
ev->channel = sas_device.channel;
ev->phy_id = sas_device.phy_id;
ev->sas_address = sas_device.sas_address;
ev->device_info = sas_device.device_info;
}

phy_info = mptsas_find_phyinfo_by_parent(ioc,
ev->parent_handle, ev->phy_id);
Expand All @@ -1310,10 +1356,23 @@ mptsas_hotplug_work(void *arg)
phy_info->attached.sas_address = ev->sas_address;
phy_info->attached.device_info = ev->device_info;

if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
ds = "ssp";
if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
ds = "stp";
if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
ds = "sata";

printk(MYIOC_s_INFO_FMT
"attaching %s device, channel %d, id %d, phy %d\n",
ioc->name, ds, ev->channel, ev->id, ev->phy_id);


rphy = sas_rphy_alloc(phy_info->phy);
if (!rphy)
break; /* non-fatal: an rphy can be added later */

rphy->scsi_target_id = phy_info->attached.id;
mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
if (sas_rphy_add(rphy)) {
sas_rphy_free(rphy);
Expand All @@ -1322,6 +1381,40 @@ mptsas_hotplug_work(void *arg)

phy_info->rphy = rphy;
break;
case MPTSAS_ADD_RAID:
sdev = scsi_device_lookup(
ioc->sh,
ioc->num_ports,
ev->id,
0);
if (sdev) {
scsi_device_put(sdev);
break;
}
printk(MYIOC_s_INFO_FMT
"attaching device, channel %d, id %d\n",
ioc->name, ioc->num_ports, ev->id);
scsi_add_device(ioc->sh,
ioc->num_ports,
ev->id,
0);
mpt_findImVolumes(ioc);
break;
case MPTSAS_DEL_RAID:
sdev = scsi_device_lookup(
ioc->sh,
ioc->num_ports,
ev->id,
0);
if (!sdev)
break;
printk(MYIOC_s_INFO_FMT
"removing device, channel %d, id %d\n",
ioc->name, ioc->num_ports, ev->id);
scsi_remove_device(sdev);
scsi_device_put(sdev);
mpt_findImVolumes(ioc);
break;
}

kfree(ev);
Expand Down Expand Up @@ -1372,23 +1465,78 @@ mptscsih_send_sas_event(MPT_ADAPTER *ioc,
schedule_work(&ev->work);
}

static void
mptscsih_send_raid_event(MPT_ADAPTER *ioc,
EVENT_DATA_RAID *raid_event_data)
{
struct mptsas_hotplug_event *ev;
RAID_VOL0_STATUS * volumeStatus;

if (ioc->bus_type != SAS)
return;

ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
if (!ev) {
printk(KERN_WARNING "mptsas: lost hotplug event\n");
return;
}

memset(ev,0,sizeof(struct mptsas_hotplug_event));
INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
ev->ioc = ioc;
ev->id = raid_event_data->VolumeID;

switch (raid_event_data->ReasonCode) {
case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
ev->event_type = MPTSAS_ADD_DEVICE;
break;
case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
ev->event_type = MPTSAS_DEL_DEVICE;
break;
case MPI_EVENT_RAID_RC_VOLUME_DELETED:
ev->event_type = MPTSAS_DEL_RAID;
break;
case MPI_EVENT_RAID_RC_VOLUME_CREATED:
ev->event_type = MPTSAS_ADD_RAID;
break;
case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
volumeStatus = (RAID_VOL0_STATUS *) &
raid_event_data->SettingsStatus;
ev->event_type = (volumeStatus->State ==
MPI_RAIDVOL0_STATUS_STATE_FAILED) ?
MPTSAS_DEL_RAID : MPTSAS_ADD_RAID;
break;
default:
break;
}
schedule_work(&ev->work);
}

static int
mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
{
int rc=1;
u8 event = le32_to_cpu(reply->Event) & 0xFF;

if (!ioc->sh)
return 1;
goto out;

switch (event) {
case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
mptscsih_send_sas_event(ioc,
(EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
return 1; /* currently means nothing really */

break;
case MPI_EVENT_INTEGRATED_RAID:
mptscsih_send_raid_event(ioc,
(EVENT_DATA_RAID *)reply->Data);
break;
default:
return mptscsih_event_process(ioc, reply);
rc = mptscsih_event_process(ioc, reply);
break;
}
out:

return rc;
}

static int
Expand Down

0 comments on commit c630ea7

Please sign in to comment.