mptbase.c
来自「linux 内核源代码」· C语言 代码 · 共 2,293 行 · 第 1/5 页
C
2,293 行
mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */ list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);#ifdef MFCNT ioc->mfcnt--;#endif spin_unlock_irqrestore(&ioc->FreeQlock, flags);}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_add_sge - Place a simple SGE at address pAddr. * @pAddr: virtual address for SGE * @flagslength: SGE flags and data transfer length * @dma_addr: Physical address * * This routine places a MPT request frame back on the MPT adapter's * FreeQ. */voidmpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr){ if (sizeof(dma_addr_t) == sizeof(u64)) { SGESimple64_t *pSge = (SGESimple64_t *) pAddr; u32 tmp = dma_addr & 0xFFFFFFFF; pSge->FlagsLength = cpu_to_le32(flagslength); pSge->Address.Low = cpu_to_le32(tmp); tmp = (u32) ((u64)dma_addr >> 32); pSge->Address.High = cpu_to_le32(tmp); } else { SGESimple32_t *pSge = (SGESimple32_t *) pAddr; pSge->FlagsLength = cpu_to_le32(flagslength); pSge->Address = cpu_to_le32(dma_addr); }}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_send_handshake_request - Send MPT request via doorbell handshake method. * @cb_idx: Handle of registered MPT protocol driver * @ioc: Pointer to MPT adapter structure * @reqBytes: Size of the request in bytes * @req: Pointer to MPT request frame * @sleepFlag: Use schedule if CAN_SLEEP else use udelay. * * This routine is used exclusively to send MptScsiTaskMgmt * requests since they are required to be sent via doorbell handshake. * * NOTE: It is the callers responsibility to byte-swap fields in the * request which are greater than 1 byte in size. * * Returns 0 for success, non-zero for failure. */intmpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag){ int r = 0; u8 *req_as_bytes; int ii; /* State is known to be good upon entering * this function so issue the bus reset * request. */ /* * Emulate what mpt_put_msg_frame() does /wrt to sanity * setting cb_idx/req_idx. But ONLY if this request * is in proper (pre-alloc'd) request buffer range... */ ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req); if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) { MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req; mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii); mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx; } /* Make sure there are no doorbells */ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); CHIPREG_WRITE32(&ioc->chip->Doorbell, ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) | ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT))); /* Wait for IOC doorbell int */ if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) { return ii; } /* Read doorbell and check for active bit */ if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE)) return -5; dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_send_handshake_request start, WaitCnt=%d\n", ioc->name, ii)); CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) { return -2; } /* Send request via doorbell handshake */ req_as_bytes = (u8 *) req; for (ii = 0; ii < reqBytes/4; ii++) { u32 word; word = ((req_as_bytes[(ii*4) + 0] << 0) | (req_as_bytes[(ii*4) + 1] << 8) | (req_as_bytes[(ii*4) + 2] << 16) | (req_as_bytes[(ii*4) + 3] << 24)); CHIPREG_WRITE32(&ioc->chip->Doorbell, word); if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) { r = -3; break; } } if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0) r = 0; else r = -4; /* Make sure there are no doorbells */ CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); return r;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_host_page_access_control - control the IOC's Host Page Buffer access * @ioc: Pointer to MPT adapter structure * @access_control_value: define bits below * @sleepFlag: Specifies whether the process can sleep * * Provides mechanism for the host driver to control the IOC's * Host Page Buffer access. * * Access Control Value - bits[15:12] * 0h Reserved * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS } * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS } * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER } * * Returns 0 for success, non-zero for failure. */static intmpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag){ int r = 0; /* return if in use */ if (CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE) return -1; CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); CHIPREG_WRITE32(&ioc->chip->Doorbell, ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL <<MPI_DOORBELL_FUNCTION_SHIFT) | (access_control_value<<12))); /* Wait for IOC to clear Doorbell Status bit */ if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) { return -2; }else return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_host_page_alloc - allocate system memory for the fw * @ioc: Pointer to pointer to IOC adapter * @ioc_init: Pointer to ioc init config page * * If we already allocated memory in past, then resend the same pointer. * Returns 0 for success, non-zero for failure. */static intmpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init){ char *psge; int flags_length; u32 host_page_buffer_sz=0; if(!ioc->HostPageBuffer) { host_page_buffer_sz = le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF; if(!host_page_buffer_sz) return 0; /* fw doesn't need any host buffers */ /* spin till we get enough memory */ while(host_page_buffer_sz > 0) { if((ioc->HostPageBuffer = pci_alloc_consistent( ioc->pcidev, host_page_buffer_sz, &ioc->HostPageBuffer_dma)) != NULL) { dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n", ioc->name, ioc->HostPageBuffer, (u32)ioc->HostPageBuffer_dma, host_page_buffer_sz)); ioc->alloc_total += host_page_buffer_sz; ioc->HostPageBuffer_sz = host_page_buffer_sz; break; } host_page_buffer_sz -= (4*1024); } } if(!ioc->HostPageBuffer) { printk(MYIOC_s_ERR_FMT "Failed to alloc memory for host_page_buffer!\n", ioc->name); return -999; } psge = (char *)&ioc_init->HostPageBufferSGE; flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_SYSTEM_ADDRESS | MPI_SGE_FLAGS_32_BIT_ADDRESSING | MPI_SGE_FLAGS_HOST_TO_IOC | MPI_SGE_FLAGS_END_OF_BUFFER; if (sizeof(dma_addr_t) == sizeof(u64)) { flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING; } flags_length = flags_length << MPI_SGE_FLAGS_SHIFT; flags_length |= ioc->HostPageBuffer_sz; mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma); ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_verify_adapter - Given IOC identifier, set pointer to its adapter structure. * @iocid: IOC unique identifier (integer) * @iocpp: Pointer to pointer to IOC adapter * * Given a unique IOC identifier, set pointer to the associated MPT * adapter structure. * * Returns iocid and sets iocpp if iocid is found. * Returns -1 if iocid is not found. */intmpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp){ MPT_ADAPTER *ioc; list_for_each_entry(ioc,&ioc_list,list) { if (ioc->id == iocid) { *iocpp =ioc; return iocid; } } *iocpp = NULL; return -1;}/** * mpt_get_product_name - returns product string * @vendor: pci vendor id * @device: pci device id * @revision: pci revision id * @prod_name: string returned * * Returns product string displayed when driver loads, * in /proc/mpt/summary and /sysfs/class/scsi_host/host<X>/version_product * **/static voidmpt_get_product_name(u16 vendor, u16 device, u8 revision, char *prod_name){ char *product_str = NULL; if (vendor == PCI_VENDOR_ID_BROCADE) { switch (device) { case MPI_MANUFACTPAGE_DEVICEID_FC949E: switch (revision) { case 0x00: product_str = "BRE040 A0"; break; case 0x01: product_str = "BRE040 A1"; break; default: product_str = "BRE040"; break; } break; } goto out; } switch (device) { case MPI_MANUFACTPAGE_DEVICEID_FC909: product_str = "LSIFC909 B1"; break; case MPI_MANUFACTPAGE_DEVICEID_FC919: product_str = "LSIFC919 B0"; break; case MPI_MANUFACTPAGE_DEVICEID_FC929: product_str = "LSIFC929 B0"; break; case MPI_MANUFACTPAGE_DEVICEID_FC919X: if (revision < 0x80) product_str = "LSIFC919X A0"; else product_str = "LSIFC919XL A1"; break; case MPI_MANUFACTPAGE_DEVICEID_FC929X: if (revision < 0x80) product_str = "LSIFC929X A0"; else product_str = "LSIFC929XL A1"; break; case MPI_MANUFACTPAGE_DEVICEID_FC939X: product_str = "LSIFC939X A1"; break; case MPI_MANUFACTPAGE_DEVICEID_FC949X: product_str = "LSIFC949X A1"; break; case MPI_MANUFACTPAGE_DEVICEID_FC949E: switch (revision) { case 0x00: product_str = "LSIFC949E A0"; break; case 0x01: product_str = "LSIFC949E A1"; break; default: product_str = "LSIFC949E"; break; } break; case MPI_MANUFACTPAGE_DEVID_53C1030: switch (revision) { case 0x00: product_str = "LSI53C1030 A0"; break; case 0x01: product_str = "LSI53C1030 B0"; break; case 0x03: product_str = "LSI53C1030 B1"; break; case 0x07: product_str = "LSI53C1030 B2"; break; case 0x08: product_str = "LSI53C1030 C0"; break; case 0x80: product_str = "LSI53C1030T A0"; break; case 0x83: product_str = "LSI53C1030T A2"; break; case 0x87: product_str = "LSI53C1030T A3"; break; case 0xc1: product_str = "LSI53C1020A A1"; break; default: product_str = "LSI53C1030"; break; } break; case MPI_MANUFACTPAGE_DEVID_1030_53C1035: switch (revision) { case 0x03: product_str = "LSI53C1035 A2"; break; case 0x04: product_str = "LSI53C1035 B0"; break; default: product_str = "LSI53C1035"; break; } break; case MPI_MANUFACTPAGE_DEVID_SAS1064: switch (revision) { case 0x00: product_str = "LSISAS1064 A1"; break; case 0x01: product_str = "LSISAS1064 A2"; break; case 0x02: product_str = "LSISAS1064 A3"; break; case 0x03: product_str = "LSISAS1064 A4"; break; default: product_str = "LSISAS1064"; break; } break; case MPI_MANUFACTPAGE_DEVID_SAS1064E: switch (revision) { case 0x00: product_str = "LSISAS1064E A0"; break; case 0x01: product_str = "LSISAS1064E B0"; break; case 0x02: product_str = "LSISAS1064E B1"; break; case 0x04: product_str = "LSISAS1064E B2"; break; case 0x08: product_str = "LSISAS1064E B3"; break; default: product_str = "LSISAS1064E"; break; } break; case MPI_MANUFACTPAGE_DEVID_SAS1068: switch (revision) { case 0x00: product_str = "LSISAS1068 A0"; break; case 0x01: product_str = "LSISAS1068 B0"; break; case 0x02: product_str = "LSISAS1068 B1"; break; default: product_str = "LSISAS1068"; break; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?