aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_init.c
diff options
context:
space:
mode:
authorGiridhar Malavali <giridhar.malavali@qlogic.com>2012-02-09 14:15:36 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-02-19 09:14:08 -0500
commit9ba56b95a588906a65664a9299a9f8ac1a0f6a91 (patch)
tree93786c52320c2a7276c99cc4d9b3672ca6e0a50d /drivers/scsi/qla2xxx/qla_init.c
parent69e5f1ea61a3e84c03103c6a18ee9cacef4cbb9e (diff)
[SCSI] qla2xxx: Consolidation of SRB processing.
Rework the structures related to SRB processing to minimize the memory allocations per I/O and manage resources associated with and completions from common routines. Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com> Signed-off-by: Chad Dupuis <chad.dupuis@qlogic.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_init.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c256
1 files changed, 98 insertions, 158 deletions
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index e5b417aa9fca..4837b5872cde 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -41,11 +41,10 @@ static int qla25xx_init_queues(struct qla_hw_data *);
41 41
42/* SRB Extensions ---------------------------------------------------------- */ 42/* SRB Extensions ---------------------------------------------------------- */
43 43
44static void 44void
45qla2x00_ctx_sp_timeout(unsigned long __data) 45qla2x00_sp_timeout(unsigned long __data)
46{ 46{
47 srb_t *sp = (srb_t *)__data; 47 srb_t *sp = (srb_t *)__data;
48 struct srb_ctx *ctx;
49 struct srb_iocb *iocb; 48 struct srb_iocb *iocb;
50 fc_port_t *fcport = sp->fcport; 49 fc_port_t *fcport = sp->fcport;
51 struct qla_hw_data *ha = fcport->vha->hw; 50 struct qla_hw_data *ha = fcport->vha->hw;
@@ -55,79 +54,25 @@ qla2x00_ctx_sp_timeout(unsigned long __data)
55 spin_lock_irqsave(&ha->hardware_lock, flags); 54 spin_lock_irqsave(&ha->hardware_lock, flags);
56 req = ha->req_q_map[0]; 55 req = ha->req_q_map[0];
57 req->outstanding_cmds[sp->handle] = NULL; 56 req->outstanding_cmds[sp->handle] = NULL;
58 ctx = sp->ctx; 57 iocb = &sp->u.iocb_cmd;
59 iocb = ctx->u.iocb_cmd;
60 iocb->timeout(sp); 58 iocb->timeout(sp);
61 iocb->free(sp); 59 sp->free(fcport->vha, sp);
62 spin_unlock_irqrestore(&ha->hardware_lock, flags); 60 spin_unlock_irqrestore(&ha->hardware_lock, flags);
63} 61}
64 62
65static void 63void
66qla2x00_ctx_sp_free(srb_t *sp) 64qla2x00_sp_free(void *data, void *ptr)
67{ 65{
68 struct srb_ctx *ctx = sp->ctx; 66 srb_t *sp = (srb_t *)ptr;
69 struct srb_iocb *iocb = ctx->u.iocb_cmd; 67 struct srb_iocb *iocb = &sp->u.iocb_cmd;
70 struct scsi_qla_host *vha = sp->fcport->vha; 68 struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
71 69
72 del_timer(&iocb->timer); 70 del_timer(&iocb->timer);
73 kfree(iocb); 71 mempool_free(sp, vha->hw->srb_mempool);
74 kfree(ctx);
75 mempool_free(sp, sp->fcport->vha->hw->srb_mempool);
76 72
77 QLA_VHA_MARK_NOT_BUSY(vha); 73 QLA_VHA_MARK_NOT_BUSY(vha);
78} 74}
79 75
80inline srb_t *
81qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size,
82 unsigned long tmo)
83{
84 srb_t *sp = NULL;
85 struct qla_hw_data *ha = vha->hw;
86 struct srb_ctx *ctx;
87 struct srb_iocb *iocb;
88 uint8_t bail;
89
90 QLA_VHA_MARK_BUSY(vha, bail);
91 if (bail)
92 return NULL;
93
94 sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL);
95 if (!sp)
96 goto done;
97 ctx = kzalloc(size, GFP_KERNEL);
98 if (!ctx) {
99 mempool_free(sp, ha->srb_mempool);
100 sp = NULL;
101 goto done;
102 }
103 iocb = kzalloc(sizeof(struct srb_iocb), GFP_KERNEL);
104 if (!iocb) {
105 mempool_free(sp, ha->srb_mempool);
106 sp = NULL;
107 kfree(ctx);
108 goto done;
109 }
110
111 memset(sp, 0, sizeof(*sp));
112 sp->fcport = fcport;
113 sp->ctx = ctx;
114 ctx->iocbs = 1;
115 ctx->u.iocb_cmd = iocb;
116 iocb->free = qla2x00_ctx_sp_free;
117
118 init_timer(&iocb->timer);
119 if (!tmo)
120 goto done;
121 iocb->timer.expires = jiffies + tmo * HZ;
122 iocb->timer.data = (unsigned long)sp;
123 iocb->timer.function = qla2x00_ctx_sp_timeout;
124 add_timer(&iocb->timer);
125done:
126 if (!sp)
127 QLA_VHA_MARK_NOT_BUSY(vha);
128 return sp;
129}
130
131/* Asynchronous Login/Logout Routines -------------------------------------- */ 76/* Asynchronous Login/Logout Routines -------------------------------------- */
132 77
133static inline unsigned long 78static inline unsigned long
@@ -149,19 +94,19 @@ qla2x00_get_async_timeout(struct scsi_qla_host *vha)
149} 94}
150 95
151static void 96static void
152qla2x00_async_iocb_timeout(srb_t *sp) 97qla2x00_async_iocb_timeout(void *data)
153{ 98{
99 srb_t *sp = (srb_t *)data;
154 fc_port_t *fcport = sp->fcport; 100 fc_port_t *fcport = sp->fcport;
155 struct srb_ctx *ctx = sp->ctx;
156 101
157 ql_dbg(ql_dbg_disc, fcport->vha, 0x2071, 102 ql_dbg(ql_dbg_disc, fcport->vha, 0x2071,
158 "Async-%s timeout - hdl=%x portid=%02x%02x%02x.\n", 103 "Async-%s timeout - hdl=%x portid=%02x%02x%02x.\n",
159 ctx->name, sp->handle, fcport->d_id.b.domain, fcport->d_id.b.area, 104 sp->name, sp->handle, fcport->d_id.b.domain, fcport->d_id.b.area,
160 fcport->d_id.b.al_pa); 105 fcport->d_id.b.al_pa);
161 106
162 fcport->flags &= ~FCF_ASYNC_SENT; 107 fcport->flags &= ~FCF_ASYNC_SENT;
163 if (ctx->type == SRB_LOGIN_CMD) { 108 if (sp->type == SRB_LOGIN_CMD) {
164 struct srb_iocb *lio = ctx->u.iocb_cmd; 109 struct srb_iocb *lio = &sp->u.iocb_cmd;
165 qla2x00_post_async_logout_work(fcport->vha, fcport, NULL); 110 qla2x00_post_async_logout_work(fcport->vha, fcport, NULL);
166 /* Retry as needed. */ 111 /* Retry as needed. */
167 lio->u.logio.data[0] = MBS_COMMAND_ERROR; 112 lio->u.logio.data[0] = MBS_COMMAND_ERROR;
@@ -173,14 +118,16 @@ qla2x00_async_iocb_timeout(srb_t *sp)
173} 118}
174 119
175static void 120static void
176qla2x00_async_login_ctx_done(srb_t *sp) 121qla2x00_async_login_sp_done(void *data, void *ptr, int res)
177{ 122{
178 struct srb_ctx *ctx = sp->ctx; 123 srb_t *sp = (srb_t *)ptr;
179 struct srb_iocb *lio = ctx->u.iocb_cmd; 124 struct srb_iocb *lio = &sp->u.iocb_cmd;
180 125 struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
181 qla2x00_post_async_login_done_work(sp->fcport->vha, sp->fcport, 126
182 lio->u.logio.data); 127 if (!test_bit(UNLOADING, &vha->dpc_flags))
183 lio->free(sp); 128 qla2x00_post_async_login_done_work(sp->fcport->vha, sp->fcport,
129 lio->u.logio.data);
130 sp->free(sp->fcport->vha, sp);
184} 131}
185 132
186int 133int
@@ -188,22 +135,21 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
188 uint16_t *data) 135 uint16_t *data)
189{ 136{
190 srb_t *sp; 137 srb_t *sp;
191 struct srb_ctx *ctx;
192 struct srb_iocb *lio; 138 struct srb_iocb *lio;
193 int rval; 139 int rval;
194 140
195 rval = QLA_FUNCTION_FAILED; 141 rval = QLA_FUNCTION_FAILED;
196 sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx), 142 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
197 qla2x00_get_async_timeout(vha) + 2);
198 if (!sp) 143 if (!sp)
199 goto done; 144 goto done;
200 145
201 ctx = sp->ctx; 146 sp->type = SRB_LOGIN_CMD;
202 ctx->type = SRB_LOGIN_CMD; 147 sp->name = "login";
203 ctx->name = "login"; 148 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
204 lio = ctx->u.iocb_cmd; 149
150 lio = &sp->u.iocb_cmd;
205 lio->timeout = qla2x00_async_iocb_timeout; 151 lio->timeout = qla2x00_async_iocb_timeout;
206 lio->done = qla2x00_async_login_ctx_done; 152 sp->done = qla2x00_async_login_sp_done;
207 lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI; 153 lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI;
208 if (data[1] & QLA_LOGIO_LOGIN_RETRIED) 154 if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
209 lio->u.logio.flags |= SRB_LOGIN_RETRIED; 155 lio->u.logio.flags |= SRB_LOGIN_RETRIED;
@@ -219,42 +165,43 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
219 return rval; 165 return rval;
220 166
221done_free_sp: 167done_free_sp:
222 lio->free(sp); 168 sp->free(fcport->vha, sp);
223done: 169done:
224 return rval; 170 return rval;
225} 171}
226 172
227static void 173static void
228qla2x00_async_logout_ctx_done(srb_t *sp) 174qla2x00_async_logout_sp_done(void *data, void *ptr, int res)
229{ 175{
230 struct srb_ctx *ctx = sp->ctx; 176 srb_t *sp = (srb_t *)ptr;
231 struct srb_iocb *lio = ctx->u.iocb_cmd; 177 struct srb_iocb *lio = &sp->u.iocb_cmd;
232 178 struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
233 qla2x00_post_async_logout_done_work(sp->fcport->vha, sp->fcport, 179
234 lio->u.logio.data); 180 if (!test_bit(UNLOADING, &vha->dpc_flags))
235 lio->free(sp); 181 qla2x00_post_async_logout_done_work(sp->fcport->vha, sp->fcport,
182 lio->u.logio.data);
183 sp->free(sp->fcport->vha, sp);
236} 184}
237 185
238int 186int
239qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport) 187qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
240{ 188{
241 srb_t *sp; 189 srb_t *sp;
242 struct srb_ctx *ctx;
243 struct srb_iocb *lio; 190 struct srb_iocb *lio;
244 int rval; 191 int rval;
245 192
246 rval = QLA_FUNCTION_FAILED; 193 rval = QLA_FUNCTION_FAILED;
247 sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx), 194 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
248 qla2x00_get_async_timeout(vha) + 2);
249 if (!sp) 195 if (!sp)
250 goto done; 196 goto done;
251 197
252 ctx = sp->ctx; 198 sp->type = SRB_LOGOUT_CMD;
253 ctx->type = SRB_LOGOUT_CMD; 199 sp->name = "logout";
254 ctx->name = "logout"; 200 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
255 lio = ctx->u.iocb_cmd; 201
202 lio = &sp->u.iocb_cmd;
256 lio->timeout = qla2x00_async_iocb_timeout; 203 lio->timeout = qla2x00_async_iocb_timeout;
257 lio->done = qla2x00_async_logout_ctx_done; 204 sp->done = qla2x00_async_logout_sp_done;
258 rval = qla2x00_start_sp(sp); 205 rval = qla2x00_start_sp(sp);
259 if (rval != QLA_SUCCESS) 206 if (rval != QLA_SUCCESS)
260 goto done_free_sp; 207 goto done_free_sp;
@@ -266,20 +213,22 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
266 return rval; 213 return rval;
267 214
268done_free_sp: 215done_free_sp:
269 lio->free(sp); 216 sp->free(fcport->vha, sp);
270done: 217done:
271 return rval; 218 return rval;
272} 219}
273 220
274static void 221static void
275qla2x00_async_adisc_ctx_done(srb_t *sp) 222qla2x00_async_adisc_sp_done(void *data, void *ptr, int res)
276{ 223{
277 struct srb_ctx *ctx = sp->ctx; 224 srb_t *sp = (srb_t *)ptr;
278 struct srb_iocb *lio = ctx->u.iocb_cmd; 225 struct srb_iocb *lio = &sp->u.iocb_cmd;
279 226 struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
280 qla2x00_post_async_adisc_done_work(sp->fcport->vha, sp->fcport, 227
281 lio->u.logio.data); 228 if (!test_bit(UNLOADING, &vha->dpc_flags))
282 lio->free(sp); 229 qla2x00_post_async_adisc_done_work(sp->fcport->vha, sp->fcport,
230 lio->u.logio.data);
231 sp->free(sp->fcport->vha, sp);
283} 232}
284 233
285int 234int
@@ -287,22 +236,21 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
287 uint16_t *data) 236 uint16_t *data)
288{ 237{
289 srb_t *sp; 238 srb_t *sp;
290 struct srb_ctx *ctx;
291 struct srb_iocb *lio; 239 struct srb_iocb *lio;
292 int rval; 240 int rval;
293 241
294 rval = QLA_FUNCTION_FAILED; 242 rval = QLA_FUNCTION_FAILED;
295 sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx), 243 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
296 qla2x00_get_async_timeout(vha) + 2);
297 if (!sp) 244 if (!sp)
298 goto done; 245 goto done;
299 246
300 ctx = sp->ctx; 247 sp->type = SRB_ADISC_CMD;
301 ctx->type = SRB_ADISC_CMD; 248 sp->name = "adisc";
302 ctx->name = "adisc"; 249 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
303 lio = ctx->u.iocb_cmd; 250
251 lio = &sp->u.iocb_cmd;
304 lio->timeout = qla2x00_async_iocb_timeout; 252 lio->timeout = qla2x00_async_iocb_timeout;
305 lio->done = qla2x00_async_adisc_ctx_done; 253 sp->done = qla2x00_async_adisc_sp_done;
306 if (data[1] & QLA_LOGIO_LOGIN_RETRIED) 254 if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
307 lio->u.logio.flags |= SRB_LOGIN_RETRIED; 255 lio->u.logio.flags |= SRB_LOGIN_RETRIED;
308 rval = qla2x00_start_sp(sp); 256 rval = qla2x00_start_sp(sp);
@@ -316,46 +264,62 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
316 return rval; 264 return rval;
317 265
318done_free_sp: 266done_free_sp:
319 lio->free(sp); 267 sp->free(fcport->vha, sp);
320done: 268done:
321 return rval; 269 return rval;
322} 270}
323 271
324static void 272static void
325qla2x00_async_tm_cmd_ctx_done(srb_t *sp) 273qla2x00_async_tm_cmd_done(void *data, void *ptr, int res)
326{ 274{
327 struct srb_ctx *ctx = sp->ctx; 275 srb_t *sp = (srb_t *)ptr;
328 struct srb_iocb *iocb = (struct srb_iocb *)ctx->u.iocb_cmd; 276 struct srb_iocb *iocb = &sp->u.iocb_cmd;
277 struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
278 uint32_t flags;
279 uint16_t lun;
280 int rval;
329 281
330 qla2x00_async_tm_cmd_done(sp->fcport->vha, sp->fcport, iocb); 282 if (!test_bit(UNLOADING, &vha->dpc_flags)) {
331 iocb->free(sp); 283 flags = iocb->u.tmf.flags;
284 lun = (uint16_t)iocb->u.tmf.lun;
285
286 /* Issue Marker IOCB */
287 rval = qla2x00_marker(vha, vha->hw->req_q_map[0],
288 vha->hw->rsp_q_map[0], sp->fcport->loop_id, lun,
289 flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);
290
291 if ((rval != QLA_SUCCESS) || iocb->u.tmf.data) {
292 ql_dbg(ql_dbg_taskm, vha, 0x8030,
293 "TM IOCB failed (%x).\n", rval);
294 }
295 }
296 sp->free(sp->fcport->vha, sp);
332} 297}
333 298
334int 299int
335qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, 300qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t tm_flags, uint32_t lun,
336 uint32_t tag) 301 uint32_t tag)
337{ 302{
338 struct scsi_qla_host *vha = fcport->vha; 303 struct scsi_qla_host *vha = fcport->vha;
339 srb_t *sp; 304 srb_t *sp;
340 struct srb_ctx *ctx;
341 struct srb_iocb *tcf; 305 struct srb_iocb *tcf;
342 int rval; 306 int rval;
343 307
344 rval = QLA_FUNCTION_FAILED; 308 rval = QLA_FUNCTION_FAILED;
345 sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx), 309 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
346 qla2x00_get_async_timeout(vha) + 2);
347 if (!sp) 310 if (!sp)
348 goto done; 311 goto done;
349 312
350 ctx = sp->ctx; 313 sp->type = SRB_TM_CMD;
351 ctx->type = SRB_TM_CMD; 314 sp->name = "tmf";
352 ctx->name = "tmf"; 315 qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
353 tcf = ctx->u.iocb_cmd; 316
354 tcf->u.tmf.flags = flags; 317 tcf = &sp->u.iocb_cmd;
318 tcf->u.tmf.flags = tm_flags;
355 tcf->u.tmf.lun = lun; 319 tcf->u.tmf.lun = lun;
356 tcf->u.tmf.data = tag; 320 tcf->u.tmf.data = tag;
357 tcf->timeout = qla2x00_async_iocb_timeout; 321 tcf->timeout = qla2x00_async_iocb_timeout;
358 tcf->done = qla2x00_async_tm_cmd_ctx_done; 322 sp->done = qla2x00_async_tm_cmd_done;
359 323
360 rval = qla2x00_start_sp(sp); 324 rval = qla2x00_start_sp(sp);
361 if (rval != QLA_SUCCESS) 325 if (rval != QLA_SUCCESS)
@@ -368,7 +332,7 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
368 return rval; 332 return rval;
369 333
370done_free_sp: 334done_free_sp:
371 tcf->free(sp); 335 sp->free(fcport->vha, sp);
372done: 336done:
373 return rval; 337 return rval;
374} 338}
@@ -452,30 +416,6 @@ qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport,
452 return; 416 return;
453} 417}
454 418
455void
456qla2x00_async_tm_cmd_done(struct scsi_qla_host *vha, fc_port_t *fcport,
457 struct srb_iocb *iocb)
458{
459 int rval;
460 uint32_t flags;
461 uint16_t lun;
462
463 flags = iocb->u.tmf.flags;
464 lun = (uint16_t)iocb->u.tmf.lun;
465
466 /* Issue Marker IOCB */
467 rval = qla2x00_marker(vha, vha->hw->req_q_map[0],
468 vha->hw->rsp_q_map[0], fcport->loop_id, lun,
469 flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);
470
471 if ((rval != QLA_SUCCESS) || iocb->u.tmf.data) {
472 ql_dbg(ql_dbg_taskm, vha, 0x8030,
473 "TM IOCB failed (%x).\n", rval);
474 }
475
476 return;
477}
478
479/****************************************************************************/ 419/****************************************************************************/
480/* QLogic ISP2x00 Hardware Support Functions. */ 420/* QLogic ISP2x00 Hardware Support Functions. */
481/****************************************************************************/ 421/****************************************************************************/