示例#1
0
文件: qla_isr.c 项目: wxlong/Test
/**
 * qla2x00_check_sense() - Perform any sense data interrogation.
 * @cp: SCSI Command
 * @lq: Lun queue
 *
 * Returns QLA_SUCCESS if the lun queue is suspended, else
 * QLA_FUNCTION_FAILED  (lun queue not suspended).
 */
static int 
qla2x00_check_sense(struct scsi_cmnd *cp, os_lun_t *lq)
{
	scsi_qla_host_t	*ha;
	srb_t		*sp;
	fc_port_t	*fcport;

	ha = (scsi_qla_host_t *) cp->device->host->hostdata;
	if ((cp->sense_buffer[0] & 0x70) != 0x70) {
		return (QLA_FUNCTION_FAILED);
	}

	sp = (srb_t * )CMD_SP(cp);
	sp->flags |= SRB_GOT_SENSE;

	switch (cp->sense_buffer[2] & 0xf) {
	case RECOVERED_ERROR:
		cp->result = DID_OK << 16;
		cp->sense_buffer[0] = 0;
		break;

	case NOT_READY:
		fcport = lq->fclun->fcport;

		/*
		 * Suspend the lun only for hard disk device type.
		 */
		if ((fcport->flags & FCF_TAPE_PRESENT) == 0 &&
		    lq->q_state != LUN_STATE_TIMEOUT) {
			/*
			 * If target is in process of being ready then suspend
			 * lun for 6 secs and retry all the commands.
			 */
			if (cp->sense_buffer[12] == 0x4 &&
			    cp->sense_buffer[13] == 0x1) {

				/* Suspend the lun for 6 secs */
				qla2x00_suspend_lun(ha, lq, 6,
				    ql2xsuspendcount);

				return (QLA_SUCCESS);
			}
		}
		break;
	}

	return (QLA_FUNCTION_FAILED);
}
示例#2
0
/**
 * qla2x00_ms_req_pkt() - Retrieve a Management Server request packet from
 * 				the request ring.
 * @ha: HA context
 * @sp: pointer to handle post function call
 *
 * Note: The caller must hold the hardware lock before calling this routine.
 *
 * Returns NULL if function failed, else, a pointer to the request packet.
 */
request_t *
qla2x00_ms_req_pkt(scsi_qla_host_t *ha, srb_t  *sp)
{
	device_reg_t	*reg = ha->iobase;
	request_t	*pkt = NULL;
	uint16_t	cnt, i, index;
	uint32_t	*dword_ptr;
	uint32_t	timer;
	uint8_t		found = 0;
	uint16_t	req_cnt = 1;

	/* Wait 1 second for slot. */
	for (timer = HZ; timer; timer--) {
		if ((req_cnt + 2) >= ha->req_q_cnt) {
			/* Calculate number of free request entries. */
			cnt = qla2x00_debounce_register(ISP_REQ_Q_OUT(ha, reg));
			if (ha->req_ring_index < cnt) {
				ha->req_q_cnt = cnt - ha->req_ring_index;
			} else {
				ha->req_q_cnt = ha->request_q_length -
				    (ha->req_ring_index - cnt);
			}
		}

		/* Check for room in outstanding command list. */
		cnt = ha->current_outstanding_cmd;
		for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) {
			cnt++;
			if (cnt == MAX_OUTSTANDING_COMMANDS)
				cnt = 1;

			if (ha->outstanding_cmds[cnt] == 0) {
				found = 1;
				ha->current_outstanding_cmd = cnt;
				break;
			}
		}

		/* If room for request in request ring. */
		if (found && (req_cnt + 2) < ha->req_q_cnt) {
			pkt = ha->request_ring_ptr;

			/* Zero out packet. */
			dword_ptr = (uint32_t *)pkt;
			for (i = 0; i < REQUEST_ENTRY_SIZE / 4; i++ )
				*dword_ptr++ = 0;

			DEBUG5(printk("%s(): putting sp=%p in "
			    "outstanding_cmds[%x]\n",
			    __func__,
			    sp, cnt));

			ha->outstanding_cmds[cnt] = sp;

			/* save the handle */
			sp->cmd->host_scribble = (unsigned char *) (u_long) cnt;
			CMD_SP(sp->cmd) = (void *)sp;

			ha->req_q_cnt--;
			pkt->handle = (uint32_t)cnt;

			/* Set system defined field. */
			pkt->sys_define = (uint8_t)ha->req_ring_index;
			pkt->entry_status = 0;

			break;
		}

		/* Release ring specific lock */
		spin_unlock(&ha->hardware_lock);
		udelay(20);

		/* Check for pending interrupts. */
		qla2x00_poll(ha);

		spin_lock_irq(&ha->hardware_lock);
	}
	if (!pkt) {
		DEBUG2_3(printk("%s(): **** FAILED ****\n", __func__));
	}

	return (pkt);
}