mptbase.c

来自「linux 内核源代码」· C语言 代码 · 共 2,293 行 · 第 1/5 页

C
2,293
字号
	func = reply->u.hdr.Function;	dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply, Function=%02Xh\n",			ioc->name, func));	if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {		EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;		int evHandlers = 0;		int results;		results = ProcessEventNotification(ioc, pEvReply, &evHandlers);		if (results != evHandlers) {			/* CHECKME! Any special handling needed here? */			devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",					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;		} else {			devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",				ioc->name, pEvReply));		}#ifdef CONFIG_PROC_FS//		LogEvent(ioc, pEvReply);#endif	} else if (func == MPI_FUNCTION_EVENT_ACK) {		dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply, EventAck reply received\n",				ioc->name));	} else if (func == MPI_FUNCTION_CONFIG) {		CONFIGPARMS *pCfg;		unsigned long flags;		dcprintk(ioc, printk(MYIOC_s_DEBUG_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(ioc, printk(MYIOC_s_NOTE_FMT "  IOCStatus=%04xh, IOCLogInfo=%08xh\n",				     ioc->name, 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 its 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 u8 valued "handle" in the range (and S.O.D. order) *	{N,...,7,6,5,...,1} if successful. *	A return value of MPT_MAX_PROTOCOL_DRIVERS (including zero!) should be *	considered an error by the caller. */u8mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass){	u8 cb_idx;	last_drv_idx = MPT_MAX_PROTOCOL_DRIVERS;	/*	 *  Search for empty callback slot in this order: {N,...,7,6,5,...,1}	 *  (slot/handle 0 is reserved!)	 */	for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {		if (MptCallbacks[cb_idx] == NULL) {			MptCallbacks[cb_idx] = cbfunc;			MptDriverClass[cb_idx] = dclass;			MptEvHandlers[cb_idx] = NULL;			last_drv_idx = cb_idx;			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 its *	module is unloaded. */voidmpt_deregister(u8 cb_idx){	if (cb_idx && (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(u8 cb_idx, MPT_EVHANDLER ev_cbfunc){	if (!cb_idx || 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 its module is unloaded. */voidmpt_event_deregister(u8 cb_idx){	if (!cb_idx || 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(u8 cb_idx, MPT_RESETHANDLER reset_func){	if (!cb_idx || 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 its module is unloaded. */voidmpt_reset_deregister(u8 cb_idx){	if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)		return;	MptResetHandlers[cb_idx] = NULL;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mpt_device_driver_register - Register device driver hooks *	@dd_cbfunc: driver callbacks struct *	@cb_idx: MPT protocol driver index */intmpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, u8 cb_idx){	MPT_ADAPTER	*ioc;	const struct pci_device_id *id;	if (!cb_idx || 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) {		id = ioc->pcidev->driver ?		    ioc->pcidev->driver->id_table : NULL;		if (dd_cbfunc->probe)			dd_cbfunc->probe(ioc->pcidev, id);	 }	return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mpt_device_driver_deregister - DeRegister device driver hooks *	@cb_idx: MPT protocol driver index */voidmpt_device_driver_deregister(u8 cb_idx){	struct mpt_pci_driver *dd_cbfunc;	MPT_ADAPTER	*ioc;	if (!cb_idx || 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. *	@cb_idx: 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(u8 cb_idx, 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(MYIOC_s_WARN_FMT "IOC Not Active! mpt_get_msg_frame "		    "returning NULL!\n", ioc->name);#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 = cb_idx;	/* 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;		/* Default, will be changed if necessary in SG generation */		ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame;#ifdef MFCNT		ioc->mfcnt++;#endif	}	else		mf = NULL;	spin_unlock_irqrestore(&ioc->FreeQlock, flags);#ifdef MFCNT	if (mf == NULL)		printk(MYIOC_s_WARN_FMT "IOC Active. No free Msg Frames! "		    "Count 0x%x Max 0x%x\n", ioc->name, ioc->mfcnt,		    ioc->req_depth);	mfcounter++;	if (mfcounter == PRINT_MF_COUNT)		printk(MYIOC_s_INFO_FMT "MF Count 0x%x Max 0x%x \n", ioc->name,		    ioc->mfcnt, ioc->req_depth);#endif	dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_get_msg_frame(%d,%d), got mf=%p\n",	    ioc->name, cb_idx, ioc->id, mf));	return mf;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//** *	mpt_put_msg_frame - Send a protocol specific MPT request frame *	to a IOC. *	@cb_idx: 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(u8 cb_idx, 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 = cb_idx;		/* 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;	DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf);	mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];	dsgprintk(ioc, printk(MYIOC_s_DEBUG_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_put_msg_frame_hi_pri - Send a protocol specific MPT request frame *	to a IOC using hi priority request queue. *	@cb_idx: 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_hi_pri(u8 cb_idx, 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 = cb_idx;	req_offset = (u8 *)mf - (u8 *)ioc->req_frames;	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;	DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf);	mf_dma_addr = (ioc->req_frames_low_dma + req_offset);	dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d\n",		ioc->name, mf_dma_addr, req_idx));	CHIPREG_WRITE32(&ioc->chip->RequestHiPriFifo, 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);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?