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