📄 mptbase.c
字号:
CONFIGPARMS *pCfg; unsigned long flags; dcprintk((MYIOC_s_INFO_FMT "config_complete (mf=%p,mr=%p)\n", ioc->name, mf, reply)); pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *))); if (pCfg) { /* disable timer and remove from linked list */ del_timer(&pCfg->timer); spin_lock_irqsave(&ioc->FreeQlock, flags); list_del(&pCfg->linkage); spin_unlock_irqrestore(&ioc->FreeQlock, flags); /* * If IOC Status is SUCCESS, save the header * and set the status code to GOOD. */ pCfg->status = MPT_CONFIG_ERROR; if (reply) { ConfigReply_t *pReply = (ConfigReply_t *)reply; u16 status; status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK; dcprintk((KERN_NOTICE " IOCStatus=%04xh, IOCLogInfo=%08xh\n", status, le32_to_cpu(pReply->IOCLogInfo))); pCfg->status = status; if (status == MPI_IOCSTATUS_SUCCESS) { if ((pReply->Header.PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) { pCfg->cfghdr.ehdr->ExtPageLength = le16_to_cpu(pReply->ExtPageLength); pCfg->cfghdr.ehdr->ExtPageType = pReply->ExtPageType; } pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion; /* If this is a regular header, save PageLength. */ /* LMP Do this better so not using a reserved field! */ pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength; pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber; pCfg->cfghdr.hdr->PageType = pReply->Header.PageType; } } /* * Wake up the original calling thread */ pCfg->wait_done = 1; wake_up(&mpt_waitq); } } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) { /* we should be always getting a reply frame */ memcpy(ioc->persist_reply_frame, reply, min(MPT_DEFAULT_FRAME_SIZE, 4*reply->u.reply.MsgLength)); del_timer(&ioc->persist_timer); ioc->persist_wait_done = 1; wake_up(&mpt_waitq); } else { printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n", ioc->name, func); } /* * Conditionally tell caller to free the original * EventNotification/EventAck/unexpected request frame! */ return freereq;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_register - Register protocol-specific main callback handler. * @cbfunc: callback function pointer * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value) * * This routine is called by a protocol-specific driver (SCSI host, * LAN, SCSI target) to register it's reply callback routine. Each * protocol-specific driver must do this before it will be able to * use any IOC resources, such as obtaining request frames. * * NOTES: The SCSI protocol driver currently calls this routine thrice * in order to register separate callbacks; one for "normal" SCSI IO; * one for MptScsiTaskMgmt requests; one for Scan/DV requests. * * Returns a positive integer valued "handle" in the * range (and S.O.D. order) {N,...,7,6,5,...,1} if successful. * Any non-positive return value (including zero!) should be considered * an error by the caller. */intmpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass){ int i; last_drv_idx = -1; /* * Search for empty callback slot in this order: {N,...,7,6,5,...,1} * (slot/handle 0 is reserved!) */ for (i = MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) { if (MptCallbacks[i] == NULL) { MptCallbacks[i] = cbfunc; MptDriverClass[i] = dclass; MptEvHandlers[i] = NULL; last_drv_idx = i; break; } } return last_drv_idx;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_deregister - Deregister a protocol drivers resources. * @cb_idx: previously registered callback handle * * Each protocol-specific driver should call this routine when it's * module is unloaded. */voidmpt_deregister(int cb_idx){ if ((cb_idx >= 0) && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) { MptCallbacks[cb_idx] = NULL; MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER; MptEvHandlers[cb_idx] = NULL; last_drv_idx++; }}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_event_register - Register protocol-specific event callback * handler. * @cb_idx: previously registered (via mpt_register) callback handle * @ev_cbfunc: callback function * * This routine can be called by one or more protocol-specific drivers * if/when they choose to be notified of MPT events. * * Returns 0 for success. */intmpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc){ if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) return -1; MptEvHandlers[cb_idx] = ev_cbfunc; return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_event_deregister - Deregister protocol-specific event callback * handler. * @cb_idx: previously registered callback handle * * Each protocol-specific driver should call this routine * when it does not (or can no longer) handle events, * or when it's module is unloaded. */voidmpt_event_deregister(int cb_idx){ if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) return; MptEvHandlers[cb_idx] = NULL;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_reset_register - Register protocol-specific IOC reset handler. * @cb_idx: previously registered (via mpt_register) callback handle * @reset_func: reset function * * This routine can be called by one or more protocol-specific drivers * if/when they choose to be notified of IOC resets. * * Returns 0 for success. */intmpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func){ if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) return -1; MptResetHandlers[cb_idx] = reset_func; return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_reset_deregister - Deregister protocol-specific IOC reset handler. * @cb_idx: previously registered callback handle * * Each protocol-specific driver should call this routine * when it does not (or can no longer) handle IOC reset handling, * or when it's module is unloaded. */voidmpt_reset_deregister(int cb_idx){ if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) return; MptResetHandlers[cb_idx] = NULL;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_device_driver_register - Register device driver hooks */intmpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx){ MPT_ADAPTER *ioc; if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) { return -EINVAL; } MptDeviceDriverHandlers[cb_idx] = dd_cbfunc; /* call per pci device probe entry point */ list_for_each_entry(ioc, &ioc_list, list) { if(dd_cbfunc->probe) { dd_cbfunc->probe(ioc->pcidev, ioc->pcidev->driver->id_table); } } return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_device_driver_deregister - DeRegister device driver hooks */voidmpt_device_driver_deregister(int cb_idx){ struct mpt_pci_driver *dd_cbfunc; MPT_ADAPTER *ioc; if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) return; dd_cbfunc = MptDeviceDriverHandlers[cb_idx]; list_for_each_entry(ioc, &ioc_list, list) { if (dd_cbfunc->remove) dd_cbfunc->remove(ioc->pcidev); } MptDeviceDriverHandlers[cb_idx] = NULL;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024) * allocated per MPT adapter. * @handle: Handle of registered MPT protocol driver * @ioc: Pointer to MPT adapter structure * * Returns pointer to a MPT request frame or %NULL if none are available * or IOC is not active. */MPT_FRAME_HDR*mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc){ MPT_FRAME_HDR *mf; unsigned long flags; u16 req_idx; /* Request index */ /* validate handle and ioc identifier */#ifdef MFCNT if (!ioc->active) printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n");#endif /* If interrupts are not attached, do not return a request frame */ if (!ioc->active) return NULL; spin_lock_irqsave(&ioc->FreeQlock, flags); if (!list_empty(&ioc->FreeQ)) { int req_offset; mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR, u.frame.linkage.list); list_del(&mf->u.frame.linkage.list); mf->u.frame.linkage.arg1 = 0; mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */ req_offset = (u8 *)mf - (u8 *)ioc->req_frames; /* u16! */ req_idx = req_offset / ioc->req_sz; mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx); mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0; ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */#ifdef MFCNT ioc->mfcnt++;#endif } else mf = NULL; spin_unlock_irqrestore(&ioc->FreeQlock, flags);#ifdef MFCNT if (mf == NULL) printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", ioc->mfcnt, ioc->req_depth); mfcounter++; if (mfcounter == PRINT_MF_COUNT) printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", ioc->mfcnt, ioc->req_depth);#endif dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n", ioc->name, handle, ioc->id, mf)); return mf;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_put_msg_frame - Send a protocol specific MPT request frame * to a IOC. * @handle: Handle of registered MPT protocol driver * @ioc: Pointer to MPT adapter structure * @mf: Pointer to MPT request frame * * This routine posts a MPT request frame to the request post FIFO of a * specific MPT adapter. */voidmpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf){ u32 mf_dma_addr; int req_offset; u16 req_idx; /* Request index */ /* ensure values are reset properly! */ mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */ req_offset = (u8 *)mf - (u8 *)ioc->req_frames; /* u16! */ req_idx = req_offset / ioc->req_sz; mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx); mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;#ifdef MPT_DEBUG_MSG_FRAME { u32 *m = mf->u.frame.hwhdr.__hdr; int ii, n; printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ", ioc->name, m); n = ioc->req_sz/4 - 1; while (m[n] == 0) n--; for (ii=0; ii<=n; ii++) { if (ii && ((ii%8)==0)) printk("\n" KERN_INFO " "); printk(" %08x", le32_to_cpu(m[ii])); } printk("\n"); }#endif mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx]; dsgprintk((MYIOC_s_INFO_FMT "mf_dma_addr=%x req_idx=%d RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx, ioc->RequestNB[req_idx])); CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_free_msg_frame - Place MPT request frame back on FreeQ. * @handle: Handle of registered MPT protocol driver * @ioc: Pointer to MPT adapter structure * @mf: Pointer to MPT request frame * * This routine places a MPT request frame back on the MPT adapter's * FreeQ. */voidmpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf){ unsigned long flags; /* Put Request back on FreeQ! */ spin_lock_irqsave(&ioc->FreeQlock, flags); 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. * @handle: 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. *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -