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