📄 mptspi.c
字号:
nego = mptspi_getRP(starget); pg1.RequestedParameters = cpu_to_le32(nego); pg1.Reserved = 0; pg1.Configuration = 0; mptspi_write_spi_device_pg1(starget, &pg1);}struct work_queue_wrapper { struct work_struct work; struct _MPT_SCSI_HOST *hd; int disk;};static void mpt_work_wrapper(struct work_struct *work){ struct work_queue_wrapper *wqw = container_of(work, struct work_queue_wrapper, work); struct _MPT_SCSI_HOST *hd = wqw->hd; MPT_ADAPTER *ioc = hd->ioc; struct Scsi_Host *shost = ioc->sh; struct scsi_device *sdev; int disk = wqw->disk; struct _CONFIG_PAGE_IOC_3 *pg3; kfree(wqw); mpt_findImVolumes(ioc); pg3 = ioc->raid_data.pIocPg3; if (!pg3) return; shost_for_each_device(sdev,shost) { struct scsi_target *starget = scsi_target(sdev); VirtTarget *vtarget = starget->hostdata; /* only want to search RAID components */ if (sdev->channel != 1) continue; /* The id is the raid PhysDiskNum, even if * starget->id is the actual target address */ if(vtarget->id != disk) continue; starget_printk(KERN_INFO, vtarget->starget, MYIOC_s_FMT "Integrated RAID requests DV of new device\n", ioc->name); mptspi_dv_device(hd, sdev); } shost_printk(KERN_INFO, shost, MYIOC_s_FMT "Integrated RAID detects new device %d\n", ioc->name, disk); scsi_scan_target(&ioc->sh->shost_gendev, 1, disk, 0, 1);}static void mpt_dv_raid(struct _MPT_SCSI_HOST *hd, int disk){ struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC); MPT_ADAPTER *ioc = hd->ioc; if (!wqw) { shost_printk(KERN_ERR, ioc->sh, MYIOC_s_FMT "Failed to act on RAID event for physical disk %d\n", ioc->name, disk); return; } INIT_WORK(&wqw->work, mpt_work_wrapper); wqw->hd = hd; wqw->disk = disk; schedule_work(&wqw->work);}static intmptspi_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply){ u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; struct _MPT_SCSI_HOST *hd = shost_priv(ioc->sh); if (hd && event == MPI_EVENT_INTEGRATED_RAID) { int reason = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16; if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) { int disk = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24; mpt_dv_raid(hd, disk); } } return mptscsih_event_process(ioc, pEvReply);}static intmptspi_deny_binding(struct scsi_target *starget){ struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)dev_to_shost(starget->dev.parent)->hostdata; return ((mptspi_is_raid(hd, starget->id)) && starget->channel == 0) ? 1 : 0;}static struct spi_function_template mptspi_transport_functions = { .get_offset = mptspi_read_parameters, .set_offset = mptspi_write_offset, .show_offset = 1, .get_period = mptspi_read_parameters, .set_period = mptspi_write_period, .show_period = 1, .get_width = mptspi_read_parameters, .set_width = mptspi_write_width, .show_width = 1, .get_iu = mptspi_read_parameters, .set_iu = mptspi_write_iu, .show_iu = 1, .get_dt = mptspi_read_parameters, .set_dt = mptspi_write_dt, .show_dt = 1, .get_qas = mptspi_read_parameters, .set_qas = mptspi_write_qas, .show_qas = 1, .get_wr_flow = mptspi_read_parameters, .set_wr_flow = mptspi_write_wr_flow, .show_wr_flow = 1, .get_rd_strm = mptspi_read_parameters, .set_rd_strm = mptspi_write_rd_strm, .show_rd_strm = 1, .get_rti = mptspi_read_parameters, .set_rti = mptspi_write_rti, .show_rti = 1, .get_pcomp_en = mptspi_read_parameters, .set_pcomp_en = mptspi_write_pcomp_en, .show_pcomp_en = 1, .get_hold_mcs = mptspi_read_parameters, .set_hold_mcs = mptspi_write_hold_mcs, .show_hold_mcs = 1, .deny_binding = mptspi_deny_binding,};/**************************************************************************** * Supported hardware */static struct pci_device_id mptspi_pci_table[] = { { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_53C1030, PCI_ANY_ID, PCI_ANY_ID }, { PCI_VENDOR_ID_ATTO, MPI_MANUFACTPAGE_DEVID_53C1030, PCI_ANY_ID, PCI_ANY_ID }, { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_53C1035, PCI_ANY_ID, PCI_ANY_ID }, {0} /* Terminating entry */};MODULE_DEVICE_TABLE(pci, mptspi_pci_table);/* * renegotiate for a given target */static voidmptspi_dv_renegotiate_work(struct work_struct *work){ struct work_queue_wrapper *wqw = container_of(work, struct work_queue_wrapper, work); struct _MPT_SCSI_HOST *hd = wqw->hd; struct scsi_device *sdev; struct scsi_target *starget; struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; u32 nego; MPT_ADAPTER *ioc = hd->ioc; kfree(wqw); if (hd->spi_pending) { shost_for_each_device(sdev, ioc->sh) { if (hd->spi_pending & (1 << sdev->id)) continue; starget = scsi_target(sdev); nego = mptspi_getRP(starget); pg1.RequestedParameters = cpu_to_le32(nego); pg1.Reserved = 0; pg1.Configuration = 0; mptspi_write_spi_device_pg1(starget, &pg1); } } else { shost_for_each_device(sdev, ioc->sh) mptspi_dv_device(hd, sdev); }}static voidmptspi_dv_renegotiate(struct _MPT_SCSI_HOST *hd){ struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC); if (!wqw) return; INIT_WORK(&wqw->work, mptspi_dv_renegotiate_work); wqw->hd = hd; schedule_work(&wqw->work);}/* * spi module reset handler */static intmptspi_ioc_reset(MPT_ADAPTER *ioc, int reset_phase){ struct _MPT_SCSI_HOST *hd = shost_priv(ioc->sh); int rc; rc = mptscsih_ioc_reset(ioc, reset_phase); if (reset_phase == MPT_IOC_POST_RESET) mptspi_dv_renegotiate(hd); return rc;}#ifdef CONFIG_PM/* * spi module resume handler */static intmptspi_resume(struct pci_dev *pdev){ MPT_ADAPTER *ioc = pci_get_drvdata(pdev); struct _MPT_SCSI_HOST *hd = shost_priv(ioc->sh); int rc; rc = mptscsih_resume(pdev); mptspi_dv_renegotiate(hd); return rc;}#endif/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * mptspi_probe - Installs scsi devices per bus. * @pdev: Pointer to pci_dev structure * * Returns 0 for success, non-zero for failure. * */static intmptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id){ struct Scsi_Host *sh; MPT_SCSI_HOST *hd; MPT_ADAPTER *ioc; unsigned long flags; int ii; int numSGE = 0; int scale; int ioc_cap; int error=0; int r; if ((r = mpt_attach(pdev,id)) != 0) return r; ioc = pci_get_drvdata(pdev); ioc->DoneCtx = mptspiDoneCtx; ioc->TaskCtx = mptspiTaskCtx; ioc->InternalCtx = mptspiInternalCtx; /* Added sanity check on readiness of the MPT adapter. */ if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) { printk(MYIOC_s_WARN_FMT "Skipping because it's not operational!\n", ioc->name); error = -ENODEV; goto out_mptspi_probe; } if (!ioc->active) { printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n", ioc->name); error = -ENODEV; goto out_mptspi_probe; } /* Sanity check - ensure at least 1 port is INITIATOR capable */ ioc_cap = 0; for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { if (ioc->pfacts[ii].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) ioc_cap ++; } if (!ioc_cap) { printk(MYIOC_s_WARN_FMT "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n", ioc->name, ioc); return 0; } sh = scsi_host_alloc(&mptspi_driver_template, sizeof(MPT_SCSI_HOST)); if (!sh) { printk(MYIOC_s_WARN_FMT "Unable to register controller with SCSI subsystem\n", ioc->name); error = -1; goto out_mptspi_probe; } spin_lock_irqsave(&ioc->FreeQlock, flags); /* Attach the SCSI Host to the IOC structure */ ioc->sh = sh; sh->io_port = 0; sh->n_io_port = 0; sh->irq = 0; /* set 16 byte cdb's */ sh->max_cmd_len = 16; /* Yikes! This is important! * Otherwise, by default, linux * only scans target IDs 0-7! * pfactsN->MaxDevices unreliable * (not supported in early * versions of the FW). * max_id = 1 + actual max id, * max_lun = 1 + actual last lun, * see hosts.h :o( */ sh->max_id = ioc->devices_per_bus; sh->max_lun = MPT_LAST_LUN + 1; /* * If RAID Firmware Detected, setup virtual channel */ if (ioc->ir_firmware) sh->max_channel = 1; else sh->max_channel = 0; sh->this_id = ioc->pfacts[0].PortSCSIID; /* Required entry. */ sh->unique_id = ioc->id; /* Verify that we won't exceed the maximum * number of chain buffers * We can optimize: ZZ = req_sz/sizeof(SGE) * For 32bit SGE's: * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ * + (req_sz - 64)/sizeof(SGE) * A slightly different algorithm is required for * 64bit SGEs. */ scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); if (sizeof(dma_addr_t) == sizeof(u64)) { numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32)); } else { numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32)); } if (numSGE < sh->sg_tablesize) { /* Reset this value */ dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Resetting sg_tablesize to %d from %d\n", ioc->name, numSGE, sh->sg_tablesize)); sh->sg_tablesize = numSGE; } spin_unlock_irqrestore(&ioc->FreeQlock, flags); hd = shost_priv(sh); hd->ioc = ioc; /* SCSI needs scsi_cmnd lookup table! * (with size equal to req_depth*PtrSz!) */ ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC); if (!ioc->ScsiLookup) { error = -ENOMEM; goto out_mptspi_probe; } spin_lock_init(&ioc->scsi_lookup_lock); dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n", ioc->name, ioc->ScsiLookup)); /* Clear the TM flags */ hd->tmPending = 0; hd->tmState = TM_STATE_NONE; hd->resetPending = 0; hd->abortSCpnt = NULL; /* Clear the pointer used to store * single-threaded commands, i.e., those * issued during a bus scan, dv and * configuration pages. */ hd->cmdPtr = NULL; /* Initialize this SCSI Hosts' timers * To use, set the timer expires field * and add_timer */ init_timer(&hd->timer); hd->timer.data = (unsigned long) hd; hd->timer.function = mptscsih_timer_expired; ioc->spi_data.Saf_Te = mpt_saf_te; hd->negoNvram = MPT_SCSICFG_USE_NVRAM; ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "saf_te %x\n", ioc->name, mpt_saf_te)); ioc->spi_data.noQas = 0; init_waitqueue_head(&hd->scandv_waitq); hd->scandv_wait_done = 0; hd->last_queue_full = 0; hd->spi_pending = 0; /* Some versions of the firmware don't support page 0; without * that we can't get the parameters */ if (ioc->spi_data.sdp0length != 0) sh->transportt = mptspi_transport_template; error = scsi_add_host (sh, &ioc->pcidev->dev); if(error) { dprintk(ioc, printk(MYIOC_s_ERR_FMT "scsi_add_host failed\n", ioc->name)); goto out_mptspi_probe; } /* * issue internal bus reset */ if (ioc->spi_data.bus_reset) mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, 0, 0, 0, 0, 5); scsi_scan_host(sh); return 0;out_mptspi_probe: mptscsih_remove(pdev); return error;}static struct pci_driver mptspi_driver = { .name = "mptspi", .id_table = mptspi_pci_table, .probe = mptspi_probe, .remove = __devexit_p(mptscsih_remove), .shutdown = mptscsih_shutdown,#ifdef CONFIG_PM .suspend = mptscsih_suspend, .resume = mptspi_resume,#endif};/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mptspi_init - Register MPT adapter(s) as SCSI host(s) with SCSI mid-layer. * * Returns 0 for success, non-zero for failure. */static int __initmptspi_init(void){ int error; show_mptmod_ver(my_NAME, my_VERSION); mptspi_transport_template = spi_attach_transport(&mptspi_transport_functions); if (!mptspi_transport_template) return -ENODEV; mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER); mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER); mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER); mpt_event_register(mptspiDoneCtx, mptspi_event_process); mpt_reset_register(mptspiDoneCtx, mptspi_ioc_reset); error = pci_register_driver(&mptspi_driver); if (error) spi_release_transport(mptspi_transport_template); return error;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mptspi_exit - Unregisters MPT adapter(s) */static void __exitmptspi_exit(void){ pci_unregister_driver(&mptspi_driver); mpt_reset_deregister(mptspiDoneCtx); mpt_event_deregister(mptspiDoneCtx); mpt_deregister(mptspiInternalCtx); mpt_deregister(mptspiTaskCtx); mpt_deregister(mptspiDoneCtx); spi_release_transport(mptspi_transport_template);}module_init(mptspi_init);module_exit(mptspi_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -