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

📄 qla_os.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
	int		i;	int		return_status = FAILED;	os_lun_t	*q;	scsi_qla_host_t *ha;	scsi_qla_host_t *vis_ha;	srb_t		*sp;	srb_t		*rp;	struct list_head *list, *temp;	struct Scsi_Host *host;	uint8_t		found = 0;	unsigned int	b, t, l;	/* Get the SCSI request ptr */	sp = (srb_t *) CMD_SP(cmd);	/*	 * If sp is NULL, command is already returned.	 * sp is NULLED just before we call back scsi_done	 *	 */	if ((sp == NULL)) {		/* no action - we don't have command */		qla_printk(KERN_INFO, to_qla_host(cmd->device->host),		    "qla2xxx_eh_abort: cmd already done sp=%p\n", sp);		DEBUG(printk("qla2xxx_eh_abort: cmd already done sp=%p\n", sp);)		return SUCCESS;	}	if (sp) {		DEBUG(printk("qla2xxx_eh_abort: refcount %i \n",		    atomic_read(&sp->ref_count));)	}	vis_ha = (scsi_qla_host_t *) cmd->device->host->hostdata;	ha = (scsi_qla_host_t *)cmd->device->host->hostdata;	host = ha->host;	/* Generate LU queue on bus, target, LUN */	b = cmd->device->channel;	t = cmd->device->id;	l = cmd->device->lun;	q = GET_LU_Q(vis_ha, t, l);	qla_printk(KERN_INFO, ha, 	    "%s scsi(%ld:%d:%d:%d): cmd_timeout_in_sec=0x%x.\n", __func__,	    ha->host_no, (int)b, (int)t, (int)l,	    cmd->timeout_per_command / HZ);	/*	 * if no LUN queue then something is very wrong!!!	 */	if (q == NULL) {		qla_printk(KERN_WARNING, ha,			"qla2x00: (%x:%x:%x) No LUN queue.\n", b, t, l);		/* no action - we don't have command */		return FAILED;	}	DEBUG2(printk("scsi(%ld): ABORTing cmd=%p sp=%p jiffies = 0x%lx, "	    "timeout=%x, dpc_flags=%lx, vis_ha->dpc_flags=%lx q->flag=%lx\n",	    ha->host_no, cmd, sp, jiffies, cmd->timeout_per_command / HZ,	    ha->dpc_flags, vis_ha->dpc_flags, q->q_flag));	DEBUG2(qla2x00_print_scsi_cmd(cmd));	spin_unlock_irq(ha->host->host_lock);	if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS) {		DEBUG2(printk("%s failed:board disabled\n", __func__);)		spin_lock_irq(ha->host->host_lock);		return FAILED;	}	spin_lock_irq(ha->host->host_lock);	/* Search done queue */	spin_lock(&ha->list_lock);	list_for_each_safe(list, temp, &ha->done_queue) {		rp = list_entry(list, srb_t, list);		if (cmd != rp->cmd)			continue;		/*		 * Found command.Remove it from done list.		 * And proceed to post completion to scsi mid layer.		 */		return_status = SUCCESS;		found++;		qla2x00_delete_from_done_queue(ha, sp);		break;	} /* list_for_each_safe() */	spin_unlock(&ha->list_lock);	/*	 * Return immediately if the aborted command was already in the done	 * queue	 */	if (found) {		qla_printk(KERN_INFO, ha,		    "qla2xxx_eh_abort: Returning completed command=%p sp=%p\n",		    cmd, sp);		sp_put(ha, sp);		return (return_status);	}		/*	 * See if this command is in the retry queue	 */	DEBUG3(printk("qla2xxx_eh_abort: searching sp %p in retry "		    "queue.\n", sp);)	spin_lock(&ha->list_lock);	list_for_each_safe(list, temp, &ha->retry_queue) {		rp = list_entry(list, srb_t, list);		if (cmd != rp->cmd)			continue;		DEBUG2(printk("qla2xxx_eh_abort: found "		    "in retry queue. SP=%p\n", sp);)		__del_from_retry_queue(ha, rp);		cmd->result = DID_ABORT << 16;		__add_to_done_queue(ha, rp);		return_status = SUCCESS;		found++;		break;	} 	spin_unlock(&ha->list_lock);	/*	 * Our SP pointer points at the command we want to remove from the	 * pending queue providing we haven't already sent it to the adapter.	 */	if (!found) {		DEBUG3(printk("qla2xxx_eh_abort: searching sp %p "		    "in pending queue.\n", sp);)		spin_lock(&vis_ha->list_lock);		list_for_each_safe(list, temp, &vis_ha->pending_queue) {			rp = list_entry(list, srb_t, list);			if (rp->cmd != cmd)				continue;			/* Remove srb from LUN queue. */			rp->flags |=  SRB_ABORTED;			DEBUG2(printk("qla2xxx_eh_abort: Cmd in pending queue."			    " serial_number %ld.\n",			    sp->cmd->serial_number);)			__del_from_pending_queue(vis_ha, rp);			cmd->result = DID_ABORT << 16;			__add_to_done_queue(vis_ha, rp);			return_status = SUCCESS;			found++;			break;		} /* list_for_each_safe() */		spin_unlock(&vis_ha->list_lock);	} /*End of if !found */	if (!found) {  /* find the command in our active list */		DEBUG3(printk("qla2xxx_eh_abort: searching sp %p "		    "in outstanding queue.\n", sp);)		spin_lock(&ha->hardware_lock);		for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) {			sp = ha->outstanding_cmds[i];			if (sp == NULL)				continue;			if (sp->cmd != cmd)				continue;			DEBUG2(printk("qla2xxx_eh_abort(%ld): aborting sp %p "			    "from RISC. pid=%ld sp->state=%x q->q_flag=%lx\n",			    ha->host_no, sp, sp->cmd->serial_number,			    sp->state, q->q_flag);)			DEBUG(qla2x00_print_scsi_cmd(cmd);)			/* Get a reference to the sp and drop the lock.*/			sp_get(ha, sp);			spin_unlock(&ha->hardware_lock);			spin_unlock_irq(ha->host->host_lock);			if (qla2x00_abort_command(ha, sp)) {				DEBUG2(printk("qla2xxx_eh_abort: abort_command "				    "mbx failed.\n");)				return_status = FAILED;			} else {				DEBUG3(printk("qla2xxx_eh_abort: abort_command "				    " mbx success.\n");)				return_status = SUCCESS;			}			sp_put(ha,sp);			spin_lock_irq(ha->host->host_lock);			spin_lock(&ha->hardware_lock);			/*			 * Regardless of mailbox command status, go check on			 * done queue just in case the sp is already done.			 */			break;		}/*End of for loop */		spin_unlock(&ha->hardware_lock);	} /*End of if !found */	/* Waiting for our command in done_queue to be returned to OS.*/	if (qla2x00_eh_wait_on_command(ha, cmd) != 0) {		DEBUG2(printk("qla2xxx_eh_abort: cmd returned back to OS.\n");)		return_status = SUCCESS;	}	if (return_status == FAILED) {		qla_printk(KERN_INFO, ha, 			"qla2xxx_eh_abort Exiting: status=Failed\n");		return FAILED;	}	DEBUG2(printk("qla2xxx_eh_abort: Exiting. return_status=0x%x.\n",	    return_status));	return return_status;}/*************************************************************************** qla2x00_eh_wait_for_pending_target_commands** Description:*    Waits for all the commands to come back from the specified target.** Input:*    ha - pointer to scsi_qla_host structure.*    t  - target 	* Returns:*    Either SUCCESS or FAILED.** Note:**************************************************************************/static intqla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t){	int	cnt;	int	status;	srb_t		*sp;	struct scsi_cmnd *cmd;	status = 0;	/*	 * Waiting for all commands for the designated target in the active	 * array	 */	for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {		spin_lock(&ha->hardware_lock);		sp = ha->outstanding_cmds[cnt];		if (sp) {			cmd = sp->cmd;			spin_unlock(&ha->hardware_lock);			if (cmd->device->id == t) {				if (!qla2x00_eh_wait_on_command(ha, cmd)) {					status = 1;					break;				}			}		}		else {			spin_unlock(&ha->hardware_lock);		}	}	return (status);}/*************************************************************************** qla2xxx_eh_device_reset** Description:*    The device reset function will reset the target and abort any*    executing commands.**    NOTE: The use of SP is undefined within this context.  Do *NOT**          attempt to use this value, even if you determine it is *          non-null.** Input:*    cmd = Linux SCSI command packet of the command that cause the*          bus device reset.** Returns:*    SUCCESS/FAILURE (defined as macro in scsi.h).***************************************************************************/intqla2xxx_eh_device_reset(struct scsi_cmnd *cmd){	int		return_status;	unsigned int	b, t, l;	scsi_qla_host_t	*ha;	os_tgt_t	*tq;	os_lun_t	*lq;	fc_port_t	*fcport_to_reset;	srb_t		*rp;	struct list_head *list, *temp;	return_status = FAILED;	if (cmd == NULL) {		printk(KERN_INFO		    "%s(): **** SCSI mid-layer passing in NULL cmd\n",		    __func__);		return (return_status);	}	b = cmd->device->channel;	t = cmd->device->id;	l = cmd->device->lun;	ha = (scsi_qla_host_t *)cmd->device->host->hostdata;	tq = TGT_Q(ha, t);	if (tq == NULL) {		qla_printk(KERN_INFO, ha,		    "%s(): **** CMD derives a NULL TGT_Q\n", __func__);		return (return_status);	}	lq = (os_lun_t *)LUN_Q(ha, t, l);	if (lq == NULL) {		printk(KERN_INFO		    "%s(): **** CMD derives a NULL LUN_Q\n", __func__);		return (return_status);	}	fcport_to_reset = lq->fclun->fcport;	/* If we are coming in from the back-door, stall I/O until complete. */	if (!cmd->device->host->eh_active)		set_bit(TQF_SUSPENDED, &tq->flags);	qla_printk(KERN_INFO, ha,	    "scsi(%ld:%d:%d:%d): DEVICE RESET ISSUED.\n", ha->host_no, b, t, l);	DEBUG2(printk(KERN_INFO	    "scsi(%ld): DEVICE_RESET cmd=%p jiffies = 0x%lx, timeout=%x, "	    "dpc_flags=%lx, status=%x allowed=%d cmd.state=%x\n",	    ha->host_no, cmd, jiffies, cmd->timeout_per_command / HZ,	    ha->dpc_flags, cmd->result, cmd->allowed, cmd->state)); 	/* Clear commands from the retry queue. */ 	spin_lock(&ha->list_lock); 	list_for_each_safe(list, temp, &ha->retry_queue) { 		rp = list_entry(list, srb_t, list);  		if (t != rp->cmd->device->id)  			continue;  		DEBUG2(printk(KERN_INFO		    "qla2xxx_eh_reset: found in retry queue. SP=%p\n", rp));  		__del_from_retry_queue(ha, rp); 		rp->cmd->result = DID_RESET << 16; 		__add_to_done_queue(ha, rp); 	} 	spin_unlock(&ha->list_lock);	spin_unlock_irq(ha->host->host_lock);	if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS) {		DEBUG2(printk(KERN_INFO		    "%s failed:board disabled\n",__func__));		spin_lock_irq(ha->host->host_lock);		goto eh_dev_reset_done;	}	if (qla2x00_wait_for_loop_ready(ha) == QLA_SUCCESS) {		if (qla2x00_device_reset(ha, fcport_to_reset) == 0) {			return_status = SUCCESS;		}#if defined(LOGOUT_AFTER_DEVICE_RESET)		if (return_status == SUCCESS) {			if (fcport_to_reset->flags & FC_FABRIC_DEVICE) {				qla2x00_fabric_logout(ha,				    fcport_to_reset->loop_id);				qla2x00_mark_device_lost(ha, fcport_to_reset);			}		}#endif	} else {		DEBUG2(printk(KERN_INFO		    "%s failed: loop not ready\n",__func__);)	}	spin_lock_irq(ha->host->host_lock);	if (return_status == FAILED) {		DEBUG3(printk("%s(%ld): device reset failed\n",		    __func__, ha->host_no));		qla_printk(KERN_INFO, ha, "%s: device reset failed\n",		    __func__);		goto eh_dev_reset_done;	}	/*	 * If we are coming down the EH path, wait for all commands to	 * complete for the device.	 */	if (cmd->device->host->eh_active) {		if (qla2x00_eh_wait_for_pending_target_commands(ha, t))			return_status = FAILED;		if (return_status == FAILED) {			DEBUG3(printk("%s(%ld): failed while waiting for "			    "commands\n", __func__, ha->host_no));			qla_printk(KERN_INFO, ha,			    "%s: failed while waiting for commands\n",			    __func__); 			goto eh_dev_reset_done;		}	}	qla_printk(KERN_INFO, ha,	    "scsi(%ld:%d:%d:%d): DEVICE RESET SUCCEEDED.\n",	    ha->host_no, b, t, l);eh_dev_reset_done:	if (!cmd->device->host->eh_active)		clear_bit(TQF_SUSPENDED, &tq->flags);	return (return_status);}/*************************************************************************** qla2x00_eh_wait_for_pending_commands** Description:*    Waits for all the commands to come back from the specified host.** Input:*    ha - pointer to scsi_qla_host structure.** Returns:*    1 : SUCCESS*    0 : FAILED** Note:**************************************************************************/static intqla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha){	int	cnt;	int	status;	srb_t		*sp;	struct scsi_cmnd *cmd;	status = 1;	/*	 * Waiting for all commands for the designated target in the active	 * array	 */	for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {		spin_lock(&ha->hardware_lock);		sp = ha->outstanding_cmds[cnt];		if (sp) {			cmd = sp->cmd;			spin_unlock(&ha->hardware_lock);			status = qla2x00_eh_wait_on_command(ha, cmd);			if (status == 0)				break;		}		else {			spin_unlock(&ha->hardware_lock);		}	}	return (status);}/*************************************************************************** qla2xxx_eh_bus_reset** Description:*    The bus reset function will reset the bus and abort any executing*    commands.** Input:*    cmd = Linux SCSI command packet of the command that cause the*          bus reset.** Returns:*    SUCCESS/FAILURE (defined as macro in scsi.h).***************************************************************************/intqla2xxx_eh_bus_reset(struct scsi_cmnd *cmd){

⌨️ 快捷键说明

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