📄 mptsas.c
字号:
ioc->sh, ioc->num_ports, ev->id, 0); if (!sdev) break; printk(MYIOC_s_INFO_FMT "removing device, channel %d, id %d\n", ioc->name, ioc->num_ports, ev->id); scsi_remove_device(sdev); scsi_device_put(sdev); mpt_findImVolumes(ioc); break; } kfree(ev);}static voidmptscsih_send_sas_event(MPT_ADAPTER *ioc, EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data){ struct mptsas_hotplug_event *ev; u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo); __le64 sas_address; if ((device_info & (MPI_SAS_DEVICE_INFO_SSP_TARGET | MPI_SAS_DEVICE_INFO_STP_TARGET | 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; 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);}static voidmptscsih_send_raid_event(MPT_ADAPTER *ioc, EVENT_DATA_RAID *raid_event_data){ struct mptsas_hotplug_event *ev; RAID_VOL0_STATUS * volumeStatus; if (ioc->bus_type != SAS) return; ev = kmalloc(sizeof(*ev), GFP_ATOMIC); if (!ev) { printk(KERN_WARNING "mptsas: lost hotplug event\n"); return; } memset(ev,0,sizeof(struct mptsas_hotplug_event)); INIT_WORK(&ev->work, mptsas_hotplug_work, ev); ev->ioc = ioc; ev->id = raid_event_data->VolumeID; switch (raid_event_data->ReasonCode) { case MPI_EVENT_RAID_RC_PHYSDISK_DELETED: ev->event_type = MPTSAS_ADD_DEVICE; break; case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: ev->event_type = MPTSAS_DEL_DEVICE; break; case MPI_EVENT_RAID_RC_VOLUME_DELETED: ev->event_type = MPTSAS_DEL_RAID; break; case MPI_EVENT_RAID_RC_VOLUME_CREATED: ev->event_type = MPTSAS_ADD_RAID; break; case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED: volumeStatus = (RAID_VOL0_STATUS *) & raid_event_data->SettingsStatus; ev->event_type = (volumeStatus->State == MPI_RAIDVOL0_STATUS_STATE_FAILED) ? MPTSAS_DEL_RAID : MPTSAS_ADD_RAID; break; default: break; } schedule_work(&ev->work);}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* work queue thread to clear the persitency table */static voidmptscsih_sas_persist_clear_table(void * arg){ MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);}static intmptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply){ int rc=1; u8 event = le32_to_cpu(reply->Event) & 0xFF; if (!ioc->sh) goto out; switch (event) { case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: mptscsih_send_sas_event(ioc, (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data); break; case MPI_EVENT_INTEGRATED_RAID: mptscsih_send_raid_event(ioc, (EVENT_DATA_RAID *)reply->Data); break; case MPI_EVENT_PERSISTENT_TABLE_FULL: INIT_WORK(&ioc->mptscsih_persistTask, mptscsih_sas_persist_clear_table, (void *)ioc); schedule_work(&ioc->mptscsih_persistTask); break; default: rc = mptscsih_event_process(ioc, reply); break; } out: return rc;}static intmptsas_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; r = mpt_attach(pdev,id); if (r) return r; ioc = pci_get_drvdata(pdev); ioc->DoneCtx = mptsasDoneCtx; ioc->TaskCtx = mptsasTaskCtx; ioc->InternalCtx = mptsasInternalCtx; /* 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_mptsas_probe; } if (!ioc->active) { printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n", ioc->name); error = -ENODEV; goto out_mptsas_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(&mptsas_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_mptsas_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; sh->max_id = ioc->pfacts->MaxDevices + 1; sh->transportt = mptsas_transport_template; sh->max_lun = MPT_LAST_LUN + 1; sh->max_channel = 0; sh->this_id = ioc->pfacts[0].PortSCSIID; /* Required entry. */ sh->unique_id = ioc->id; INIT_LIST_HEAD(&ioc->sas_topology); mutex_init(&ioc->sas_topology_mutex); mutex_init(&ioc->sas_mgmt.mutex); init_completion(&ioc->sas_mgmt.done); /* 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((MYIOC_s_INFO_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 = (MPT_SCSI_HOST *) sh->hostdata; hd->ioc = ioc; /* SCSI needs scsi_cmnd lookup table! * (with size equal to req_depth*PtrSz!) */ hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC); if (!hd->ScsiLookup) { error = -ENOMEM; goto out_mptsas_probe; } dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n", ioc->name, hd->ScsiLookup)); /* Allocate memory for the device structures. * A non-Null pointer at an offset * indicates a device exists. * max_id = 1 + maximum id (hosts.h) */ hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC); if (!hd->Targets) { error = -ENOMEM; goto out_mptsas_probe; } dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets)); /* 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; hd->mpt_pq_filter = mpt_pq_filter; ioc->sas_data.ptClear = mpt_pt_clear; if (ioc->sas_data.ptClear==1) { mptbase_sas_persist_operation( 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; error = scsi_add_host(sh, &ioc->pcidev->dev); if (error) { dprintk((KERN_ERR MYNAM "scsi_add_host failed\n")); goto out_mptsas_probe; } 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;ii<ioc->raid_data.pIocPg2->NumActiveVolumes;ii++) { scsi_add_device(sh, ioc->num_ports, ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID, 0); } return 0;out_mptsas_probe: mptscsih_remove(pdev); return error;}static void __devexit mptsas_remove(struct pci_dev *pdev){ MPT_ADAPTER *ioc = pci_get_drvdata(pdev); struct mptsas_portinfo *p, *n; sas_remove_host(ioc->sh); mutex_lock(&ioc->sas_topology_mutex); list_for_each_entry_safe(p, n, &ioc->sas_topology, list) { list_del(&p->list); kfree(p); } mutex_unlock(&ioc->sas_topology_mutex); mptscsih_remove(pdev);}static struct pci_device_id mptsas_pci_table[] = { { 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, PCI_DEVICE_ID_LSI_SAS1068, PCI_ANY_ID, PCI_ANY_ID }, { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064E, PCI_ANY_ID, PCI_ANY_ID }, { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066E, PCI_ANY_ID, PCI_ANY_ID }, { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068E, PCI_ANY_ID, PCI_ANY_ID }, {0} /* Terminating entry */};MODULE_DEVICE_TABLE(pci, mptsas_pci_table);static struct pci_driver mptsas_driver = { .name = "mptsas", .id_table = mptsas_pci_table, .probe = mptsas_probe, .remove = __devexit_p(mptsas_remove), .shutdown = mptscsih_shutdown,#ifdef CONFIG_PM .suspend = mptscsih_suspend, .resume = mptscsih_resume,#endif};static int __initmptsas_init(void){ show_mptmod_ver(my_NAME, my_VERSION); mptsas_transport_template = sas_attach_transport(&mptsas_transport_functions); if (!mptsas_transport_template) return -ENODEV; mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER); mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER); mptsasInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER); mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER); if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) { devtprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n")); } if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) { dprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n")); } return pci_register_driver(&mptsas_driver);}static void __exitmptsas_exit(void){ pci_unregister_driver(&mptsas_driver); sas_release_transport(mptsas_transport_template); mpt_reset_deregister(mptsasDoneCtx); mpt_event_deregister(mptsasDoneCtx); mpt_deregister(mptsasMgmtCtx); mpt_deregister(mptsasInternalCtx); mpt_deregister(mptsasTaskCtx); mpt_deregister(mptsasDoneCtx);}module_init(mptsas_init);module_exit(mptsas_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -