Merge ../bleed-2.6
[deliverable/linux.git] / drivers / scsi / qla2xxx / qla_rscn.c
CommitLineData
1da177e4
LT
1/*
2 * QLOGIC LINUX SOFTWARE
3 *
4 * QLogic ISP2x00 device driver for Linux 2.6.x
ae91193c 5 * Copyright (C) 2003-2005 QLogic Corporation
1da177e4
LT
6 * (www.qlogic.com)
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
11 * later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 */
19#include "qla_def.h"
20
21/**
22 * IO descriptor handle definitions.
23 *
24 * Signature form:
25 *
26 * |31------28|27-------------------12|11-------0|
27 * | Type | Rolling Signature | Index |
28 * |----------|-----------------------|----------|
29 *
30 **/
31
32#define HDL_TYPE_SCSI 0
33#define HDL_TYPE_ASYNC_IOCB 0x0A
34
35#define HDL_INDEX_BITS 12
36#define HDL_ITER_BITS 16
37#define HDL_TYPE_BITS 4
38
39#define HDL_INDEX_MASK ((1UL << HDL_INDEX_BITS) - 1)
40#define HDL_ITER_MASK ((1UL << HDL_ITER_BITS) - 1)
41#define HDL_TYPE_MASK ((1UL << HDL_TYPE_BITS) - 1)
42
43#define HDL_INDEX_SHIFT 0
44#define HDL_ITER_SHIFT (HDL_INDEX_SHIFT + HDL_INDEX_BITS)
45#define HDL_TYPE_SHIFT (HDL_ITER_SHIFT + HDL_ITER_BITS)
46
47/* Local Prototypes. */
48static inline uint32_t qla2x00_to_handle(uint16_t, uint16_t, uint16_t);
49static inline uint16_t qla2x00_handle_to_idx(uint32_t);
50static inline uint32_t qla2x00_iodesc_to_handle(struct io_descriptor *);
51static inline struct io_descriptor *qla2x00_handle_to_iodesc(scsi_qla_host_t *,
52 uint32_t);
53
54static inline struct io_descriptor *qla2x00_alloc_iodesc(scsi_qla_host_t *);
55static inline void qla2x00_free_iodesc(struct io_descriptor *);
56static inline void qla2x00_init_io_descriptors(scsi_qla_host_t *);
57
58static void qla2x00_iodesc_timeout(unsigned long);
59static inline void qla2x00_add_iodesc_timer(struct io_descriptor *);
60static inline void qla2x00_remove_iodesc_timer(struct io_descriptor *);
61
62static inline void qla2x00_update_login_fcport(scsi_qla_host_t *,
63 struct mbx_entry *, fc_port_t *);
64
65static int qla2x00_send_abort_iocb(scsi_qla_host_t *, struct io_descriptor *,
66 uint32_t, int);
67static int qla2x00_send_abort_iocb_cb(scsi_qla_host_t *, struct io_descriptor *,
68 struct mbx_entry *);
69
70static int qla2x00_send_adisc_iocb(scsi_qla_host_t *, struct io_descriptor *,
71 int);
72static int qla2x00_send_adisc_iocb_cb(scsi_qla_host_t *, struct io_descriptor *,
73 struct mbx_entry *);
74
75static int qla2x00_send_logout_iocb(scsi_qla_host_t *, struct io_descriptor *,
76 int);
77static int qla2x00_send_logout_iocb_cb(scsi_qla_host_t *,
78 struct io_descriptor *, struct mbx_entry *);
79
80static int qla2x00_send_login_iocb(scsi_qla_host_t *, struct io_descriptor *,
81 port_id_t *, int);
82static int qla2x00_send_login_iocb_cb(scsi_qla_host_t *, struct io_descriptor *,
83 struct mbx_entry *);
84
fa2a1ce5 85/**
1da177e4
LT
86 * Mailbox IOCB callback array.
87 **/
88static int (*iocb_function_cb_list[LAST_IOCB_CB])
89 (scsi_qla_host_t *, struct io_descriptor *, struct mbx_entry *) = {
90
91 qla2x00_send_abort_iocb_cb,
92 qla2x00_send_adisc_iocb_cb,
93 qla2x00_send_logout_iocb_cb,
94 qla2x00_send_login_iocb_cb,
95};
96
97
fa2a1ce5 98/**
1da177e4
LT
99 * Generic IO descriptor handle routines.
100 **/
101
102/**
103 * qla2x00_to_handle() - Create a descriptor handle.
104 * @type: descriptor type
105 * @iter: descriptor rolling signature
106 * @idx: index to the descriptor array
107 *
108 * Returns a composite handle based in the @type, @iter, and @idx.
109 */
110static inline uint32_t
111qla2x00_to_handle(uint16_t type, uint16_t iter, uint16_t idx)
112{
113 return ((uint32_t)(((uint32_t)type << HDL_TYPE_SHIFT) |
114 ((uint32_t)iter << HDL_ITER_SHIFT) |
115 ((uint32_t)idx << HDL_INDEX_SHIFT)));
116}
117
118/**
119 * qla2x00_handle_to_idx() - Retrive the index for a given handle.
120 * @handle: descriptor handle
121 *
122 * Returns the index specified by the @handle.
123 */
124static inline uint16_t
125qla2x00_handle_to_idx(uint32_t handle)
126{
127 return ((uint16_t)(((handle) >> HDL_INDEX_SHIFT) & HDL_INDEX_MASK));
128}
129
130/**
131 * qla2x00_iodesc_to_handle() - Convert an IO descriptor to a unique handle.
132 * @iodesc: io descriptor
133 *
134 * Returns a unique handle for @iodesc.
135 */
136static inline uint32_t
137qla2x00_iodesc_to_handle(struct io_descriptor *iodesc)
138{
139 uint32_t handle;
140
141 handle = qla2x00_to_handle(HDL_TYPE_ASYNC_IOCB,
142 ++iodesc->ha->iodesc_signature, iodesc->idx);
143 iodesc->signature = handle;
144
145 return (handle);
146}
147
148/**
149 * qla2x00_handle_to_iodesc() - Retrieve an IO descriptor given a unique handle.
150 * @ha: HA context
151 * @handle: handle to io descriptor
152 *
153 * Returns a pointer to the io descriptor, or NULL, if the io descriptor does
154 * not exist or the io descriptors signature does not @handle.
155 */
156static inline struct io_descriptor *
157qla2x00_handle_to_iodesc(scsi_qla_host_t *ha, uint32_t handle)
158{
159 uint16_t idx;
160 struct io_descriptor *iodesc;
161
162 idx = qla2x00_handle_to_idx(handle);
163 iodesc = &ha->io_descriptors[idx];
164 if (iodesc)
165 if (iodesc->signature != handle)
166 iodesc = NULL;
167
168 return (iodesc);
169}
170
171
fa2a1ce5 172/**
1da177e4
LT
173 * IO descriptor allocation routines.
174 **/
175
176/**
177 * qla2x00_alloc_iodesc() - Allocate an IO descriptor from the pool.
178 * @ha: HA context
179 *
180 * Returns a pointer to the allocated io descriptor, or NULL, if none available.
181 */
182static inline struct io_descriptor *
183qla2x00_alloc_iodesc(scsi_qla_host_t *ha)
184{
185 uint16_t iter;
186 struct io_descriptor *iodesc;
187
188 iodesc = NULL;
189 for (iter = 0; iter < MAX_IO_DESCRIPTORS; iter++) {
190 if (ha->io_descriptors[iter].used)
191 continue;
192
193 iodesc = &ha->io_descriptors[iter];
194 iodesc->used = 1;
195 iodesc->idx = iter;
196 init_timer(&iodesc->timer);
197 iodesc->ha = ha;
198 iodesc->signature = qla2x00_iodesc_to_handle(iodesc);
199 break;
200 }
201
202 return (iodesc);
203}
204
205/**
206 * qla2x00_free_iodesc() - Free an IO descriptor.
207 * @iodesc: io descriptor
208 *
209 * NOTE: The io descriptors timer *must* be stopped before it can be free'd.
210 */
211static inline void
212qla2x00_free_iodesc(struct io_descriptor *iodesc)
213{
214 iodesc->used = 0;
215 iodesc->signature = 0;
216}
217
218/**
219 * qla2x00_remove_iodesc_timer() - Remove an active timer from an IO descriptor.
220 * @iodesc: io descriptor
221 */
222static inline void
223qla2x00_remove_iodesc_timer(struct io_descriptor *iodesc)
224{
225 if (iodesc->timer.function != NULL) {
226 del_timer_sync(&iodesc->timer);
227 iodesc->timer.data = (unsigned long) NULL;
228 iodesc->timer.function = NULL;
229 }
230}
231
232/**
233 * qla2x00_init_io_descriptors() - Initialize the pool of IO descriptors.
234 * @ha: HA context
235 */
236static inline void
237qla2x00_init_io_descriptors(scsi_qla_host_t *ha)
238{
239 uint16_t iter;
240
241 for (iter = 0; iter < MAX_IO_DESCRIPTORS; iter++) {
242 if (!ha->io_descriptors[iter].used)
243 continue;
244
245 qla2x00_remove_iodesc_timer(&ha->io_descriptors[iter]);
246 qla2x00_free_iodesc(&ha->io_descriptors[iter]);
247 }
248}
249
250
fa2a1ce5 251/**
1da177e4
LT
252 * IO descriptor timer routines.
253 **/
254
255/**
256 * qla2x00_iodesc_timeout() - Timeout IO descriptor handler.
257 * @data: io descriptor
258 */
259static void
260qla2x00_iodesc_timeout(unsigned long data)
261{
262 struct io_descriptor *iodesc;
263
264 iodesc = (struct io_descriptor *) data;
265
266 DEBUG14(printk("scsi(%ld): IO descriptor timeout, index=%x "
267 "signature=%08x, scheduling ISP abort.\n", iodesc->ha->host_no,
268 iodesc->idx, iodesc->signature));
269
270 qla2x00_free_iodesc(iodesc);
271
272 qla_printk(KERN_WARNING, iodesc->ha,
273 "IO descriptor timeout. Scheduling ISP abort.\n");
274 set_bit(ISP_ABORT_NEEDED, &iodesc->ha->dpc_flags);
275}
276
277/**
278 * qla2x00_add_iodesc_timer() - Add and start a timer for an IO descriptor.
279 * @iodesc: io descriptor
280 *
281 * NOTE:
282 * The firmware shall timeout an outstanding mailbox IOCB in 2 * R_A_TOV (in
283 * tenths of a second) after it hits the wire. But, if there are any request
284 * resource contraints (i.e. during heavy I/O), exchanges can be held off for
285 * at most R_A_TOV. Therefore, the driver will wait 4 * R_A_TOV before
286 * scheduling a recovery (big hammer).
287 */
288static inline void
289qla2x00_add_iodesc_timer(struct io_descriptor *iodesc)
290{
291 unsigned long timeout;
292
293 timeout = (iodesc->ha->r_a_tov * 4) / 10;
294 init_timer(&iodesc->timer);
295 iodesc->timer.data = (unsigned long) iodesc;
296 iodesc->timer.expires = jiffies + (timeout * HZ);
297 iodesc->timer.function =
298 (void (*) (unsigned long)) qla2x00_iodesc_timeout;
299 add_timer(&iodesc->timer);
300}
301
fa2a1ce5 302/**
1da177e4
LT
303 * IO descriptor support routines.
304 **/
305
306/**
307 * qla2x00_update_login_fcport() - Update fcport data after login processing.
308 * @ha: HA context
309 * @mbxstat: Mailbox command status IOCB
310 * @fcport: port to update
311 */
312static inline void
313qla2x00_update_login_fcport(scsi_qla_host_t *ha, struct mbx_entry *mbxstat,
314 fc_port_t *fcport)
315{
316 if (le16_to_cpu(mbxstat->mb1) & BIT_0) {
317 fcport->port_type = FCT_INITIATOR;
318 } else {
319 fcport->port_type = FCT_TARGET;
320 if (le16_to_cpu(mbxstat->mb1) & BIT_1) {
321 fcport->flags |= FCF_TAPE_PRESENT;
322 }
323 }
324 fcport->login_retry = 0;
325 fcport->port_login_retry_count = ha->port_down_retry_count *
326 PORT_RETRY_TIME;
327 atomic_set(&fcport->port_down_timer, ha->port_down_retry_count *
328 PORT_RETRY_TIME);
329 fcport->flags |= FCF_FABRIC_DEVICE;
330 fcport->flags &= ~FCF_FAILOVER_NEEDED;
331 fcport->iodesc_idx_sent = IODESC_INVALID_INDEX;
332 atomic_set(&fcport->state, FCS_ONLINE);
44550322
AV
333 if (fcport->rport)
334 fc_remote_port_unblock(fcport->rport);
1da177e4
LT
335}
336
337
fa2a1ce5 338/**
1da177e4
LT
339 * Mailbox IOCB commands.
340 **/
341
342/**
343 * qla2x00_get_mbx_iocb_entry() - Retrieve an IOCB from the request queue.
344 * @ha: HA context
345 * @handle: handle to io descriptor
346 *
347 * Returns a pointer to the reqest entry, or NULL, if none were available.
348 */
349static inline struct mbx_entry *
350qla2x00_get_mbx_iocb_entry(scsi_qla_host_t *ha, uint32_t handle)
351{
352 uint16_t cnt;
3d71644c 353 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
1da177e4
LT
354 struct mbx_entry *mbxentry;
355
356 mbxentry = NULL;
357
358 if (ha->req_q_cnt < 3) {
359 cnt = qla2x00_debounce_register(ISP_REQ_Q_OUT(ha, reg));
360 if (ha->req_ring_index < cnt)
361 ha->req_q_cnt = cnt - ha->req_ring_index;
362 else
363 ha->req_q_cnt = ha->request_q_length -
364 (ha->req_ring_index - cnt);
365 }
366 if (ha->req_q_cnt >= 3) {
367 mbxentry = (struct mbx_entry *)ha->request_ring_ptr;
368
369 memset(mbxentry, 0, sizeof(struct mbx_entry));
370 mbxentry->entry_type = MBX_IOCB_TYPE;
371 mbxentry->entry_count = 1;
372 mbxentry->sys_define1 = SOURCE_ASYNC_IOCB;
373 mbxentry->handle = handle;
374 }
375 return (mbxentry);
376}
377
378/**
379 * qla2x00_send_abort_iocb() - Issue an abort IOCB to the firmware.
380 * @ha: HA context
381 * @iodesc: io descriptor
382 * @handle_to_abort: firmware handle to abort
383 * @ha_locked: is function called with the hardware lock
384 *
385 * Returns QLA_SUCCESS if the IOCB was issued.
386 */
387static int
fa2a1ce5 388qla2x00_send_abort_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
1da177e4
LT
389 uint32_t handle_to_abort, int ha_locked)
390{
391 unsigned long flags = 0;
392 struct mbx_entry *mbxentry;
393
394 /* Send marker if required. */
395 if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS)
396 return (QLA_FUNCTION_FAILED);
397
398 if (!ha_locked)
399 spin_lock_irqsave(&ha->hardware_lock, flags);
400
401 /* Build abort mailbox IOCB. */
402 mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature);
403 if (mbxentry == NULL) {
404 if (!ha_locked)
405 spin_unlock_irqrestore(&ha->hardware_lock, flags);
406
407 return (QLA_FUNCTION_FAILED);
408 }
409 mbxentry->mb0 = __constant_cpu_to_le16(MBC_ABORT_COMMAND);
410 mbxentry->mb1 = mbxentry->loop_id.extended =
411 cpu_to_le16(iodesc->remote_fcport->loop_id);
412 mbxentry->mb2 = LSW(handle_to_abort);
413 mbxentry->mb3 = MSW(handle_to_abort);
414 wmb();
415
416 qla2x00_add_iodesc_timer(iodesc);
417
418 /* Issue command to ISP. */
419 qla2x00_isp_cmd(ha);
420
421 if (!ha_locked)
422 spin_unlock_irqrestore(&ha->hardware_lock, flags);
423
424 DEBUG14(printk("scsi(%ld): Sending Abort IOCB (%08x) to [%x], aborting "
425 "%08x.\n", ha->host_no, iodesc->signature,
426 iodesc->remote_fcport->loop_id, handle_to_abort));
427
428 return (QLA_SUCCESS);
429}
430
431/**
432 * qla2x00_send_abort_iocb_cb() - Abort IOCB callback.
433 * @ha: HA context
434 * @iodesc: io descriptor
435 * @mbxstat: mailbox status IOCB
436 *
437 * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc
438 * will be used for a retry.
439 */
440static int
441qla2x00_send_abort_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
442 struct mbx_entry *mbxstat)
443{
444 DEBUG14(printk("scsi(%ld): Abort IOCB -- sent to [%x/%02x%02x%02x], "
445 "status=%x mb0=%x.\n", ha->host_no, iodesc->remote_fcport->loop_id,
446 iodesc->d_id.b.domain, iodesc->d_id.b.area, iodesc->d_id.b.al_pa,
447 le16_to_cpu(mbxstat->status), le16_to_cpu(mbxstat->mb0)));
448
449 return (QLA_SUCCESS);
450}
451
452
453/**
454 * qla2x00_send_adisc_iocb() - Issue a Get Port Database IOCB to the firmware.
455 * @ha: HA context
456 * @iodesc: io descriptor
457 * @ha_locked: is function called with the hardware lock
458 *
459 * Returns QLA_SUCCESS if the IOCB was issued.
460 */
461static int
462qla2x00_send_adisc_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
463 int ha_locked)
464{
465 unsigned long flags = 0;
466 struct mbx_entry *mbxentry;
467
468 /* Send marker if required. */
469 if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS)
470 return (QLA_FUNCTION_FAILED);
471
472 if (!ha_locked)
473 spin_lock_irqsave(&ha->hardware_lock, flags);
474
475 /* Build Get Port Database IOCB. */
476 mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature);
477 if (mbxentry == NULL) {
478 if (!ha_locked)
479 spin_unlock_irqrestore(&ha->hardware_lock, flags);
480
481 return (QLA_FUNCTION_FAILED);
482 }
483 mbxentry->mb0 = __constant_cpu_to_le16(MBC_GET_PORT_DATABASE);
484 mbxentry->mb1 = mbxentry->loop_id.extended =
485 cpu_to_le16(iodesc->remote_fcport->loop_id);
486 mbxentry->mb2 = cpu_to_le16(MSW(LSD(ha->iodesc_pd_dma)));
487 mbxentry->mb3 = cpu_to_le16(LSW(LSD(ha->iodesc_pd_dma)));
488 mbxentry->mb6 = cpu_to_le16(MSW(MSD(ha->iodesc_pd_dma)));
489 mbxentry->mb7 = cpu_to_le16(LSW(MSD(ha->iodesc_pd_dma)));
490 mbxentry->mb10 = __constant_cpu_to_le16(BIT_0);
491 wmb();
492
493 qla2x00_add_iodesc_timer(iodesc);
494
495 /* Issue command to ISP. */
496 qla2x00_isp_cmd(ha);
497
498 if (!ha_locked)
499 spin_unlock_irqrestore(&ha->hardware_lock, flags);
500
501 DEBUG14(printk("scsi(%ld): Sending Adisc IOCB (%08x) to [%x].\n",
502 ha->host_no, iodesc->signature, iodesc->remote_fcport->loop_id));
503
504 return (QLA_SUCCESS);
505}
506
507/**
508 * qla2x00_send_adisc_iocb_cb() - Get Port Database IOCB callback.
509 * @ha: HA context
510 * @iodesc: io descriptor
511 * @mbxstat: mailbox status IOCB
512 *
513 * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc
514 * will be used for a retry.
515 */
516static int
517qla2x00_send_adisc_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
518 struct mbx_entry *mbxstat)
519{
520 fc_port_t *remote_fcport;
521
522 remote_fcport = iodesc->remote_fcport;
523
524 /* Ensure the port IDs are consistent. */
525 if (remote_fcport->d_id.b24 != iodesc->d_id.b24) {
526 DEBUG14(printk("scsi(%ld): Adisc IOCB -- ignoring, remote port "
527 "id changed from [%02x%02x%02x] to [%02x%02x%02x].\n",
528 ha->host_no, remote_fcport->d_id.b.domain,
529 remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa,
530 iodesc->d_id.b.domain, iodesc->d_id.b.area,
531 iodesc->d_id.b.al_pa));
532
533 return (QLA_SUCCESS);
534 }
535
536 /* Only process the last command. */
537 if (remote_fcport->iodesc_idx_sent != iodesc->idx) {
538 DEBUG14(printk("scsi(%ld): Adisc IOCB -- ignoring, sent to "
539 "[%02x%02x%02x], expected %x, received %x.\n", ha->host_no,
540 iodesc->d_id.b.domain, iodesc->d_id.b.area,
541 iodesc->d_id.b.al_pa, remote_fcport->iodesc_idx_sent,
542 iodesc->idx));
543
544 return (QLA_SUCCESS);
545 }
546
547 if (le16_to_cpu(mbxstat->status) == CS_COMPLETE) {
548 DEBUG14(printk("scsi(%ld): Adisc IOCB -- marking "
549 "[%x/%02x%02x%02x] online.\n", ha->host_no,
550 remote_fcport->loop_id, remote_fcport->d_id.b.domain,
551 remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa));
552
553 atomic_set(&remote_fcport->state, FCS_ONLINE);
554 } else {
555 DEBUG14(printk("scsi(%ld): Adisc IOCB -- marking "
556 "[%x/%02x%02x%02x] lost, status=%x mb0=%x.\n", ha->host_no,
557 remote_fcport->loop_id, remote_fcport->d_id.b.domain,
558 remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa,
559 le16_to_cpu(mbxstat->status), le16_to_cpu(mbxstat->mb0)));
560
561 if (atomic_read(&remote_fcport->state) != FCS_DEVICE_DEAD)
562 atomic_set(&remote_fcport->state, FCS_DEVICE_LOST);
563 }
564 remote_fcport->iodesc_idx_sent = IODESC_INVALID_INDEX;
565
566 return (QLA_SUCCESS);
567}
568
569
570/**
571 * qla2x00_send_logout_iocb() - Issue a fabric port logout IOCB to the firmware.
572 * @ha: HA context
573 * @iodesc: io descriptor
574 * @ha_locked: is function called with the hardware lock
575 *
576 * Returns QLA_SUCCESS if the IOCB was issued.
577 */
578static int
579qla2x00_send_logout_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
580 int ha_locked)
581{
582 unsigned long flags = 0;
583 struct mbx_entry *mbxentry;
584
585 /* Send marker if required. */
586 if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS)
587 return (QLA_FUNCTION_FAILED);
588
589 if (!ha_locked)
590 spin_lock_irqsave(&ha->hardware_lock, flags);
591
592 /* Build fabric port logout mailbox IOCB. */
593 mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature);
594 if (mbxentry == NULL) {
595 if (!ha_locked)
596 spin_unlock_irqrestore(&ha->hardware_lock, flags);
597
598 return (QLA_FUNCTION_FAILED);
599 }
600 mbxentry->mb0 = __constant_cpu_to_le16(MBC_LOGOUT_FABRIC_PORT);
601 mbxentry->mb1 = mbxentry->loop_id.extended =
602 cpu_to_le16(iodesc->remote_fcport->loop_id);
603 wmb();
604
605 qla2x00_add_iodesc_timer(iodesc);
606
607 /* Issue command to ISP. */
608 qla2x00_isp_cmd(ha);
609
610 if (!ha_locked)
611 spin_unlock_irqrestore(&ha->hardware_lock, flags);
612
613 DEBUG14(printk("scsi(%ld): Sending Logout IOCB (%08x) to [%x].\n",
614 ha->host_no, iodesc->signature, iodesc->remote_fcport->loop_id));
615
616 return (QLA_SUCCESS);
617}
618
619/**
620 * qla2x00_send_logout_iocb_cb() - Fabric port logout IOCB callback.
621 * @ha: HA context
622 * @iodesc: io descriptor
623 * @mbxstat: mailbox status IOCB
624 *
625 * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc
626 * will be used for a retry.
627 */
628static int
629qla2x00_send_logout_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
630 struct mbx_entry *mbxstat)
631{
632 DEBUG14(printk("scsi(%ld): Logout IOCB -- sent to [%x/%02x%02x%02x], "
633 "status=%x mb0=%x mb1=%x.\n", ha->host_no,
634 iodesc->remote_fcport->loop_id,
635 iodesc->remote_fcport->d_id.b.domain,
636 iodesc->remote_fcport->d_id.b.area,
637 iodesc->remote_fcport->d_id.b.al_pa, le16_to_cpu(mbxstat->status),
638 le16_to_cpu(mbxstat->mb0), le16_to_cpu(mbxstat->mb1)));
639
640 return (QLA_SUCCESS);
641}
642
643
644/**
645 * qla2x00_send_login_iocb() - Issue a fabric port login IOCB to the firmware.
646 * @ha: HA context
647 * @iodesc: io descriptor
648 * @d_id: port id for device
649 * @ha_locked: is function called with the hardware lock
650 *
651 * Returns QLA_SUCCESS if the IOCB was issued.
652 */
653static int
654qla2x00_send_login_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
655 port_id_t *d_id, int ha_locked)
656{
657 unsigned long flags = 0;
658 struct mbx_entry *mbxentry;
659
660 /* Send marker if required. */
661 if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS)
662 return (QLA_FUNCTION_FAILED);
663
664 if (!ha_locked)
665 spin_lock_irqsave(&ha->hardware_lock, flags);
666
667 /* Build fabric port login mailbox IOCB. */
668 mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature);
669 if (mbxentry == NULL) {
670 if (!ha_locked)
671 spin_unlock_irqrestore(&ha->hardware_lock, flags);
672
673 return (QLA_FUNCTION_FAILED);
674 }
675 mbxentry->mb0 = __constant_cpu_to_le16(MBC_LOGIN_FABRIC_PORT);
676 mbxentry->mb1 = mbxentry->loop_id.extended =
677 cpu_to_le16(iodesc->remote_fcport->loop_id);
678 mbxentry->mb2 = cpu_to_le16(d_id->b.domain);
679 mbxentry->mb3 = cpu_to_le16(d_id->b.area << 8 | d_id->b.al_pa);
680 mbxentry->mb10 = __constant_cpu_to_le16(BIT_0);
681 wmb();
682
683 qla2x00_add_iodesc_timer(iodesc);
684
685 /* Issue command to ISP. */
686 qla2x00_isp_cmd(ha);
687
688 if (!ha_locked)
689 spin_unlock_irqrestore(&ha->hardware_lock, flags);
690
691 DEBUG14(printk("scsi(%ld): Sending Login IOCB (%08x) to "
692 "[%x/%02x%02x%02x].\n", ha->host_no, iodesc->signature,
693 iodesc->remote_fcport->loop_id, d_id->b.domain, d_id->b.area,
694 d_id->b.al_pa));
695
696 return (QLA_SUCCESS);
697}
698
699/**
700 * qla2x00_send_login_iocb_cb() - Fabric port logout IOCB callback.
701 * @ha: HA context
702 * @iodesc: io descriptor
703 * @mbxstat: mailbox status IOCB
704 *
705 * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc
706 * will be used for a retry.
707 */
708static int
709qla2x00_send_login_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
710 struct mbx_entry *mbxstat)
711{
712 int rval;
713 fc_port_t *fcport, *remote_fcport, *exist_fcport;
714 struct io_descriptor *abort_iodesc, *login_iodesc;
715 uint16_t status, mb[8];
716 uint16_t reuse;
717 uint16_t remote_loopid;
718 port_id_t remote_did, inuse_did;
719
720 remote_fcport = iodesc->remote_fcport;
721
722 /* Only process the last command. */
723 if (remote_fcport->iodesc_idx_sent != iodesc->idx) {
724 DEBUG14(printk("scsi(%ld): Login IOCB -- ignoring, sent to "
fa2a1ce5 725 "[%02x%02x%02x], expected %x, received %x.\n",
1da177e4
LT
726 ha->host_no, iodesc->d_id.b.domain, iodesc->d_id.b.area,
727 iodesc->d_id.b.al_pa, remote_fcport->iodesc_idx_sent,
728 iodesc->idx));
729
730 /* Free RSCN fcport resources. */
731 if (remote_fcport->port_type == FCT_RSCN) {
732 DEBUG14(printk("scsi(%ld): Login IOCB -- Freeing RSCN "
733 "fcport %p [%x/%02x%02x%02x] given ignored Login "
734 "IOCB.\n", ha->host_no, remote_fcport,
735 remote_fcport->loop_id,
736 remote_fcport->d_id.b.domain,
737 remote_fcport->d_id.b.area,
738 remote_fcport->d_id.b.al_pa));
739
740 list_del(&remote_fcport->list);
741 kfree(remote_fcport);
742 }
743 return (QLA_SUCCESS);
744 }
745
746 status = le16_to_cpu(mbxstat->status);
747 mb[0] = le16_to_cpu(mbxstat->mb0);
748 mb[1] = le16_to_cpu(mbxstat->mb1);
749 mb[2] = le16_to_cpu(mbxstat->mb2);
750 mb[6] = le16_to_cpu(mbxstat->mb6);
751 mb[7] = le16_to_cpu(mbxstat->mb7);
752
753 /* Good status? */
754 if ((status == CS_COMPLETE || status == CS_COMPLETE_CHKCOND) &&
755 mb[0] == MBS_COMMAND_COMPLETE) {
756
757 DEBUG14(printk("scsi(%ld): Login IOCB -- status=%x mb1=%x pn="
758 "%02x%02x%02x%02x%02x%02x%02x%02x.\n", ha->host_no, status,
fa2a1ce5
AV
759 mb[1], mbxstat->port_name[0], mbxstat->port_name[1],
760 mbxstat->port_name[2], mbxstat->port_name[3],
761 mbxstat->port_name[4], mbxstat->port_name[5],
1da177e4
LT
762 mbxstat->port_name[6], mbxstat->port_name[7]));
763
764 memcpy(remote_fcport->node_name, mbxstat->node_name, WWN_SIZE);
765 memcpy(remote_fcport->port_name, mbxstat->port_name, WWN_SIZE);
766
767 /* Is the device already in our fcports list? */
768 if (remote_fcport->port_type != FCT_RSCN) {
769 DEBUG14(printk("scsi(%ld): Login IOCB -- marking "
770 "[%x/%02x%02x%02x] online.\n", ha->host_no,
771 remote_fcport->loop_id,
772 remote_fcport->d_id.b.domain,
773 remote_fcport->d_id.b.area,
774 remote_fcport->d_id.b.al_pa));
775
776 qla2x00_update_login_fcport(ha, mbxstat, remote_fcport);
777
778 return (QLA_SUCCESS);
779 }
780
781 /* Does the RSCN portname already exist in our fcports list? */
782 exist_fcport = NULL;
783 list_for_each_entry(fcport, &ha->fcports, list) {
784 if (memcmp(remote_fcport->port_name, fcport->port_name,
785 WWN_SIZE) == 0) {
786 exist_fcport = fcport;
787 break;
788 }
789 }
790 if (exist_fcport != NULL) {
791 DEBUG14(printk("scsi(%ld): Login IOCB -- found RSCN "
792 "fcport in fcports list [%p].\n", ha->host_no,
793 exist_fcport));
794
795 /* Abort any ADISC that could have been sent. */
796 if (exist_fcport->iodesc_idx_sent != iodesc->idx &&
797 exist_fcport->iodesc_idx_sent <
798 MAX_IO_DESCRIPTORS &&
799 ha->io_descriptors[exist_fcport->iodesc_idx_sent].
800 cb_idx == ADISC_PORT_IOCB_CB) {
801
802 abort_iodesc = qla2x00_alloc_iodesc(ha);
803 if (abort_iodesc) {
804 DEBUG14(printk("scsi(%ld): Login IOCB "
805 "-- issuing abort to outstanding "
806 "Adisc [%x/%02x%02x%02x].\n",
807 ha->host_no, remote_fcport->loop_id,
808 exist_fcport->d_id.b.domain,
809 exist_fcport->d_id.b.area,
810 exist_fcport->d_id.b.al_pa));
811
812 abort_iodesc->cb_idx = ABORT_IOCB_CB;
813 abort_iodesc->d_id.b24 =
814 exist_fcport->d_id.b24;
815 abort_iodesc->remote_fcport =
816 exist_fcport;
817 exist_fcport->iodesc_idx_sent =
818 abort_iodesc->idx;
819 qla2x00_send_abort_iocb(ha,
820 abort_iodesc, ha->io_descriptors[
821 exist_fcport->iodesc_idx_sent].
822 signature, 1);
823 } else {
824 DEBUG14(printk("scsi(%ld): Login IOCB "
825 "-- unable to abort outstanding "
826 "Adisc [%x/%02x%02x%02x].\n",
827 ha->host_no, remote_fcport->loop_id,
828 exist_fcport->d_id.b.domain,
829 exist_fcport->d_id.b.area,
830 exist_fcport->d_id.b.al_pa));
831 }
832 }
833
834 /*
835 * If the existing fcport is waiting to send an ADISC
836 * or LOGIN, then reuse remote fcport (RSCN) to
837 * continue waiting.
838 */
839 reuse = 0;
840 remote_loopid = remote_fcport->loop_id;
841 remote_did.b24 = remote_fcport->d_id.b24;
842 if (exist_fcport->iodesc_idx_sent ==
843 IODESC_ADISC_NEEDED ||
844 exist_fcport->iodesc_idx_sent ==
845 IODESC_LOGIN_NEEDED) {
846 DEBUG14(printk("scsi(%ld): Login IOCB -- "
847 "existing fcport [%x/%02x%02x%02x] "
848 "waiting for IO descriptor, reuse RSCN "
849 "fcport.\n", ha->host_no,
850 exist_fcport->loop_id,
851 exist_fcport->d_id.b.domain,
852 exist_fcport->d_id.b.area,
853 exist_fcport->d_id.b.al_pa));
854
855 reuse++;
856 remote_fcport->iodesc_idx_sent =
857 exist_fcport->iodesc_idx_sent;
858 exist_fcport->iodesc_idx_sent =
859 IODESC_INVALID_INDEX;
860 remote_fcport->loop_id = exist_fcport->loop_id;
861 remote_fcport->d_id.b24 =
862 exist_fcport->d_id.b24;
863 }
864
865 /* Logout the old loopid. */
866 if (!reuse &&
867 exist_fcport->loop_id != remote_fcport->loop_id &&
868 exist_fcport->loop_id != FC_NO_LOOP_ID) {
869 login_iodesc = qla2x00_alloc_iodesc(ha);
870 if (login_iodesc) {
871 DEBUG14(printk("scsi(%ld): Login IOCB "
872 "-- issuing logout to free old "
873 "loop id [%x/%02x%02x%02x].\n",
874 ha->host_no, exist_fcport->loop_id,
875 exist_fcport->d_id.b.domain,
876 exist_fcport->d_id.b.area,
877 exist_fcport->d_id.b.al_pa));
878
879 login_iodesc->cb_idx =
880 LOGOUT_PORT_IOCB_CB;
881 login_iodesc->d_id.b24 =
882 exist_fcport->d_id.b24;
883 login_iodesc->remote_fcport =
884 exist_fcport;
885 exist_fcport->iodesc_idx_sent =
886 login_iodesc->idx;
887 qla2x00_send_logout_iocb(ha,
888 login_iodesc, 1);
889 } else {
890 /* Ran out of IO descriptiors. */
891 DEBUG14(printk("scsi(%ld): Login IOCB "
892 "-- unable to logout to free old "
893 "loop id [%x/%02x%02x%02x].\n",
894 ha->host_no, exist_fcport->loop_id,
895 exist_fcport->d_id.b.domain,
896 exist_fcport->d_id.b.area,
897 exist_fcport->d_id.b.al_pa));
898
899 exist_fcport->iodesc_idx_sent =
900 IODESC_INVALID_INDEX;
901 }
902
903 }
904
905 /* Update existing fcport with remote fcport info. */
906 DEBUG14(printk("scsi(%ld): Login IOCB -- marking "
907 "existing fcport [%x/%02x%02x%02x] online.\n",
908 ha->host_no, remote_loopid, remote_did.b.domain,
909 remote_did.b.area, remote_did.b.al_pa));
910
911 memcpy(exist_fcport->node_name,
912 remote_fcport->node_name, WWN_SIZE);
913 exist_fcport->loop_id = remote_loopid;
914 exist_fcport->d_id.b24 = remote_did.b24;
915 qla2x00_update_login_fcport(ha, mbxstat, exist_fcport);
916
917 /* Finally, free the remote (RSCN) fcport. */
918 if (!reuse) {
919 DEBUG14(printk("scsi(%ld): Login IOCB -- "
920 "Freeing RSCN fcport %p "
921 "[%x/%02x%02x%02x].\n", ha->host_no,
922 remote_fcport, remote_fcport->loop_id,
923 remote_fcport->d_id.b.domain,
924 remote_fcport->d_id.b.area,
925 remote_fcport->d_id.b.al_pa));
926
927 list_del(&remote_fcport->list);
928 kfree(remote_fcport);
929 }
930
931 return (QLA_SUCCESS);
932 }
933
934 /*
935 * A new device has been added, move the RSCN fcport to our
936 * fcports list.
937 */
938 DEBUG14(printk("scsi(%ld): Login IOCB -- adding RSCN fcport "
939 "[%x/%02x%02x%02x] to fcports list.\n", ha->host_no,
940 remote_fcport->loop_id, remote_fcport->d_id.b.domain,
941 remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa));
942
943 list_del(&remote_fcport->list);
944 remote_fcport->flags = (FCF_RLC_SUPPORT | FCF_RESCAN_NEEDED);
945 qla2x00_update_login_fcport(ha, mbxstat, remote_fcport);
946 list_add_tail(&remote_fcport->list, &ha->fcports);
947 set_bit(FCPORT_RESCAN_NEEDED, &ha->dpc_flags);
948 } else {
949 /* Handle login failure. */
950 if (remote_fcport->login_retry != 0) {
951 if (mb[0] == MBS_LOOP_ID_USED) {
952 inuse_did.b.domain = LSB(mb[1]);
953 inuse_did.b.area = MSB(mb[2]);
954 inuse_did.b.al_pa = LSB(mb[2]);
955
956 DEBUG14(printk("scsi(%ld): Login IOCB -- loop "
957 "id [%x] used by port id [%02x%02x%02x].\n",
958 ha->host_no, remote_fcport->loop_id,
959 inuse_did.b.domain, inuse_did.b.area,
960 inuse_did.b.al_pa));
961
962 if (remote_fcport->d_id.b24 ==
963 INVALID_PORT_ID) {
964 /*
965 * Invalid port id means we are trying
966 * to login to a remote port with just
967 * a loop id without knowing about the
968 * port id. Copy the port id and try
969 * again.
970 */
971 remote_fcport->d_id.b24 = inuse_did.b24;
972 iodesc->d_id.b24 = inuse_did.b24;
973 } else {
974 remote_fcport->loop_id++;
975 rval = qla2x00_find_new_loop_id(ha,
976 remote_fcport);
977 if (rval == QLA_FUNCTION_FAILED) {
978 /* No more loop ids. */
979 return (QLA_SUCCESS);
980 }
981 }
982 } else if (mb[0] == MBS_PORT_ID_USED) {
983 /*
984 * Device has another loop ID. The firmware
985 * group recommends the driver perform an
986 * implicit login with the specified ID.
987 */
988 DEBUG14(printk("scsi(%ld): Login IOCB -- port "
989 "id [%02x%02x%02x] already assigned to "
990 "loop id [%x].\n", ha->host_no,
991 iodesc->d_id.b.domain, iodesc->d_id.b.area,
992 iodesc->d_id.b.al_pa, mb[1]));
993
994 remote_fcport->loop_id = mb[1];
995
996 } else {
997 /* Unable to perform login, try again. */
998 DEBUG14(printk("scsi(%ld): Login IOCB -- "
999 "failed login [%x/%02x%02x%02x], status=%x "
1000 "mb0=%x mb1=%x mb2=%x mb6=%x mb7=%x.\n",
1001 ha->host_no, remote_fcport->loop_id,
1002 iodesc->d_id.b.domain, iodesc->d_id.b.area,
1003 iodesc->d_id.b.al_pa, status, mb[0], mb[1],
1004 mb[2], mb[6], mb[7]));
1005 }
1006
1007 /* Reissue Login with the same IO descriptor. */
1008 iodesc->signature =
1009 qla2x00_iodesc_to_handle(iodesc);
1010 iodesc->cb_idx = LOGIN_PORT_IOCB_CB;
1011 iodesc->d_id.b24 = remote_fcport->d_id.b24;
1012 remote_fcport->iodesc_idx_sent = iodesc->idx;
1013 remote_fcport->login_retry--;
1014
1015 DEBUG14(printk("scsi(%ld): Login IOCB -- retrying "
1016 "login to [%x/%02x%02x%02x] (%d).\n", ha->host_no,
1017 remote_fcport->loop_id,
1018 remote_fcport->d_id.b.domain,
1019 remote_fcport->d_id.b.area,
1020 remote_fcport->d_id.b.al_pa,
1021 remote_fcport->login_retry));
1022
1023 qla2x00_send_login_iocb(ha, iodesc,
1024 &remote_fcport->d_id, 1);
1025
1026 return (QLA_FUNCTION_FAILED);
1027 } else {
1028 /* No more logins, mark device dead. */
1029 DEBUG14(printk("scsi(%ld): Login IOCB -- failed "
1030 "login [%x/%02x%02x%02x] after retries, status=%x "
1031 "mb0=%x mb1=%x mb2=%x mb6=%x mb7=%x.\n",
1032 ha->host_no, remote_fcport->loop_id,
1033 iodesc->d_id.b.domain, iodesc->d_id.b.area,
1034 iodesc->d_id.b.al_pa, status, mb[0], mb[1],
1035 mb[2], mb[6], mb[7]));
1036
1037 atomic_set(&remote_fcport->state, FCS_DEVICE_DEAD);
1038 if (remote_fcport->port_type == FCT_RSCN) {
1039 DEBUG14(printk("scsi(%ld): Login IOCB -- "
1040 "Freeing dead RSCN fcport %p "
1041 "[%x/%02x%02x%02x].\n", ha->host_no,
1042 remote_fcport, remote_fcport->loop_id,
1043 remote_fcport->d_id.b.domain,
1044 remote_fcport->d_id.b.area,
1045 remote_fcport->d_id.b.al_pa));
1046
1047 list_del(&remote_fcport->list);
1048 kfree(remote_fcport);
1049 }
1050 }
1051 }
1052
1053 return (QLA_SUCCESS);
1054}
1055
1056
fa2a1ce5 1057/**
1da177e4
LT
1058 * IO descriptor processing routines.
1059 **/
1060
1061/**
1062 * qla2x00_alloc_rscn_fcport() - Allocate an RSCN type fcport.
1063 * @ha: HA context
1064 * @flags: allocation flags
1065 *
1066 * Returns a pointer to the allocated RSCN fcport, or NULL, if none available.
1067 */
1068fc_port_t *
c53033f6 1069qla2x00_alloc_rscn_fcport(scsi_qla_host_t *ha, gfp_t flags)
1da177e4
LT
1070{
1071 fc_port_t *fcport;
1072
1073 fcport = qla2x00_alloc_fcport(ha, flags);
1074 if (fcport == NULL)
1075 return (fcport);
1076
1077 /* Setup RSCN fcport structure. */
1078 fcport->port_type = FCT_RSCN;
1079
1080 return (fcport);
1081}
1082
1083/**
1084 * qla2x00_handle_port_rscn() - Handle port RSCN.
1085 * @ha: HA context
1086 * @rscn_entry: RSCN entry
1087 * @fcport: fcport entry to updated
1088 *
1089 * Returns QLA_SUCCESS if the port RSCN was handled.
1090 */
1091int
1092qla2x00_handle_port_rscn(scsi_qla_host_t *ha, uint32_t rscn_entry,
1093 fc_port_t *known_fcport, int ha_locked)
1094{
1095 int rval;
1096 port_id_t rscn_pid;
1097 fc_port_t *fcport, *remote_fcport, *rscn_fcport;
1098 struct io_descriptor *iodesc;
1099
1100 remote_fcport = NULL;
1101 rscn_fcport = NULL;
1102
1103 /* Prepare port id based on incoming entries. */
1104 if (known_fcport) {
1105 rscn_pid.b24 = known_fcport->d_id.b24;
1106 remote_fcport = known_fcport;
1107
1108 DEBUG14(printk("scsi(%ld): Handle RSCN -- process RSCN for "
1109 "fcport [%02x%02x%02x].\n", ha->host_no,
1110 remote_fcport->d_id.b.domain, remote_fcport->d_id.b.area,
1111 remote_fcport->d_id.b.al_pa));
1112 } else {
1113 rscn_pid.b.domain = LSB(MSW(rscn_entry));
1114 rscn_pid.b.area = MSB(LSW(rscn_entry));
1115 rscn_pid.b.al_pa = LSB(LSW(rscn_entry));
1116
1117 DEBUG14(printk("scsi(%ld): Handle RSCN -- process RSCN for "
1118 "port id [%02x%02x%02x].\n", ha->host_no,
1119 rscn_pid.b.domain, rscn_pid.b.area, rscn_pid.b.al_pa));
1120
1121 /*
1122 * Search fcport lists for a known entry at the specified port
1123 * ID.
1124 */
1125 list_for_each_entry(fcport, &ha->fcports, list) {
1126 if (rscn_pid.b24 == fcport->d_id.b24) {
1127 remote_fcport = fcport;
1128 break;
1129 }
1130 }
1131 list_for_each_entry(fcport, &ha->rscn_fcports, list) {
1132 if (rscn_pid.b24 == fcport->d_id.b24) {
1133 rscn_fcport = fcport;
1134 break;
1135 }
1136 }
1137 if (remote_fcport == NULL)
1138 remote_fcport = rscn_fcport;
1139 }
1140
fa2a1ce5 1141 /*
1da177e4
LT
1142 * If the port is already in our fcport list and online, send an ADISC
1143 * to see if it's still alive. Issue login if a new fcport or the known
1144 * fcport is currently offline.
1145 */
1146 if (remote_fcport) {
1147 /*
1148 * No need to send request if the remote fcport is currently
1149 * waiting for an available io descriptor.
1150 */
1151 if (known_fcport == NULL &&
1152 (remote_fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED ||
1153 remote_fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED)) {
1154 /*
1155 * If previous waiting io descriptor is an ADISC, then
1156 * the new RSCN may come from a new remote fcport being
1157 * plugged into the same location.
1158 */
1159 if (remote_fcport->port_type == FCT_RSCN) {
1160 remote_fcport->iodesc_idx_sent =
1161 IODESC_LOGIN_NEEDED;
1162 } else if (remote_fcport->iodesc_idx_sent ==
1163 IODESC_ADISC_NEEDED) {
1164 fc_port_t *new_fcport;
1165
1166 remote_fcport->iodesc_idx_sent =
1167 IODESC_INVALID_INDEX;
1168
1169 /* Create new fcport for later login. */
1170 new_fcport = qla2x00_alloc_rscn_fcport(ha,
1171 ha_locked ? GFP_ATOMIC: GFP_KERNEL);
1172 if (new_fcport) {
1173 DEBUG14(printk("scsi(%ld): Handle RSCN "
1174 "-- creating RSCN fcport %p for "
1175 "future login.\n", ha->host_no,
1176 new_fcport));
1177
1178 new_fcport->d_id.b24 =
1179 remote_fcport->d_id.b24;
1180 new_fcport->iodesc_idx_sent =
1181 IODESC_LOGIN_NEEDED;
1182
1183 list_add_tail(&new_fcport->list,
1184 &ha->rscn_fcports);
1185 set_bit(IODESC_PROCESS_NEEDED,
1186 &ha->dpc_flags);
1187 } else {
1188 DEBUG14(printk("scsi(%ld): Handle RSCN "
1189 "-- unable to allocate RSCN fcport "
1190 "for future login.\n",
1191 ha->host_no));
1192 }
1193 }
1194 return (QLA_SUCCESS);
1195 }
fa2a1ce5 1196
1da177e4
LT
1197 /* Send ADISC if the fcport is online */
1198 if (atomic_read(&remote_fcport->state) == FCS_ONLINE ||
1199 remote_fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED) {
1200
1201 atomic_set(&remote_fcport->state, FCS_DEVICE_LOST);
1202
1203 iodesc = qla2x00_alloc_iodesc(ha);
1204 if (iodesc == NULL) {
1205 /* Mark fcport for later adisc processing */
1206 DEBUG14(printk("scsi(%ld): Handle RSCN -- not "
1207 "enough IO descriptors for Adisc, flag "
1208 "for later processing.\n", ha->host_no));
1209
1210 remote_fcport->iodesc_idx_sent =
1211 IODESC_ADISC_NEEDED;
1212 set_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags);
1213
1214 return (QLA_SUCCESS);
1215 }
1216
1217 iodesc->cb_idx = ADISC_PORT_IOCB_CB;
1218 iodesc->d_id.b24 = rscn_pid.b24;
1219 iodesc->remote_fcport = remote_fcport;
1220 remote_fcport->iodesc_idx_sent = iodesc->idx;
1221 qla2x00_send_adisc_iocb(ha, iodesc, ha_locked);
1222
1223 return (QLA_SUCCESS);
1224 } else if (remote_fcport->iodesc_idx_sent <
1225 MAX_IO_DESCRIPTORS &&
1226 ha->io_descriptors[remote_fcport->iodesc_idx_sent].cb_idx ==
1227 ADISC_PORT_IOCB_CB) {
1228 /*
1229 * Receiving another RSCN while an ADISC is pending,
1230 * abort the IOCB. Use the same descriptor for the
1231 * abort.
1232 */
1233 uint32_t handle_to_abort;
fa2a1ce5 1234
1da177e4
LT
1235 iodesc = &ha->io_descriptors[
1236 remote_fcport->iodesc_idx_sent];
1237 qla2x00_remove_iodesc_timer(iodesc);
1238 handle_to_abort = iodesc->signature;
1239 iodesc->signature = qla2x00_iodesc_to_handle(iodesc);
1240 iodesc->cb_idx = ABORT_IOCB_CB;
1241 iodesc->d_id.b24 = remote_fcport->d_id.b24;
1242 iodesc->remote_fcport = remote_fcport;
1243 remote_fcport->iodesc_idx_sent = iodesc->idx;
1244
1245 DEBUG14(printk("scsi(%ld): Handle RSCN -- issuing "
1246 "abort to outstanding Adisc [%x/%02x%02x%02x].\n",
1247 ha->host_no, remote_fcport->loop_id,
1248 iodesc->d_id.b.domain, iodesc->d_id.b.area,
1249 iodesc->d_id.b.al_pa));
1250
1251 qla2x00_send_abort_iocb(ha, iodesc, handle_to_abort,
1252 ha_locked);
1253 }
1254 }
1255
1256 /* We need to login to the remote port, find it. */
1257 if (known_fcport) {
1258 remote_fcport = known_fcport;
1259 } else if (rscn_fcport && rscn_fcport->d_id.b24 != INVALID_PORT_ID &&
1260 rscn_fcport->iodesc_idx_sent < MAX_IO_DESCRIPTORS &&
1261 ha->io_descriptors[rscn_fcport->iodesc_idx_sent].cb_idx ==
1262 LOGIN_PORT_IOCB_CB) {
1263 /*
1264 * Ignore duplicate RSCN on fcport which has already
1265 * initiated a login IOCB.
1266 */
1267 DEBUG14(printk("scsi(%ld): Handle RSCN -- ignoring, login "
1268 "already sent to [%02x%02x%02x].\n", ha->host_no,
1269 rscn_fcport->d_id.b.domain, rscn_fcport->d_id.b.area,
1270 rscn_fcport->d_id.b.al_pa));
1271
1272 return (QLA_SUCCESS);
1273 } else if (rscn_fcport && rscn_fcport->d_id.b24 != INVALID_PORT_ID &&
1274 rscn_fcport != remote_fcport) {
1275 /* Reuse same rscn fcport. */
1276 DEBUG14(printk("scsi(%ld): Handle RSCN -- reusing RSCN fcport "
1277 "[%02x%02x%02x].\n", ha->host_no,
1278 rscn_fcport->d_id.b.domain, rscn_fcport->d_id.b.area,
1279 rscn_fcport->d_id.b.al_pa));
1280
1281 remote_fcport = rscn_fcport;
1282 } else {
1283 /* Create new fcport for later login. */
1284 remote_fcport = qla2x00_alloc_rscn_fcport(ha,
1285 ha_locked ? GFP_ATOMIC: GFP_KERNEL);
1286 list_add_tail(&remote_fcport->list, &ha->rscn_fcports);
1287 }
1288 if (remote_fcport == NULL)
1289 return (QLA_SUCCESS);
1290
1291 /* Prepare fcport for login. */
1292 atomic_set(&remote_fcport->state, FCS_DEVICE_LOST);
1293 remote_fcport->login_retry = 3; /* ha->login_retry_count; */
1294 remote_fcport->d_id.b24 = rscn_pid.b24;
1295
1296 iodesc = qla2x00_alloc_iodesc(ha);
1297 if (iodesc == NULL) {
1298 /* Mark fcport for later adisc processing. */
1299 DEBUG14(printk("scsi(%ld): Handle RSCN -- not enough IO "
1300 "descriptors for Login, flag for later processing.\n",
1301 ha->host_no));
1302
1303 remote_fcport->iodesc_idx_sent = IODESC_LOGIN_NEEDED;
1304 set_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags);
1305
1306 return (QLA_SUCCESS);
1307 }
1308
1309 if (known_fcport == NULL || rscn_pid.b24 != INVALID_PORT_ID) {
1310 remote_fcport->loop_id = ha->min_external_loopid;
1311
1312 rval = qla2x00_find_new_loop_id(ha, remote_fcport);
1313 if (rval == QLA_FUNCTION_FAILED) {
1314 /* No more loop ids, failed. */
1315 DEBUG14(printk("scsi(%ld): Handle RSCN -- no available "
1316 "loop id to perform Login, failed.\n",
1317 ha->host_no));
1318
1319 return (rval);
1320 }
1321 }
1322
1323 iodesc->cb_idx = LOGIN_PORT_IOCB_CB;
1324 iodesc->d_id.b24 = rscn_pid.b24;
1325 iodesc->remote_fcport = remote_fcport;
1326 remote_fcport->iodesc_idx_sent = iodesc->idx;
1327
1328 DEBUG14(printk("scsi(%ld): Handle RSCN -- attempting login to "
1329 "[%x/%02x%02x%02x].\n", ha->host_no, remote_fcport->loop_id,
1330 iodesc->d_id.b.domain, iodesc->d_id.b.area, iodesc->d_id.b.al_pa));
1331
1332 qla2x00_send_login_iocb(ha, iodesc, &rscn_pid, ha_locked);
1333
1334 return (QLA_SUCCESS);
1335}
1336
1337/**
1338 * qla2x00_process_iodesc() - Complete IO descriptor processing.
1339 * @ha: HA context
1340 * @mbxstat: Mailbox IOCB status
1341 */
1342void
1343qla2x00_process_iodesc(scsi_qla_host_t *ha, struct mbx_entry *mbxstat)
1344{
1345 int rval;
1346 uint32_t signature;
1347 fc_port_t *fcport;
1348 struct io_descriptor *iodesc;
1349
1350 signature = mbxstat->handle;
1351
1352 DEBUG14(printk("scsi(%ld): Process IODesc -- processing %08x.\n",
1353 ha->host_no, signature));
1354
1355 /* Retrieve proper IO descriptor. */
1356 iodesc = qla2x00_handle_to_iodesc(ha, signature);
1357 if (iodesc == NULL) {
1358 DEBUG14(printk("scsi(%ld): Process IODesc -- ignoring, "
1359 "incorrect signature %08x.\n", ha->host_no, signature));
1360
1361 return;
1362 }
1363
1364 /* Stop IO descriptor timer. */
1365 qla2x00_remove_iodesc_timer(iodesc);
1366
1367 /* Verify signature match. */
1368 if (iodesc->signature != signature) {
1369 DEBUG14(printk("scsi(%ld): Process IODesc -- ignoring, "
1370 "signature mismatch, sent %08x, received %08x.\n",
1371 ha->host_no, iodesc->signature, signature));
1372
1373 return;
1374 }
1375
1376 /* Go with IOCB callback. */
1377 rval = iocb_function_cb_list[iodesc->cb_idx](ha, iodesc, mbxstat);
1378 if (rval != QLA_SUCCESS) {
1379 /* IO descriptor reused by callback. */
1380 return;
1381 }
1382
1383 qla2x00_free_iodesc(iodesc);
1384
1385 if (test_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags)) {
1386 /* Scan our fcports list for any RSCN requests. */
1387 list_for_each_entry(fcport, &ha->fcports, list) {
1388 if (fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED ||
1389 fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED) {
1390 qla2x00_handle_port_rscn(ha, 0, fcport, 1);
1391 return;
1392 }
1393 }
1394
1395 /* Scan our RSCN fcports list for any RSCN requests. */
1396 list_for_each_entry(fcport, &ha->rscn_fcports, list) {
1397 if (fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED ||
1398 fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED) {
1399 qla2x00_handle_port_rscn(ha, 0, fcport, 1);
1400 return;
1401 }
1402 }
1403 }
1404 clear_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags);
1405}
1406
1407/**
1408 * qla2x00_cancel_io_descriptors() - Cancel all outstanding io descriptors.
1409 * @ha: HA context
1410 *
1411 * This routine will also delete any RSCN entries related to the outstanding
1412 * IO descriptors.
1413 */
1414void
1415qla2x00_cancel_io_descriptors(scsi_qla_host_t *ha)
1416{
1417 fc_port_t *fcport, *fcptemp;
1418
1419 clear_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags);
1420
1421 /* Abort all IO descriptors. */
1422 qla2x00_init_io_descriptors(ha);
1423
1424 /* Reset all pending IO descriptors in fcports list. */
1425 list_for_each_entry(fcport, &ha->fcports, list) {
1426 fcport->iodesc_idx_sent = IODESC_INVALID_INDEX;
1427 }
1428
1429 /* Reset all pending IO descriptors in rscn fcports list. */
1430 list_for_each_entry_safe(fcport, fcptemp, &ha->rscn_fcports, list) {
1431 DEBUG14(printk("scsi(%ld): Cancel IOs -- Freeing RSCN fcport "
1432 "%p [%x/%02x%02x%02x].\n", ha->host_no, fcport,
1433 fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
1434 fcport->d_id.b.al_pa));
1435
1436 list_del(&fcport->list);
1437 kfree(fcport);
1438 }
1439}
This page took 0.130041 seconds and 5 git commands to generate.