MODULE_LICENSE("GPL");
/* Command line args */
+static int mpt_pq_filter = 0;
+module_param(mpt_pq_filter, int, 0);
+MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
+
#define MPTFC_DEV_LOSS_TMO (60)
static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; /* reasonable default */
module_param(mptfc_dev_loss_tmo, int, 0);
*/
static struct pci_device_id mptfc_pci_table[] = {
- { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC909,
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909,
PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC919,
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919,
PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC929,
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929,
PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC919X,
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X,
PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC929X,
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X,
PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC939X,
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC939X,
PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949X,
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X,
PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949E,
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949ES,
PCI_ANY_ID, PCI_ANY_ID },
{0} /* Terminating entry */
};
static struct scsi_transport_template *mptfc_transport_template = NULL;
-static struct fc_function_template mptfc_transport_functions = {
+struct fc_function_template mptfc_transport_functions = {
.dd_fcrport_size = 8,
.show_host_node_name = 1,
.show_host_port_name = 1,
};
+/* FIXME! values controlling firmware RESCAN event
+ * need to be set low to allow dev_loss_tmo to
+ * work as expected. Currently, firmware doesn't
+ * notify driver of RESCAN event until some number
+ * of seconds elapse. This value can be set via
+ * lsiutil.
+ */
static void
mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
{
}
out:
- kfree(pp0_array);
- kfree(p0_array);
+ if (pp0_array)
+ kfree(pp0_array);
+ if (p0_array)
+ kfree(p0_array);
return rc;
}
rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;
rid->port_id = pg0->PortIdentifier;
rid->roles = FC_RPORT_ROLE_UNKNOWN;
+ rid->roles |= FC_RPORT_ROLE_FCP_TARGET;
+ if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
+ rid->roles |= FC_RPORT_ROLE_FCP_INITIATOR;
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)
{
struct fc_rport *rport;
struct mptfc_rport_info *ri;
int new_ri = 1;
- u64 pn, nn;
+ u64 pn;
+ unsigned long flags;
VirtTarget *vtarget;
- u32 roles = FC_RPORT_ROLE_UNKNOWN;
if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
return;
- roles |= FC_RPORT_ROLE_FCP_TARGET;
- if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
- roles |= FC_RPORT_ROLE_FCP_INITIATOR;
-
/* scan list looking for a match */
+ spin_lock_irqsave(&ioc->fc_rport_lock, flags);
list_for_each_entry(ri, &ioc->fc_rports, list) {
pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
if (pn == rport_ids.port_name) { /* match */
}
}
if (new_ri) { /* allocate one */
+ spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
if (!ri)
return;
+ spin_lock_irqsave(&ioc->fc_rport_lock, flags);
list_add_tail(&ri->list, &ioc->fc_rports);
}
/* MPT_RPORT_INFO_FLAGS_REGISTERED - rport not previously deleted */
if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
+ spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
rport = fc_remote_port_add(ioc->sh, channel, &rport_ids);
+ spin_lock_irqsave(&ioc->fc_rport_lock, flags);
if (rport) {
ri->rport = rport;
if (new_ri) /* may have been reset by user */
rport->dev_loss_tmo = mptfc_dev_loss_tmo;
+ *((struct mptfc_rport_info **)rport->dd_data) = ri;
/*
* if already mapped, remap here. If not mapped,
* target_alloc will allocate vtarget and map,
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;
}
- *((struct mptfc_rport_info **)rport->dd_data) = ri;
- /* scan will be scheduled once rport becomes a target */
- fc_remote_port_rolechg(rport,roles);
-
- pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
- nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
dfcprintk ((MYIOC_s_INFO_FMT
"mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
"rport tid %d, tmo %d\n",
ioc->name,
- ioc->sh->host_no,
+ oc->sh->host_no,
pg0->PortIdentifier,
- (unsigned long long)nn,
- (unsigned long long)pn,
+ pg0->WWNN,
+ pg0->WWPN,
pg0->CurrentTargetID,
ri->rport->scsi_target_id,
ri->rport->dev_loss_tmo));
ri = NULL;
}
}
+ spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
+
}
/*
vtarget->target_id = ri->pg0.CurrentTargetID;
vtarget->bus_id = ri->pg0.CurrentBus;
ri->starget = starget;
+ ri->remap_needed = 0;
rc = 0;
}
}
* Return non-zero if allocation fails.
* Init memory once per LUN.
*/
-static int
+int
mptfc_slave_alloc(struct scsi_device *sdev)
{
MPT_SCSI_HOST *hd;
VirtDevice *vdev;
struct scsi_target *starget;
struct fc_rport *rport;
+ unsigned long flags;
- starget = scsi_target(sdev);
- rport = starget_to_rport(starget);
+ rport = starget_to_rport(scsi_target(sdev));
if (!rport || fc_remote_port_chkready(rport))
return -ENXIO;
return -ENOMEM;
}
+ spin_lock_irqsave(&hd->ioc->fc_rport_lock,flags);
sdev->hostdata = vdev;
+ starget = scsi_target(sdev);
vtarget = starget->hostdata;
if (vtarget->num_luns == 0) {
vtarget->ioc_id = hd->ioc->id;
- vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
+ vtarget->tflags = MPT_TARGET_FLAGS_Q_YES |
+ MPT_TARGET_FLAGS_VALID_INQUIRY;
hd->Targets[sdev->id] = vtarget;
}
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;
- vtarget->num_luns++;
+ spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
+ vtarget->num_luns++;
-#ifdef DMPT_DEBUG_FC
- {
- u64 nn, pn;
- struct mptfc_rport_info *ri;
- ri = *((struct mptfc_rport_info **)rport->dd_data);
- pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
- nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
dfcprintk ((MYIOC_s_INFO_FMT
"mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
"CurrentTargetID %d, %x %llx %llx\n",
- hd->ioc->name,
+ ioc->name,
sdev->host->host_no,
vtarget->num_luns,
sdev->id, ri->pg0.CurrentTargetID,
- ri->pg0.PortIdentifier,
- (unsigned long long)pn,
- (unsigned long long)nn));
- }
-#endif
+ ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN));
return 0;
}
done(SCpnt);
return 0;
}
-
- /* dd_data is null until finished adding target */
ri = *((struct mptfc_rport_info **)rport->dd_data);
- if (unlikely(!ri)) {
- dfcprintk ((MYIOC_s_INFO_FMT
- "mptfc_qcmd.%d: %d:%d, dd_data is null.\n",
- ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
- ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
- SCpnt->device->id,SCpnt->device->lun));
- SCpnt->result = DID_IMM_RETRY << 16;
- done(SCpnt);
- return 0;
- }
-
- err = mptscsih_qcmd(SCpnt,done);
-#ifdef DMPT_DEBUG_FC
- if (unlikely(err)) {
- dfcprintk ((MYIOC_s_INFO_FMT
- "mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero, (%x).\n",
- ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
- ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
- SCpnt->device->id,SCpnt->device->lun,err));
- }
-#endif
- return err;
-}
-
-/*
- * mptfc_GetFcPortPage0 - Fetch FCPort config Page0.
- * @ioc: Pointer to MPT_ADAPTER structure
- * @portnum: IOC Port number
- *
- * Return: 0 for success
- * -ENOMEM if no memory available
- * -EPERM if not allowed due to ISR context
- * -EAGAIN if no msg frames currently available
- * -EFAULT for non-successful reply or no reply (timeout)
- * -EINVAL portnum arg out of range (hardwired to two elements)
- */
-static int
-mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
-{
- ConfigPageHeader_t hdr;
- CONFIGPARMS cfg;
- FCPortPage0_t *ppage0_alloc;
- FCPortPage0_t *pp0dest;
- dma_addr_t page0_dma;
- int data_sz;
- int copy_sz;
- int rc;
- int count = 400;
-
- if (portnum > 1)
- return -EINVAL;
-
- /* Get FCPort Page 0 header */
- hdr.PageVersion = 0;
- hdr.PageLength = 0;
- hdr.PageNumber = 0;
- hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
- cfg.cfghdr.hdr = &hdr;
- cfg.physAddr = -1;
- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
- cfg.dir = 0;
- cfg.pageAddr = portnum;
- cfg.timeout = 0;
-
- if ((rc = mpt_config(ioc, &cfg)) != 0)
- return rc;
-
- if (hdr.PageLength == 0)
- return 0;
-
- data_sz = hdr.PageLength * 4;
- rc = -ENOMEM;
- ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
- if (ppage0_alloc) {
-
- try_again:
- memset((u8 *)ppage0_alloc, 0, data_sz);
- cfg.physAddr = page0_dma;
- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
-
- if ((rc = mpt_config(ioc, &cfg)) == 0) {
- /* save the data */
- pp0dest = &ioc->fc_port_page0[portnum];
- copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
- memcpy(pp0dest, ppage0_alloc, copy_sz);
-
- /*
- * Normalize endianness of structure data,
- * by byte-swapping all > 1 byte fields!
- */
- pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
- pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
- pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
- pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
- pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
- pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
- pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
- pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
- pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
- pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
- pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
- pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
- pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
- pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
- pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
- pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
-
- /*
- * if still doing discovery,
- * hang loose a while until finished
- */
- if ((pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) ||
- (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_ONLINE &&
- (pp0dest->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_TYPE_MASK)
- == MPI_FCPORTPAGE0_FLAGS_ATTACH_NO_INIT)) {
- if (count-- > 0) {
- msleep(100);
- goto try_again;
- }
- printk(MYIOC_s_INFO_FMT "Firmware discovery not"
- " complete.\n",
- ioc->name);
- }
- }
-
- pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
- }
-
- return rc;
-}
-
-static int
-mptfc_WriteFcPortPage1(MPT_ADAPTER *ioc, int portnum)
-{
- ConfigPageHeader_t hdr;
- CONFIGPARMS cfg;
- int rc;
-
- if (portnum > 1)
- return -EINVAL;
-
- if (!(ioc->fc_data.fc_port_page1[portnum].data))
- return -EINVAL;
-
- /* get fcport page 1 header */
- hdr.PageVersion = 0;
- hdr.PageLength = 0;
- hdr.PageNumber = 1;
- hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
- cfg.cfghdr.hdr = &hdr;
- cfg.physAddr = -1;
- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
- cfg.dir = 0;
- cfg.pageAddr = portnum;
- cfg.timeout = 0;
-
- if ((rc = mpt_config(ioc, &cfg)) != 0)
- return rc;
-
- if (hdr.PageLength == 0)
- return -ENODEV;
-
- if (hdr.PageLength*4 != ioc->fc_data.fc_port_page1[portnum].pg_sz)
- return -EINVAL;
-
- cfg.physAddr = ioc->fc_data.fc_port_page1[portnum].dma;
- cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
- cfg.dir = 1;
-
- rc = mpt_config(ioc, &cfg);
-
- return rc;
-}
-
-static int
-mptfc_GetFcPortPage1(MPT_ADAPTER *ioc, int portnum)
-{
- ConfigPageHeader_t hdr;
- CONFIGPARMS cfg;
- FCPortPage1_t *page1_alloc;
- dma_addr_t page1_dma;
- int data_sz;
- int rc;
-
- if (portnum > 1)
- return -EINVAL;
-
- /* get fcport page 1 header */
- hdr.PageVersion = 0;
- hdr.PageLength = 0;
- hdr.PageNumber = 1;
- hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
- cfg.cfghdr.hdr = &hdr;
- cfg.physAddr = -1;
- cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
- cfg.dir = 0;
- cfg.pageAddr = portnum;
- cfg.timeout = 0;
-
- if ((rc = mpt_config(ioc, &cfg)) != 0)
- return rc;
-
- if (hdr.PageLength == 0)
- return -ENODEV;
-
-start_over:
-
- if (ioc->fc_data.fc_port_page1[portnum].data == NULL) {
- data_sz = hdr.PageLength * 4;
- if (data_sz < sizeof(FCPortPage1_t))
- data_sz = sizeof(FCPortPage1_t);
-
- page1_alloc = (FCPortPage1_t *) pci_alloc_consistent(ioc->pcidev,
- data_sz,
- &page1_dma);
- if (!page1_alloc)
- return -ENOMEM;
- }
- else {
- page1_alloc = ioc->fc_data.fc_port_page1[portnum].data;
- page1_dma = ioc->fc_data.fc_port_page1[portnum].dma;
- data_sz = ioc->fc_data.fc_port_page1[portnum].pg_sz;
- if (hdr.PageLength * 4 > data_sz) {
- ioc->fc_data.fc_port_page1[portnum].data = NULL;
- pci_free_consistent(ioc->pcidev, data_sz, (u8 *)
- page1_alloc, page1_dma);
- goto start_over;
- }
- }
-
- memset(page1_alloc,0,data_sz);
+ if (unlikely(ri->remap_needed))
+ return SCSI_MLQUEUE_HOST_BUSY;
- cfg.physAddr = page1_dma;
- cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
-
- if ((rc = mpt_config(ioc, &cfg)) == 0) {
- ioc->fc_data.fc_port_page1[portnum].data = page1_alloc;
- ioc->fc_data.fc_port_page1[portnum].pg_sz = data_sz;
- ioc->fc_data.fc_port_page1[portnum].dma = page1_dma;
- }
- else {
- ioc->fc_data.fc_port_page1[portnum].data = NULL;
- pci_free_consistent(ioc->pcidev, data_sz, (u8 *)
- page1_alloc, page1_dma);
- }
-
- return rc;
+ return mptscsih_qcmd(SCpnt,done);
}
-static void
-mptfc_SetFcPortPage1_defaults(MPT_ADAPTER *ioc)
-{
- int ii;
- FCPortPage1_t *pp1;
-
- #define MPTFC_FW_DEVICE_TIMEOUT (1)
- #define MPTFC_FW_IO_PEND_TIMEOUT (1)
- #define ON_FLAGS (MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY)
- #define OFF_FLAGS (MPI_FCPORTPAGE1_FLAGS_VERBOSE_RESCAN_EVENTS)
-
- for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
- if (mptfc_GetFcPortPage1(ioc, ii) != 0)
- continue;
- pp1 = ioc->fc_data.fc_port_page1[ii].data;
- if ((pp1->InitiatorDeviceTimeout == MPTFC_FW_DEVICE_TIMEOUT)
- && (pp1->InitiatorIoPendTimeout == MPTFC_FW_IO_PEND_TIMEOUT)
- && ((pp1->Flags & ON_FLAGS) == ON_FLAGS)
- && ((pp1->Flags & OFF_FLAGS) == 0))
- continue;
- pp1->InitiatorDeviceTimeout = MPTFC_FW_DEVICE_TIMEOUT;
- pp1->InitiatorIoPendTimeout = MPTFC_FW_IO_PEND_TIMEOUT;
- pp1->Flags &= ~OFF_FLAGS;
- pp1->Flags |= ON_FLAGS;
- mptfc_WriteFcPortPage1(ioc, ii);
- }
-}
-
-
static void
mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
{
fc_host_tgtid_bind_type(ioc->sh) = FC_TGTID_BIND_BY_WWPN;
}
-static void
-mptfc_setup_reset(void *arg)
-{
- MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
- u64 pn;
- struct mptfc_rport_info *ri;
-
- /* reset about to happen, delete (block) all rports */
- list_for_each_entry(ri, &ioc->fc_rports, list) {
- if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
- ri->flags &= ~MPT_RPORT_INFO_FLAGS_REGISTERED;
- fc_remote_port_delete(ri->rport); /* won't sleep */
- ri->rport = NULL;
-
- pn = (u64)ri->pg0.WWPN.High << 32 |
- (u64)ri->pg0.WWPN.Low;
- dfcprintk ((MYIOC_s_INFO_FMT
- "mptfc_setup_reset.%d: %llx deleted\n",
- ioc->name,
- ioc->sh->host_no,
- (unsigned long long)pn));
- }
- }
-}
-
static void
mptfc_rescan_devices(void *arg)
{
MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
int ii;
- u64 pn;
+ int work_to_do;
+ unsigned long flags;
struct mptfc_rport_info *ri;
- /* start by tagging all ports as missing */
- list_for_each_entry(ri, &ioc->fc_rports, list) {
- if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
- ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
+ do {
+ /* start by tagging all ports as missing */
+ spin_lock_irqsave(&ioc->fc_rport_lock,flags);
+ list_for_each_entry(ri, &ioc->fc_rports, list) {
+ if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
+ ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
+ }
+ }
+ spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
+
+ /*
+ * now rescan devices known to adapter,
+ * will reregister existing rports
+ */
+ for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
+ (void) mptbase_GetFcPortPage0(ioc, ii);
+ mptfc_init_host_attr(ioc,ii); /* refresh */
+ mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
}
- }
-
- /*
- * now rescan devices known to adapter,
- * will reregister existing rports
- */
- for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
- (void) mptfc_GetFcPortPage0(ioc, ii);
- mptfc_init_host_attr(ioc, ii); /* refresh */
- mptfc_GetFcDevPage0(ioc, ii, mptfc_register_dev);
- }
-
- /* delete devices still missing */
- list_for_each_entry(ri, &ioc->fc_rports, list) {
- /* if newly missing, delete it */
- if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) {
-
- ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
- MPT_RPORT_INFO_FLAGS_MISSING);
- fc_remote_port_delete(ri->rport); /* won't sleep */
- ri->rport = NULL;
- pn = (u64)ri->pg0.WWPN.High << 32 |
- (u64)ri->pg0.WWPN.Low;
- dfcprintk ((MYIOC_s_INFO_FMT
- "mptfc_rescan.%d: %llx deleted\n",
- ioc->name,
- ioc->sh->host_no,
- (unsigned long long)pn));
+ /* delete devices still missing */
+ spin_lock_irqsave(&ioc->fc_rport_lock, flags);
+ list_for_each_entry(ri, &ioc->fc_rports, list) {
+ /* if newly missing, delete it */
+ if ((ri->flags & (MPT_RPORT_INFO_FLAGS_REGISTERED |
+ MPT_RPORT_INFO_FLAGS_MISSING))
+ == (MPT_RPORT_INFO_FLAGS_REGISTERED |
+ MPT_RPORT_INFO_FLAGS_MISSING)) {
+
+ ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
+ MPT_RPORT_INFO_FLAGS_MISSING);
+ ri->remap_needed = 1;
+ fc_remote_port_delete(ri->rport);
+ /*
+ * remote port not really deleted 'cause
+ * binding is by WWPN and driver only
+ * registers FCP_TARGETs but cannot trust
+ * data structures.
+ */
+ ri->rport = NULL;
+ dfcprintk ((MYIOC_s_INFO_FMT
+ "mptfc_rescan.%d: %llx deleted\n",
+ ioc->name,
+ ioc->sh->host_no,
+ ri->pg0.WWPN));
+ }
}
- }
+ spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
+
+ /*
+ * allow multiple passes as target state
+ * might have changed during scan
+ */
+ spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+ if (ioc->fc_rescan_work_count > 2) /* only need one more */
+ ioc->fc_rescan_work_count = 2;
+ work_to_do = --ioc->fc_rescan_work_count;
+ spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+ } while (work_to_do);
}
static int
goto out_mptfc_probe;
}
- spin_lock_init(&ioc->fc_rescan_work_lock);
INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc);
- INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset, (void *)ioc);
spin_lock_irqsave(&ioc->FreeQlock, flags);
hd->timer.data = (unsigned long) hd;
hd->timer.function = mptscsih_timer_expired;
+ hd->mpt_pq_filter = mpt_pq_filter;
+
+ ddvprintk((MYIOC_s_INFO_FMT
+ "mpt_pq_filter %x\n",
+ ioc->name,
+ mpt_pq_filter));
+
init_waitqueue_head(&hd->scandv_waitq);
hd->scandv_wait_done = 0;
hd->last_queue_full = 0;
goto out_mptfc_probe;
}
- /* initialize workqueue */
-
- snprintf(ioc->fc_rescan_work_q_name, KOBJ_NAME_LEN, "mptfc_wq_%d",
- sh->host_no);
- ioc->fc_rescan_work_q =
- create_singlethread_workqueue(ioc->fc_rescan_work_q_name);
- if (!ioc->fc_rescan_work_q)
- goto out_mptfc_probe;
-
- /*
- * Pre-fetch FC port WWN and stuff...
- * (FCPortPage0_t stuff)
- */
for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
- (void) mptfc_GetFcPortPage0(ioc, ii);
+ mptfc_init_host_attr(ioc,ii);
+ mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
}
- mptfc_SetFcPortPage1_defaults(ioc);
-
- /*
- * scan for rports -
- * by doing it via the workqueue, some locking is eliminated
- */
-
- queue_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work);
- flush_workqueue(ioc->fc_rescan_work_q);
return 0;
#endif
};
-static int
-mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
-{
- MPT_SCSI_HOST *hd;
- u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
- unsigned long flags;
- int rc=1;
-
- devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
- ioc->name, event));
-
- if (ioc->sh == NULL ||
- ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
- return 1;
-
- switch (event) {
- case MPI_EVENT_RESCAN:
- spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
- if (ioc->fc_rescan_work_q) {
- queue_work(ioc->fc_rescan_work_q,
- &ioc->fc_rescan_work);
- }
- spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
- break;
- default:
- rc = mptscsih_event_process(ioc,pEvReply);
- break;
- }
- return rc;
-}
-
-static int
-mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
-{
- int rc;
- unsigned long flags;
-
- rc = mptscsih_ioc_reset(ioc,reset_phase);
- if (rc == 0)
- return rc;
-
-
- dtmprintk((KERN_WARNING MYNAM
- ": IOC %s_reset routed to FC host driver!\n",
- reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
- reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
-
- if (reset_phase == MPT_IOC_SETUP_RESET) {
- spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
- if (ioc->fc_rescan_work_q) {
- queue_work(ioc->fc_rescan_work_q,
- &ioc->fc_setup_reset_work);
- }
- spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
- }
-
- else if (reset_phase == MPT_IOC_PRE_RESET) {
- }
-
- else { /* MPT_IOC_POST_RESET */
- mptfc_SetFcPortPage1_defaults(ioc);
- spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
- if (ioc->fc_rescan_work_q) {
- queue_work(ioc->fc_rescan_work_q,
- &ioc->fc_rescan_work);
- }
- spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
- }
- return 1;
-}
-
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptfc_init - Register MPT adapter(s) as SCSI host(s) with
show_mptmod_ver(my_NAME, my_VERSION);
- /* sanity check module parameters */
- if (mptfc_dev_loss_tmo <= 0)
+ /* sanity check module parameter */
+ if (mptfc_dev_loss_tmo == 0)
mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
mptfc_transport_template =
mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
- if (mpt_event_register(mptfcDoneCtx, mptfc_event_process) == 0) {
- devtverboseprintk((KERN_INFO MYNAM
+ if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) {
+ devtprintk((KERN_INFO MYNAM
": Registered for IOC event notifications\n"));
}
- if (mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset) == 0) {
+ if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) {
dprintk((KERN_INFO MYNAM
": Registered for IOC reset notifications\n"));
}
static void __devexit
mptfc_remove(struct pci_dev *pdev)
{
- MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
- struct mptfc_rport_info *p, *n;
- struct workqueue_struct *work_q;
- unsigned long flags;
- int ii;
-
- /* destroy workqueue */
- if ((work_q=ioc->fc_rescan_work_q)) {
- spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
- ioc->fc_rescan_work_q = NULL;
- spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
- destroy_workqueue(work_q);
- }
+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+ struct mptfc_rport_info *p, *n;
fc_remove_host(ioc->sh);
kfree(p);
}
- for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
- if (ioc->fc_data.fc_port_page1[ii].data) {
- pci_free_consistent(ioc->pcidev,
- ioc->fc_data.fc_port_page1[ii].pg_sz,
- (u8 *) ioc->fc_data.fc_port_page1[ii].data,
- ioc->fc_data.fc_port_page1[ii].dma);
- ioc->fc_data.fc_port_page1[ii].data = NULL;
- }
- }
-
mptscsih_remove(pdev);
}