From e3094447e013a59ccedcf60f6055f18225bd8465 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 16 Feb 2006 13:25:36 +0100 Subject: [SCSI] mptsas: add support for enclosure and bay identifier attributes Adds support to retrieve the enclosure and bay identifiers. This patch is from Eric with minor modifications from me, rewritten from a buggy patch of mine, based on the earlier CSMI implementation from Eric.. Signed-off-by: Christoph Hellwig Signed-off-by: James Bottomley --- drivers/message/fusion/mptsas.c | 196 +++++++++++++++++++++++++++++++++------- 1 file changed, 161 insertions(+), 35 deletions(-) (limited to 'drivers/message/fusion/mptsas.c') diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 2512d0e6155..74f4368c79a 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -117,6 +117,8 @@ struct mptsas_hotplug_event { struct mptsas_devinfo { u16 handle; /* unique id to address this device */ u16 handle_parent; /* unique id to address parent device */ + u16 handle_enclosure; /* enclosure identifier of the enclosure */ + u16 slot; /* physical slot in enclosure */ u8 phy_id; /* phy number of parent device */ u8 port_id; /* sas physical port this device is assoc'd with */ @@ -146,6 +148,18 @@ struct mptsas_portinfo { struct mptsas_phyinfo *phy_info; }; +struct mptsas_enclosure { + u64 enclosure_logical_id; /* The WWN for the enclosure */ + u16 enclosure_handle; /* unique id to address this */ + u16 flags; /* details enclosure management */ + u16 num_slot; /* num slots */ + u16 start_slot; /* first slot */ + u8 start_id; /* starting logical target id */ + u8 start_channel; /* starting logical channel id */ + u8 sep_id; /* SEP device logical target id */ + u8 sep_channel; /* SEP channel logical channel id */ +}; + #ifdef SASDEBUG static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) @@ -205,6 +219,7 @@ static void mptsas_print_device_pg0(SasDevicePage0_t *pg0) printk("---- SAS DEVICE PAGE 0 ---------\n"); printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle)); + printk("Parent Handle=0x%X\n" ,le16_to_cpu(pg0->ParentDevHandle)); printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle)); printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot)); printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address)); @@ -243,6 +258,82 @@ static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1) #define mptsas_print_expander_pg1(pg1) do { } while (0) #endif +static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy) +{ + struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); + return ((MPT_SCSI_HOST *)shost->hostdata)->ioc; +} + +static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy) +{ + struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); + return ((MPT_SCSI_HOST *)shost->hostdata)->ioc; +} + +static int +mptsas_sas_exclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure, + u32 form, u32 form_specific) +{ + ConfigExtendedPageHeader_t hdr; + CONFIGPARMS cfg; + SasEnclosurePage0_t *buffer; + dma_addr_t dma_handle; + int error; + __le64 le_identifier; + + memset(&hdr, 0, sizeof(hdr)); + hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION; + hdr.PageNumber = 0; + hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; + hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE; + + cfg.cfghdr.ehdr = &hdr; + cfg.physAddr = -1; + cfg.pageAddr = form + form_specific; + cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; + cfg.dir = 0; /* read */ + cfg.timeout = 10; + + error = mpt_config(ioc, &cfg); + if (error) + goto out; + if (!hdr.ExtPageLength) { + error = -ENXIO; + goto out; + } + + buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + &dma_handle); + if (!buffer) { + error = -ENOMEM; + goto out; + } + + cfg.physAddr = dma_handle; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + + error = mpt_config(ioc, &cfg); + if (error) + goto out_free_consistent; + + /* save config data */ + memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64)); + enclosure->enclosure_logical_id = le64_to_cpu(le_identifier); + enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle); + enclosure->flags = le16_to_cpu(buffer->Flags); + enclosure->num_slot = le16_to_cpu(buffer->NumSlots); + enclosure->start_slot = le16_to_cpu(buffer->StartSlot); + enclosure->start_id = buffer->StartTargetID; + enclosure->start_channel = buffer->StartBus; + enclosure->sep_id = buffer->SEPTargetID; + enclosure->sep_channel = buffer->SEPBus; + + out_free_consistent: + pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, + buffer, dma_handle); + out: + return error; +} /* * This is pretty ugly. We will be able to seriously clean it up @@ -399,12 +490,6 @@ static struct scsi_host_template mptsas_driver_template = { .use_clustering = ENABLE_CLUSTERING, }; -static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy) -{ - struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); - return ((MPT_SCSI_HOST *)shost->hostdata)->ioc; -} - static int mptsas_get_linkerrors(struct sas_phy *phy) { MPT_ADAPTER *ioc = phy_to_ioc(phy); @@ -546,8 +631,67 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset) return error; } +static int +mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier) +{ + MPT_ADAPTER *ioc = rphy_to_ioc(rphy); + int i, error; + struct mptsas_portinfo *p; + struct mptsas_enclosure enclosure_info; + u64 enclosure_handle; + + mutex_lock(&ioc->sas_topology_mutex); + list_for_each_entry(p, &ioc->sas_topology, list) { + for (i = 0; i < p->num_phys; i++) { + if (p->phy_info[i].attached.sas_address == + rphy->identify.sas_address) { + enclosure_handle = p->phy_info[i]. + attached.handle_enclosure; + goto found_info; + } + } + } + mutex_unlock(&ioc->sas_topology_mutex); + return -ENXIO; + + found_info: + mutex_unlock(&ioc->sas_topology_mutex); + memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure)); + error = mptsas_sas_exclosure_pg0(ioc, &enclosure_info, + (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE << + MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle); + if (!error) + *identifier = enclosure_info.enclosure_logical_id; + return error; +} + +static int +mptsas_get_bay_identifier(struct sas_rphy *rphy) +{ + MPT_ADAPTER *ioc = rphy_to_ioc(rphy); + struct mptsas_portinfo *p; + int i, rc; + + mutex_lock(&ioc->sas_topology_mutex); + list_for_each_entry(p, &ioc->sas_topology, list) { + for (i = 0; i < p->num_phys; i++) { + if (p->phy_info[i].attached.sas_address == + rphy->identify.sas_address) { + rc = p->phy_info[i].attached.slot; + goto out; + } + } + } + rc = -ENXIO; + out: + mutex_unlock(&ioc->sas_topology_mutex); + return rc; +} + static struct sas_function_template mptsas_transport_functions = { .get_linkerrors = mptsas_get_linkerrors, + .get_enclosure_identifier = mptsas_get_enclosure_identifier, + .get_bay_identifier = mptsas_get_bay_identifier, .phy_reset = mptsas_phy_reset, }; @@ -739,6 +883,9 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, device_info->handle = le16_to_cpu(buffer->DevHandle); device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle); + device_info->handle_enclosure = + le16_to_cpu(buffer->EnclosureHandle); + device_info->slot = le16_to_cpu(buffer->Slot); device_info->phy_id = buffer->PhyNum; device_info->port_id = buffer->PhysicalPort; device_info->id = buffer->TargetID; @@ -1335,29 +1482,15 @@ mptsas_hotplug_work(void *arg) case MPTSAS_ADD_DEVICE: /* - * 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 + * Refresh sas device pg0 data */ - 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; - } + if (mptsas_sas_device_pg0(ioc, &sas_device, + (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << + MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id)) + break; phy_info = mptsas_find_phyinfo_by_parent(ioc, - ev->parent_handle, ev->phy_id); + sas_device.handle_parent, sas_device.phy_id); if (!phy_info) { printk("mptsas: add event for non-existant PHY.\n"); break; @@ -1368,14 +1501,8 @@ mptsas_hotplug_work(void *arg) break; } - /* fill attached info */ - phy_info->attached.handle = ev->handle; - phy_info->attached.phy_id = ev->phy_id; - phy_info->attached.port_id = phy_info->identify.port_id; - phy_info->attached.id = ev->id; - phy_info->attached.channel = ev->channel; - phy_info->attached.sas_address = ev->sas_address; - phy_info->attached.device_info = ev->device_info; + memcpy(&phy_info->attached, &sas_device, + sizeof(struct mptsas_devinfo)); if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) ds = "ssp"; @@ -1393,7 +1520,6 @@ mptsas_hotplug_work(void *arg) 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); -- cgit v1.2.3-70-g09d2 From 3a892bef3f7e94c4d6c2c20b9a1b546f43679fd3 Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Tue, 14 Mar 2006 09:14:03 -0700 Subject: [SCSI] fusion - move some debug firmware event debug msgs to verbose level Created a debug level MPT_DEBUG_VERBOSE_EVENTS. Moving some of the more vebose debug messages for firwmare events into new debug level. Also added some more firmware events descriptions. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/Makefile | 1 + drivers/message/fusion/mptbase.c | 125 ++++++++++++++++++++++++++++++++------ drivers/message/fusion/mptbase.h | 8 ++- drivers/message/fusion/mptctl.c | 6 +- drivers/message/fusion/mptfc.c | 2 +- drivers/message/fusion/mptsas.c | 2 +- drivers/message/fusion/mptscsih.c | 2 +- drivers/message/fusion/mptspi.c | 2 +- 8 files changed, 122 insertions(+), 26 deletions(-) (limited to 'drivers/message/fusion/mptsas.c') diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile index 33ace373241..51740b34622 100644 --- a/drivers/message/fusion/Makefile +++ b/drivers/message/fusion/Makefile @@ -4,6 +4,7 @@ #EXTRA_CFLAGS += -DMPT_DEBUG_MSG_FRAME #EXTRA_CFLAGS += -DMPT_DEBUG_SG #EXTRA_CFLAGS += -DMPT_DEBUG_EVENTS +#EXTRA_CFLAGS += -DMPT_DEBUG_VERBOSE_EVENTS #EXTRA_CFLAGS += -DMPT_DEBUG_INIT #EXTRA_CFLAGS += -DMPT_DEBUG_EXIT #EXTRA_CFLAGS += -DMPT_DEBUG_FAIL diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 39c0b16d8d0..9960ef10366 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -428,7 +428,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) results = ProcessEventNotification(ioc, pEvReply, &evHandlers); if (results != evHandlers) { /* CHECKME! Any special handling needed here? */ - devtprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n", + devtverboseprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n", ioc->name, evHandlers, results)); } @@ -438,10 +438,10 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) */ if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) { freereq = 0; - devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n", + devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p does not return Request frame\n", ioc->name, pEvReply)); } else { - devtprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n", + devtverboseprintk((MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n", ioc->name, pEvReply)); } @@ -5079,13 +5079,13 @@ SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch) evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc); if (evnp == NULL) { - devtprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n", + devtverboseprintk((MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n", ioc->name)); return 0; } memset(evnp, 0, sizeof(*evnp)); - devtprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp)); + devtverboseprintk((MYIOC_s_INFO_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp)); evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION; evnp->ChainOffset = 0; @@ -5840,24 +5840,27 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) break; case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: { + char buf[50]; + u8 id = (u8)(evData0); u8 ReasonCode = (u8)(evData0 >> 16); switch (ReasonCode) { case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: - ds = "SAS Device Status Change: Added"; + sprintf(buf,"SAS Device Status Change: Added: id=%d", id); break; case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: - ds = "SAS Device Status Change: Deleted"; + sprintf(buf,"SAS Device Status Change: Deleted: id=%d", id); break; case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: - ds = "SAS Device Status Change: SMART Data"; + sprintf(buf,"SAS Device Status Change: SMART Data: id=%d", id); break; case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED: - ds = "SAS Device Status Change: No Persistancy Added"; + sprintf(buf,"SAS Device Status Change: No Persistancy Added: id=%d", id); break; default: - ds = "SAS Device Status Change: Unknown"; + sprintf(buf,"SAS Device Status Change: Unknown: id=%d", id); break; } + ds = buf; break; } case MPI_EVENT_ON_BUS_TIMER_EXPIRED: @@ -5873,11 +5876,97 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) ds = "Persistent Table Full"; break; case MPI_EVENT_SAS_PHY_LINK_STATUS: - ds = "SAS PHY Link Status"; + { + char buf[50]; + u8 LinkRates = (u8)(evData0 >> 8); + u8 PhyNumber = (u8)(evData0); + LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >> + MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT; + switch (LinkRates) { + case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN: + sprintf(buf,"SAS PHY Link Status: Phy=%d:" + " Rate Unknown",PhyNumber); + break; + case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED: + sprintf(buf,"SAS PHY Link Status: Phy=%d:" + " Phy Disabled",PhyNumber); + break; + case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION: + sprintf(buf,"SAS PHY Link Status: Phy=%d:" + " Failed Speed Nego",PhyNumber); + break; + case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE: + sprintf(buf,"SAS PHY Link Status: Phy=%d:" + " Sata OOB Completed",PhyNumber); + break; + case MPI_EVENT_SAS_PLS_LR_RATE_1_5: + sprintf(buf,"SAS PHY Link Status: Phy=%d:" + " Rate 1.5 Gbps",PhyNumber); + break; + case MPI_EVENT_SAS_PLS_LR_RATE_3_0: + sprintf(buf,"SAS PHY Link Status: Phy=%d:" + " Rate 3.0 Gpbs",PhyNumber); + break; + default: + sprintf(buf,"SAS PHY Link Status: Phy=%d", PhyNumber); + break; + } + ds = buf; break; + } case MPI_EVENT_SAS_DISCOVERY_ERROR: ds = "SAS Discovery Error"; break; + case MPI_EVENT_IR_RESYNC_UPDATE: + { + u8 resync_complete = (u8)(evData0 >> 16); + char buf[40]; + sprintf(buf,"IR Resync Update: Complete = %d:",resync_complete); + ds = buf; + break; + } + case MPI_EVENT_IR2: + { + u8 ReasonCode = (u8)(evData0 >> 16); + switch (ReasonCode) { + case MPI_EVENT_IR2_RC_LD_STATE_CHANGED: + ds = "IR2: LD State Changed"; + break; + case MPI_EVENT_IR2_RC_PD_STATE_CHANGED: + ds = "IR2: PD State Changed"; + break; + case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL: + ds = "IR2: Bad Block Table Full"; + break; + case MPI_EVENT_IR2_RC_PD_INSERTED: + ds = "IR2: PD Inserted"; + break; + case MPI_EVENT_IR2_RC_PD_REMOVED: + ds = "IR2: PD Removed"; + break; + case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED: + ds = "IR2: Foreign CFG Detected"; + break; + case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR: + ds = "IR2: Rebuild Medium Error"; + break; + default: + ds = "IR2"; + break; + } + break; + } + case MPI_EVENT_SAS_DISCOVERY: + { + if (evData0) + ds = "SAS Discovery: Start"; + else + ds = "SAS Discovery: Stop"; + break; + } + case MPI_EVENT_LOG_ENTRY_ADDED: + ds = "SAS Log Entry Added"; + break; /* * MPT base "custom" events may be added here... @@ -5922,12 +6011,12 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply } EventDescriptionStr(event, evData0, evStr); - devtprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n", + devtprintk((MYIOC_s_INFO_FMT "MPT event:(%02Xh) : %s\n", ioc->name, - evStr, - event)); + event, + evStr)); -#if defined(MPT_DEBUG) || defined(MPT_DEBUG_EVENTS) +#if defined(MPT_DEBUG) || defined(MPT_DEBUG_VERBOSE_EVENTS) printk(KERN_INFO MYNAM ": Event data:\n" KERN_INFO); for (ii = 0; ii < evDataLen; ii++) printk(" %08x", le32_to_cpu(pEventReply->Data[ii])); @@ -5986,7 +6075,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply */ for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { if (MptEvHandlers[ii]) { - devtprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n", + devtverboseprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n", ioc->name, ii)); r += (*(MptEvHandlers[ii]))(ioc, pEventReply); handlers++; @@ -5998,10 +6087,10 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply * If needed, send (a single) EventAck. */ if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) { - devtprintk((MYIOC_s_WARN_FMT + devtverboseprintk((MYIOC_s_WARN_FMT "EventAck required\n",ioc->name)); if ((ii = SendEventAck(ioc, pEventReply)) != 0) { - devtprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n", + devtverboseprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n", ioc->name, ii)); } } diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index f4197a9962a..fb22b28d1ab 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -719,12 +719,18 @@ typedef struct _mpt_sge { #define dhsprintk(x) #endif -#ifdef MPT_DEBUG_EVENTS +#if defined(MPT_DEBUG_EVENTS) || defined(MPT_DEBUG_VERBOSE_EVENTS) #define devtprintk(x) printk x #else #define devtprintk(x) #endif +#ifdef MPT_DEBUG_VERBOSE_EVENTS +#define devtverboseprintk(x) printk x +#else +#define devtverboseprintk(x) +#endif + #ifdef MPT_DEBUG_RESET #define drsprintk(x) printk x #else diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 9b64e07400d..3d555b724ed 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -497,7 +497,7 @@ mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) if (event == 0x21 ) { ioc->aen_event_read_flag=1; dctlprintk(("Raised SIGIO to application\n")); - devtprintk(("Raised SIGIO to application\n")); + devtverboseprintk(("Raised SIGIO to application\n")); kill_fasync(&async_queue, SIGIO, POLL_IN); return 1; } @@ -515,7 +515,7 @@ mptctl_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) if (ioc->events && (ioc->eventTypes & ( 1 << event))) { ioc->aen_event_read_flag=1; dctlprintk(("Raised SIGIO to application\n")); - devtprintk(("Raised SIGIO to application\n")); + devtverboseprintk(("Raised SIGIO to application\n")); kill_fasync(&async_queue, SIGIO, POLL_IN); } return 1; @@ -2968,7 +2968,7 @@ static int __init mptctl_init(void) } if (mpt_event_register(mptctl_id, mptctl_event_process) == 0) { - devtprintk((KERN_INFO MYNAM + devtverboseprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n")); } diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 8ea12ea652a..5a30621051c 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -941,7 +941,7 @@ mptfc_init(void) mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER); if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) { - devtprintk((KERN_INFO MYNAM + devtverboseprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n")); } diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 74f4368c79a..ba93ef13a41 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -1993,7 +1993,7 @@ mptsas_init(void) mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER); if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) { - devtprintk((KERN_INFO MYNAM + devtverboseprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n")); } diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index a2183103b8c..77289fd07fe 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -2531,7 +2531,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) int work_count; unsigned long flags; - devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", + devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", ioc->name, event)); if (ioc->sh == NULL || diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 437189f871b..9af69dd66f8 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -1057,7 +1057,7 @@ mptspi_init(void) mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER); if (mpt_event_register(mptspiDoneCtx, mptspi_event_process) == 0) { - devtprintk((KERN_INFO MYNAM + devtverboseprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n")); } -- cgit v1.2.3-70-g09d2 From 914c2d8e597798d62c2e0a3cba737bf6f611eecf Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Tue, 14 Mar 2006 09:19:36 -0700 Subject: [SCSI] fusion - removing target_id/bus_id from the VirtDevice structure It makes no sense in keeping the target_id and bus_id in the VirtDevice structure, when it can be obtained from the VirtTarget structure. In addition, this patch fix's couple compilation bugs in mptfc.c when MPT_DEBUG_FC is enabled. This provided by Micheal Reed. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.h | 5 +---- drivers/message/fusion/mptfc.c | 33 ++++++++------------------------- drivers/message/fusion/mptsas.c | 24 +++++++++++------------- drivers/message/fusion/mptscsih.c | 19 ++++++++----------- drivers/message/fusion/mptspi.c | 4 ++-- 5 files changed, 30 insertions(+), 55 deletions(-) (limited to 'drivers/message/fusion/mptsas.c') diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 2b9c8b5522f..9b58234add3 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -347,10 +347,7 @@ typedef struct _VirtTarget { } VirtTarget; typedef struct _VirtDevice { - VirtTarget *vtarget; - u8 ioc_id; - u8 bus_id; - u8 target_id; + VirtTarget *vtarget; u8 configured_lun; u32 lun; } VirtDevice; diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 5a30621051c..b343f2a68b1 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -348,24 +348,6 @@ mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid) return 0; } -static void -mptfc_remap_sdev(struct scsi_device *sdev, void *arg) -{ - VirtDevice *vdev; - VirtTarget *vtarget; - struct scsi_target *starget; - - starget = scsi_target(sdev); - if (starget->hostdata == arg) { - vtarget = arg; - vdev = sdev->hostdata; - if (vdev) { - vdev->bus_id = vtarget->bus_id; - vdev->target_id = vtarget->target_id; - } - } -} - static void mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) { @@ -423,8 +405,6 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) if (vtarget) { vtarget->target_id = pg0->CurrentTargetID; vtarget->bus_id = pg0->CurrentBus; - starget_for_each_device(ri->starget, - vtarget,mptfc_remap_sdev); } ri->remap_needed = 0; } @@ -432,7 +412,7 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) "mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, " "rport tid %d, tmo %d\n", ioc->name, - oc->sh->host_no, + ioc->sh->host_no, pg0->PortIdentifier, pg0->WWNN, pg0->WWPN, @@ -553,23 +533,26 @@ mptfc_slave_alloc(struct scsi_device *sdev) } vdev->vtarget = vtarget; - vdev->ioc_id = hd->ioc->id; vdev->lun = sdev->lun; - vdev->target_id = vtarget->target_id; - vdev->bus_id = vtarget->bus_id; spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags); vtarget->num_luns++; +#ifdef DMPT_DEBUG_FC + { + struct mptfc_rport_info *ri; + ri = *((struct mptfc_rport_info **)rport->dd_data); dfcprintk ((MYIOC_s_INFO_FMT "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, " "CurrentTargetID %d, %x %llx %llx\n", - ioc->name, + hd->ioc->name, sdev->host->host_no, vtarget->num_luns, sdev->id, ri->pg0.CurrentTargetID, ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN)); + } +#endif return 0; } diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index ba93ef13a41..ba555a60bf7 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -350,6 +350,7 @@ mptsas_slave_alloc(struct scsi_device *sdev) VirtTarget *vtarget; VirtDevice *vdev; struct scsi_target *starget; + u32 target_id; int i; vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL); @@ -358,10 +359,10 @@ mptsas_slave_alloc(struct scsi_device *sdev) hd->ioc->name, sizeof(VirtDevice)); return -ENOMEM; } - vdev->ioc_id = hd->ioc->id; sdev->hostdata = vdev; starget = scsi_target(sdev); vtarget = starget->hostdata; + vtarget->ioc_id = hd->ioc->id; vdev->vtarget = vtarget; if (vtarget->num_luns == 0) { vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY; @@ -372,8 +373,8 @@ mptsas_slave_alloc(struct scsi_device *sdev) RAID volumes placed beyond the last expected port. */ if (sdev->channel == hd->ioc->num_ports) { - vdev->target_id = sdev->id; - vdev->bus_id = 0; + target_id = sdev->id; + vtarget->bus_id = 0; vdev->lun = 0; goto out; } @@ -384,11 +385,10 @@ mptsas_slave_alloc(struct scsi_device *sdev) for (i = 0; i < p->num_phys; i++) { if (p->phy_info[i].attached.sas_address == rphy->identify.sas_address) { - vdev->target_id = - p->phy_info[i].attached.id; - vdev->bus_id = p->phy_info[i].attached.channel; + target_id = p->phy_info[i].attached.id; + vtarget->bus_id = p->phy_info[i].attached.channel; vdev->lun = sdev->lun; - mutex_unlock(&hd->ioc->sas_topology_mutex); + mutex_unlock(&hd->ioc->sas_topology_mutex); goto out; } } @@ -399,9 +399,7 @@ mptsas_slave_alloc(struct scsi_device *sdev) return -ENXIO; out: - vtarget->ioc_id = vdev->ioc_id; - vtarget->target_id = vdev->target_id; - vtarget->bus_id = vdev->bus_id; + vtarget->target_id = target_id; vtarget->num_luns++; return 0; } @@ -444,8 +442,8 @@ mptsas_slave_destroy(struct scsi_device *sdev) if (vdev->configured_lun){ if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, - vdev->bus_id, - vdev->target_id, + vdev->vtarget->bus_id, + vdev->vtarget->target_id, 0, 0, 5 /* 5 second timeout */) < 0){ @@ -455,7 +453,7 @@ mptsas_slave_destroy(struct scsi_device *sdev) printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt id=%d TARGET_RESET\n", hd->ioc->name, - vdev->target_id); + vdev->vtarget->target_id); hd->tmPending = 0; hd->tmState = TM_STATE_NONE; diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 77289fd07fe..c99a918feb5 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -887,7 +887,7 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice) dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n", hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1])); - if ((mf->TargetID != ((u8)vdevice->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun))) + if ((mf->TargetID != ((u8)vdevice->vtarget->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun))) continue; /* Cleanup @@ -1285,8 +1285,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) /* Use the above information to set up the message frame */ - pScsiReq->TargetID = (u8) vdev->target_id; - pScsiReq->Bus = vdev->bus_id; + pScsiReq->TargetID = (u8) vdev->vtarget->target_id; + pScsiReq->Bus = vdev->vtarget->bus_id; pScsiReq->ChainOffset = 0; if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; @@ -1701,7 +1701,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) vdev = SCpnt->device->hostdata; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, - vdev->bus_id, vdev->target_id, vdev->lun, + vdev->vtarget->bus_id, vdev->vtarget->target_id, vdev->lun, ctx2abort, mptscsih_get_tm_timeout(ioc)); printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n", @@ -1752,7 +1752,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) vdev = SCpnt->device->hostdata; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, - vdev->bus_id, vdev->target_id, + vdev->vtarget->bus_id, vdev->vtarget->target_id, 0, 0, mptscsih_get_tm_timeout(hd->ioc)); printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n", @@ -1803,7 +1803,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) vdev = SCpnt->device->hostdata; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, - vdev->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc)); + vdev->vtarget->bus_id, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc)); printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n", hd->ioc->name, @@ -2162,9 +2162,6 @@ mptscsih_slave_alloc(struct scsi_device *sdev) return -ENOMEM; } - vdev->ioc_id = hd->ioc->id; - vdev->target_id = sdev->id; - vdev->bus_id = sdev->channel; vdev->lun = sdev->lun; sdev->hostdata = vdev; @@ -3366,8 +3363,8 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice) iocmd.data_dma = -1; iocmd.size = 0; iocmd.rsvd = iocmd.rsvd2 = 0; - iocmd.bus = vdevice->bus_id; - iocmd.id = vdevice->target_id; + iocmd.bus = vdevice->vtarget->bus_id; + iocmd.id = vdevice->vtarget->target_id; iocmd.lun = (u8)vdevice->lun; if ((vdevice->vtarget->type == TYPE_DISK) && diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 9af69dd66f8..09c745b19cc 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -343,9 +343,9 @@ static int mptspi_slave_alloc(struct scsi_device *sdev) sdev->no_uld_attach = 1; vdev->vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; /* The real channel for this device is zero */ - vdev->bus_id = 0; + vdev->vtarget->bus_id = 0; /* The actual physdisknum (for RAID passthrough) */ - vdev->target_id = physdisknum; + vdev->vtarget->target_id = physdisknum; } return 0; -- cgit v1.2.3-70-g09d2 From 4b766471e388352f35a6171563dfc0d272f12b59 Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Tue, 14 Mar 2006 09:14:12 -0700 Subject: [SCSI] fusion - cleanup mptsas event handling functions Cleanup of mptsas firmware event handlers. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptsas.c | 96 ++++++++++++++++++++++++----------------- 1 file changed, 57 insertions(+), 39 deletions(-) (limited to 'drivers/message/fusion/mptsas.c') diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index ba555a60bf7..84643ac6c70 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -1441,6 +1441,17 @@ mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id) return phy_info; } +/* + * Work queue thread to clear the persitency table + */ +static void +mptscsih_sas_persist_clear_table(void * arg) +{ + MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; + + mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT); +} + static void mptsas_hotplug_work(void *arg) { @@ -1537,7 +1548,7 @@ mptsas_hotplug_work(void *arg) break; } printk(MYIOC_s_INFO_FMT - "attaching device, channel %d, id %d\n", + "attaching raid volume, channel %d, id %d\n", ioc->name, ioc->num_ports, ev->id); scsi_add_device(ioc->sh, ioc->num_ports, @@ -1554,7 +1565,7 @@ mptsas_hotplug_work(void *arg) if (!sdev) break; printk(MYIOC_s_INFO_FMT - "removing device, channel %d, id %d\n", + "removing raid volume, channel %d, id %d\n", ioc->name, ioc->num_ports, ev->id); scsi_remove_device(sdev); scsi_device_put(sdev); @@ -1579,35 +1590,51 @@ mptscsih_send_sas_event(MPT_ADAPTER *ioc, MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0) return; - if ((sas_event_data->ReasonCode & - (MPI_EVENT_SAS_DEV_STAT_RC_ADDED | - MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING)) == 0) - return; + switch (sas_event_data->ReasonCode) { + case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: + case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: + ev = kmalloc(sizeof(*ev), GFP_ATOMIC); + if (!ev) { + printk(KERN_WARNING "mptsas: lost hotplug event\n"); + break; + } - ev = kmalloc(sizeof(*ev), GFP_ATOMIC); - if (!ev) { - printk(KERN_WARNING "mptsas: lost hotplug event\n"); - return; + INIT_WORK(&ev->work, mptsas_hotplug_work, ev); + ev->ioc = ioc; + ev->handle = le16_to_cpu(sas_event_data->DevHandle); + ev->parent_handle = + le16_to_cpu(sas_event_data->ParentDevHandle); + ev->channel = sas_event_data->Bus; + ev->id = sas_event_data->TargetID; + ev->phy_id = sas_event_data->PhyNum; + memcpy(&sas_address, &sas_event_data->SASAddress, + sizeof(__le64)); + ev->sas_address = le64_to_cpu(sas_address); + ev->device_info = device_info; + + if (sas_event_data->ReasonCode & + MPI_EVENT_SAS_DEV_STAT_RC_ADDED) + ev->event_type = MPTSAS_ADD_DEVICE; + else + ev->event_type = MPTSAS_DEL_DEVICE; + schedule_work(&ev->work); + break; + case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED: + /* + * Persistent table is full. + */ + INIT_WORK(&ioc->mptscsih_persistTask, + mptscsih_sas_persist_clear_table, + (void *)ioc); + schedule_work(&ioc->mptscsih_persistTask); + break; + case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: + /* TODO */ + case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: + /* TODO */ + default: + break; } - - - INIT_WORK(&ev->work, mptsas_hotplug_work, ev); - ev->ioc = ioc; - ev->handle = le16_to_cpu(sas_event_data->DevHandle); - ev->parent_handle = le16_to_cpu(sas_event_data->ParentDevHandle); - ev->channel = sas_event_data->Bus; - ev->id = sas_event_data->TargetID; - ev->phy_id = sas_event_data->PhyNum; - memcpy(&sas_address, &sas_event_data->SASAddress, sizeof(__le64)); - ev->sas_address = le64_to_cpu(sas_address); - ev->device_info = device_info; - - if (sas_event_data->ReasonCode & MPI_EVENT_SAS_DEV_STAT_RC_ADDED) - ev->event_type = MPTSAS_ADD_DEVICE; - else - ev->event_type = MPTSAS_DEL_DEVICE; - - schedule_work(&ev->work); } static void @@ -1657,16 +1684,6 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc, schedule_work(&ev->work); } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* work queue thread to clear the persitency table */ -static void -mptscsih_sas_persist_clear_table(void * arg) -{ - MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; - - mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT); -} - static int mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) { @@ -1691,6 +1708,7 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) (void *)ioc); schedule_work(&ioc->mptscsih_persistTask); break; + case MPI_EVENT_SAS_DISCOVERY: default: rc = mptscsih_event_process(ioc, reply); break; -- cgit v1.2.3-70-g09d2 From 52435430fc8724f09ad0e917eddf677583cdd45c Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Tue, 14 Mar 2006 09:14:15 -0700 Subject: [SCSI] fusion - exclosure misspelled exclosure should be enclosure Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptsas.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/message/fusion/mptsas.c') diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 84643ac6c70..cea10aa50d4 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -271,7 +271,7 @@ static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy) } static int -mptsas_sas_exclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure, +mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure, u32 form, u32 form_specific) { ConfigExtendedPageHeader_t hdr; @@ -655,7 +655,7 @@ mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier) found_info: mutex_unlock(&ioc->sas_topology_mutex); memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure)); - error = mptsas_sas_exclosure_pg0(ioc, &enclosure_info, + error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info, (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE << MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle); if (!error) -- cgit v1.2.3-70-g09d2 From db9c9174e42bdc8d52bc18df7c55823cf4546eda Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Tue, 14 Mar 2006 09:14:18 -0700 Subject: [SCSI] fusion - memory leak, and initializing fields Changelog: (1) fix memory leak: p->phy_info (2) initialize device_info and port_info data fields (3) initialize the hba firmware handle (4) initialize phy_id for attached phy_info data fields (5) initialize attached phy_info data fields Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptsas.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/message/fusion/mptsas.c') diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index cea10aa50d4..b6a6f27082b 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -749,6 +749,9 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) goto out_free_consistent; } + if (port_info->num_phys) + port_info->handle = + le16_to_cpu(buffer->PhyData[0].ControllerDevHandle); for (i = 0; i < port_info->num_phys; i++) { mptsas_print_phy_data(&buffer->PhyData[i]); port_info->phy_info[i].phy_id = i; @@ -855,6 +858,7 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, cfg.dir = 0; /* read */ cfg.timeout = 10; + memset(device_info, 0, sizeof(struct mptsas_devinfo)); error = mpt_config(ioc, &cfg); if (error) goto out; @@ -925,6 +929,7 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info, cfg.dir = 0; /* read */ cfg.timeout = 10; + memset(port_info, 0, sizeof(struct mptsas_portinfo)); error = mpt_config(ioc, &cfg); if (error) goto out; @@ -1334,6 +1339,8 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index) (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << MPI_SAS_DEVICE_PGAD_FORM_SHIFT), port_info->phy_info[i].attached.handle); + port_info->phy_info[i].attached.phy_id = + port_info->phy_info[i].phy_id; } /* @@ -1360,6 +1367,7 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index) return 0; out_free_port_info: + kfree(port_info->phy_info); kfree(port_info); out: return error; @@ -1485,6 +1493,7 @@ mptsas_hotplug_work(void *arg) if (phy_info->rphy) { sas_rphy_delete(phy_info->rphy); + memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo)); phy_info->rphy = NULL; } break; @@ -1955,6 +1964,8 @@ static void __devexit mptsas_remove(struct pci_dev *pdev) mutex_lock(&ioc->sas_topology_mutex); list_for_each_entry_safe(p, n, &ioc->sas_topology, list) { list_del(&p->list); + if (p->phy_info) + kfree(p->phy_info); kfree(p); } mutex_unlock(&ioc->sas_topology_mutex); -- cgit v1.2.3-70-g09d2 From f44e5461d919a344d44f7ca4f06cf8d169da8454 Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Tue, 14 Mar 2006 09:14:21 -0700 Subject: [SCSI] fusion - exposing raid components in mptsas Suppport for exposing hidden raid components for sg interface. The sdev->no_uld_attach flag will set set accordingly. The sas module supports adding/removing raid volumes using online storage management application interface. This patch rely's on patch's provided to me by Christoph Hellwig, that exports device_reprobe. I will post those patch's on behalf of Christoph. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptsas.c | 112 +++++++++++++++++++++++++++++--------- drivers/message/fusion/mptscsih.c | 21 ++++++- drivers/message/fusion/mptscsih.h | 1 + 3 files changed, 107 insertions(+), 27 deletions(-) (limited to 'drivers/message/fusion/mptsas.c') diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index b6a6f27082b..289fcdbe89b 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -104,6 +104,8 @@ struct mptsas_hotplug_event { u16 handle; u16 parent_handle; 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 sas_phy *phy; struct sas_rphy *rphy; + struct scsi_target *starget; }; struct mptsas_portinfo { @@ -388,6 +391,17 @@ mptsas_slave_alloc(struct scsi_device *sdev) target_id = p->phy_info[i].attached.id; vtarget->bus_id = p->phy_info[i].attached.channel; 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); goto out; } @@ -1378,10 +1392,24 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc) { u32 handle = 0xFFFF; int index = 0; + int i; mptsas_probe_hba_phys(ioc, &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; iraid_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 * @@ -1460,6 +1488,20 @@ mptscsih_sas_persist_clear_table(void * arg) 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 mptsas_hotplug_work(void *arg) { @@ -1470,14 +1512,33 @@ mptsas_hotplug_work(void *arg) struct scsi_device *sdev; char *ds = NULL; struct mptsas_devinfo sas_device; + VirtTarget *vtarget; switch (ev->event_type) { case MPTSAS_DEL_DEVICE: 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; + 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) @@ -1491,11 +1552,10 @@ mptsas_hotplug_work(void *arg) "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); - 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; case MPTSAS_ADD_DEVICE: @@ -1509,16 +1569,27 @@ mptsas_hotplug_work(void *arg) phy_info = mptsas_find_phyinfo_by_parent(ioc, sas_device.handle_parent, sas_device.phy_id); - if (!phy_info) { - printk("mptsas: add event for non-existant PHY.\n"); + if (!phy_info) 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; } + if (phy_info->rphy) + break; + memcpy(&phy_info->attached, &sas_device, sizeof(struct mptsas_devinfo)); @@ -1672,6 +1743,9 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc, ev->event_type = MPTSAS_ADD_DEVICE; break; 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; break; 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); - /* - Reporting RAID volumes. - */ - if (!ioc->raid_data.pIocPg2) - return 0; - if (!ioc->raid_data.pIocPg2->NumActiveVolumes) - return 0; - for (ii=0;iiraid_data.pIocPg2->NumActiveVolumes;ii++) { - scsi_add_device(sh, - ioc->num_ports, - ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID, - 0); - } - return 0; out_mptsas_probe: diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index c99a918feb5..3729062db31 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1235,7 +1235,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) return SCSI_MLQUEUE_HOST_BUSY; } - if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT && + if ((hd->ioc->bus_type == SPI) && + vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT && mptscsih_raid_id_to_num(hd, SCpnt->device->id) < 0) { SCpnt->result = DID_NO_CONNECT << 16; done(SCpnt); @@ -2103,6 +2104,24 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, return 0; } +/* Search IOC page 3 to determine if this is hidden physical disk + * + */ +int +mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) +{ + int i; + + if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3) + return 0; + for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { + if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) + return 1; + } + return 0; +} +EXPORT_SYMBOL(mptscsih_is_phys_disk); + int mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid) { diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 2447a203513..14a5b6c2e2b 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h @@ -100,3 +100,4 @@ extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth); extern void mptscsih_timer_expired(unsigned long data); extern int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout); extern int mptscsih_raid_id_to_num(MPT_SCSI_HOST *hd, uint physdiskid); +extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id); -- cgit v1.2.3-70-g09d2 From e6b2d76a49f0ee48527691867d8af2b8f9c10452 Mon Sep 17 00:00:00 2001 From: "Moore, Eric" Date: Tue, 14 Mar 2006 09:14:24 -0700 Subject: [SCSI] fusion - expander hotplug suport in mptsas module This adds support for hot adding and removing expanders, and its associated attached devices. When there is a change in topology, the fusion firmware sends the MPI_EVENT_SAS_DISCOVERY event to the driver. The driver will read firmware config pages to determine what changes took place, and refresh drivers view of the world stored in ioc->sas_topology. Here is the details of the action the driver does: (1) Expander Added : The mptsas_discovery_work workqueue is called. Config pages read, and ioc->sas_topology is refreshed. The sas_phy_add() is called for each phy of the expander. The expanders attached devices are added via sas_rphy_add(). Added end devices are handled within the MPT_ADD_DEVICE logic in mptsas_hotplug_work workqueue. (2) Expander Delete : The sas_rphy_delete() will be called for the top most compenent of the parent that the expander is attached to. The sas_rphy_delete call will delete all the children phys, rphys, and end devices. This is handled from mptsas_discovery_work workqueue. Signed-off-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.h | 4 + drivers/message/fusion/mptsas.c | 354 +++++++++++++++++++++++++++++++-------- 2 files changed, 289 insertions(+), 69 deletions(-) (limited to 'drivers/message/fusion/mptsas.c') diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 9b58234add3..892af47cb91 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -619,6 +619,10 @@ typedef struct _MPT_ADAPTER struct net_device *netdev; struct list_head sas_topology; struct mutex sas_topology_mutex; + struct mutex sas_discovery_mutex; + u8 sas_discovery_runtime; + u8 sas_discovery_ignore_events; + int sas_index; /* index refrencing */ MPT_SAS_MGMT sas_mgmt; int num_ports; struct work_struct mptscsih_persistTask; diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 289fcdbe89b..be4eb8a308b 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -108,6 +108,11 @@ struct mptsas_hotplug_event { u8 phys_disk_num_valid; }; +struct mptsas_discovery_event { + struct work_struct work; + MPT_ADAPTER *ioc; +}; + /* * SAS topology structures * @@ -163,7 +168,6 @@ struct mptsas_enclosure { u8 sep_channel; /* SEP channel logical channel id */ }; - #ifdef SASDEBUG static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) { @@ -273,6 +277,27 @@ static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy) return ((MPT_SCSI_HOST *)shost->hostdata)->ioc; } +/* + * mptsas_find_portinfo_by_handle + * + * This function should be called with the sas_topology_mutex already held + */ +static struct mptsas_portinfo * +mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle) +{ + struct mptsas_portinfo *port_info, *rc=NULL; + int i; + + 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].identify.handle == handle) { + rc = port_info; + goto out; + } + out: + return rc; +} + static int mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure, u32 form, u32 form_specific) @@ -423,32 +448,8 @@ mptsas_slave_destroy(struct scsi_device *sdev) { struct Scsi_Host *host = sdev->host; MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; - struct sas_rphy *rphy; - struct mptsas_portinfo *p; - int i; VirtDevice *vdev; - /* - * Handle hotplug removal case. - * We need to clear out attached data structure. - */ - rphy = dev_to_rphy(sdev->sdev_target->dev.parent); - - mutex_lock(&hd->ioc->sas_topology_mutex); - list_for_each_entry(p, &hd->ioc->sas_topology, list) { - for (i = 0; i < p->num_phys; i++) { - if (p->phy_info[i].attached.sas_address == - rphy->identify.sas_address) { - memset(&p->phy_info[i].attached, 0, - sizeof(struct mptsas_devinfo)); - p->phy_info[i].rphy = NULL; - goto out; - } - } - } - - out: - mutex_unlock(&hd->ioc->sas_topology_mutex); /* * Issue target reset to flush firmware outstanding commands. */ @@ -1044,7 +1045,6 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle); phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle); - out_free_consistent: pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, buffer, dma_handle); @@ -1134,12 +1134,19 @@ mptsas_parse_device_info(struct sas_identify *identify, static int mptsas_probe_one_phy(struct device *dev, struct mptsas_phyinfo *phy_info, int index, int local) { + MPT_ADAPTER *ioc; struct sas_phy *phy; int error; - phy = sas_phy_alloc(dev, index); - if (!phy) - return -ENOMEM; + if (!dev) + return -ENODEV; + + if (!phy_info->phy) { + phy = sas_phy_alloc(dev, index); + if (!phy) + return -ENOMEM; + } else + phy = phy_info->phy; phy->port_identifier = phy_info->port_id; mptsas_parse_device_info(&phy->identify, &phy_info->identify); @@ -1225,19 +1232,35 @@ static int mptsas_probe_one_phy(struct device *dev, break; } - if (local) - phy->local_attached = 1; + if (!phy_info->phy) { - error = sas_phy_add(phy); - if (error) { - sas_phy_free(phy); - return error; + if (local) + phy->local_attached = 1; + + error = sas_phy_add(phy); + if (error) { + sas_phy_free(phy); + return error; + } + phy_info->phy = phy; } - phy_info->phy = phy; - if (phy_info->attached.handle) { + if ((phy_info->attached.handle) && + (!phy_info->rphy)) { + struct sas_rphy *rphy; + ioc = phy_to_ioc(phy_info->phy); + + /* + * Let the hotplug_work thread handle processing + * the adding/removing of devices that occur + * after start of day. + */ + if (ioc->sas_discovery_runtime && + mptsas_is_end_device(&phy_info->attached)) + return 0; + rphy = sas_rphy_alloc(phy); if (!rphy) return 0; /* non-fatal: an rphy can be added later */ @@ -1256,24 +1279,37 @@ static int mptsas_probe_one_phy(struct device *dev, } static int -mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index) +mptsas_probe_hba_phys(MPT_ADAPTER *ioc) { - struct mptsas_portinfo *port_info; + struct mptsas_portinfo *port_info, *hba; u32 handle = 0xFFFF; int error = -ENOMEM, i; - port_info = kzalloc(sizeof(*port_info), GFP_KERNEL); - if (!port_info) + hba = kzalloc(sizeof(*port_info), GFP_KERNEL); + if (! hba) goto out; - error = mptsas_sas_io_unit_pg0(ioc, port_info); + error = mptsas_sas_io_unit_pg0(ioc, hba); if (error) goto out_free_port_info; - ioc->num_ports = port_info->num_phys; mutex_lock(&ioc->sas_topology_mutex); - list_add_tail(&port_info->list, &ioc->sas_topology); + port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle); + if (!port_info) { + port_info = hba; + list_add_tail(&port_info->list, &ioc->sas_topology); + } else { + port_info->handle = hba->handle; + for (i = 0; i < hba->num_phys; i++) + port_info->phy_info[i].negotiated_link_rate = + hba->phy_info[i].negotiated_link_rate; + if (hba->phy_info) + kfree(hba->phy_info); + kfree(hba); + hba = NULL; + } mutex_unlock(&ioc->sas_topology_mutex); + ioc->num_ports = port_info->num_phys; for (i = 0; i < port_info->num_phys; i++) { mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i], @@ -1296,38 +1332,49 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index) } mptsas_probe_one_phy(&ioc->sh->shost_gendev, - &port_info->phy_info[i], *index, 1); - (*index)++; + &port_info->phy_info[i], ioc->sas_index, 1); + ioc->sas_index++; } return 0; out_free_port_info: - kfree(port_info); + if (hba) + kfree(hba); out: return error; } static int -mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index) +mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle) { - struct mptsas_portinfo *port_info, *p; + struct mptsas_portinfo *port_info, *p, *ex; int error = -ENOMEM, i, j; - port_info = kzalloc(sizeof(*port_info), GFP_KERNEL); - if (!port_info) + ex = kzalloc(sizeof(*port_info), GFP_KERNEL); + if (!ex) goto out; - error = mptsas_sas_expander_pg0(ioc, port_info, + error = mptsas_sas_expander_pg0(ioc, ex, (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE << MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle); if (error) goto out_free_port_info; - *handle = port_info->handle; + *handle = ex->handle; mutex_lock(&ioc->sas_topology_mutex); - list_add_tail(&port_info->list, &ioc->sas_topology); + port_info = mptsas_find_portinfo_by_handle(ioc, *handle); + if (!port_info) { + port_info = ex; + list_add_tail(&port_info->list, &ioc->sas_topology); + } else { + port_info->handle = ex->handle; + if (ex->phy_info) + kfree(ex->phy_info); + kfree(ex); + ex = NULL; + } mutex_unlock(&ioc->sas_topology_mutex); for (i = 0; i < port_info->num_phys; i++) { @@ -1374,28 +1421,101 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index) mutex_unlock(&ioc->sas_topology_mutex); mptsas_probe_one_phy(parent, &port_info->phy_info[i], - *index, 0); - (*index)++; + ioc->sas_index, 0); + ioc->sas_index++; } return 0; out_free_port_info: - kfree(port_info->phy_info); - kfree(port_info); + if (ex) { + if (ex->phy_info) + kfree(ex->phy_info); + kfree(ex); + } out: return error; } +/* + * mptsas_delete_expander_phys + * + * + * This will traverse topology, and remove expanders + * that are no longer present + */ +static void +mptsas_delete_expander_phys(MPT_ADAPTER *ioc) +{ + struct mptsas_portinfo buffer; + struct mptsas_portinfo *port_info, *n, *parent; + int i; + + mutex_lock(&ioc->sas_topology_mutex); + list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) { + + if (port_info->phy_info && + (!(port_info->phy_info[0].identify.device_info & + MPI_SAS_DEVICE_INFO_SMP_TARGET))) + continue; + + if (mptsas_sas_expander_pg0(ioc, &buffer, + (MPI_SAS_EXPAND_PGAD_FORM_HANDLE << + MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) { + + /* + * Obtain the port_info instance to the parent port + */ + parent = mptsas_find_portinfo_by_handle(ioc, + port_info->phy_info[0].identify.handle_parent); + + if (!parent) + goto next_port; + + /* + * Delete rphys in the parent that point + * to this expander. The transport layer will + * cleanup all the children. + */ + for (i = 0; i < parent->num_phys; i++) { + if ((!parent->phy_info[i].rphy) || + (parent->phy_info[i].attached.sas_address != + port_info->phy_info[i].identify.sas_address)) + continue; + sas_rphy_delete(parent->phy_info[i].rphy); + memset(&parent->phy_info[i].attached, 0, + sizeof(struct mptsas_devinfo)); + parent->phy_info[i].rphy = NULL; + parent->phy_info[i].starget = NULL; + } + next_port: + list_del(&port_info->list); + if (port_info->phy_info) + kfree(port_info->phy_info); + kfree(port_info); + } + /* + * Free this memory allocated from inside + * mptsas_sas_expander_pg0 + */ + if (buffer.phy_info) + kfree(buffer.phy_info); + } + mutex_unlock(&ioc->sas_topology_mutex); +} + +/* + * Start of day discovery + */ static void mptsas_scan_sas_topology(MPT_ADAPTER *ioc) { u32 handle = 0xFFFF; - int index = 0; int i; - mptsas_probe_hba_phys(ioc, &index); - while (!mptsas_probe_expander_phys(ioc, &handle, &index)) + mutex_lock(&ioc->sas_discovery_mutex); + mptsas_probe_hba_phys(ioc); + while (!mptsas_probe_expander_phys(ioc, &handle)) ; /* Reporting RAID volumes. @@ -1409,7 +1529,29 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc) ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0); } out: - return; + mutex_unlock(&ioc->sas_discovery_mutex); +} + +/* + * Work queue thread to handle Runtime discovery + * Mere purpose is the hot add/delete of expanders + */ +static void +mptscsih_discovery_work(void * arg) +{ + struct mptsas_discovery_event *ev = arg; + MPT_ADAPTER *ioc = ev->ioc; + u32 handle = 0xFFFF; + + mutex_lock(&ioc->sas_discovery_mutex); + ioc->sas_discovery_runtime=1; + mptsas_delete_expander_phys(ioc); + mptsas_probe_hba_phys(ioc); + while (!mptsas_probe_expander_phys(ioc, &handle)) + ; + kfree(ev); + ioc->sas_discovery_runtime=0; + mutex_unlock(&ioc->sas_discovery_mutex); } static struct mptsas_phyinfo * @@ -1427,10 +1569,8 @@ mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id) (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << MPI_SAS_DEVICE_PGAD_FORM_SHIFT), parent_handle); - if (error) { - printk("mptsas: failed to retrieve device page\n"); + if (error) return NULL; - } /* * The phy_info structures are never deallocated during lifetime of @@ -1502,6 +1642,10 @@ mptsas_reprobe_target(struct scsi_target *starget, int uld_attach) mptsas_reprobe_lun); } + +/* + * Work queue thread to handle SAS hotplug events + */ static void mptsas_hotplug_work(void *arg) { @@ -1514,10 +1658,13 @@ mptsas_hotplug_work(void *arg) struct mptsas_devinfo sas_device; VirtTarget *vtarget; + mutex_lock(&ioc->sas_discovery_mutex); + switch (ev->event_type) { case MPTSAS_DEL_DEVICE: phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id); + /* * Sanity checks, for non-existing phys and remote rphys. */ @@ -1569,8 +1716,36 @@ mptsas_hotplug_work(void *arg) phy_info = mptsas_find_phyinfo_by_parent(ioc, sas_device.handle_parent, sas_device.phy_id); - if (!phy_info) - break; + + if (!phy_info) { + u32 handle = 0xFFFF; + + /* + * Its possible when an expander has been hot added + * containing attached devices, the sas firmware + * may send a RC_ADDED event prior to the + * DISCOVERY STOP event. If that occurs, our + * view of the topology in the driver in respect to this + * expander might of not been setup, and we hit this + * condition. + * Therefore, this code kicks off discovery to + * refresh the data. + * Then again, we check whether the parent phy has + * been created. + */ + ioc->sas_discovery_runtime=1; + mptsas_delete_expander_phys(ioc); + mptsas_probe_hba_phys(ioc); + while (!mptsas_probe_expander_phys(ioc, &handle)) + ; + ioc->sas_discovery_runtime=0; + + phy_info = mptsas_find_phyinfo_by_parent(ioc, + sas_device.handle_parent, sas_device.phy_id); + if (!phy_info) + break; + } + if (phy_info->starget) { vtarget = phy_info->starget->hostdata; @@ -1604,7 +1779,6 @@ mptsas_hotplug_work(void *arg) "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 */ @@ -1654,6 +1828,7 @@ mptsas_hotplug_work(void *arg) } kfree(ev); + mutex_unlock(&ioc->sas_discovery_mutex); } static void @@ -1767,6 +1942,32 @@ mptscsih_send_raid_event(MPT_ADAPTER *ioc, schedule_work(&ev->work); } +static void +mptscsih_send_discovery(MPT_ADAPTER *ioc, + EVENT_DATA_SAS_DISCOVERY *discovery_data) +{ + struct mptsas_discovery_event *ev; + + /* + * DiscoveryStatus + * + * This flag will be non-zero when firmware + * kicks off discovery, and return to zero + * once its completed. + */ + if (discovery_data->DiscoveryStatus) + return; + + ev = kmalloc(sizeof(*ev), GFP_ATOMIC); + if (!ev) + return; + memset(ev,0,sizeof(struct mptsas_discovery_event)); + INIT_WORK(&ev->work, mptscsih_discovery_work, ev); + ev->ioc = ioc; + schedule_work(&ev->work); +}; + + static int mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) { @@ -1776,6 +1977,17 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) if (!ioc->sh) goto out; + /* + * sas_discovery_ignore_events + * + * This flag is to prevent anymore processing of + * sas events once mptsas_remove function is called. + */ + if (ioc->sas_discovery_ignore_events) { + rc = mptscsih_event_process(ioc, reply); + goto out; + } + switch (event) { case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: mptscsih_send_sas_event(ioc, @@ -1792,6 +2004,9 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) schedule_work(&ioc->mptscsih_persistTask); break; case MPI_EVENT_SAS_DISCOVERY: + mptscsih_send_discovery(ioc, + (EVENT_DATA_SAS_DISCOVERY *)reply->Data); + break; default: rc = mptscsih_event_process(ioc, reply); break; @@ -1893,7 +2108,7 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) INIT_LIST_HEAD(&ioc->sas_topology); mutex_init(&ioc->sas_topology_mutex); - + mutex_init(&ioc->sas_discovery_mutex); mutex_init(&ioc->sas_mgmt.mutex); init_completion(&ioc->sas_mgmt.done); @@ -2019,6 +2234,7 @@ static void __devexit mptsas_remove(struct pci_dev *pdev) MPT_ADAPTER *ioc = pci_get_drvdata(pdev); struct mptsas_portinfo *p, *n; + ioc->sas_discovery_ignore_events=1; sas_remove_host(ioc->sh); mutex_lock(&ioc->sas_topology_mutex); -- cgit v1.2.3-70-g09d2 From f013db3284376070fc4c196e58d204180b8ed62a Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 18 Mar 2006 14:54:36 -0600 Subject: [SCSI] convert mptsas over to end_device/expander allocations The conversion of mptsas should allow the elimination of the contained flag in the sas transport class. Acked-by: "Moore, Eric" Signed-off-by: James Bottomley --- drivers/message/fusion/mptsas.c | 45 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) (limited to 'drivers/message/fusion/mptsas.c') diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index be4eb8a308b..010d4a39269 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -363,6 +363,14 @@ mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure, return error; } +static int +mptsas_slave_configure(struct scsi_device *sdev) +{ + sas_read_port_mode_page(sdev); + + return mptscsih_slave_configure(sdev); +} + /* * This is pretty ugly. We will be able to seriously clean it up * once the DV code in mptscsih goes away and we can properly @@ -486,7 +494,7 @@ static struct scsi_host_template mptsas_driver_template = { .queuecommand = mptscsih_qcmd, .target_alloc = mptscsih_target_alloc, .slave_alloc = mptsas_slave_alloc, - .slave_configure = mptscsih_slave_configure, + .slave_configure = mptsas_slave_configure, .target_destroy = mptscsih_target_destroy, .slave_destroy = mptsas_slave_destroy, .change_queue_depth = mptscsih_change_queue_depth, @@ -1249,6 +1257,7 @@ static int mptsas_probe_one_phy(struct device *dev, (!phy_info->rphy)) { struct sas_rphy *rphy; + struct sas_identify identify; ioc = phy_to_ioc(phy_info->phy); @@ -1261,11 +1270,24 @@ static int mptsas_probe_one_phy(struct device *dev, mptsas_is_end_device(&phy_info->attached)) return 0; - rphy = sas_rphy_alloc(phy); + mptsas_parse_device_info(&identify, &phy_info->attached); + switch (identify.device_type) { + case SAS_END_DEVICE: + rphy = sas_end_device_alloc(phy); + break; + case SAS_EDGE_EXPANDER_DEVICE: + case SAS_FANOUT_EXPANDER_DEVICE: + rphy = sas_expander_alloc(phy, identify.device_type); + break; + default: + rphy = NULL; + break; + } if (!rphy) return 0; /* non-fatal: an rphy can be added later */ - mptsas_parse_device_info(&rphy->identify, &phy_info->attached); + rphy->identify = identify; + error = sas_rphy_add(rphy); if (error) { sas_rphy_free(rphy); @@ -1654,6 +1676,7 @@ mptsas_hotplug_work(void *arg) struct mptsas_phyinfo *phy_info; struct sas_rphy *rphy; struct scsi_device *sdev; + struct sas_identify identify; char *ds = NULL; struct mptsas_devinfo sas_device; VirtTarget *vtarget; @@ -1779,11 +1802,23 @@ mptsas_hotplug_work(void *arg) "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); + mptsas_parse_device_info(&identify, &phy_info->attached); + switch (identify.device_type) { + case SAS_END_DEVICE: + rphy = sas_end_device_alloc(phy_info->phy); + break; + case SAS_EDGE_EXPANDER_DEVICE: + case SAS_FANOUT_EXPANDER_DEVICE: + rphy = sas_expander_alloc(phy_info->phy, identify.device_type); + break; + default: + rphy = NULL; + break; + } if (!rphy) break; /* non-fatal: an rphy can be added later */ - mptsas_parse_device_info(&rphy->identify, &phy_info->attached); + rphy->identify = identify; if (sas_rphy_add(rphy)) { sas_rphy_free(rphy); break; -- cgit v1.2.3-70-g09d2