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