diff options
Diffstat (limited to 'drivers/scsi/qla4xxx/ql4_iocb.c')
| -rw-r--r-- | drivers/scsi/qla4xxx/ql4_iocb.c | 133 | 
1 files changed, 60 insertions, 73 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c index 912a67494ad..e0c32159749 100644 --- a/drivers/scsi/qla4xxx/ql4_iocb.c +++ b/drivers/scsi/qla4xxx/ql4_iocb.c @@ -10,9 +10,42 @@  #include "ql4_dbg.h"  #include "ql4_inline.h" -  #include <scsi/scsi_tcq.h> +static int +qla4xxx_space_in_req_ring(struct scsi_qla_host *ha, uint16_t req_cnt) +{ +	uint16_t cnt; + +	/* Calculate number of free request entries. */ +	if ((req_cnt + 2) >= ha->req_q_count) { +		cnt = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out); +		if (ha->request_in < cnt) +			ha->req_q_count = cnt - ha->request_in; +		else +			ha->req_q_count = REQUEST_QUEUE_DEPTH - +						(ha->request_in - cnt); +	} + +	/* Check if room for request in request ring. */ +	if ((req_cnt + 2) < ha->req_q_count) +		return 1; +	else +		return 0; +} + +static void qla4xxx_advance_req_ring_ptr(struct scsi_qla_host *ha) +{ +	/* Advance request queue pointer */ +	if (ha->request_in == (REQUEST_QUEUE_DEPTH - 1)) { +		ha->request_in = 0; +		ha->request_ptr = ha->request_ring; +	} else { +		ha->request_in++; +		ha->request_ptr++; +	} +} +  /**   * qla4xxx_get_req_pkt - returns a valid entry in request queue.   * @ha: Pointer to host adapter structure. @@ -26,35 +59,18 @@  static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha,  			       struct queue_entry **queue_entry)  { -	uint16_t request_in; -	uint8_t status = QLA_SUCCESS; - -	*queue_entry = ha->request_ptr; +	uint16_t req_cnt = 1; -	/* get the latest request_in and request_out index */ -	request_in = ha->request_in; -	ha->request_out = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out); - -	/* Advance request queue pointer and check for queue full */ -	if (request_in == (REQUEST_QUEUE_DEPTH - 1)) { -		request_in = 0; -		ha->request_ptr = ha->request_ring; -	} else { -		request_in++; -		ha->request_ptr++; -	} - -	/* request queue is full, try again later */ -	if ((ha->iocb_cnt + 1) >= ha->iocb_hiwat) { -		/* restore request pointer */ -		ha->request_ptr = *queue_entry; -		status = QLA_ERROR; -	} else { -		ha->request_in = request_in; +	if (qla4xxx_space_in_req_ring(ha, req_cnt)) { +		*queue_entry = ha->request_ptr;  		memset(*queue_entry, 0, sizeof(**queue_entry)); + +		qla4xxx_advance_req_ring_ptr(ha); +		ha->req_q_count -= req_cnt; +		return QLA_SUCCESS;  	} -	return status; +	return QLA_ERROR;  }  /** @@ -100,21 +116,14 @@ exit_send_marker:  	return status;  } -static struct continuation_t1_entry* qla4xxx_alloc_cont_entry( -	struct scsi_qla_host *ha) +static struct continuation_t1_entry * +qla4xxx_alloc_cont_entry(struct scsi_qla_host *ha)  {  	struct continuation_t1_entry *cont_entry;  	cont_entry = (struct continuation_t1_entry *)ha->request_ptr; -	/* Advance request queue pointer */ -	if (ha->request_in == (REQUEST_QUEUE_DEPTH - 1)) { -		ha->request_in = 0; -		ha->request_ptr = ha->request_ring; -	} else { -		ha->request_in++; -		ha->request_ptr++; -	} +	qla4xxx_advance_req_ring_ptr(ha);  	/* Load packet defaults */  	cont_entry->hdr.entryType = ET_CONTINUE; @@ -197,13 +206,10 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)  	struct scsi_cmnd *cmd = srb->cmd;  	struct ddb_entry *ddb_entry;  	struct command_t3_entry *cmd_entry; -  	int nseg;  	uint16_t tot_dsds;  	uint16_t req_cnt; -  	unsigned long flags; -	uint16_t cnt;  	uint32_t index;  	char tag[2]; @@ -217,6 +223,19 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)  	index = (uint32_t)cmd->request->tag; +	/* +	 * Check to see if adapter is online before placing request on +	 * request queue.  If a reset occurs and a request is in the queue, +	 * the firmware will still attempt to process the request, retrieving +	 * garbage for pointers. +	 */ +	if (!test_bit(AF_ONLINE, &ha->flags)) { +		DEBUG2(printk("scsi%ld: %s: Adapter OFFLINE! " +			      "Do not issue command.\n", +			      ha->host_no, __func__)); +		goto queuing_error; +	} +  	/* Calculate the number of request entries needed. */  	nseg = scsi_dma_map(cmd);  	if (nseg < 0) @@ -224,17 +243,7 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)  	tot_dsds = nseg;  	req_cnt = qla4xxx_calc_request_entries(tot_dsds); - -	if (ha->req_q_count < (req_cnt + 2)) { -		cnt = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out); -		if (ha->request_in < cnt) -			ha->req_q_count = cnt - ha->request_in; -		else -			ha->req_q_count = REQUEST_QUEUE_DEPTH - -				(ha->request_in - cnt); -	} - -	if (ha->req_q_count < (req_cnt + 2)) +	if (!qla4xxx_space_in_req_ring(ha, req_cnt))  		goto queuing_error;  	/* total iocbs active */ @@ -286,32 +295,10 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)  			break;  		} - -	/* Advance request queue pointer */ -	ha->request_in++; -	if (ha->request_in == REQUEST_QUEUE_DEPTH) { -		ha->request_in = 0; -		ha->request_ptr = ha->request_ring; -	} else -		ha->request_ptr++; - - +	qla4xxx_advance_req_ring_ptr(ha);  	qla4xxx_build_scsi_iocbs(srb, cmd_entry, tot_dsds);  	wmb(); -	/* -	 * Check to see if adapter is online before placing request on -	 * request queue.  If a reset occurs and a request is in the queue, -	 * the firmware will still attempt to process the request, retrieving -	 * garbage for pointers. -	 */ -	if (!test_bit(AF_ONLINE, &ha->flags)) { -		DEBUG2(printk("scsi%ld: %s: Adapter OFFLINE! " -			      "Do not issue command.\n", -			      ha->host_no, __func__)); -		goto queuing_error; -	} -  	srb->cmd->host_scribble = (unsigned char *)srb;  	/* update counters */  |