aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla4xxx/ql4_iocb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla4xxx/ql4_iocb.c')
-rw-r--r--drivers/scsi/qla4xxx/ql4_iocb.c133
1 files changed, 60 insertions, 73 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c
index 912a67494adf..e0c32159749c 100644
--- a/drivers/scsi/qla4xxx/ql4_iocb.c
+++ b/drivers/scsi/qla4xxx/ql4_iocb.c
@@ -10,9 +10,42 @@
10#include "ql4_dbg.h" 10#include "ql4_dbg.h"
11#include "ql4_inline.h" 11#include "ql4_inline.h"
12 12
13
14#include <scsi/scsi_tcq.h> 13#include <scsi/scsi_tcq.h>
15 14
15static int
16qla4xxx_space_in_req_ring(struct scsi_qla_host *ha, uint16_t req_cnt)
17{
18 uint16_t cnt;
19
20 /* Calculate number of free request entries. */
21 if ((req_cnt + 2) >= ha->req_q_count) {
22 cnt = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out);
23 if (ha->request_in < cnt)
24 ha->req_q_count = cnt - ha->request_in;
25 else
26 ha->req_q_count = REQUEST_QUEUE_DEPTH -
27 (ha->request_in - cnt);
28 }
29
30 /* Check if room for request in request ring. */
31 if ((req_cnt + 2) < ha->req_q_count)
32 return 1;
33 else
34 return 0;
35}
36
37static void qla4xxx_advance_req_ring_ptr(struct scsi_qla_host *ha)
38{
39 /* Advance request queue pointer */
40 if (ha->request_in == (REQUEST_QUEUE_DEPTH - 1)) {
41 ha->request_in = 0;
42 ha->request_ptr = ha->request_ring;
43 } else {
44 ha->request_in++;
45 ha->request_ptr++;
46 }
47}
48
16/** 49/**
17 * qla4xxx_get_req_pkt - returns a valid entry in request queue. 50 * qla4xxx_get_req_pkt - returns a valid entry in request queue.
18 * @ha: Pointer to host adapter structure. 51 * @ha: Pointer to host adapter structure.
@@ -26,35 +59,18 @@
26static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha, 59static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha,
27 struct queue_entry **queue_entry) 60 struct queue_entry **queue_entry)
28{ 61{
29 uint16_t request_in; 62 uint16_t req_cnt = 1;
30 uint8_t status = QLA_SUCCESS;
31
32 *queue_entry = ha->request_ptr;
33 63
34 /* get the latest request_in and request_out index */ 64 if (qla4xxx_space_in_req_ring(ha, req_cnt)) {
35 request_in = ha->request_in; 65 *queue_entry = ha->request_ptr;
36 ha->request_out = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out);
37
38 /* Advance request queue pointer and check for queue full */
39 if (request_in == (REQUEST_QUEUE_DEPTH - 1)) {
40 request_in = 0;
41 ha->request_ptr = ha->request_ring;
42 } else {
43 request_in++;
44 ha->request_ptr++;
45 }
46
47 /* request queue is full, try again later */
48 if ((ha->iocb_cnt + 1) >= ha->iocb_hiwat) {
49 /* restore request pointer */
50 ha->request_ptr = *queue_entry;
51 status = QLA_ERROR;
52 } else {
53 ha->request_in = request_in;
54 memset(*queue_entry, 0, sizeof(**queue_entry)); 66 memset(*queue_entry, 0, sizeof(**queue_entry));
67
68 qla4xxx_advance_req_ring_ptr(ha);
69 ha->req_q_count -= req_cnt;
70 return QLA_SUCCESS;
55 } 71 }
56 72
57 return status; 73 return QLA_ERROR;
58} 74}
59 75
60/** 76/**
@@ -100,21 +116,14 @@ exit_send_marker:
100 return status; 116 return status;
101} 117}
102 118
103static struct continuation_t1_entry* qla4xxx_alloc_cont_entry( 119static struct continuation_t1_entry *
104 struct scsi_qla_host *ha) 120qla4xxx_alloc_cont_entry(struct scsi_qla_host *ha)
105{ 121{
106 struct continuation_t1_entry *cont_entry; 122 struct continuation_t1_entry *cont_entry;
107 123
108 cont_entry = (struct continuation_t1_entry *)ha->request_ptr; 124 cont_entry = (struct continuation_t1_entry *)ha->request_ptr;
109 125
110 /* Advance request queue pointer */ 126 qla4xxx_advance_req_ring_ptr(ha);
111 if (ha->request_in == (REQUEST_QUEUE_DEPTH - 1)) {
112 ha->request_in = 0;
113 ha->request_ptr = ha->request_ring;
114 } else {
115 ha->request_in++;
116 ha->request_ptr++;
117 }
118 127
119 /* Load packet defaults */ 128 /* Load packet defaults */
120 cont_entry->hdr.entryType = ET_CONTINUE; 129 cont_entry->hdr.entryType = ET_CONTINUE;
@@ -197,13 +206,10 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)
197 struct scsi_cmnd *cmd = srb->cmd; 206 struct scsi_cmnd *cmd = srb->cmd;
198 struct ddb_entry *ddb_entry; 207 struct ddb_entry *ddb_entry;
199 struct command_t3_entry *cmd_entry; 208 struct command_t3_entry *cmd_entry;
200
201 int nseg; 209 int nseg;
202 uint16_t tot_dsds; 210 uint16_t tot_dsds;
203 uint16_t req_cnt; 211 uint16_t req_cnt;
204
205 unsigned long flags; 212 unsigned long flags;
206 uint16_t cnt;
207 uint32_t index; 213 uint32_t index;
208 char tag[2]; 214 char tag[2];
209 215
@@ -217,6 +223,19 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)
217 223
218 index = (uint32_t)cmd->request->tag; 224 index = (uint32_t)cmd->request->tag;
219 225
226 /*
227 * Check to see if adapter is online before placing request on
228 * request queue. If a reset occurs and a request is in the queue,
229 * the firmware will still attempt to process the request, retrieving
230 * garbage for pointers.
231 */
232 if (!test_bit(AF_ONLINE, &ha->flags)) {
233 DEBUG2(printk("scsi%ld: %s: Adapter OFFLINE! "
234 "Do not issue command.\n",
235 ha->host_no, __func__));
236 goto queuing_error;
237 }
238
220 /* Calculate the number of request entries needed. */ 239 /* Calculate the number of request entries needed. */
221 nseg = scsi_dma_map(cmd); 240 nseg = scsi_dma_map(cmd);
222 if (nseg < 0) 241 if (nseg < 0)
@@ -224,17 +243,7 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)
224 tot_dsds = nseg; 243 tot_dsds = nseg;
225 244
226 req_cnt = qla4xxx_calc_request_entries(tot_dsds); 245 req_cnt = qla4xxx_calc_request_entries(tot_dsds);
227 246 if (!qla4xxx_space_in_req_ring(ha, req_cnt))
228 if (ha->req_q_count < (req_cnt + 2)) {
229 cnt = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out);
230 if (ha->request_in < cnt)
231 ha->req_q_count = cnt - ha->request_in;
232 else
233 ha->req_q_count = REQUEST_QUEUE_DEPTH -
234 (ha->request_in - cnt);
235 }
236
237 if (ha->req_q_count < (req_cnt + 2))
238 goto queuing_error; 247 goto queuing_error;
239 248
240 /* total iocbs active */ 249 /* total iocbs active */
@@ -286,32 +295,10 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)
286 break; 295 break;
287 } 296 }
288 297
289 298 qla4xxx_advance_req_ring_ptr(ha);
290 /* Advance request queue pointer */
291 ha->request_in++;
292 if (ha->request_in == REQUEST_QUEUE_DEPTH) {
293 ha->request_in = 0;
294 ha->request_ptr = ha->request_ring;
295 } else
296 ha->request_ptr++;
297
298
299 qla4xxx_build_scsi_iocbs(srb, cmd_entry, tot_dsds); 299 qla4xxx_build_scsi_iocbs(srb, cmd_entry, tot_dsds);
300 wmb(); 300 wmb();
301 301
302 /*
303 * Check to see if adapter is online before placing request on
304 * request queue. If a reset occurs and a request is in the queue,
305 * the firmware will still attempt to process the request, retrieving
306 * garbage for pointers.
307 */
308 if (!test_bit(AF_ONLINE, &ha->flags)) {
309 DEBUG2(printk("scsi%ld: %s: Adapter OFFLINE! "
310 "Do not issue command.\n",
311 ha->host_no, __func__));
312 goto queuing_error;
313 }
314
315 srb->cmd->host_scribble = (unsigned char *)srb; 302 srb->cmd->host_scribble = (unsigned char *)srb;
316 303
317 /* update counters */ 304 /* update counters */