📄 mptbase.c
字号:
ioc->name, evHandlers, results)); } /* * Hmmm... It seems that EventNotificationReply is an exception * to the rule of one reply per request. */ if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) freereq = 0;#ifdef CONFIG_PROC_FS// LogEvent(ioc, pEvReply);#endif } else if (func == MPI_FUNCTION_EVENT_ACK) { dprintk((KERN_INFO MYNAM ": %s: mpt_base_reply, EventAck reply received\n", ioc->name)); } else { printk(KERN_ERR MYNAM ": %s: ERROR - 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 twice * in order to register separate callbacks; one for "normal" SCSI IO * and another for MptScsiTaskMgmt requests. * * Returns a positive integer valued "handle" in the * range (and S.O.D. order) {7,6,...,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 r = -1; int i;#ifndef MODULE /* * Handle possibility of the mptscsih_detect() routine getting * called *before* fusion_init! */ if (!FusionInitCalled) { dprintk((KERN_INFO MYNAM ": Hmmm, calling fusion_init from mpt_register!\n")); /* * NOTE! We'll get recursion here, as fusion_init() * calls mpt_register()! */ fusion_init(); FusionInitCalled++; }#endif /* * Search for empty callback slot in this order: {7,6,...,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; r = i; if (cbfunc != mpt_base_reply) { MOD_INC_USE_COUNT; } break; } } return r;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * 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 && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) { MptCallbacks[cb_idx] = NULL; MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER; MptEvHandlers[cb_idx] = NULL; if (cb_idx != mpt_base_index) { MOD_DEC_USE_COUNT; } }}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * 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_get_msg_frame - Obtain a MPT request frame from the pool (of 1024) * allocated per MPT adapter. * @handle: Handle of registered MPT protocol driver * @iocid: IOC unique identifier (integer) * * Returns pointer to a MPT request frame or %NULL if none are available. */MPT_FRAME_HDR*mpt_get_msg_frame(int handle, int iocid){ MPT_FRAME_HDR *mf = NULL; MPT_ADAPTER *iocp; unsigned long flags; /* validate handle and ioc identifier */ iocp = mpt_adapters[iocid]; spin_lock_irqsave(&iocp->FreeQlock, flags); if (! Q_IS_EMPTY(&iocp->FreeQ)) { int req_offset; mf = iocp->FreeQ.head; Q_DEL_ITEM(&mf->u.frame.linkage); mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */ req_offset = (u8 *)mf - (u8 *)iocp->req_frames; /* u16! */ mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_offset / iocp->req_sz); mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0; } spin_unlock_irqrestore(&iocp->FreeQlock, flags); dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n", iocp->name, handle, iocid, mf)); return mf;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_put_msg_frame - Send a protocol specific MPT request frame * to a IOC. * @handle: Handle of registered MPT protocol driver * @iocid: IOC unique identifier (integer) * @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, int iocid, MPT_FRAME_HDR *mf){ MPT_ADAPTER *iocp; iocp = mpt_adapters[iocid]; if (iocp != NULL) { dma_addr_t mf_dma_addr; int req_offset; /* ensure values are reset properly! */ mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */ req_offset = (u8 *)mf - (u8 *)iocp->req_frames; /* u16! */ mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_offset / iocp->req_sz); mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;#ifdef MPT_DEBUG_MSG_FRAME { u32 *m = mf->u.frame.hwhdr.__hdr; int i, n; printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ", iocp->name, m); n = iocp->req_sz/4 - 1; while (m[n] == 0) n--; for (i=0; i<=n; i++) { if (i && ((i%8)==0)) printk("\n" KERN_INFO " "); printk(" %08x", le32_to_cpu(m[i])); } printk("\n"); }#endif mf_dma_addr = iocp->req_frames_dma + req_offset; CHIPREG_WRITE32(&iocp->chip->RequestFifo, mf_dma_addr); }}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_free_msg_frame - Place MPT request frame back on FreeQ. * @handle: Handle of registered MPT protocol driver * @iocid: IOC unique identifier (integer) * @mf: Pointer to MPT request frame * * This routine places a MPT request frame back on the MPT adapter's * FreeQ. */voidmpt_free_msg_frame(int handle, int iocid, MPT_FRAME_HDR *mf){ MPT_ADAPTER *iocp; unsigned long flags; iocp = mpt_adapters[iocid]; if (iocp != NULL) { /* Put Request back on FreeQ! */ spin_lock_irqsave(&iocp->FreeQlock, flags); Q_ADD_TAIL(&iocp->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR); spin_unlock_irqrestore(&iocp->FreeQlock, flags); }}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_send_handshake_request - Send MPT request via doorbell * handshake method. * @handle: Handle of registered MPT protocol driver * @iocid: IOC unique identifier (integer) * @reqBytes: Size of the request in bytes * @req: Pointer to MPT request frame * * This routine is used exclusively by mptscsih 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(int handle, int iocid, int reqBytes, u32 *req){ MPT_ADAPTER *iocp; int r = 0; iocp = mpt_adapters[iocid]; if (iocp != NULL) { u8 *req_as_bytes; u32 ioc_raw_state; int i; /* YIKES! We already know something is amiss. * Do upfront check on IOC state. */ ioc_raw_state = GetIocState(iocp, 0); if ((ioc_raw_state & MPI_DOORBELL_ACTIVE) || ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL)) { printk(KERN_WARNING MYNAM ": %s: Bad IOC state (%08x) WARNING!\n", iocp->name, ioc_raw_state); if ((r = mpt_do_ioc_recovery(iocp, MPT_HOSTEVENT_IOC_RECOVER)) != 0) { printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n", r, iocp->name); return r; } } /* * 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... */ i = MFPTR_2_MPT_INDEX(iocp,(MPT_FRAME_HDR*)req); if (reqBytes >= 12 && i >= 0 && i < iocp->req_depth) { MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req; mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(i); mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; } /* Make sure there are no doorbells */ CHIPREG_WRITE32(&iocp->chip->IntStatus, 0); CHIPREG_WRITE32(&iocp->chip->Doorbell, ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) | ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT))); /* Wait for IOC doorbell int */ if ((i = WaitForDoorbellInt(iocp, 2)) < 0) { return i; } dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n", iocp->name, i)); CHIPREG_WRITE32(&iocp->chip->IntStatus, 0); if ((r = WaitForDoorbellAck(iocp, 1)) < 0) { return -2; } /* Send request via doorbell handshake */ req_as_bytes = (u8 *) req; for (i = 0; i < reqBytes/4; i++) { u32 word; word = ((req_as_bytes[(i*4) + 0] << 0) | (req_as_bytes[(i*4) + 1] << 8) | (req_as_bytes[(i*4) + 2] << 16) | (req_as_bytes[(i*4) + 3] << 24)); CHIPREG_WRITE32(&iocp->chip->Doorbell, word); if ((r = WaitForDoorbellAck(iocp, 1)) < 0) { r = -3; break; } } if ((r = WaitForDoorbellInt(iocp, 2)) >= 0) r = 0; else r = -4; /* Make sure there are no doorbells */ CHIPREG_WRITE32(&iocp->chip->IntStatus, 0); } return r;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_adapter_find_first - Find first MPT adapter pointer. * * Returns first MPT adapter pointer or %NULL if no MPT adapters * are present. */MPT_ADAPTER *mpt_adapter_find_first(void){ MPT_ADAPTER *this = NULL; if (! Q_IS_EMPTY(&MptAdapters)) this = MptAdapters.head; return this;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** * mpt_adapter_find_next - Find next MPT adapter pointer. * @prev: Pointer to previous MPT adapter * * Returns next MPT adapter pointer or %NULL if there are no more. */MPT_ADAPTER *mpt_adapter_find_next(MPT_ADAPTER *prev){ MPT_ADAPTER *next = NULL; if (prev && (prev->forw != (MPT_ADAPTER*)&MptAdapters.head)) next = prev->forw; return next;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -