X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fmessage%2Ffusion%2Fmptsas.c;h=af6ec553ff7ca54c3cf4ee14c7e43e32cd9e73a2;hb=9464c7cf61b9433057924c36e6e02f303a00e768;hp=f66f2203143a8435c8e84840a12204afefda76ba;hpb=41689045f6a3cbe0550e1d34e9cc20d2e8c432ba;p=linux-2.6.git diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index f66f22031..af6ec553f 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -50,14 +50,11 @@ #include #include #include -#include /* for mdelay */ -#include #include #include #include #include -#include #include "mptbase.h" #include "mptscsih.h" @@ -67,19 +64,20 @@ #define my_VERSION MPT_LINUX_VERSION_COMMON #define MYNAM "mptsas" -/* - * Reserved channel for integrated raid - */ -#define MPTSAS_RAID_CHANNEL 1 - MODULE_AUTHOR(MODULEAUTHOR); MODULE_DESCRIPTION(my_NAME); MODULE_LICENSE("GPL"); +static int mpt_pq_filter; +module_param(mpt_pq_filter, int, 0); +MODULE_PARM_DESC(mpt_pq_filter, + "Enable peripheral qualifier filter: enable=1 " + "(default=0)"); + static int mpt_pt_clear; module_param(mpt_pt_clear, int, 0); MODULE_PARM_DESC(mpt_pt_clear, - " Clear persistency table: enable=1 " + "Clear persistency table: enable=1 " "(default=MPTSCSIH_PT_CLEAR=0)"); static int mptsasDoneCtx = -1; @@ -139,36 +137,23 @@ struct mptsas_devinfo { u32 device_info; /* bitfield detailed info about this device */ }; -/* - * Specific details on ports, wide/narrow - */ -struct mptsas_portinfo_details{ - u16 num_phys; /* number of phys belong to this port */ - u64 phy_bitmask; /* TODO, extend support for 255 phys */ - struct sas_rphy *rphy; /* transport layer rphy object */ - struct sas_port *port; /* transport layer port object */ - struct scsi_target *starget; - struct mptsas_portinfo *port_info; -}; - struct mptsas_phyinfo { u8 phy_id; /* phy index */ - u8 port_id; /* firmware port identifier */ + u8 port_id; /* port number this phy is part of */ u8 negotiated_link_rate; /* nego'd link rate for this phy */ u8 hw_link_rate; /* hardware max/min phys link rate */ u8 programmed_link_rate; /* programmed max/min phy link rate */ - u8 sas_port_add_phy; /* flag to request sas_port_add_phy*/ struct mptsas_devinfo identify; /* point to phy device info */ struct mptsas_devinfo attached; /* point to attached device info */ - struct sas_phy *phy; /* transport layer phy object */ - struct mptsas_portinfo *portinfo; - struct mptsas_portinfo_details * port_details; + struct sas_phy *phy; + struct sas_rphy *rphy; + struct scsi_target *starget; }; struct mptsas_portinfo { struct list_head list; u16 handle; /* unique id to address this */ - u16 num_phys; /* number of phys */ + u8 num_phys; /* number of phys */ struct mptsas_phyinfo *phy_info; }; @@ -184,7 +169,7 @@ struct mptsas_enclosure { u8 sep_channel; /* SEP channel logical channel id */ }; -#ifdef MPT_DEBUG_SAS +#ifdef SASDEBUG static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) { printk("---- IO UNIT PAGE 0 ------------\n"); @@ -320,7 +305,7 @@ mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle) static inline int mptsas_is_end_device(struct mptsas_devinfo * attached) { - if ((attached->sas_address) && + if ((attached->handle) && (attached->device_info & MPI_SAS_DEVICE_INFO_END_DEVICE) && ((attached->device_info & @@ -334,247 +319,6 @@ mptsas_is_end_device(struct mptsas_devinfo * attached) return 0; } -/* no mutex */ -static void -mptsas_port_delete(struct mptsas_portinfo_details * port_details) -{ - struct mptsas_portinfo *port_info; - struct mptsas_phyinfo *phy_info; - u8 i; - - if (!port_details) - return; - - port_info = port_details->port_info; - phy_info = port_info->phy_info; - - dsaswideprintk((KERN_DEBUG "%s: [%p]: num_phys=%02d " - "bitmask=0x%016llX\n", - __FUNCTION__, port_details, port_details->num_phys, - port_details->phy_bitmask)); - - for (i = 0; i < port_info->num_phys; i++, phy_info++) { - if(phy_info->port_details != port_details) - continue; - memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo)); - phy_info->port_details = NULL; - } - kfree(port_details); -} - -static inline struct sas_rphy * -mptsas_get_rphy(struct mptsas_phyinfo *phy_info) -{ - if (phy_info->port_details) - return phy_info->port_details->rphy; - else - return NULL; -} - -static inline void -mptsas_set_rphy(struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy) -{ - if (phy_info->port_details) { - phy_info->port_details->rphy = rphy; - dsaswideprintk((KERN_DEBUG "sas_rphy_add: rphy=%p\n", rphy)); - } - -#ifdef MPT_DEBUG_SAS_WIDE - if (rphy) { - dev_printk(KERN_DEBUG, &rphy->dev, "add:"); - printk("rphy=%p release=%p\n", - rphy, rphy->dev.release); - } -#endif -} - -static inline struct sas_port * -mptsas_get_port(struct mptsas_phyinfo *phy_info) -{ - if (phy_info->port_details) - return phy_info->port_details->port; - else - return NULL; -} - -static inline void -mptsas_set_port(struct mptsas_phyinfo *phy_info, struct sas_port *port) -{ - if (phy_info->port_details) - phy_info->port_details->port = port; - -#ifdef MPT_DEBUG_SAS_WIDE - if (port) { - dev_printk(KERN_DEBUG, &port->dev, "add: "); - printk("port=%p release=%p\n", - port, port->dev.release); - } -#endif -} - -static inline struct scsi_target * -mptsas_get_starget(struct mptsas_phyinfo *phy_info) -{ - if (phy_info->port_details) - return phy_info->port_details->starget; - else - return NULL; -} - -static inline void -mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target * -starget) -{ - if (phy_info->port_details) - phy_info->port_details->starget = starget; -} - - -/* - * mptsas_setup_wide_ports - * - * Updates for new and existing narrow/wide port configuration - * in the sas_topology - */ -static void -mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) -{ - struct mptsas_portinfo_details * port_details; - struct mptsas_phyinfo *phy_info, *phy_info_cmp; - u64 sas_address; - int i, j; - - mutex_lock(&ioc->sas_topology_mutex); - - phy_info = port_info->phy_info; - for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) { - if (phy_info->attached.handle) - continue; - port_details = phy_info->port_details; - if (!port_details) - continue; - if (port_details->num_phys < 2) - continue; - /* - * Removing a phy from a port, letting the last - * phy be removed by firmware events. - */ - dsaswideprintk((KERN_DEBUG - "%s: [%p]: deleting phy = %d\n", - __FUNCTION__, port_details, i)); - port_details->num_phys--; - port_details->phy_bitmask &= ~ (1 << phy_info->phy_id); - memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo)); - sas_port_delete_phy(port_details->port, phy_info->phy); - phy_info->port_details = NULL; - } - - /* - * Populate and refresh the tree - */ - phy_info = port_info->phy_info; - for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) { - sas_address = phy_info->attached.sas_address; - dsaswideprintk((KERN_DEBUG "phy_id=%d sas_address=0x%018llX\n", - i, sas_address)); - if (!sas_address) - continue; - port_details = phy_info->port_details; - /* - * Forming a port - */ - if (!port_details) { - port_details = kzalloc(sizeof(*port_details), - GFP_KERNEL); - if (!port_details) - goto out; - port_details->num_phys = 1; - port_details->port_info = port_info; - if (phy_info->phy_id < 64 ) - port_details->phy_bitmask |= - (1 << phy_info->phy_id); - phy_info->sas_port_add_phy=1; - dsaswideprintk((KERN_DEBUG "\t\tForming port\n\t\t" - "phy_id=%d sas_address=0x%018llX\n", - i, sas_address)); - phy_info->port_details = port_details; - } - - if (i == port_info->num_phys - 1) - continue; - phy_info_cmp = &port_info->phy_info[i + 1]; - for (j = i + 1 ; j < port_info->num_phys ; j++, - phy_info_cmp++) { - if (!phy_info_cmp->attached.sas_address) - continue; - if (sas_address != phy_info_cmp->attached.sas_address) - continue; - if (phy_info_cmp->port_details == port_details ) - continue; - dsaswideprintk((KERN_DEBUG - "\t\tphy_id=%d sas_address=0x%018llX\n", - j, phy_info_cmp->attached.sas_address)); - if (phy_info_cmp->port_details) { - port_details->rphy = - mptsas_get_rphy(phy_info_cmp); - port_details->port = - mptsas_get_port(phy_info_cmp); - port_details->starget = - mptsas_get_starget(phy_info_cmp); - port_details->num_phys = - phy_info_cmp->port_details->num_phys; - if (!phy_info_cmp->port_details->num_phys) - kfree(phy_info_cmp->port_details); - } else - phy_info_cmp->sas_port_add_phy=1; - /* - * Adding a phy to a port - */ - phy_info_cmp->port_details = port_details; - if (phy_info_cmp->phy_id < 64 ) - port_details->phy_bitmask |= - (1 << phy_info_cmp->phy_id); - port_details->num_phys++; - } - } - - out: - -#ifdef MPT_DEBUG_SAS_WIDE - for (i = 0; i < port_info->num_phys; i++) { - port_details = port_info->phy_info[i].port_details; - if (!port_details) - continue; - dsaswideprintk((KERN_DEBUG - "%s: [%p]: phy_id=%02d num_phys=%02d " - "bitmask=0x%016llX\n", - __FUNCTION__, - port_details, i, port_details->num_phys, - port_details->phy_bitmask)); - dsaswideprintk((KERN_DEBUG"\t\tport = %p rphy=%p\n", - port_details->port, port_details->rphy)); - } - dsaswideprintk((KERN_DEBUG"\n")); -#endif - mutex_unlock(&ioc->sas_topology_mutex); -} - -static void -mptsas_target_reset(MPT_ADAPTER *ioc, VirtTarget * vtarget) -{ - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; - - if (mptscsih_TMHandler(hd, - MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, - vtarget->bus_id, vtarget->target_id, 0, 0, 5) < 0) { - hd->tmPending = 0; - hd->tmState = TM_STATE_NONE; - printk(MYIOC_s_WARN_FMT - "Error processing TaskMgmt id=%d TARGET_RESET\n", - ioc->name, vtarget->target_id); - } -} - static int mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure, u32 form, u32 form_specific) @@ -643,112 +387,24 @@ mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure, static int mptsas_slave_configure(struct scsi_device *sdev) { - - if (sdev->channel == MPTSAS_RAID_CHANNEL) - goto out; - - sas_read_port_mode_page(sdev); - - out: - return mptscsih_slave_configure(sdev); -} - -static int -mptsas_target_alloc(struct scsi_target *starget) -{ - struct Scsi_Host *host = dev_to_shost(&starget->dev); - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; - VirtTarget *vtarget; - u32 target_id; - u32 channel; - struct sas_rphy *rphy; - struct mptsas_portinfo *p; - int i; - - vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL); - if (!vtarget) - return -ENOMEM; - - vtarget->starget = starget; - vtarget->ioc_id = hd->ioc->id; - vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY; - - target_id = starget->id; - channel = 0; - - hd->Targets[target_id] = vtarget; - - if (starget->channel == MPTSAS_RAID_CHANNEL) - goto out; - - rphy = dev_to_rphy(starget->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) - continue; - target_id = p->phy_info[i].attached.id; - channel = p->phy_info[i].attached.channel; - mptsas_set_starget(&p->phy_info[i], starget); - - /* - * Exposing hidden raid components - */ - if (mptscsih_is_phys_disk(hd->ioc, target_id)) { - target_id = mptscsih_raid_id_to_num(hd, - target_id); - vtarget->tflags |= - MPT_TARGET_FLAGS_RAID_COMPONENT; - } - mutex_unlock(&hd->ioc->sas_topology_mutex); - goto out; - } - } - mutex_unlock(&hd->ioc->sas_topology_mutex); - - kfree(vtarget); - return -ENXIO; - - out: - vtarget->target_id = target_id; - vtarget->bus_id = channel; - starget->hostdata = vtarget; - return 0; -} - -static void -mptsas_target_destroy(struct scsi_target *starget) -{ - struct Scsi_Host *host = dev_to_shost(&starget->dev); + 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; - if (!starget->hostdata) - return; - - if (starget->channel == MPTSAS_RAID_CHANNEL) - goto out; - - rphy = dev_to_rphy(starget->dev.parent); - 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) - continue; - mptsas_set_starget(&p->phy_info[i], NULL); - goto out; - } - } + /* + * RAID volumes placed beyond the last expected port. + * Ignore sending sas mode pages in that case.. + */ + if (sdev->channel < hd->ioc->num_ports) + sas_read_port_mode_page(sdev); - out: - kfree(starget->hostdata); - starget->hostdata = NULL; + 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 + * implement ->target_alloc. + */ static int mptsas_slave_alloc(struct scsi_device *sdev) { @@ -756,38 +412,61 @@ mptsas_slave_alloc(struct scsi_device *sdev) MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; struct sas_rphy *rphy; struct mptsas_portinfo *p; + VirtTarget *vtarget; VirtDevice *vdev; struct scsi_target *starget; - int i; + u32 target_id; + int i; vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL); if (!vdev) { - printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n", + printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", hd->ioc->name, sizeof(VirtDevice)); return -ENOMEM; } + sdev->hostdata = vdev; starget = scsi_target(sdev); - vdev->vtarget = starget->hostdata; + 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; + hd->Targets[sdev->id] = vtarget; + } - if (sdev->channel == MPTSAS_RAID_CHANNEL) + /* + RAID volumes placed beyond the last expected port. + */ + if (sdev->channel == hd->ioc->num_ports) { + target_id = sdev->id; + vtarget->bus_id = 0; + vdev->lun = 0; goto out; + } 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) - continue; - vdev->lun = sdev->lun; - /* - * Exposing hidden raid components - */ - if (mptscsih_is_phys_disk(hd->ioc, - p->phy_info[i].attached.id)) - sdev->no_uld_attach = 1; - mutex_unlock(&hd->ioc->sas_topology_mutex); - goto out; + if (p->phy_info[i].attached.sas_address == + rphy->identify.sas_address) { + 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; + } } } mutex_unlock(&hd->ioc->sas_topology_mutex); @@ -796,39 +475,57 @@ mptsas_slave_alloc(struct scsi_device *sdev) return -ENXIO; out: - vdev->vtarget->num_luns++; - sdev->hostdata = vdev; + vtarget->target_id = target_id; + vtarget->num_luns++; return 0; } -static int -mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) +static void +mptsas_slave_destroy(struct scsi_device *sdev) { - VirtDevice *vdev = SCpnt->device->hostdata; + struct Scsi_Host *host = sdev->host; + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + VirtDevice *vdev; -// scsi_print_command(SCpnt); - if (vdev->vtarget->deleted) { - SCpnt->result = DID_NO_CONNECT << 16; - done(SCpnt); - return 0; - } + /* + * Issue target reset to flush firmware outstanding commands. + */ + vdev = sdev->hostdata; + if (vdev->configured_lun){ + if (mptscsih_TMHandler(hd, + MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, + vdev->vtarget->bus_id, + vdev->vtarget->target_id, + 0, 0, 5 /* 5 second timeout */) + < 0){ + + /* The TM request failed! + * Fatal error case. + */ + printk(MYIOC_s_WARN_FMT + "Error processing TaskMgmt id=%d TARGET_RESET\n", + hd->ioc->name, + vdev->vtarget->target_id); - return mptscsih_qcmd(SCpnt,done); + hd->tmPending = 0; + hd->tmState = TM_STATE_NONE; + } + } + mptscsih_slave_destroy(sdev); } - static struct scsi_host_template mptsas_driver_template = { .module = THIS_MODULE, .proc_name = "mptsas", .proc_info = mptscsih_proc_info, .name = "MPT SPI Host", .info = mptscsih_info, - .queuecommand = mptsas_qcmd, - .target_alloc = mptsas_target_alloc, + .queuecommand = mptscsih_qcmd, + .target_alloc = mptscsih_target_alloc, .slave_alloc = mptsas_slave_alloc, .slave_configure = mptsas_slave_configure, - .target_destroy = mptsas_target_destroy, - .slave_destroy = mptscsih_slave_destroy, + .target_destroy = mptscsih_target_destroy, + .slave_destroy = mptsas_slave_destroy, .change_queue_depth = mptscsih_change_queue_depth, .eh_abort_handler = mptscsih_abort, .eh_device_reset_handler = mptscsih_dev_reset, @@ -1098,7 +795,7 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) port_info->num_phys = buffer->NumPhys; port_info->phy_info = kcalloc(port_info->num_phys, - sizeof(*port_info->phy_info),GFP_KERNEL); + sizeof(struct mptsas_phyinfo),GFP_KERNEL); if (!port_info->phy_info) { error = -ENOMEM; goto out_free_consistent; @@ -1114,7 +811,6 @@ mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) buffer->PhyData[i].Port; port_info->phy_info[i].negotiated_link_rate = buffer->PhyData[i].NegotiatedLinkRate; - port_info->phy_info[i].portinfo = port_info; } out_free_consistent: @@ -1272,7 +968,7 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info, CONFIGPARMS cfg; SasExpanderPage0_t *buffer; dma_addr_t dma_handle; - int i, error; + int error; hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION; hdr.ExtPageLength = 0; @@ -1317,15 +1013,12 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info, port_info->num_phys = buffer->NumPhys; port_info->handle = le16_to_cpu(buffer->DevHandle); port_info->phy_info = kcalloc(port_info->num_phys, - sizeof(*port_info->phy_info),GFP_KERNEL); + sizeof(struct mptsas_phyinfo),GFP_KERNEL); if (!port_info->phy_info) { error = -ENOMEM; goto out_free_consistent; } - for (i = 0; i < port_info->num_phys; i++) - port_info->phy_info[i].portinfo = port_info; - out_free_consistent: pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, buffer, dma_handle); @@ -1468,23 +1161,19 @@ static int mptsas_probe_one_phy(struct device *dev, { MPT_ADAPTER *ioc; struct sas_phy *phy; - struct sas_port *port; - int error = 0; + int error; - if (!dev) { - error = -ENODEV; - goto out; - } + if (!dev) + return -ENODEV; if (!phy_info->phy) { phy = sas_phy_alloc(dev, index); - if (!phy) { - error = -ENOMEM; - goto out; - } + 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); /* @@ -1576,51 +1265,19 @@ static int mptsas_probe_one_phy(struct device *dev, error = sas_phy_add(phy); if (error) { sas_phy_free(phy); - goto out; + return error; } phy_info->phy = phy; } - if (!phy_info->attached.handle || - !phy_info->port_details) - goto out; - - port = mptsas_get_port(phy_info); - ioc = phy_to_ioc(phy_info->phy); - - if (phy_info->sas_port_add_phy) { - - if (!port) { - port = sas_port_alloc_num(dev); - if (!port) { - error = -ENOMEM; - goto out; - } - error = sas_port_add(port); - if (error) { - dfailprintk((MYIOC_s_ERR_FMT - "%s: exit at line=%d\n", ioc->name, - __FUNCTION__, __LINE__)); - goto out; - } - mptsas_set_port(phy_info, port); - dsaswideprintk((KERN_DEBUG - "sas_port_alloc: port=%p dev=%p port_id=%d\n", - port, dev, port->port_identifier)); - } - dsaswideprintk((KERN_DEBUG "sas_port_add_phy: phy_id=%d\n", - phy_info->phy_id)); - sas_port_add_phy(port, phy_info->phy); - phy_info->sas_port_add_phy = 0; - } - - if (!mptsas_get_rphy(phy_info) && port && !port->rphy) { + if ((phy_info->attached.handle) && + (!phy_info->rphy)) { struct sas_rphy *rphy; - struct device *parent; struct sas_identify identify; - parent = dev->parent->parent; + ioc = phy_to_ioc(phy_info->phy); + /* * Let the hotplug_work thread handle processing * the adding/removing of devices that occur @@ -1628,63 +1285,36 @@ static int mptsas_probe_one_phy(struct device *dev, */ if (ioc->sas_discovery_runtime && mptsas_is_end_device(&phy_info->attached)) - goto out; + return 0; mptsas_parse_device_info(&identify, &phy_info->attached); - if (scsi_is_host_device(parent)) { - struct mptsas_portinfo *port_info; - int i; - - mutex_lock(&ioc->sas_topology_mutex); - port_info = mptsas_find_portinfo_by_handle(ioc, - ioc->handle); - mutex_unlock(&ioc->sas_topology_mutex); - - for (i = 0; i < port_info->num_phys; i++) - if (port_info->phy_info[i].identify.sas_address == - identify.sas_address) - goto out; - - } else if (scsi_is_sas_rphy(parent)) { - struct sas_rphy *parent_rphy = dev_to_rphy(parent); - if (identify.sas_address == - parent_rphy->identify.sas_address) - goto out; - } - switch (identify.device_type) { case SAS_END_DEVICE: - rphy = sas_end_device_alloc(port); + rphy = sas_end_device_alloc(phy); break; case SAS_EDGE_EXPANDER_DEVICE: case SAS_FANOUT_EXPANDER_DEVICE: - rphy = sas_expander_alloc(port, identify.device_type); + rphy = sas_expander_alloc(phy, identify.device_type); break; default: rphy = NULL; break; } - if (!rphy) { - dfailprintk((MYIOC_s_ERR_FMT - "%s: exit at line=%d\n", ioc->name, - __FUNCTION__, __LINE__)); - goto out; - } + if (!rphy) + return 0; /* non-fatal: an rphy can be added later */ rphy->identify = identify; + error = sas_rphy_add(rphy); if (error) { - dfailprintk((MYIOC_s_ERR_FMT - "%s: exit at line=%d\n", ioc->name, - __FUNCTION__, __LINE__)); sas_rphy_free(rphy); - goto out; + return error; } - mptsas_set_rphy(phy_info, rphy); + + phy_info->rphy = rphy; } - out: - return error; + return 0; } static int @@ -1703,7 +1333,6 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc) goto out_free_port_info; mutex_lock(&ioc->sas_topology_mutex); - ioc->handle = hba->handle; port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle); if (!port_info) { port_info = hba; @@ -1713,11 +1342,13 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc) for (i = 0; i < hba->num_phys; i++) port_info->phy_info[i].negotiated_link_rate = hba->phy_info[i].negotiated_link_rate; - kfree(hba->phy_info); + 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], @@ -1731,24 +1362,24 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc) port_info->phy_info[i].phy_id; handle = port_info->phy_info[i].identify.handle; - if (port_info->phy_info[i].attached.handle) + if (port_info->phy_info[i].attached.handle) { mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].attached, (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << MPI_SAS_DEVICE_PGAD_FORM_SHIFT), port_info->phy_info[i].attached.handle); - } - - mptsas_setup_wide_ports(ioc, port_info); + } - for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++) mptsas_probe_one_phy(&ioc->sh->shost_gendev, &port_info->phy_info[i], ioc->sas_index, 1); + ioc->sas_index++; + } return 0; out_free_port_info: - kfree(hba); + if (hba) + kfree(hba); out: return error; } @@ -1757,8 +1388,6 @@ static int mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle) { struct mptsas_portinfo *port_info, *p, *ex; - struct device *parent; - struct sas_rphy *rphy; int error = -ENOMEM, i, j; ex = kzalloc(sizeof(*port_info), GFP_KERNEL); @@ -1780,13 +1409,16 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle) list_add_tail(&port_info->list, &ioc->sas_topology); } else { port_info->handle = ex->handle; - kfree(ex->phy_info); + 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++) { + struct device *parent; + mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i], (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM << MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle); @@ -1810,34 +1442,34 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle) port_info->phy_info[i].attached.phy_id = port_info->phy_info[i].phy_id; } - } - parent = &ioc->sh->shost_gendev; - for (i = 0; i < port_info->num_phys; i++) { + /* + * If we find a parent port handle this expander is + * attached to another expander, else it hangs of the + * HBA phys. + */ + parent = &ioc->sh->shost_gendev; mutex_lock(&ioc->sas_topology_mutex); list_for_each_entry(p, &ioc->sas_topology, list) { for (j = 0; j < p->num_phys; j++) { - if (port_info->phy_info[i].identify.handle != + if (port_info->phy_info[i].identify.handle == p->phy_info[j].attached.handle) - continue; - rphy = mptsas_get_rphy(&p->phy_info[j]); - parent = &rphy->dev; + parent = &p->phy_info[j].rphy->dev; } } mutex_unlock(&ioc->sas_topology_mutex); - } - mptsas_setup_wide_ports(ioc, port_info); - - for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++) mptsas_probe_one_phy(parent, &port_info->phy_info[i], ioc->sas_index, 0); + ioc->sas_index++; + } return 0; out_free_port_info: if (ex) { - kfree(ex->phy_info); + if (ex->phy_info) + kfree(ex->phy_info); kfree(ex); } out: @@ -1856,12 +1488,7 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc) { struct mptsas_portinfo buffer; struct mptsas_portinfo *port_info, *n, *parent; - struct mptsas_phyinfo *phy_info; - struct scsi_target * starget; - VirtTarget * vtarget; - struct sas_port * port; int i; - u64 expander_sas_address; mutex_lock(&ioc->sas_topology_mutex); list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) { @@ -1875,25 +1502,6 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc) (MPI_SAS_EXPAND_PGAD_FORM_HANDLE << MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) { - /* - * Issue target reset to all child end devices - * then mark them deleted to prevent further - * IO going to them. - */ - phy_info = port_info->phy_info; - for (i = 0; i < port_info->num_phys; i++, phy_info++) { - starget = mptsas_get_starget(phy_info); - if (!starget) - continue; - vtarget = starget->hostdata; - if(vtarget->deleted) - continue; - vtarget->deleted = 1; - mptsas_target_reset(ioc, vtarget); - sas_port_delete(mptsas_get_port(phy_info)); - mptsas_port_delete(phy_info->port_details); - } - /* * Obtain the port_info instance to the parent port */ @@ -1903,44 +1511,34 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc) if (!parent) goto next_port; - expander_sas_address = - port_info->phy_info[0].identify.sas_address; - /* * Delete rphys in the parent that point * to this expander. The transport layer will * cleanup all the children. */ - phy_info = parent->phy_info; - for (i = 0; i < parent->num_phys; i++, phy_info++) { - port = mptsas_get_port(phy_info); - if (!port) + 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; - if (phy_info->attached.sas_address != - expander_sas_address) - continue; -#ifdef MPT_DEBUG_SAS_WIDE - dev_printk(KERN_DEBUG, &port->dev, - "delete port (%d)\n", port->port_identifier); -#endif - sas_port_delete(port); - mptsas_port_delete(phy_info->port_details); + 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: - - phy_info = port_info->phy_info; - for (i = 0; i < port_info->num_phys; i++, phy_info++) - mptsas_port_delete(phy_info->port_details); - list_del(&port_info->list); - kfree(port_info->phy_info); + if (port_info->phy_info) + kfree(port_info->phy_info); kfree(port_info); } /* * Free this memory allocated from inside * mptsas_sas_expander_pg0 */ - kfree(buffer.phy_info); + if (buffer.phy_info) + kfree(buffer.phy_info); } mutex_unlock(&ioc->sas_topology_mutex); } @@ -1966,7 +1564,7 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc) if (!ioc->raid_data.pIocPg2->NumActiveVolumes) goto out; for (i=0; iraid_data.pIocPg2->NumActiveVolumes; i++) { - scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, + scsi_add_device(ioc->sh, ioc->num_ports, ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0); } out: @@ -1976,59 +1574,60 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc) /* * Work queue thread to handle Runtime discovery * Mere purpose is the hot add/delete of expanders - *(Mutex UNLOCKED) */ static void -__mptsas_discovery_work(MPT_ADAPTER *ioc) +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; -} - -/* - * Work queue thread to handle Runtime discovery - * Mere purpose is the hot add/delete of expanders - *(Mutex LOCKED) - */ -static void -mptsas_discovery_work(void * arg) -{ - struct mptsas_discovery_event *ev = arg; - MPT_ADAPTER *ioc = ev->ioc; - - mutex_lock(&ioc->sas_discovery_mutex); - __mptsas_discovery_work(ioc); mutex_unlock(&ioc->sas_discovery_mutex); - kfree(ev); } static struct mptsas_phyinfo * -mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address) +mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id) { struct mptsas_portinfo *port_info; + struct mptsas_devinfo device_info; struct mptsas_phyinfo *phy_info = NULL; - int i; + int i, error; + /* + * Retrieve the parent sas_address + */ + error = mptsas_sas_device_pg0(ioc, &device_info, + (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << + MPI_SAS_DEVICE_PGAD_FORM_SHIFT), + parent_handle); + if (error) + return NULL; + + /* + * The phy_info structures are never deallocated during lifetime of + * a host, so the code below is safe without additional refcounting. + */ 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.sas_address - != sas_address) - continue; - if (!mptsas_is_end_device( - &port_info->phy_info[i].attached)) - continue; - phy_info = &port_info->phy_info[i]; - break; + if (port_info->phy_info[i].identify.sas_address == + device_info.sas_address && + port_info->phy_info[i].phy_id == phy_id) { + phy_info = &port_info->phy_info[i]; + break; + } } } mutex_unlock(&ioc->sas_topology_mutex); + return phy_info; } @@ -2039,19 +1638,21 @@ mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id) struct mptsas_phyinfo *phy_info = NULL; int i; + /* + * The phy_info structures are never deallocated during lifetime of + * a host, so the code below is safe without additional refcounting. + */ 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.id != id) - continue; - if (!mptsas_is_end_device( - &port_info->phy_info[i].attached)) - continue; - 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); + return phy_info; } @@ -2059,7 +1660,7 @@ mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id) * Work queue thread to clear the persitency table */ static void -mptsas_persist_clear_table(void * arg) +mptscsih_sas_persist_clear_table(void * arg) { MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; @@ -2080,6 +1681,7 @@ mptsas_reprobe_target(struct scsi_target *starget, int uld_attach) mptsas_reprobe_lun); } + /* * Work queue thread to handle SAS hotplug events */ @@ -2090,17 +1692,14 @@ mptsas_hotplug_work(void *arg) MPT_ADAPTER *ioc = ev->ioc; struct mptsas_phyinfo *phy_info; struct sas_rphy *rphy; - struct sas_port *port; struct scsi_device *sdev; - struct scsi_target * starget; struct sas_identify identify; char *ds = NULL; struct mptsas_devinfo sas_device; VirtTarget *vtarget; - VirtDevice *vdevice; - mutex_lock(&ioc->sas_discovery_mutex); + switch (ev->event_type) { case MPTSAS_DEL_DEVICE: @@ -2109,50 +1708,24 @@ mptsas_hotplug_work(void *arg) /* * Sanity checks, for non-existing phys and remote rphys. */ - if (!phy_info || !phy_info->port_details) { - dfailprintk((MYIOC_s_ERR_FMT - "%s: exit at line=%d\n", ioc->name, - __FUNCTION__, __LINE__)); + if (!phy_info) break; - } - rphy = mptsas_get_rphy(phy_info); - if (!rphy) { - dfailprintk((MYIOC_s_ERR_FMT - "%s: exit at line=%d\n", ioc->name, - __FUNCTION__, __LINE__)); + if (!phy_info->rphy) break; - } - port = mptsas_get_port(phy_info); - if (!port) { - dfailprintk((MYIOC_s_ERR_FMT - "%s: exit at line=%d\n", ioc->name, - __FUNCTION__, __LINE__)); - break; - } + if (phy_info->starget) { + vtarget = phy_info->starget->hostdata; - starget = mptsas_get_starget(phy_info); - if (starget) { - vtarget = starget->hostdata; - - if (!vtarget) { - dfailprintk((MYIOC_s_ERR_FMT - "%s: exit at line=%d\n", ioc->name, - __FUNCTION__, __LINE__)); + 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(starget, 1); + mptsas_reprobe_target(vtarget->starget, 1); break; } - - vtarget->deleted = 1; - mptsas_target_reset(ioc, vtarget); } if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET) @@ -2166,12 +1739,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); -#ifdef MPT_DEBUG_SAS_WIDE - dev_printk(KERN_DEBUG, &port->dev, - "delete port (%d)\n", port->port_identifier); -#endif - sas_port_delete(port); - mptsas_port_delete(phy_info->port_details); + 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: @@ -2183,60 +1754,59 @@ mptsas_hotplug_work(void *arg) */ if (mptsas_sas_device_pg0(ioc, &sas_device, (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID << - MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id)) { - dfailprintk((MYIOC_s_ERR_FMT - "%s: exit at line=%d\n", ioc->name, - __FUNCTION__, __LINE__)); + MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id)) break; - } - ssleep(2); - __mptsas_discovery_work(ioc); + phy_info = mptsas_find_phyinfo_by_parent(ioc, + sas_device.handle_parent, sas_device.phy_id); - phy_info = mptsas_find_phyinfo_by_sas_address(ioc, - sas_device.sas_address); + if (!phy_info) { + u32 handle = 0xFFFF; - if (!phy_info || !phy_info->port_details) { - dfailprintk((MYIOC_s_ERR_FMT - "%s: exit at line=%d\n", ioc->name, - __FUNCTION__, __LINE__)); - break; + /* + * 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; } - starget = mptsas_get_starget(phy_info); - if (starget) { - vtarget = starget->hostdata; + if (phy_info->starget) { + vtarget = phy_info->starget->hostdata; - if (!vtarget) { - dfailprintk((MYIOC_s_ERR_FMT - "%s: exit at line=%d\n", ioc->name, - __FUNCTION__, __LINE__)); + 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(starget, 0); + mptsas_reprobe_target(phy_info->starget, 0); } break; } - if (mptsas_get_rphy(phy_info)) { - dfailprintk((MYIOC_s_ERR_FMT - "%s: exit at line=%d\n", ioc->name, - __FUNCTION__, __LINE__)); - break; - } - port = mptsas_get_port(phy_info); - if (!port) { - dfailprintk((MYIOC_s_ERR_FMT - "%s: exit at line=%d\n", ioc->name, - __FUNCTION__, __LINE__)); + if (phy_info->rphy) break; - } memcpy(&phy_info->attached, &sas_device, sizeof(struct mptsas_devinfo)); @@ -2253,48 +1823,59 @@ mptsas_hotplug_work(void *arg) ioc->name, ds, ev->channel, ev->id, ev->phy_id); mptsas_parse_device_info(&identify, &phy_info->attached); - rphy = sas_end_device_alloc(port); - if (!rphy) { - dfailprintk((MYIOC_s_ERR_FMT - "%s: exit at line=%d\n", ioc->name, - __FUNCTION__, __LINE__)); - break; /* non-fatal: an rphy can be added later */ + 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 */ rphy->identify = identify; if (sas_rphy_add(rphy)) { - dfailprintk((MYIOC_s_ERR_FMT - "%s: exit at line=%d\n", ioc->name, - __FUNCTION__, __LINE__)); sas_rphy_free(rphy); break; } - mptsas_set_rphy(phy_info, rphy); + + phy_info->rphy = rphy; break; case MPTSAS_ADD_RAID: - sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, - ev->id, 0); + 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 raid volume, channel %d, id %d\n", - ioc->name, MPTSAS_RAID_CHANNEL, ev->id); - scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ev->id, 0); + 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, MPTSAS_RAID_CHANNEL, - ev->id, 0); + sdev = scsi_device_lookup( + ioc->sh, + ioc->num_ports, + ev->id, + 0); if (!sdev) break; printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, id %d\n", - ioc->name, MPTSAS_RAID_CHANNEL, ev->id); - vdevice = sdev->hostdata; - vdevice->vtarget->deleted = 1; - mptsas_target_reset(ioc, vdevice->vtarget); + ioc->name, ioc->num_ports, ev->id); scsi_remove_device(sdev); scsi_device_put(sdev); mpt_findImVolumes(ioc); @@ -2304,13 +1885,12 @@ mptsas_hotplug_work(void *arg) break; } - mutex_unlock(&ioc->sas_discovery_mutex); kfree(ev); - + mutex_unlock(&ioc->sas_discovery_mutex); } static void -mptsas_send_sas_event(MPT_ADAPTER *ioc, +mptscsih_send_sas_event(MPT_ADAPTER *ioc, EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data) { struct mptsas_hotplug_event *ev; @@ -2326,7 +1906,7 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc, switch (sas_event_data->ReasonCode) { case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: - ev = kzalloc(sizeof(*ev), GFP_ATOMIC); + ev = kmalloc(sizeof(*ev), GFP_ATOMIC); if (!ev) { printk(KERN_WARNING "mptsas: lost hotplug event\n"); break; @@ -2356,9 +1936,10 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc, /* * Persistent table is full. */ - INIT_WORK(&ioc->sas_persist_task, - mptsas_persist_clear_table, (void *)ioc); - schedule_work(&ioc->sas_persist_task); + 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 */ @@ -2370,7 +1951,7 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc, } static void -mptsas_send_raid_event(MPT_ADAPTER *ioc, +mptscsih_send_raid_event(MPT_ADAPTER *ioc, EVENT_DATA_RAID *raid_event_data) { struct mptsas_hotplug_event *ev; @@ -2380,12 +1961,13 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc, if (ioc->bus_type != SAS) return; - ev = kzalloc(sizeof(*ev), GFP_ATOMIC); + 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; @@ -2447,7 +2029,7 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc, } static void -mptsas_send_discovery_event(MPT_ADAPTER *ioc, +mptscsih_send_discovery(MPT_ADAPTER *ioc, EVENT_DATA_SAS_DISCOVERY *discovery_data) { struct mptsas_discovery_event *ev; @@ -2462,10 +2044,11 @@ mptsas_send_discovery_event(MPT_ADAPTER *ioc, if (discovery_data->DiscoveryStatus) return; - ev = kzalloc(sizeof(*ev), GFP_ATOMIC); + ev = kmalloc(sizeof(*ev), GFP_ATOMIC); if (!ev) return; - INIT_WORK(&ev->work, mptsas_discovery_work, ev); + memset(ev,0,sizeof(struct mptsas_discovery_event)); + INIT_WORK(&ev->work, mptscsih_discovery_work, ev); ev->ioc = ioc; schedule_work(&ev->work); }; @@ -2493,21 +2076,21 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) switch (event) { case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: - mptsas_send_sas_event(ioc, + mptscsih_send_sas_event(ioc, (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data); break; case MPI_EVENT_INTEGRATED_RAID: - mptsas_send_raid_event(ioc, + mptscsih_send_raid_event(ioc, (EVENT_DATA_RAID *)reply->Data); break; case MPI_EVENT_PERSISTENT_TABLE_FULL: - INIT_WORK(&ioc->sas_persist_task, - mptsas_persist_clear_table, + INIT_WORK(&ioc->mptscsih_persistTask, + mptscsih_sas_persist_clear_table, (void *)ioc); - schedule_work(&ioc->sas_persist_task); + schedule_work(&ioc->mptscsih_persistTask); break; case MPI_EVENT_SAS_DISCOVERY: - mptsas_send_discovery_event(ioc, + mptscsih_send_discovery(ioc, (EVENT_DATA_SAS_DISCOVERY *)reply->Data); break; default: @@ -2697,6 +2280,7 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) hd->timer.data = (unsigned long) hd; hd->timer.function = mptscsih_timer_expired; + hd->mpt_pq_filter = mpt_pq_filter; ioc->sas_data.ptClear = mpt_pt_clear; if (ioc->sas_data.ptClear==1) { @@ -2704,6 +2288,12 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT); } + ddvprintk((MYIOC_s_INFO_FMT + "mpt_pq_filter %x mpt_pq_filter %x\n", + ioc->name, + mpt_pq_filter, + mpt_pq_filter)); + init_waitqueue_head(&hd->scandv_waitq); hd->scandv_wait_done = 0; hd->last_queue_full = 0; @@ -2719,7 +2309,7 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) return 0; - out_mptsas_probe: +out_mptsas_probe: mptscsih_remove(pdev); return error; @@ -2729,7 +2319,6 @@ static void __devexit mptsas_remove(struct pci_dev *pdev) { MPT_ADAPTER *ioc = pci_get_drvdata(pdev); struct mptsas_portinfo *p, *n; - int i; ioc->sas_discovery_ignore_events=1; sas_remove_host(ioc->sh); @@ -2737,9 +2326,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); - for (i = 0 ; i < p->num_phys ; i++) - mptsas_port_delete(p->phy_info[i].port_details); - kfree(p->phy_info); + if (p->phy_info) + kfree(p->phy_info); kfree(p); } mutex_unlock(&ioc->sas_topology_mutex); @@ -2748,15 +2336,17 @@ static void __devexit mptsas_remove(struct pci_dev *pdev) } static struct pci_device_id mptsas_pci_table[] = { - { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064, + PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066, PCI_ANY_ID, PCI_ANY_ID }, - { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068, PCI_ANY_ID, PCI_ANY_ID }, - { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064E, PCI_ANY_ID, PCI_ANY_ID }, - { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066E, PCI_ANY_ID, PCI_ANY_ID }, - { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078, + { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068E, PCI_ANY_ID, PCI_ANY_ID }, {0} /* Terminating entry */ };