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

📄 qla_os.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
		msleep(1000);	}	if (ha->flags.online)		return_status = QLA_SUCCESS;	else		return_status = QLA_FUNCTION_FAILED;	DEBUG2(printk("%s return_status=%d\n",__func__,return_status));	return (return_status);}/* * qla2x00_wait_for_loop_ready *    Wait for MAX_LOOP_TIMEOUT(5 min) value for loop *    to be in LOOP_READY state. * Input: *     ha - pointer to host adapter structure * * Note: *    Does context switching-Release SPIN_LOCK *    (if any) before calling this routine. * * * Return: *    Success (LOOP_READY) : 0 *    Failed  (LOOP_NOT_READY) : 1 */static inline intqla2x00_wait_for_loop_ready(scsi_qla_host_t *ha){	int 	 return_status = QLA_SUCCESS;	unsigned long loop_timeout ;	/* wait for 5 min at the max for loop to be ready */	loop_timeout = jiffies + (MAX_LOOP_TIMEOUT * HZ);	while ((!atomic_read(&ha->loop_down_timer) &&	    atomic_read(&ha->loop_state) == LOOP_DOWN) ||	    atomic_read(&ha->loop_state) != LOOP_READY) {		msleep(1000);		if (time_after_eq(jiffies, loop_timeout)) {			return_status = QLA_FUNCTION_FAILED;			break;		}	}	return (return_status);}/*************************************************************************** qla2xxx_eh_abort** Description:*    The abort function will abort the specified command.** Input:*    cmd = Linux SCSI command packet to be aborted.** Returns:*    Either SUCCESS or FAILED.** Note:**************************************************************************/intqla2xxx_eh_abort(struct scsi_cmnd *cmd){	scsi_qla_host_t *ha = to_qla_host(cmd->device->host);	srb_t *sp;	int ret, i;	unsigned int id, lun;	unsigned long serial;	unsigned long flags;	if (!CMD_SP(cmd))		return FAILED;	ret = FAILED;	id = cmd->device->id;	lun = cmd->device->lun;	serial = cmd->serial_number;	/* Check active list for command command. */	spin_lock_irqsave(&ha->hardware_lock, flags);	for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) {		sp = ha->outstanding_cmds[i];		if (sp == NULL)			continue;		if (sp->cmd != cmd)			continue;		DEBUG2(printk("%s(%ld): aborting sp %p from RISC. pid=%ld "		    "sp->state=%x\n", __func__, ha->host_no, sp, serial,		    sp->state));		DEBUG3(qla2x00_print_scsi_cmd(cmd);)		spin_unlock_irqrestore(&ha->hardware_lock, flags);		if (ha->isp_ops.abort_command(ha, sp)) {			DEBUG2(printk("%s(%ld): abort_command "			    "mbx failed.\n", __func__, ha->host_no));		} else {			DEBUG3(printk("%s(%ld): abort_command "			    "mbx success.\n", __func__, ha->host_no));			ret = SUCCESS;		}		spin_lock_irqsave(&ha->hardware_lock, flags);		break;	}	spin_unlock_irqrestore(&ha->hardware_lock, flags);	/* Wait for the command to be returned. */	if (ret == SUCCESS) {		if (qla2x00_eh_wait_on_command(ha, cmd) != QLA_SUCCESS) {			qla_printk(KERN_ERR, ha,			    "scsi(%ld:%d:%d): Abort handler timed out -- %lx "			    "%x.\n", ha->host_no, id, lun, serial, ret);		}	}	qla_printk(KERN_INFO, ha,	    "scsi(%ld:%d:%d): Abort command issued -- %lx %x.\n", ha->host_no,	    id, lun, serial, ret);	return ret;}/*************************************************************************** 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;	unsigned long flags;	status = 0;	/*	 * Waiting for all commands for the designated target in the active	 * array	 */	for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {		spin_lock_irqsave(&ha->hardware_lock, flags);		sp = ha->outstanding_cmds[cnt];		if (sp) {			cmd = sp->cmd;			spin_unlock_irqrestore(&ha->hardware_lock, flags);			if (cmd->device->id == t) {				if (!qla2x00_eh_wait_on_command(ha, cmd)) {					status = 1;					break;				}			}		} else {			spin_unlock_irqrestore(&ha->hardware_lock, flags);		}	}	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){	scsi_qla_host_t *ha = to_qla_host(cmd->device->host);	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;	srb_t *sp;	int ret;	unsigned int id, lun;	unsigned long serial;	ret = FAILED;	id = cmd->device->id;	lun = cmd->device->lun;	serial = cmd->serial_number;	sp = (srb_t *) CMD_SP(cmd);	if (!sp || !fcport)		return ret;	qla_printk(KERN_INFO, ha,	    "scsi(%ld:%d:%d): DEVICE RESET ISSUED.\n", ha->host_no, id, lun);	if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS)		goto eh_dev_reset_done;	if (qla2x00_wait_for_loop_ready(ha) == QLA_SUCCESS) {		if (qla2x00_device_reset(ha, fcport) == 0)			ret = SUCCESS;#if defined(LOGOUT_AFTER_DEVICE_RESET)		if (ret == SUCCESS) {			if (fcport->flags & FC_FABRIC_DEVICE) {				ha->isp_ops.fabric_logout(ha, fcport->loop_id);				qla2x00_mark_device_lost(ha, fcport);			}		}#endif	} else {		DEBUG2(printk(KERN_INFO		    "%s failed: loop not ready\n",__func__);)	}	if (ret == 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;	}	/* Flush outstanding commands. */	if (qla2x00_eh_wait_for_pending_target_commands(ha, id))		ret = FAILED;	if (ret == 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__);	} else		qla_printk(KERN_INFO, ha,		    "scsi(%ld:%d:%d): DEVICE RESET SUCCEEDED.\n", ha->host_no,		    id, lun); eh_dev_reset_done:	return ret;}/*************************************************************************** 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;	unsigned long flags;	status = 1;	/*	 * Waiting for all commands for the designated target in the active	 * array	 */	for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {		spin_lock_irqsave(&ha->hardware_lock, flags);		sp = ha->outstanding_cmds[cnt];		if (sp) {			cmd = sp->cmd;			spin_unlock_irqrestore(&ha->hardware_lock, flags);			status = qla2x00_eh_wait_on_command(ha, cmd);			if (status == 0)				break;		}		else {			spin_unlock_irqrestore(&ha->hardware_lock, flags);		}	}	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){	scsi_qla_host_t *ha = to_qla_host(cmd->device->host);	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;	srb_t *sp;	int ret;	unsigned int id, lun;	unsigned long serial;	ret = FAILED;	id = cmd->device->id;	lun = cmd->device->lun;	serial = cmd->serial_number;	sp = (srb_t *) CMD_SP(cmd);	if (!sp || !fcport)		return ret;	qla_printk(KERN_INFO, ha,	    "scsi(%ld:%d:%d): LOOP RESET ISSUED.\n", ha->host_no, id, lun);	if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS) {		DEBUG2(printk("%s failed:board disabled\n",__func__));		goto eh_bus_reset_done;	}	if (qla2x00_wait_for_loop_ready(ha) == QLA_SUCCESS) {		if (qla2x00_loop_reset(ha) == QLA_SUCCESS)			ret = SUCCESS;	}	if (ret == FAILED)		goto eh_bus_reset_done;	/* Flush outstanding commands. */	if (!qla2x00_eh_wait_for_pending_commands(ha))		ret = FAILED;eh_bus_reset_done:	qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__,	    (ret == FAILED) ? "failed" : "succeded");	return ret;}/*************************************************************************** qla2xxx_eh_host_reset** Description:*    The reset function will reset the Adapter.** Input:*      cmd = Linux SCSI command packet of the command that cause the*            adapter reset.** Returns:*      Either SUCCESS or FAILED.** Note:**************************************************************************/intqla2xxx_eh_host_reset(struct scsi_cmnd *cmd){	scsi_qla_host_t *ha = to_qla_host(cmd->device->host);	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;	srb_t *sp;	int ret;	unsigned int id, lun;	unsigned long serial;	ret = FAILED;	id = cmd->device->id;	lun = cmd->device->lun;	serial = cmd->serial_number;	sp = (srb_t *) CMD_SP(cmd);	if (!sp || !fcport)		return ret;	qla_printk(KERN_INFO, ha,	    "scsi(%ld:%d:%d): ADAPTER RESET ISSUED.\n", ha->host_no, id, lun);	if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS)		goto eh_host_reset_lock;	/*	 * Fixme-may be dpc thread is active and processing	 * loop_resync,so wait a while for it to	 * be completed and then issue big hammer.Otherwise	 * it may cause I/O failure as big hammer marks the	 * devices as lost kicking of the port_down_timer	 * while dpc is stuck for the mailbox to complete.	 */	qla2x00_wait_for_loop_ready(ha);	set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags);	if (qla2x00_abort_isp(ha)) {		clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags);		/* failed. schedule dpc to try */		set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);		if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS)			goto eh_host_reset_lock;	}	clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags);	/* Waiting for our command in done_queue to be returned to OS.*/	if (qla2x00_eh_wait_for_pending_commands(ha))		ret = SUCCESS;eh_host_reset_lock:	qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__,	    (ret == FAILED) ? "failed" : "succeded");	return ret;}/** qla2x00_loop_reset*      Issue loop reset.** Input:*      ha = adapter block pointer.** Returns:*      0 = success*/static intqla2x00_loop_reset(scsi_qla_host_t *ha){	int status = QLA_SUCCESS;	struct fc_port *fcport;	if (ha->flags.enable_lip_reset) {		status = qla2x00_lip_reset(ha);	}	if (status == QLA_SUCCESS && ha->flags.enable_target_reset) {		list_for_each_entry(fcport, &ha->fcports, list) {			if (fcport->port_type != FCT_TARGET)				continue;			status = qla2x00_device_reset(ha, fcport);			if (status != QLA_SUCCESS)				break;		}	}	if (status == QLA_SUCCESS &&		((!ha->flags.enable_target_reset &&		  !ha->flags.enable_lip_reset) ||		ha->flags.enable_lip_full_login)) {		status = qla2x00_full_login_lip(ha);	}	/* Issue marker command only when we are going to start the I/O */	ha->marker_needed = 1;	if (status) {		/* Empty */		DEBUG2_3(printk("%s(%ld): **** FAILED ****\n",				__func__,				ha->host_no);)	} else {		/* Empty */		DEBUG3(printk("%s(%ld): exiting normally.\n",				__func__,				ha->host_no);)	}	return(status);}/* * qla2x00_device_reset *	Issue bus device reset message to the target. * * Input: *	ha = adapter block pointer. *	t = SCSI ID. *	TARGET_QUEUE_LOCK must be released. *	ADAPTER_STATE_LOCK must be released. * * Context: *	Kernel context. */static intqla2x00_device_reset(scsi_qla_host_t *ha, fc_port_t *reset_fcport){

⌨️ 快捷键说明

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