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.c1437
1 files changed, 1437 insertions, 0 deletions
diff --git a/drivers/scsi/qla2xxx/qla_rscn.c b/drivers/scsi/qla2xxx/qla_rscn.c
new file mode 100644
index 000000000000..fb545b50fc2f
--- /dev/null
+++ b/drivers/scsi/qla2xxx/qla_rscn.c
@@ -0,0 +1,1437 @@
1/*
2 * QLOGIC LINUX SOFTWARE
3 *
4 * QLogic ISP2x00 device driver for Linux 2.6.x
5 * Copyright (C) 2003-2004 QLogic Corporation
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
85/**
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
98/**
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
172/**
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
251/**
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
302/**
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);
333}
334
335
336/**
337 * Mailbox IOCB commands.
338 **/
339
340/**
341 * qla2x00_get_mbx_iocb_entry() - Retrieve an IOCB from the request queue.
342 * @ha: HA context
343 * @handle: handle to io descriptor
344 *
345 * Returns a pointer to the reqest entry, or NULL, if none were available.
346 */
347static inline struct mbx_entry *
348qla2x00_get_mbx_iocb_entry(scsi_qla_host_t *ha, uint32_t handle)
349{
350 uint16_t cnt;
351 device_reg_t __iomem *reg = ha->iobase;
352 struct mbx_entry *mbxentry;
353
354 mbxentry = NULL;
355
356 if (ha->req_q_cnt < 3) {
357 cnt = qla2x00_debounce_register(ISP_REQ_Q_OUT(ha, reg));
358 if (ha->req_ring_index < cnt)
359 ha->req_q_cnt = cnt - ha->req_ring_index;
360 else
361 ha->req_q_cnt = ha->request_q_length -
362 (ha->req_ring_index - cnt);
363 }
364 if (ha->req_q_cnt >= 3) {
365 mbxentry = (struct mbx_entry *)ha->request_ring_ptr;
366
367 memset(mbxentry, 0, sizeof(struct mbx_entry));
368 mbxentry->entry_type = MBX_IOCB_TYPE;
369 mbxentry->entry_count = 1;
370 mbxentry->sys_define1 = SOURCE_ASYNC_IOCB;
371 mbxentry->handle = handle;
372 }
373 return (mbxentry);
374}
375
376/**
377 * qla2x00_send_abort_iocb() - Issue an abort IOCB to the firmware.
378 * @ha: HA context
379 * @iodesc: io descriptor
380 * @handle_to_abort: firmware handle to abort
381 * @ha_locked: is function called with the hardware lock
382 *
383 * Returns QLA_SUCCESS if the IOCB was issued.
384 */
385static int
386qla2x00_send_abort_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
387 uint32_t handle_to_abort, int ha_locked)
388{
389 unsigned long flags = 0;
390 struct mbx_entry *mbxentry;
391
392 /* Send marker if required. */
393 if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS)
394 return (QLA_FUNCTION_FAILED);
395
396 if (!ha_locked)
397 spin_lock_irqsave(&ha->hardware_lock, flags);
398
399 /* Build abort mailbox IOCB. */
400 mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature);
401 if (mbxentry == NULL) {
402 if (!ha_locked)
403 spin_unlock_irqrestore(&ha->hardware_lock, flags);
404
405 return (QLA_FUNCTION_FAILED);
406 }
407 mbxentry->mb0 = __constant_cpu_to_le16(MBC_ABORT_COMMAND);
408 mbxentry->mb1 = mbxentry->loop_id.extended =
409 cpu_to_le16(iodesc->remote_fcport->loop_id);
410 mbxentry->mb2 = LSW(handle_to_abort);
411 mbxentry->mb3 = MSW(handle_to_abort);
412 wmb();
413
414 qla2x00_add_iodesc_timer(iodesc);
415
416 /* Issue command to ISP. */
417 qla2x00_isp_cmd(ha);
418
419 if (!ha_locked)
420 spin_unlock_irqrestore(&ha->hardware_lock, flags);
421
422 DEBUG14(printk("scsi(%ld): Sending Abort IOCB (%08x) to [%x], aborting "
423 "%08x.\n", ha->host_no, iodesc->signature,
424 iodesc->remote_fcport->loop_id, handle_to_abort));
425
426 return (QLA_SUCCESS);
427}
428
429/**
430 * qla2x00_send_abort_iocb_cb() - Abort IOCB callback.
431 * @ha: HA context
432 * @iodesc: io descriptor
433 * @mbxstat: mailbox status IOCB
434 *
435 * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc
436 * will be used for a retry.
437 */
438static int
439qla2x00_send_abort_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
440 struct mbx_entry *mbxstat)
441{
442 DEBUG14(printk("scsi(%ld): Abort IOCB -- sent to [%x/%02x%02x%02x], "
443 "status=%x mb0=%x.\n", ha->host_no, iodesc->remote_fcport->loop_id,
444 iodesc->d_id.b.domain, iodesc->d_id.b.area, iodesc->d_id.b.al_pa,
445 le16_to_cpu(mbxstat->status), le16_to_cpu(mbxstat->mb0)));
446
447 return (QLA_SUCCESS);
448}
449
450
451/**
452 * qla2x00_send_adisc_iocb() - Issue a Get Port Database IOCB to the firmware.
453 * @ha: HA context
454 * @iodesc: io descriptor
455 * @ha_locked: is function called with the hardware lock
456 *
457 * Returns QLA_SUCCESS if the IOCB was issued.
458 */
459static int
460qla2x00_send_adisc_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
461 int ha_locked)
462{
463 unsigned long flags = 0;
464 struct mbx_entry *mbxentry;
465
466 /* Send marker if required. */
467 if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS)
468 return (QLA_FUNCTION_FAILED);
469
470 if (!ha_locked)
471 spin_lock_irqsave(&ha->hardware_lock, flags);
472
473 /* Build Get Port Database IOCB. */
474 mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature);
475 if (mbxentry == NULL) {
476 if (!ha_locked)
477 spin_unlock_irqrestore(&ha->hardware_lock, flags);
478
479 return (QLA_FUNCTION_FAILED);
480 }
481 mbxentry->mb0 = __constant_cpu_to_le16(MBC_GET_PORT_DATABASE);
482 mbxentry->mb1 = mbxentry->loop_id.extended =
483 cpu_to_le16(iodesc->remote_fcport->loop_id);
484 mbxentry->mb2 = cpu_to_le16(MSW(LSD(ha->iodesc_pd_dma)));
485 mbxentry->mb3 = cpu_to_le16(LSW(LSD(ha->iodesc_pd_dma)));
486 mbxentry->mb6 = cpu_to_le16(MSW(MSD(ha->iodesc_pd_dma)));
487 mbxentry->mb7 = cpu_to_le16(LSW(MSD(ha->iodesc_pd_dma)));
488 mbxentry->mb10 = __constant_cpu_to_le16(BIT_0);
489 wmb();
490
491 qla2x00_add_iodesc_timer(iodesc);
492
493 /* Issue command to ISP. */
494 qla2x00_isp_cmd(ha);
495
496 if (!ha_locked)
497 spin_unlock_irqrestore(&ha->hardware_lock, flags);
498
499 DEBUG14(printk("scsi(%ld): Sending Adisc IOCB (%08x) to [%x].\n",
500 ha->host_no, iodesc->signature, iodesc->remote_fcport->loop_id));
501
502 return (QLA_SUCCESS);
503}
504
505/**
506 * qla2x00_send_adisc_iocb_cb() - Get Port Database IOCB callback.
507 * @ha: HA context
508 * @iodesc: io descriptor
509 * @mbxstat: mailbox status IOCB
510 *
511 * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc
512 * will be used for a retry.
513 */
514static int
515qla2x00_send_adisc_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
516 struct mbx_entry *mbxstat)
517{
518 fc_port_t *remote_fcport;
519
520 remote_fcport = iodesc->remote_fcport;
521
522 /* Ensure the port IDs are consistent. */
523 if (remote_fcport->d_id.b24 != iodesc->d_id.b24) {
524 DEBUG14(printk("scsi(%ld): Adisc IOCB -- ignoring, remote port "
525 "id changed from [%02x%02x%02x] to [%02x%02x%02x].\n",
526 ha->host_no, remote_fcport->d_id.b.domain,
527 remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa,
528 iodesc->d_id.b.domain, iodesc->d_id.b.area,
529 iodesc->d_id.b.al_pa));
530
531 return (QLA_SUCCESS);
532 }
533
534 /* Only process the last command. */
535 if (remote_fcport->iodesc_idx_sent != iodesc->idx) {
536 DEBUG14(printk("scsi(%ld): Adisc IOCB -- ignoring, sent to "
537 "[%02x%02x%02x], expected %x, received %x.\n", ha->host_no,
538 iodesc->d_id.b.domain, iodesc->d_id.b.area,
539 iodesc->d_id.b.al_pa, remote_fcport->iodesc_idx_sent,
540 iodesc->idx));
541
542 return (QLA_SUCCESS);
543 }
544
545 if (le16_to_cpu(mbxstat->status) == CS_COMPLETE) {
546 DEBUG14(printk("scsi(%ld): Adisc IOCB -- marking "
547 "[%x/%02x%02x%02x] online.\n", ha->host_no,
548 remote_fcport->loop_id, remote_fcport->d_id.b.domain,
549 remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa));
550
551 atomic_set(&remote_fcport->state, FCS_ONLINE);
552 } else {
553 DEBUG14(printk("scsi(%ld): Adisc IOCB -- marking "
554 "[%x/%02x%02x%02x] lost, status=%x mb0=%x.\n", ha->host_no,
555 remote_fcport->loop_id, remote_fcport->d_id.b.domain,
556 remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa,
557 le16_to_cpu(mbxstat->status), le16_to_cpu(mbxstat->mb0)));
558
559 if (atomic_read(&remote_fcport->state) != FCS_DEVICE_DEAD)
560 atomic_set(&remote_fcport->state, FCS_DEVICE_LOST);
561 }
562 remote_fcport->iodesc_idx_sent = IODESC_INVALID_INDEX;
563
564 return (QLA_SUCCESS);
565}
566
567
568/**
569 * qla2x00_send_logout_iocb() - Issue a fabric port logout IOCB to the firmware.
570 * @ha: HA context
571 * @iodesc: io descriptor
572 * @ha_locked: is function called with the hardware lock
573 *
574 * Returns QLA_SUCCESS if the IOCB was issued.
575 */
576static int
577qla2x00_send_logout_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
578 int ha_locked)
579{
580 unsigned long flags = 0;
581 struct mbx_entry *mbxentry;
582
583 /* Send marker if required. */
584 if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS)
585 return (QLA_FUNCTION_FAILED);
586
587 if (!ha_locked)
588 spin_lock_irqsave(&ha->hardware_lock, flags);
589
590 /* Build fabric port logout mailbox IOCB. */
591 mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature);
592 if (mbxentry == NULL) {
593 if (!ha_locked)
594 spin_unlock_irqrestore(&ha->hardware_lock, flags);
595
596 return (QLA_FUNCTION_FAILED);
597 }
598 mbxentry->mb0 = __constant_cpu_to_le16(MBC_LOGOUT_FABRIC_PORT);
599 mbxentry->mb1 = mbxentry->loop_id.extended =
600 cpu_to_le16(iodesc->remote_fcport->loop_id);
601 wmb();
602
603 qla2x00_add_iodesc_timer(iodesc);
604
605 /* Issue command to ISP. */
606 qla2x00_isp_cmd(ha);
607
608 if (!ha_locked)
609 spin_unlock_irqrestore(&ha->hardware_lock, flags);
610
611 DEBUG14(printk("scsi(%ld): Sending Logout IOCB (%08x) to [%x].\n",
612 ha->host_no, iodesc->signature, iodesc->remote_fcport->loop_id));
613
614 return (QLA_SUCCESS);
615}
616
617/**
618 * qla2x00_send_logout_iocb_cb() - Fabric port logout IOCB callback.
619 * @ha: HA context
620 * @iodesc: io descriptor
621 * @mbxstat: mailbox status IOCB
622 *
623 * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc
624 * will be used for a retry.
625 */
626static int
627qla2x00_send_logout_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
628 struct mbx_entry *mbxstat)
629{
630 DEBUG14(printk("scsi(%ld): Logout IOCB -- sent to [%x/%02x%02x%02x], "
631 "status=%x mb0=%x mb1=%x.\n", ha->host_no,
632 iodesc->remote_fcport->loop_id,
633 iodesc->remote_fcport->d_id.b.domain,
634 iodesc->remote_fcport->d_id.b.area,
635 iodesc->remote_fcport->d_id.b.al_pa, le16_to_cpu(mbxstat->status),
636 le16_to_cpu(mbxstat->mb0), le16_to_cpu(mbxstat->mb1)));
637
638 return (QLA_SUCCESS);
639}
640
641
642/**
643 * qla2x00_send_login_iocb() - Issue a fabric port login IOCB to the firmware.
644 * @ha: HA context
645 * @iodesc: io descriptor
646 * @d_id: port id for device
647 * @ha_locked: is function called with the hardware lock
648 *
649 * Returns QLA_SUCCESS if the IOCB was issued.
650 */
651static int
652qla2x00_send_login_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
653 port_id_t *d_id, int ha_locked)
654{
655 unsigned long flags = 0;
656 struct mbx_entry *mbxentry;
657
658 /* Send marker if required. */
659 if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS)
660 return (QLA_FUNCTION_FAILED);
661
662 if (!ha_locked)
663 spin_lock_irqsave(&ha->hardware_lock, flags);
664
665 /* Build fabric port login mailbox IOCB. */
666 mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature);
667 if (mbxentry == NULL) {
668 if (!ha_locked)
669 spin_unlock_irqrestore(&ha->hardware_lock, flags);
670
671 return (QLA_FUNCTION_FAILED);
672 }
673 mbxentry->mb0 = __constant_cpu_to_le16(MBC_LOGIN_FABRIC_PORT);
674 mbxentry->mb1 = mbxentry->loop_id.extended =
675 cpu_to_le16(iodesc->remote_fcport->loop_id);
676 mbxentry->mb2 = cpu_to_le16(d_id->b.domain);
677 mbxentry->mb3 = cpu_to_le16(d_id->b.area << 8 | d_id->b.al_pa);
678 mbxentry->mb10 = __constant_cpu_to_le16(BIT_0);
679 wmb();
680
681 qla2x00_add_iodesc_timer(iodesc);
682
683 /* Issue command to ISP. */
684 qla2x00_isp_cmd(ha);
685
686 if (!ha_locked)
687 spin_unlock_irqrestore(&ha->hardware_lock, flags);
688
689 DEBUG14(printk("scsi(%ld): Sending Login IOCB (%08x) to "
690 "[%x/%02x%02x%02x].\n", ha->host_no, iodesc->signature,
691 iodesc->remote_fcport->loop_id, d_id->b.domain, d_id->b.area,
692 d_id->b.al_pa));
693
694 return (QLA_SUCCESS);
695}
696
697/**
698 * qla2x00_send_login_iocb_cb() - Fabric port logout IOCB callback.
699 * @ha: HA context
700 * @iodesc: io descriptor
701 * @mbxstat: mailbox status IOCB
702 *
703 * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc
704 * will be used for a retry.
705 */
706static int
707qla2x00_send_login_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
708 struct mbx_entry *mbxstat)
709{
710 int rval;
711 fc_port_t *fcport, *remote_fcport, *exist_fcport;
712 struct io_descriptor *abort_iodesc, *login_iodesc;
713 uint16_t status, mb[8];
714 uint16_t reuse;
715 uint16_t remote_loopid;
716 port_id_t remote_did, inuse_did;
717
718 remote_fcport = iodesc->remote_fcport;
719
720 /* Only process the last command. */
721 if (remote_fcport->iodesc_idx_sent != iodesc->idx) {
722 DEBUG14(printk("scsi(%ld): Login IOCB -- ignoring, sent to "
723 "[%02x%02x%02x], expected %x, received %x.\n",
724 ha->host_no, iodesc->d_id.b.domain, iodesc->d_id.b.area,
725 iodesc->d_id.b.al_pa, remote_fcport->iodesc_idx_sent,
726 iodesc->idx));
727
728 /* Free RSCN fcport resources. */
729 if (remote_fcport->port_type == FCT_RSCN) {
730 DEBUG14(printk("scsi(%ld): Login IOCB -- Freeing RSCN "
731 "fcport %p [%x/%02x%02x%02x] given ignored Login "
732 "IOCB.\n", ha->host_no, remote_fcport,
733 remote_fcport->loop_id,
734 remote_fcport->d_id.b.domain,
735 remote_fcport->d_id.b.area,
736 remote_fcport->d_id.b.al_pa));
737
738 list_del(&remote_fcport->list);
739 kfree(remote_fcport);
740 }
741 return (QLA_SUCCESS);
742 }
743
744 status = le16_to_cpu(mbxstat->status);
745 mb[0] = le16_to_cpu(mbxstat->mb0);
746 mb[1] = le16_to_cpu(mbxstat->mb1);
747 mb[2] = le16_to_cpu(mbxstat->mb2);
748 mb[6] = le16_to_cpu(mbxstat->mb6);
749 mb[7] = le16_to_cpu(mbxstat->mb7);
750
751 /* Good status? */
752 if ((status == CS_COMPLETE || status == CS_COMPLETE_CHKCOND) &&
753 mb[0] == MBS_COMMAND_COMPLETE) {
754
755 DEBUG14(printk("scsi(%ld): Login IOCB -- status=%x mb1=%x pn="
756 "%02x%02x%02x%02x%02x%02x%02x%02x.\n", ha->host_no, status,
757 mb[1], mbxstat->port_name[0], mbxstat->port_name[1],
758 mbxstat->port_name[2], mbxstat->port_name[3],
759 mbxstat->port_name[4], mbxstat->port_name[5],
760 mbxstat->port_name[6], mbxstat->port_name[7]));
761
762 memcpy(remote_fcport->node_name, mbxstat->node_name, WWN_SIZE);
763 memcpy(remote_fcport->port_name, mbxstat->port_name, WWN_SIZE);
764
765 /* Is the device already in our fcports list? */
766 if (remote_fcport->port_type != FCT_RSCN) {
767 DEBUG14(printk("scsi(%ld): Login IOCB -- marking "
768 "[%x/%02x%02x%02x] online.\n", ha->host_no,
769 remote_fcport->loop_id,
770 remote_fcport->d_id.b.domain,
771 remote_fcport->d_id.b.area,
772 remote_fcport->d_id.b.al_pa));
773
774 qla2x00_update_login_fcport(ha, mbxstat, remote_fcport);
775
776 return (QLA_SUCCESS);
777 }
778
779 /* Does the RSCN portname already exist in our fcports list? */
780 exist_fcport = NULL;
781 list_for_each_entry(fcport, &ha->fcports, list) {
782 if (memcmp(remote_fcport->port_name, fcport->port_name,
783 WWN_SIZE) == 0) {
784 exist_fcport = fcport;
785 break;
786 }
787 }
788 if (exist_fcport != NULL) {
789 DEBUG14(printk("scsi(%ld): Login IOCB -- found RSCN "
790 "fcport in fcports list [%p].\n", ha->host_no,
791 exist_fcport));
792
793 /* Abort any ADISC that could have been sent. */
794 if (exist_fcport->iodesc_idx_sent != iodesc->idx &&
795 exist_fcport->iodesc_idx_sent <
796 MAX_IO_DESCRIPTORS &&
797 ha->io_descriptors[exist_fcport->iodesc_idx_sent].
798 cb_idx == ADISC_PORT_IOCB_CB) {
799
800 abort_iodesc = qla2x00_alloc_iodesc(ha);
801 if (abort_iodesc) {
802 DEBUG14(printk("scsi(%ld): Login IOCB "
803 "-- issuing abort to outstanding "
804 "Adisc [%x/%02x%02x%02x].\n",
805 ha->host_no, remote_fcport->loop_id,
806 exist_fcport->d_id.b.domain,
807 exist_fcport->d_id.b.area,
808 exist_fcport->d_id.b.al_pa));
809
810 abort_iodesc->cb_idx = ABORT_IOCB_CB;
811 abort_iodesc->d_id.b24 =
812 exist_fcport->d_id.b24;
813 abort_iodesc->remote_fcport =
814 exist_fcport;
815 exist_fcport->iodesc_idx_sent =
816 abort_iodesc->idx;
817 qla2x00_send_abort_iocb(ha,
818 abort_iodesc, ha->io_descriptors[
819 exist_fcport->iodesc_idx_sent].
820 signature, 1);
821 } else {
822 DEBUG14(printk("scsi(%ld): Login IOCB "
823 "-- unable to abort outstanding "
824 "Adisc [%x/%02x%02x%02x].\n",
825 ha->host_no, remote_fcport->loop_id,
826 exist_fcport->d_id.b.domain,
827 exist_fcport->d_id.b.area,
828 exist_fcport->d_id.b.al_pa));
829 }
830 }
831
832 /*
833 * If the existing fcport is waiting to send an ADISC
834 * or LOGIN, then reuse remote fcport (RSCN) to
835 * continue waiting.
836 */
837 reuse = 0;
838 remote_loopid = remote_fcport->loop_id;
839 remote_did.b24 = remote_fcport->d_id.b24;
840 if (exist_fcport->iodesc_idx_sent ==
841 IODESC_ADISC_NEEDED ||
842 exist_fcport->iodesc_idx_sent ==
843 IODESC_LOGIN_NEEDED) {
844 DEBUG14(printk("scsi(%ld): Login IOCB -- "
845 "existing fcport [%x/%02x%02x%02x] "
846 "waiting for IO descriptor, reuse RSCN "
847 "fcport.\n", ha->host_no,
848 exist_fcport->loop_id,
849 exist_fcport->d_id.b.domain,
850 exist_fcport->d_id.b.area,
851 exist_fcport->d_id.b.al_pa));
852
853 reuse++;
854 remote_fcport->iodesc_idx_sent =
855 exist_fcport->iodesc_idx_sent;
856 exist_fcport->iodesc_idx_sent =
857 IODESC_INVALID_INDEX;
858 remote_fcport->loop_id = exist_fcport->loop_id;
859 remote_fcport->d_id.b24 =
860 exist_fcport->d_id.b24;
861 }
862
863 /* Logout the old loopid. */
864 if (!reuse &&
865 exist_fcport->loop_id != remote_fcport->loop_id &&
866 exist_fcport->loop_id != FC_NO_LOOP_ID) {
867 login_iodesc = qla2x00_alloc_iodesc(ha);
868 if (login_iodesc) {
869 DEBUG14(printk("scsi(%ld): Login IOCB "
870 "-- issuing logout to free old "
871 "loop id [%x/%02x%02x%02x].\n",
872 ha->host_no, exist_fcport->loop_id,
873 exist_fcport->d_id.b.domain,
874 exist_fcport->d_id.b.area,
875 exist_fcport->d_id.b.al_pa));
876
877 login_iodesc->cb_idx =
878 LOGOUT_PORT_IOCB_CB;
879 login_iodesc->d_id.b24 =
880 exist_fcport->d_id.b24;
881 login_iodesc->remote_fcport =
882 exist_fcport;
883 exist_fcport->iodesc_idx_sent =
884 login_iodesc->idx;
885 qla2x00_send_logout_iocb(ha,
886 login_iodesc, 1);
887 } else {
888 /* Ran out of IO descriptiors. */
889 DEBUG14(printk("scsi(%ld): Login IOCB "
890 "-- unable to logout to free old "
891 "loop id [%x/%02x%02x%02x].\n",
892 ha->host_no, exist_fcport->loop_id,
893 exist_fcport->d_id.b.domain,
894 exist_fcport->d_id.b.area,
895 exist_fcport->d_id.b.al_pa));
896
897 exist_fcport->iodesc_idx_sent =
898 IODESC_INVALID_INDEX;
899 }
900
901 }
902
903 /* Update existing fcport with remote fcport info. */
904 DEBUG14(printk("scsi(%ld): Login IOCB -- marking "
905 "existing fcport [%x/%02x%02x%02x] online.\n",
906 ha->host_no, remote_loopid, remote_did.b.domain,
907 remote_did.b.area, remote_did.b.al_pa));
908
909 memcpy(exist_fcport->node_name,
910 remote_fcport->node_name, WWN_SIZE);
911 exist_fcport->loop_id = remote_loopid;
912 exist_fcport->d_id.b24 = remote_did.b24;
913 qla2x00_update_login_fcport(ha, mbxstat, exist_fcport);
914
915 /* Finally, free the remote (RSCN) fcport. */
916 if (!reuse) {
917 DEBUG14(printk("scsi(%ld): Login IOCB -- "
918 "Freeing RSCN fcport %p "
919 "[%x/%02x%02x%02x].\n", ha->host_no,
920 remote_fcport, remote_fcport->loop_id,
921 remote_fcport->d_id.b.domain,
922 remote_fcport->d_id.b.area,
923 remote_fcport->d_id.b.al_pa));
924
925 list_del(&remote_fcport->list);
926 kfree(remote_fcport);
927 }
928
929 return (QLA_SUCCESS);
930 }
931
932 /*
933 * A new device has been added, move the RSCN fcport to our
934 * fcports list.
935 */
936 DEBUG14(printk("scsi(%ld): Login IOCB -- adding RSCN fcport "
937 "[%x/%02x%02x%02x] to fcports list.\n", ha->host_no,
938 remote_fcport->loop_id, remote_fcport->d_id.b.domain,
939 remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa));
940
941 list_del(&remote_fcport->list);
942 remote_fcport->flags = (FCF_RLC_SUPPORT | FCF_RESCAN_NEEDED);
943 qla2x00_update_login_fcport(ha, mbxstat, remote_fcport);
944 list_add_tail(&remote_fcport->list, &ha->fcports);
945 set_bit(FCPORT_RESCAN_NEEDED, &ha->dpc_flags);
946 } else {
947 /* Handle login failure. */
948 if (remote_fcport->login_retry != 0) {
949 if (mb[0] == MBS_LOOP_ID_USED) {
950 inuse_did.b.domain = LSB(mb[1]);
951 inuse_did.b.area = MSB(mb[2]);
952 inuse_did.b.al_pa = LSB(mb[2]);
953
954 DEBUG14(printk("scsi(%ld): Login IOCB -- loop "
955 "id [%x] used by port id [%02x%02x%02x].\n",
956 ha->host_no, remote_fcport->loop_id,
957 inuse_did.b.domain, inuse_did.b.area,
958 inuse_did.b.al_pa));
959
960 if (remote_fcport->d_id.b24 ==
961 INVALID_PORT_ID) {
962 /*
963 * Invalid port id means we are trying
964 * to login to a remote port with just
965 * a loop id without knowing about the
966 * port id. Copy the port id and try
967 * again.
968 */
969 remote_fcport->d_id.b24 = inuse_did.b24;
970 iodesc->d_id.b24 = inuse_did.b24;
971 } else {
972 remote_fcport->loop_id++;
973 rval = qla2x00_find_new_loop_id(ha,
974 remote_fcport);
975 if (rval == QLA_FUNCTION_FAILED) {
976 /* No more loop ids. */
977 return (QLA_SUCCESS);
978 }
979 }
980 } else if (mb[0] == MBS_PORT_ID_USED) {
981 /*
982 * Device has another loop ID. The firmware
983 * group recommends the driver perform an
984 * implicit login with the specified ID.
985 */
986 DEBUG14(printk("scsi(%ld): Login IOCB -- port "
987 "id [%02x%02x%02x] already assigned to "
988 "loop id [%x].\n", ha->host_no,
989 iodesc->d_id.b.domain, iodesc->d_id.b.area,
990 iodesc->d_id.b.al_pa, mb[1]));
991
992 remote_fcport->loop_id = mb[1];
993
994 } else {
995 /* Unable to perform login, try again. */
996 DEBUG14(printk("scsi(%ld): Login IOCB -- "
997 "failed login [%x/%02x%02x%02x], status=%x "
998 "mb0=%x mb1=%x mb2=%x mb6=%x mb7=%x.\n",
999 ha->host_no, remote_fcport->loop_id,
1000 iodesc->d_id.b.domain, iodesc->d_id.b.area,
1001 iodesc->d_id.b.al_pa, status, mb[0], mb[1],
1002 mb[2], mb[6], mb[7]));
1003 }
1004
1005 /* Reissue Login with the same IO descriptor. */
1006 iodesc->signature =
1007 qla2x00_iodesc_to_handle(iodesc);
1008 iodesc->cb_idx = LOGIN_PORT_IOCB_CB;
1009 iodesc->d_id.b24 = remote_fcport->d_id.b24;
1010 remote_fcport->iodesc_idx_sent = iodesc->idx;
1011 remote_fcport->login_retry--;
1012
1013 DEBUG14(printk("scsi(%ld): Login IOCB -- retrying "
1014 "login to [%x/%02x%02x%02x] (%d).\n", ha->host_no,
1015 remote_fcport->loop_id,
1016 remote_fcport->d_id.b.domain,
1017 remote_fcport->d_id.b.area,
1018 remote_fcport->d_id.b.al_pa,
1019 remote_fcport->login_retry));
1020
1021 qla2x00_send_login_iocb(ha, iodesc,
1022 &remote_fcport->d_id, 1);
1023
1024 return (QLA_FUNCTION_FAILED);
1025 } else {
1026 /* No more logins, mark device dead. */
1027 DEBUG14(printk("scsi(%ld): Login IOCB -- failed "
1028 "login [%x/%02x%02x%02x] after retries, status=%x "
1029 "mb0=%x mb1=%x mb2=%x mb6=%x mb7=%x.\n",
1030 ha->host_no, remote_fcport->loop_id,
1031 iodesc->d_id.b.domain, iodesc->d_id.b.area,
1032 iodesc->d_id.b.al_pa, status, mb[0], mb[1],
1033 mb[2], mb[6], mb[7]));
1034
1035 atomic_set(&remote_fcport->state, FCS_DEVICE_DEAD);
1036 if (remote_fcport->port_type == FCT_RSCN) {
1037 DEBUG14(printk("scsi(%ld): Login IOCB -- "
1038 "Freeing dead RSCN fcport %p "
1039 "[%x/%02x%02x%02x].\n", ha->host_no,
1040 remote_fcport, remote_fcport->loop_id,
1041 remote_fcport->d_id.b.domain,
1042 remote_fcport->d_id.b.area,
1043 remote_fcport->d_id.b.al_pa));
1044
1045 list_del(&remote_fcport->list);
1046 kfree(remote_fcport);
1047 }
1048 }
1049 }
1050
1051 return (QLA_SUCCESS);
1052}
1053
1054
1055/**
1056 * IO descriptor processing routines.
1057 **/
1058
1059/**
1060 * qla2x00_alloc_rscn_fcport() - Allocate an RSCN type fcport.
1061 * @ha: HA context
1062 * @flags: allocation flags
1063 *
1064 * Returns a pointer to the allocated RSCN fcport, or NULL, if none available.
1065 */
1066fc_port_t *
1067qla2x00_alloc_rscn_fcport(scsi_qla_host_t *ha, int flags)
1068{
1069 fc_port_t *fcport;
1070
1071 fcport = qla2x00_alloc_fcport(ha, flags);
1072 if (fcport == NULL)
1073 return (fcport);
1074
1075 /* Setup RSCN fcport structure. */
1076 fcport->port_type = FCT_RSCN;
1077
1078 return (fcport);
1079}
1080
1081/**
1082 * qla2x00_handle_port_rscn() - Handle port RSCN.
1083 * @ha: HA context
1084 * @rscn_entry: RSCN entry
1085 * @fcport: fcport entry to updated
1086 *
1087 * Returns QLA_SUCCESS if the port RSCN was handled.
1088 */
1089int
1090qla2x00_handle_port_rscn(scsi_qla_host_t *ha, uint32_t rscn_entry,
1091 fc_port_t *known_fcport, int ha_locked)
1092{
1093 int rval;
1094 port_id_t rscn_pid;
1095 fc_port_t *fcport, *remote_fcport, *rscn_fcport;
1096 struct io_descriptor *iodesc;
1097
1098 remote_fcport = NULL;
1099 rscn_fcport = NULL;
1100
1101 /* Prepare port id based on incoming entries. */
1102 if (known_fcport) {
1103 rscn_pid.b24 = known_fcport->d_id.b24;
1104 remote_fcport = known_fcport;
1105
1106 DEBUG14(printk("scsi(%ld): Handle RSCN -- process RSCN for "
1107 "fcport [%02x%02x%02x].\n", ha->host_no,
1108 remote_fcport->d_id.b.domain, remote_fcport->d_id.b.area,
1109 remote_fcport->d_id.b.al_pa));
1110 } else {
1111 rscn_pid.b.domain = LSB(MSW(rscn_entry));
1112 rscn_pid.b.area = MSB(LSW(rscn_entry));
1113 rscn_pid.b.al_pa = LSB(LSW(rscn_entry));
1114
1115 DEBUG14(printk("scsi(%ld): Handle RSCN -- process RSCN for "
1116 "port id [%02x%02x%02x].\n", ha->host_no,
1117 rscn_pid.b.domain, rscn_pid.b.area, rscn_pid.b.al_pa));
1118
1119 /*
1120 * Search fcport lists for a known entry at the specified port
1121 * ID.
1122 */
1123 list_for_each_entry(fcport, &ha->fcports, list) {
1124 if (rscn_pid.b24 == fcport->d_id.b24) {
1125 remote_fcport = fcport;
1126 break;
1127 }
1128 }
1129 list_for_each_entry(fcport, &ha->rscn_fcports, list) {
1130 if (rscn_pid.b24 == fcport->d_id.b24) {
1131 rscn_fcport = fcport;
1132 break;
1133 }
1134 }
1135 if (remote_fcport == NULL)
1136 remote_fcport = rscn_fcport;
1137 }
1138
1139 /*
1140 * If the port is already in our fcport list and online, send an ADISC
1141 * to see if it's still alive. Issue login if a new fcport or the known
1142 * fcport is currently offline.
1143 */
1144 if (remote_fcport) {
1145 /*
1146 * No need to send request if the remote fcport is currently
1147 * waiting for an available io descriptor.
1148 */
1149 if (known_fcport == NULL &&
1150 (remote_fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED ||
1151 remote_fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED)) {
1152 /*
1153 * If previous waiting io descriptor is an ADISC, then
1154 * the new RSCN may come from a new remote fcport being
1155 * plugged into the same location.
1156 */
1157 if (remote_fcport->port_type == FCT_RSCN) {
1158 remote_fcport->iodesc_idx_sent =
1159 IODESC_LOGIN_NEEDED;
1160 } else if (remote_fcport->iodesc_idx_sent ==
1161 IODESC_ADISC_NEEDED) {
1162 fc_port_t *new_fcport;
1163
1164 remote_fcport->iodesc_idx_sent =
1165 IODESC_INVALID_INDEX;
1166
1167 /* Create new fcport for later login. */
1168 new_fcport = qla2x00_alloc_rscn_fcport(ha,
1169 ha_locked ? GFP_ATOMIC: GFP_KERNEL);
1170 if (new_fcport) {
1171 DEBUG14(printk("scsi(%ld): Handle RSCN "
1172 "-- creating RSCN fcport %p for "
1173 "future login.\n", ha->host_no,
1174 new_fcport));
1175
1176 new_fcport->d_id.b24 =
1177 remote_fcport->d_id.b24;
1178 new_fcport->iodesc_idx_sent =
1179 IODESC_LOGIN_NEEDED;
1180
1181 list_add_tail(&new_fcport->list,
1182 &ha->rscn_fcports);
1183 set_bit(IODESC_PROCESS_NEEDED,
1184 &ha->dpc_flags);
1185 } else {
1186 DEBUG14(printk("scsi(%ld): Handle RSCN "
1187 "-- unable to allocate RSCN fcport "
1188 "for future login.\n",
1189 ha->host_no));
1190 }
1191 }
1192 return (QLA_SUCCESS);
1193 }
1194
1195 /* Send ADISC if the fcport is online */
1196 if (atomic_read(&remote_fcport->state) == FCS_ONLINE ||
1197 remote_fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED) {
1198
1199 atomic_set(&remote_fcport->state, FCS_DEVICE_LOST);
1200
1201 iodesc = qla2x00_alloc_iodesc(ha);
1202 if (iodesc == NULL) {
1203 /* Mark fcport for later adisc processing */
1204 DEBUG14(printk("scsi(%ld): Handle RSCN -- not "
1205 "enough IO descriptors for Adisc, flag "
1206 "for later processing.\n", ha->host_no));
1207
1208 remote_fcport->iodesc_idx_sent =
1209 IODESC_ADISC_NEEDED;
1210 set_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags);
1211
1212 return (QLA_SUCCESS);
1213 }
1214
1215 iodesc->cb_idx = ADISC_PORT_IOCB_CB;
1216 iodesc->d_id.b24 = rscn_pid.b24;
1217 iodesc->remote_fcport = remote_fcport;
1218 remote_fcport->iodesc_idx_sent = iodesc->idx;
1219 qla2x00_send_adisc_iocb(ha, iodesc, ha_locked);
1220
1221 return (QLA_SUCCESS);
1222 } else if (remote_fcport->iodesc_idx_sent <
1223 MAX_IO_DESCRIPTORS &&
1224 ha->io_descriptors[remote_fcport->iodesc_idx_sent].cb_idx ==
1225 ADISC_PORT_IOCB_CB) {
1226 /*
1227 * Receiving another RSCN while an ADISC is pending,
1228 * abort the IOCB. Use the same descriptor for the
1229 * abort.
1230 */
1231 uint32_t handle_to_abort;
1232
1233 iodesc = &ha->io_descriptors[
1234 remote_fcport->iodesc_idx_sent];
1235 qla2x00_remove_iodesc_timer(iodesc);
1236 handle_to_abort = iodesc->signature;
1237 iodesc->signature = qla2x00_iodesc_to_handle(iodesc);
1238 iodesc->cb_idx = ABORT_IOCB_CB;
1239 iodesc->d_id.b24 = remote_fcport->d_id.b24;
1240 iodesc->remote_fcport = remote_fcport;
1241 remote_fcport->iodesc_idx_sent = iodesc->idx;
1242
1243 DEBUG14(printk("scsi(%ld): Handle RSCN -- issuing "
1244 "abort to outstanding Adisc [%x/%02x%02x%02x].\n",
1245 ha->host_no, remote_fcport->loop_id,
1246 iodesc->d_id.b.domain, iodesc->d_id.b.area,
1247 iodesc->d_id.b.al_pa));
1248
1249 qla2x00_send_abort_iocb(ha, iodesc, handle_to_abort,
1250 ha_locked);
1251 }
1252 }
1253
1254 /* We need to login to the remote port, find it. */
1255 if (known_fcport) {
1256 remote_fcport = known_fcport;
1257 } else if (rscn_fcport && rscn_fcport->d_id.b24 != INVALID_PORT_ID &&
1258 rscn_fcport->iodesc_idx_sent < MAX_IO_DESCRIPTORS &&
1259 ha->io_descriptors[rscn_fcport->iodesc_idx_sent].cb_idx ==
1260 LOGIN_PORT_IOCB_CB) {
1261 /*
1262 * Ignore duplicate RSCN on fcport which has already
1263 * initiated a login IOCB.
1264 */
1265 DEBUG14(printk("scsi(%ld): Handle RSCN -- ignoring, login "
1266 "already sent to [%02x%02x%02x].\n", ha->host_no,
1267 rscn_fcport->d_id.b.domain, rscn_fcport->d_id.b.area,
1268 rscn_fcport->d_id.b.al_pa));
1269
1270 return (QLA_SUCCESS);
1271 } else if (rscn_fcport && rscn_fcport->d_id.b24 != INVALID_PORT_ID &&
1272 rscn_fcport != remote_fcport) {
1273 /* Reuse same rscn fcport. */
1274 DEBUG14(printk("scsi(%ld): Handle RSCN -- reusing RSCN fcport "
1275 "[%02x%02x%02x].\n", ha->host_no,
1276 rscn_fcport->d_id.b.domain, rscn_fcport->d_id.b.area,
1277 rscn_fcport->d_id.b.al_pa));
1278
1279 remote_fcport = rscn_fcport;
1280 } else {
1281 /* Create new fcport for later login. */
1282 remote_fcport = qla2x00_alloc_rscn_fcport(ha,
1283 ha_locked ? GFP_ATOMIC: GFP_KERNEL);
1284 list_add_tail(&remote_fcport->list, &ha->rscn_fcports);
1285 }
1286 if (remote_fcport == NULL)
1287 return (QLA_SUCCESS);
1288
1289 /* Prepare fcport for login. */
1290 atomic_set(&remote_fcport->state, FCS_DEVICE_LOST);
1291 remote_fcport->login_retry = 3; /* ha->login_retry_count; */
1292 remote_fcport->d_id.b24 = rscn_pid.b24;
1293
1294 iodesc = qla2x00_alloc_iodesc(ha);
1295 if (iodesc == NULL) {
1296 /* Mark fcport for later adisc processing. */
1297 DEBUG14(printk("scsi(%ld): Handle RSCN -- not enough IO "
1298 "descriptors for Login, flag for later processing.\n",
1299 ha->host_no));
1300
1301 remote_fcport->iodesc_idx_sent = IODESC_LOGIN_NEEDED;
1302 set_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags);
1303
1304 return (QLA_SUCCESS);
1305 }
1306
1307 if (known_fcport == NULL || rscn_pid.b24 != INVALID_PORT_ID) {
1308 remote_fcport->loop_id = ha->min_external_loopid;
1309
1310 rval = qla2x00_find_new_loop_id(ha, remote_fcport);
1311 if (rval == QLA_FUNCTION_FAILED) {
1312 /* No more loop ids, failed. */
1313 DEBUG14(printk("scsi(%ld): Handle RSCN -- no available "
1314 "loop id to perform Login, failed.\n",
1315 ha->host_no));
1316
1317 return (rval);
1318 }
1319 }
1320
1321 iodesc->cb_idx = LOGIN_PORT_IOCB_CB;
1322 iodesc->d_id.b24 = rscn_pid.b24;
1323 iodesc->remote_fcport = remote_fcport;
1324 remote_fcport->iodesc_idx_sent = iodesc->idx;
1325
1326 DEBUG14(printk("scsi(%ld): Handle RSCN -- attempting login to "
1327 "[%x/%02x%02x%02x].\n", ha->host_no, remote_fcport->loop_id,
1328 iodesc->d_id.b.domain, iodesc->d_id.b.area, iodesc->d_id.b.al_pa));
1329
1330 qla2x00_send_login_iocb(ha, iodesc, &rscn_pid, ha_locked);
1331
1332 return (QLA_SUCCESS);
1333}
1334
1335/**
1336 * qla2x00_process_iodesc() - Complete IO descriptor processing.
1337 * @ha: HA context
1338 * @mbxstat: Mailbox IOCB status
1339 */
1340void
1341qla2x00_process_iodesc(scsi_qla_host_t *ha, struct mbx_entry *mbxstat)
1342{
1343 int rval;
1344 uint32_t signature;
1345 fc_port_t *fcport;
1346 struct io_descriptor *iodesc;
1347
1348 signature = mbxstat->handle;
1349
1350 DEBUG14(printk("scsi(%ld): Process IODesc -- processing %08x.\n",
1351 ha->host_no, signature));
1352
1353 /* Retrieve proper IO descriptor. */
1354 iodesc = qla2x00_handle_to_iodesc(ha, signature);
1355 if (iodesc == NULL) {
1356 DEBUG14(printk("scsi(%ld): Process IODesc -- ignoring, "
1357 "incorrect signature %08x.\n", ha->host_no, signature));
1358
1359 return;
1360 }
1361
1362 /* Stop IO descriptor timer. */
1363 qla2x00_remove_iodesc_timer(iodesc);
1364
1365 /* Verify signature match. */
1366 if (iodesc->signature != signature) {
1367 DEBUG14(printk("scsi(%ld): Process IODesc -- ignoring, "
1368 "signature mismatch, sent %08x, received %08x.\n",
1369 ha->host_no, iodesc->signature, signature));
1370
1371 return;
1372 }
1373
1374 /* Go with IOCB callback. */
1375 rval = iocb_function_cb_list[iodesc->cb_idx](ha, iodesc, mbxstat);
1376 if (rval != QLA_SUCCESS) {
1377 /* IO descriptor reused by callback. */
1378 return;
1379 }
1380
1381 qla2x00_free_iodesc(iodesc);
1382
1383 if (test_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags)) {
1384 /* Scan our fcports list for any RSCN requests. */
1385 list_for_each_entry(fcport, &ha->fcports, list) {
1386 if (fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED ||
1387 fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED) {
1388 qla2x00_handle_port_rscn(ha, 0, fcport, 1);
1389 return;
1390 }
1391 }
1392
1393 /* Scan our RSCN fcports list for any RSCN requests. */
1394 list_for_each_entry(fcport, &ha->rscn_fcports, list) {
1395 if (fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED ||
1396 fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED) {
1397 qla2x00_handle_port_rscn(ha, 0, fcport, 1);
1398 return;
1399 }
1400 }
1401 }
1402 clear_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags);
1403}
1404
1405/**
1406 * qla2x00_cancel_io_descriptors() - Cancel all outstanding io descriptors.
1407 * @ha: HA context
1408 *
1409 * This routine will also delete any RSCN entries related to the outstanding
1410 * IO descriptors.
1411 */
1412void
1413qla2x00_cancel_io_descriptors(scsi_qla_host_t *ha)
1414{
1415 fc_port_t *fcport, *fcptemp;
1416
1417 clear_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags);
1418
1419 /* Abort all IO descriptors. */
1420 qla2x00_init_io_descriptors(ha);
1421
1422 /* Reset all pending IO descriptors in fcports list. */
1423 list_for_each_entry(fcport, &ha->fcports, list) {
1424 fcport->iodesc_idx_sent = IODESC_INVALID_INDEX;
1425 }
1426
1427 /* Reset all pending IO descriptors in rscn fcports list. */
1428 list_for_each_entry_safe(fcport, fcptemp, &ha->rscn_fcports, list) {
1429 DEBUG14(printk("scsi(%ld): Cancel IOs -- Freeing RSCN fcport "
1430 "%p [%x/%02x%02x%02x].\n", ha->host_no, fcport,
1431 fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
1432 fcport->d_id.b.al_pa));
1433
1434 list_del(&fcport->list);
1435 kfree(fcport);
1436 }
1437}