📄 mptsas.c
字号:
"bitmask=0x%016llX\n", ioc->name, __FUNCTION__, port_details, i, port_details->num_phys, (unsigned long long)port_details->phy_bitmask)); dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tport = %p rphy=%p\n", ioc->name, port_details->port, port_details->rphy)); } dsaswideprintk(ioc, printk("\n")); mutex_unlock(&ioc->sas_topology_mutex);}/** * csmisas_find_vtarget * * @ioc * @volume_id * @volume_bus * **/static VirtTarget *mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id){ struct scsi_device *sdev; VirtDevice *vdevice; VirtTarget *vtarget = NULL; shost_for_each_device(sdev, ioc->sh) { if ((vdevice = sdev->hostdata) == NULL) continue; if (vdevice->vtarget->id == id && vdevice->vtarget->channel == channel) vtarget = vdevice->vtarget; } return vtarget;}/** * mptsas_target_reset * * Issues TARGET_RESET to end device using handshaking method * * @ioc * @channel * @id * * Returns (1) success * (0) failure * **/static intmptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id){ MPT_FRAME_HDR *mf; SCSITaskMgmt_t *pScsiTm; if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) { dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n", ioc->name,__FUNCTION__, __LINE__)); return 0; } /* Format the Request */ pScsiTm = (SCSITaskMgmt_t *) mf; memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t)); pScsiTm->TargetID = id; pScsiTm->Bus = channel; pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET; pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION; DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf); mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf); return 1;}/** * mptsas_target_reset_queue * * Receive request for TARGET_RESET after recieving an firmware * event NOT_RESPONDING_EVENT, then put command in link list * and queue if task_queue already in use. * * @ioc * @sas_event_data * **/static voidmptsas_target_reset_queue(MPT_ADAPTER *ioc, EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data){ MPT_SCSI_HOST *hd = shost_priv(ioc->sh); VirtTarget *vtarget = NULL; struct mptsas_target_reset_event *target_reset_list; u8 id, channel; id = sas_event_data->TargetID; channel = sas_event_data->Bus; if (!(vtarget = mptsas_find_vtarget(ioc, channel, id))) return; vtarget->deleted = 1; /* block IO */ target_reset_list = kzalloc(sizeof(*target_reset_list), GFP_ATOMIC); if (!target_reset_list) { dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n", ioc->name,__FUNCTION__, __LINE__)); return; } memcpy(&target_reset_list->sas_event_data, sas_event_data, sizeof(*sas_event_data)); list_add_tail(&target_reset_list->list, &hd->target_reset_list); if (hd->resetPending) return; if (mptsas_target_reset(ioc, channel, id)) { target_reset_list->target_reset_issued = 1; hd->resetPending = 1; }}/** * mptsas_dev_reset_complete * * Completion for TARGET_RESET after NOT_RESPONDING_EVENT, * enable work queue to finish off removing device from upper layers. * then send next TARGET_RESET in the queue. * * @ioc * **/static voidmptsas_dev_reset_complete(MPT_ADAPTER *ioc){ MPT_SCSI_HOST *hd = shost_priv(ioc->sh); struct list_head *head = &hd->target_reset_list; struct mptsas_target_reset_event *target_reset_list; struct mptsas_hotplug_event *ev; EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data; u8 id, channel; __le64 sas_address; if (list_empty(head)) return; target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, list); sas_event_data = &target_reset_list->sas_event_data; id = sas_event_data->TargetID; channel = sas_event_data->Bus; hd->resetPending = 0; /* * retry target reset */ if (!target_reset_list->target_reset_issued) { if (mptsas_target_reset(ioc, channel, id)) { target_reset_list->target_reset_issued = 1; hd->resetPending = 1; } return; } /* * enable work queue to remove device from upper layers */ list_del(&target_reset_list->list); ev = kzalloc(sizeof(*ev), GFP_ATOMIC); if (!ev) { dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n", ioc->name,__FUNCTION__, __LINE__)); return; } INIT_WORK(&ev->work, mptsas_hotplug_work); ev->ioc = ioc; ev->handle = le16_to_cpu(sas_event_data->DevHandle); ev->parent_handle = le16_to_cpu(sas_event_data->ParentDevHandle); ev->channel = channel; ev->id =id; 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 = le32_to_cpu(sas_event_data->DeviceInfo); ev->event_type = MPTSAS_DEL_DEVICE; schedule_work(&ev->work); kfree(target_reset_list); /* * issue target reset to next device in the queue */ head = &hd->target_reset_list; if (list_empty(head)) return; target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, list); sas_event_data = &target_reset_list->sas_event_data; id = sas_event_data->TargetID; channel = sas_event_data->Bus; if (mptsas_target_reset(ioc, channel, id)) { target_reset_list->target_reset_issued = 1; hd->resetPending = 1; }}/** * mptsas_taskmgmt_complete * * @ioc * @mf * @mr * **/static intmptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr){ mptsas_dev_reset_complete(ioc); return mptscsih_taskmgmt_complete(ioc, mf, mr);}/** * mptscsih_ioc_reset * * @ioc * @reset_phase * **/static intmptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase){ MPT_SCSI_HOST *hd; struct mptsas_target_reset_event *target_reset_list, *n; int rc; rc = mptscsih_ioc_reset(ioc, reset_phase); if (ioc->bus_type != SAS) goto out; if (reset_phase != MPT_IOC_POST_RESET) goto out; if (!ioc->sh || !ioc->sh->hostdata) goto out; hd = shost_priv(ioc->sh); if (!hd->ioc) goto out; if (list_empty(&hd->target_reset_list)) goto out; /* flush the target_reset_list */ list_for_each_entry_safe(target_reset_list, n, &hd->target_reset_list, list) { list_del(&target_reset_list->list); kfree(target_reset_list); } out: return rc;}static intmptsas_sas_enclosure_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;}static intmptsas_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 intmptsas_target_alloc(struct scsi_target *starget){ struct Scsi_Host *host = dev_to_shost(&starget->dev); MPT_SCSI_HOST *hd = shost_priv(host); VirtTarget *vtarget; u8 id, channel; struct sas_rphy *rphy; struct mptsas_portinfo *p; int i; MPT_ADAPTER *ioc = hd->ioc; vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL); if (!vtarget) return -ENOMEM; vtarget->starget = starget; vtarget->ioc_id = ioc->id; vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; id = starget->id; channel = 0; /* * RAID volumes placed beyond the last expected port. */ if (starget->channel == MPTSAS_RAID_CHANNEL) { for (i=0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) if (id == ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID) channel = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus; goto out; } rphy = dev_to_rphy(starget->dev.parent); 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) continue; 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(ioc, channel, id)) { id = mptscsih_raid_id_to_num(ioc, channel, id); vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; p->phy_info[i].attached.phys_disk_num = id; } mutex_unlock(&ioc->sas_topology_mutex); goto out; } } mutex_unlock(&ioc->sas_topology_mutex); kfree(vtarget); return -ENXIO; out: vtarget->id = id; vtarget->channel = channel; starget->hostdata = vtarget; return 0;}static voidmptsas_target_destroy(struct scsi_target *starget){ struct Scsi_Host *host = dev_to_shost(&starget->dev); MPT_SCSI_HOST *hd = shost_priv(host); struct sas_rphy *rphy; struct mptsas_portinfo *p; int i; MPT_ADAPTER *ioc = hd->ioc; if (!starget->hostdata) return; if (starget->channel == MPTSAS_RAID_CHANNEL) goto out; rphy = dev_to_rphy(starget->dev.parent); 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) continue; mptsas_set_starget(&p->phy_info[i], NULL); goto out; } } out: kfree(starget->hostdata); starget->hostdata = NULL;}static intmptsas_slave_alloc(struct scsi_device *sdev){ struct Scsi_Host *host = sdev->host; MPT_SCSI_HOST *hd = shost_priv(host); struct sas_rphy *rphy; struct mptsas_portinfo *p; VirtDevice *vdevice; struct scsi_target *starget; int i; MPT_ADAPTER *ioc = hd->ioc; vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL); if (!vdevice) { printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n", ioc->name, sizeof(VirtDevice)); return -ENOMEM; } starget = scsi_target(sdev); vdevice->vtarget = starget->hostdata; if (sdev->channel == MPTSAS_RAID_CHANNEL) goto out; rphy = dev_to_rphy(sdev->sdev_target->dev.parent); 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) continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -