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