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