⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 megaraid_mbox.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (unlikely(mbox->busy)) {		do {			udelay(1);			i++;			rmb();		} while(mbox->busy && (i < max_mbox_busy_wait));		if (mbox->busy) {			spin_unlock_irqrestore(MAILBOX_LOCK(raid_dev), flags);			return -1;		}	}	// Copy this command's mailbox data into "adapter's" mailbox	memcpy((caddr_t)mbox64, (caddr_t)ccb->mbox64, 22);	mbox->cmdid = scb->sno;	adapter->outstanding_cmds++;	if (scb->dma_direction == PCI_DMA_TODEVICE) {		if (!scb->scp->use_sg) {	// sg list not used			pci_dma_sync_single_for_device(adapter->pdev,					ccb->buf_dma_h,					scb->scp->request_bufflen,					PCI_DMA_TODEVICE);		}		else {			pci_dma_sync_sg_for_device(adapter->pdev,				scb->scp->request_buffer,				scb->scp->use_sg, PCI_DMA_TODEVICE);		}	}	mbox->busy	= 1;	// Set busy	mbox->poll	= 0;	mbox->ack	= 0;	wmb();	WRINDOOR(raid_dev, raid_dev->mbox_dma | 0x1);	spin_unlock_irqrestore(MAILBOX_LOCK(raid_dev), flags);	return 0;}/** * megaraid_queue_command - generic queue entry point for all LLDs * @scp		: pointer to the scsi command to be executed * @done	: callback routine to be called after the cmd has be completed * * Queue entry point for mailbox based controllers. */static intmegaraid_queue_command(struct scsi_cmnd *scp, void (* done)(struct scsi_cmnd *)){	adapter_t	*adapter;	scb_t		*scb;	int		if_busy;	adapter		= SCP2ADAPTER(scp);	scp->scsi_done	= done;	scp->result	= 0;	assert_spin_locked(adapter->host_lock);	spin_unlock(adapter->host_lock);	/*	 * Allocate and build a SCB request	 * if_busy flag will be set if megaraid_mbox_build_cmd() command could	 * not allocate scb. We will return non-zero status in that case.	 * NOTE: scb can be null even though certain commands completed	 * successfully, e.g., MODE_SENSE and TEST_UNIT_READY, it would	 * return 0 in that case, and we would do the callback right away.	 */	if_busy	= 0;	scb	= megaraid_mbox_build_cmd(adapter, scp, &if_busy);	if (scb) {		megaraid_mbox_runpendq(adapter, scb);	}	spin_lock(adapter->host_lock);	if (!scb) {	// command already completed		done(scp);		return 0;	}	return if_busy;}/** * megaraid_mbox_build_cmd - transform the mid-layer scsi command to megaraid * firmware lingua * @adapter	- controller's soft state * @scp		- mid-layer scsi command pointer * @busy	- set if request could not be completed because of lack of *		resources * * convert the command issued by mid-layer to format understood by megaraid * firmware. We also complete certain command without sending them to firmware */static scb_t *megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy){	mraid_device_t		*rdev = ADAP2RAIDDEV(adapter);	int			channel;	int			target;	int			islogical;	mbox_ccb_t		*ccb;	mraid_passthru_t	*pthru;	mbox64_t		*mbox64;	mbox_t			*mbox;	scb_t			*scb;	char			skip[] = "skipping";	char			scan[] = "scanning";	char			*ss;	/*	 * Get the appropriate device map for the device this command is	 * intended for	 */	MRAID_GET_DEVICE_MAP(adapter, scp, channel, target, islogical);	/*	 * Logical drive commands	 */	if (islogical) {		switch (scp->cmnd[0]) {		case TEST_UNIT_READY:			/*			 * Do we support clustering and is the support enabled			 * If no, return success always			 */			if (!adapter->ha) {				scp->result = (DID_OK << 16);				return NULL;			}			if (!(scb = megaraid_alloc_scb(adapter, scp))) {				scp->result = (DID_ERROR << 16);				*busy = 1;				return NULL;			}			scb->dma_direction	= scp->sc_data_direction;			scb->dev_channel	= 0xFF;			scb->dev_target		= target;			ccb			= (mbox_ccb_t *)scb->ccb;			/*			 * The command id will be provided by the command			 * issuance routine			 */			ccb->raw_mbox[0]	= CLUSTER_CMD;			ccb->raw_mbox[2]	= RESERVATION_STATUS;			ccb->raw_mbox[3]	= target;			return scb;		case MODE_SENSE:			if (scp->use_sg) {				struct scatterlist	*sgl;				caddr_t			vaddr;				sgl = (struct scatterlist *)scp->request_buffer;				if (sgl->page) {					vaddr = (caddr_t)						(page_address((&sgl[0])->page)						+ (&sgl[0])->offset);					memset(vaddr, 0, scp->cmnd[4]);				}				else {					con_log(CL_ANN, (KERN_WARNING					"megaraid mailbox: invalid sg:%d\n",					__LINE__));				}			}			else {				memset(scp->request_buffer, 0, scp->cmnd[4]);			}			scp->result = (DID_OK << 16);			return NULL;		case INQUIRY:			/*			 * Display the channel scan for logical drives			 * Do not display scan for a channel if already done.			 */			if (!(rdev->last_disp & (1L << SCP2CHANNEL(scp)))) {				con_log(CL_ANN, (KERN_INFO					"scsi[%d]: scanning scsi channel %d",					adapter->host->host_no,					SCP2CHANNEL(scp)));				con_log(CL_ANN, (					" [virtual] for logical drives\n"));				rdev->last_disp |= (1L << SCP2CHANNEL(scp));			}			/* Fall through */		case READ_CAPACITY:			/*			 * Do not allow LUN > 0 for logical drives and			 * requests for more than 40 logical drives			 */			if (SCP2LUN(scp)) {				scp->result = (DID_BAD_TARGET << 16);				return NULL;			}			if ((target % 0x80) >= MAX_LOGICAL_DRIVES_40LD) {				scp->result = (DID_BAD_TARGET << 16);				return NULL;			}			/* Allocate a SCB and initialize passthru */			if (!(scb = megaraid_alloc_scb(adapter, scp))) {				scp->result = (DID_ERROR << 16);				*busy = 1;				return NULL;			}			ccb			= (mbox_ccb_t *)scb->ccb;			scb->dev_channel	= 0xFF;			scb->dev_target		= target;			pthru			= ccb->pthru;			mbox			= ccb->mbox;			mbox64			= ccb->mbox64;			pthru->timeout		= 0;			pthru->ars		= 1;			pthru->reqsenselen	= 14;			pthru->islogical	= 1;			pthru->logdrv		= target;			pthru->cdblen		= scp->cmd_len;			memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);			mbox->cmd		= MBOXCMD_PASSTHRU64;			scb->dma_direction	= scp->sc_data_direction;			pthru->dataxferlen	= scp->request_bufflen;			pthru->dataxferaddr	= ccb->sgl_dma_h;			pthru->numsge		= megaraid_mbox_mksgl(adapter,							scb);			mbox->xferaddr		= 0xFFFFFFFF;			mbox64->xferaddr_lo	= (uint32_t )ccb->pthru_dma_h;			mbox64->xferaddr_hi	= 0;			return scb;		case READ_6:		case WRITE_6:		case READ_10:		case WRITE_10:		case READ_12:		case WRITE_12:			/*			 * Allocate a SCB and initialize mailbox			 */			if (!(scb = megaraid_alloc_scb(adapter, scp))) {				scp->result = (DID_ERROR << 16);				*busy = 1;				return NULL;			}			ccb			= (mbox_ccb_t *)scb->ccb;			scb->dev_channel	= 0xFF;			scb->dev_target		= target;			mbox			= ccb->mbox;			mbox64			= ccb->mbox64;			mbox->logdrv		= target;			/*			 * A little HACK: 2nd bit is zero for all scsi read			 * commands and is set for all scsi write commands			 */			mbox->cmd = (scp->cmnd[0] & 0x02) ?  MBOXCMD_LWRITE64:					MBOXCMD_LREAD64 ;			/*			 * 6-byte READ(0x08) or WRITE(0x0A) cdb			 */			if (scp->cmd_len == 6) {				mbox->numsectors = (uint32_t)scp->cmnd[4];				mbox->lba =					((uint32_t)scp->cmnd[1] << 16)	|					((uint32_t)scp->cmnd[2] << 8)	|					(uint32_t)scp->cmnd[3];				mbox->lba &= 0x1FFFFF;			}			/*			 * 10-byte READ(0x28) or WRITE(0x2A) cdb			 */			else if (scp->cmd_len == 10) {				mbox->numsectors =					(uint32_t)scp->cmnd[8] |					((uint32_t)scp->cmnd[7] << 8);				mbox->lba =					((uint32_t)scp->cmnd[2] << 24) |					((uint32_t)scp->cmnd[3] << 16) |					((uint32_t)scp->cmnd[4] << 8) |					(uint32_t)scp->cmnd[5];			}			/*			 * 12-byte READ(0xA8) or WRITE(0xAA) cdb			 */			else if (scp->cmd_len == 12) {				mbox->lba =					((uint32_t)scp->cmnd[2] << 24) |					((uint32_t)scp->cmnd[3] << 16) |					((uint32_t)scp->cmnd[4] << 8) |					(uint32_t)scp->cmnd[5];				mbox->numsectors =					((uint32_t)scp->cmnd[6] << 24) |					((uint32_t)scp->cmnd[7] << 16) |					((uint32_t)scp->cmnd[8] << 8) |					(uint32_t)scp->cmnd[9];			}			else {				con_log(CL_ANN, (KERN_WARNING					"megaraid: unsupported CDB length\n"));				megaraid_dealloc_scb(adapter, scb);				scp->result = (DID_ERROR << 16);				return NULL;			}			scb->dma_direction = scp->sc_data_direction;			// Calculate Scatter-Gather info			mbox64->xferaddr_lo	= (uint32_t )ccb->sgl_dma_h;			mbox->numsge		= megaraid_mbox_mksgl(adapter,							scb);			mbox->xferaddr		= 0xFFFFFFFF;			mbox64->xferaddr_hi	= 0;			return scb;		case RESERVE:		case RELEASE:			/*			 * Do we support clustering and is the support enabled			 */			if (!adapter->ha) {				scp->result = (DID_BAD_TARGET << 16);				return NULL;			}			/*			 * Allocate a SCB and initialize mailbox			 */			if (!(scb = megaraid_alloc_scb(adapter, scp))) {				scp->result = (DID_ERROR << 16);				*busy = 1;				return NULL;			}			ccb			= (mbox_ccb_t *)scb->ccb;			scb->dev_channel	= 0xFF;			scb->dev_target		= target;			ccb->raw_mbox[0]	= CLUSTER_CMD;			ccb->raw_mbox[2]	=  (scp->cmnd[0] == RESERVE) ?						RESERVE_LD : RELEASE_LD;			ccb->raw_mbox[3]	= target;			scb->dma_direction	= scp->sc_data_direction;			return scb;		default:			scp->result = (DID_BAD_TARGET << 16);			return NULL;		}	}	else { // Passthru device commands		// Do not allow access to target id > 15 or LUN > 7		if (target > 15 || SCP2LUN(scp) > 7) {			scp->result = (DID_BAD_TARGET << 16);			return NULL;		}		// if fast load option was set and scan for last device is		// over, reset the fast_load flag so that during a possible		// next scan, devices can be made available		if (rdev->fast_load && (target == 15) &&			(SCP2CHANNEL(scp) == adapter->max_channel -1)) {			con_log(CL_ANN, (KERN_INFO			"megaraid[%d]: physical device scan re-enabled\n",				adapter->host->host_no));			rdev->fast_load = 0;		}		/*		 * Display the channel scan for physical devices		 */		if (!(rdev->last_disp & (1L << SCP2CHANNEL(scp)))) {			ss = rdev->fast_load ? skip : scan;			con_log(CL_ANN, (KERN_INFO				"scsi[%d]: %s scsi channel %d [Phy %d]",				adapter->host->host_no, ss, SCP2CHANNEL(scp),				channel));			con_log(CL_ANN, (				" for non-raid devices\n"));			rdev->last_disp |= (1L << SCP2CHANNEL(scp));		}		// disable channel sweep if fast load option given		if (rdev->fast_load) {			scp->result = (DID_BAD_TARGET << 16);			return NULL;		}		// Allocate a SCB and initialize passthru		if (!(scb = megaraid_alloc_scb(adapter, scp))) {			scp->result = (DID_ERROR << 16);			*busy = 1;			return NULL;		}		ccb			= (mbox_ccb_t *)scb->ccb;		scb->dev_channel	= channel;		scb->dev_target		= target;		scb->dma_direction	= scp->sc_data_direction;		mbox			= ccb->mbox;		mbox64			= ccb->mbox64;		// Does this firmware support extended CDBs		if (adapter->max_cdb_sz == 16) {			mbox->cmd		= MBOXCMD_EXTPTHRU;			megaraid_mbox_prepare_epthru(adapter, scb, scp);			mbox64->xferaddr_lo	= (uint32_t)ccb->epthru_dma_h;			mbox64->xferaddr_hi	= 0;			mbox->xferaddr		= 0xFFFFFFFF;		}		else {			mbox->cmd = MBOXCMD_PASSTHRU64;			megaraid_mbox_prepare_pthru(adapter, scb, scp);			mbox64->xferaddr_lo	= (uint32_t)ccb->pthru_dma_h;			mbox64->xferaddr_hi	= 0;			mbox->xferaddr		= 0xFFFFFFFF;		}		return scb;	}	// NOT REACHED}/** * megaraid_mbox_runpendq - execute commands queued in the pending queue * @adapter	: controller's soft state * @scb		: SCB to be queued in the pending list * * scan the pending list for commands which are not yet issued and try to * post to the controller. The SCB can be a null pointer, which would indicate * no SCB to be queue, just try to execute the ones in the pending list. * * NOTE: We do not actually traverse the pending list. The SCBs are plucked * out from the head of the pending list. If it is successfully issued, the * next SCB is at the head now. */static voidmegaraid_mbox_runpendq(adapter_t *adapter, scb_t *scb_q){	scb_t			*scb;	unsigned long		flags;	spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);	if (scb_q) {		scb_q->state = SCB_PENDQ;		list_add_tail(&scb_q->list, &adapter->pend_list);	}	// if the adapter in not in quiescent mode, post the commands to FW	if (adapter->quiescent) {		spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);		return;	}	while (!list_empty(&adapter->pend_list)) {		assert_spin_locked(PENDING_LIST_LOCK(adapter));		scb = list_entry(adapter->pend_list.next, scb_t, list);		// remove the scb from the pending list and try to		// issue. If we are unable to issue it, put back in		// the pending list and return		list_del_init(&scb->list);		spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);		// if mailbox was busy, return SCB back to pending		// list. Make sure to add at the head, since that's		// where it would have been removed from		scb->state = SCB_ISSUED;		if (mbox_post_cmd(adapter, scb) != 0) {			spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);

⌨️ 快捷键说明

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