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 + -
显示快捷键?