📄 mptfc.c
字号:
ri->starget = NULL; } if (starget->hostdata) kfree(starget->hostdata); starget->hostdata = NULL;}/* * OS entry point to allow host driver to alloc memory * for each scsi target. Called once per device the bus scan. * Return non-zero if allocation fails. */static intmptfc_target_alloc(struct scsi_target *starget){ VirtTarget *vtarget; struct fc_rport *rport; struct mptfc_rport_info *ri; int rc; vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL); if (!vtarget) return -ENOMEM; starget->hostdata = vtarget; rc = -ENODEV; rport = starget_to_rport(starget); if (rport) { ri = *((struct mptfc_rport_info **)rport->dd_data); if (ri) { /* better be! */ vtarget->id = ri->pg0.CurrentTargetID; vtarget->channel = ri->pg0.CurrentBus; ri->starget = starget; rc = 0; } } if (rc != 0) { kfree(vtarget); starget->hostdata = NULL; } return rc;}/* * mptfc_dump_lun_info * @ioc * @rport * @sdev * */static voidmptfc_dump_lun_info(MPT_ADAPTER *ioc, struct fc_rport *rport, struct scsi_device *sdev, VirtTarget *vtarget){ 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 (ioc, printk(MYIOC_s_DEBUG_FMT "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, " "CurrentTargetID %d, %x %llx %llx\n", 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));}/* * OS entry point to allow host driver to alloc memory * for each scsi device. Called once per device the bus scan. * Return non-zero if allocation fails. * Init memory once per LUN. */static intmptfc_slave_alloc(struct scsi_device *sdev){ MPT_SCSI_HOST *hd; VirtTarget *vtarget; VirtDevice *vdevice; struct scsi_target *starget; struct fc_rport *rport; MPT_ADAPTER *ioc; starget = scsi_target(sdev); rport = starget_to_rport(starget); if (!rport || fc_remote_port_chkready(rport)) return -ENXIO; hd = shost_priv(sdev->host); ioc = hd->ioc; vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL); if (!vdevice) { printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", ioc->name, sizeof(VirtDevice)); return -ENOMEM; } sdev->hostdata = vdevice; vtarget = starget->hostdata; if (vtarget->num_luns == 0) { vtarget->ioc_id = ioc->id; vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; } vdevice->vtarget = vtarget; vdevice->lun = sdev->lun; vtarget->num_luns++; mptfc_dump_lun_info(ioc, rport, sdev, vtarget); return 0;}static intmptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)){ struct mptfc_rport_info *ri; struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device)); int err; VirtDevice *vdevice = SCpnt->device->hostdata; if (!vdevice || !vdevice->vtarget) { SCpnt->result = DID_NO_CONNECT << 16; done(SCpnt); return 0; } err = fc_remote_port_chkready(rport); if (unlikely(err)) { SCpnt->result = err; done(SCpnt); return 0; } /* dd_data is null until finished adding target */ ri = *((struct mptfc_rport_info **)rport->dd_data); if (unlikely(!ri)) { SCpnt->result = DID_IMM_RETRY << 16; done(SCpnt); return 0; } return mptscsih_qcmd(SCpnt,done);}/* * mptfc_display_port_link_speed - displaying link speed * @ioc: Pointer to MPT_ADAPTER structure * @portnum: IOC Port number * @pp0dest: port page0 data payload * */static voidmptfc_display_port_link_speed(MPT_ADAPTER *ioc, int portnum, FCPortPage0_t *pp0dest){ u8 old_speed, new_speed, state; char *old, *new; if (portnum >= 2) return; old_speed = ioc->fc_link_speed[portnum]; new_speed = pp0dest->CurrentSpeed; state = pp0dest->PortState; if (state != MPI_FCPORTPAGE0_PORTSTATE_OFFLINE && new_speed != MPI_FCPORTPAGE0_CURRENT_SPEED_UKNOWN) { old = old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT ? "1 Gbps" : old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT ? "2 Gbps" : old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT ? "4 Gbps" : "Unknown"; new = new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT ? "1 Gbps" : new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT ? "2 Gbps" : new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT ? "4 Gbps" : "Unknown"; if (old_speed == 0) printk(MYIOC_s_NOTE_FMT "FC Link Established, Speed = %s\n", ioc->name, new); else if (old_speed != new_speed) printk(MYIOC_s_WARN_FMT "FC Link Speed Change, Old Speed = %s, New Speed = %s\n", ioc->name, old, new); ioc->fc_link_speed[portnum] = new_speed; }}/* * 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 intmptfc_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); } mptfc_display_port_link_speed(ioc, portnum, pp0dest); } pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma); } return rc;}static intmptfc_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 intmptfc_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); 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;}static voidmptfc_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 voidmptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum){ unsigned class = 0; unsigned cos = 0; unsigned speed; unsigned port_type; unsigned port_state; FCPortPage0_t *pp0; struct Scsi_Host *sh; char *sn; /* don't know what to do as only one scsi (fc) host was allocated */ if (portnum != 0) return; pp0 = &ioc->fc_port_page0[portnum]; sh = ioc->sh; sn = fc_host_symbolic_name(sh); snprintf(sn, FC_SYMBOLIC_NAME_SIZE, "%s %s%08xh", ioc->prod_name, MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word); fc_host_tgtid_bind_type(sh) = FC_TGTID_BIND_BY_WWPN; fc_host_maxframe_size(sh) = pp0->MaxFrameSize; fc_host_node_name(sh) = (u64)pp0->WWNN.High << 32 | (u64)pp0->WWNN.Low; fc_host_port_name(sh) = (u64)pp0->WWPN.High << 32 | (u64)pp0->WWPN.Low; fc_host_port_id(sh) = pp0->PortIdentifier; class = pp0->SupportedServiceClass; if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1) cos |= FC_COS_CLASS1; if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2) cos |= FC_COS_CLASS2; if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3) cos |= FC_COS_CLASS3; fc_host_supported_classes(sh) = cos; if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT) speed = FC_PORTSPEED_1GBIT; else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT) speed = FC_PORTSPEED_2GBIT; else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT) speed = FC_PORTSPEED_4GBIT; else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_10GBIT) speed = FC_PORTSPEED_10GBIT; else speed = FC_PORTSPEED_UNKNOWN; fc_host_speed(sh) = speed; speed = 0; if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED) speed |= FC_PORTSPEED_1GBIT; if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED) speed |= FC_PORTSPEED_2GBIT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -