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