Merge master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb
[pandora-kernel.git] / drivers / message / fusion / mptfc.c
1 /*
2  *  linux/drivers/message/fusion/mptfc.c
3  *      For use with LSI Logic PCI chip/adapter(s)
4  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
5  *
6  *  Copyright (c) 1999-2005 LSI Logic Corporation
7  *  (mailto:mpt_linux_developer@lsil.com)
8  *
9  */
10 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11 /*
12     This program is free software; you can redistribute it and/or modify
13     it under the terms of the GNU General Public License as published by
14     the Free Software Foundation; version 2 of the License.
15
16     This program is distributed in the hope that it will be useful,
17     but WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19     GNU General Public License for more details.
20
21     NO WARRANTY
22     THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
23     CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
24     LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
25     MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
26     solely responsible for determining the appropriateness of using and
27     distributing the Program and assumes all risks associated with its
28     exercise of rights under this Agreement, including but not limited to
29     the risks and costs of program errors, damage to or loss of data,
30     programs or equipment, and unavailability or interruption of operations.
31
32     DISCLAIMER OF LIABILITY
33     NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
34     DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35     DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
36     ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37     TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38     USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
39     HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
40
41     You should have received a copy of the GNU General Public License
42     along with this program; if not, write to the Free Software
43     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
44 */
45 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
46 #include "linux_compat.h"       /* linux-2.6 tweaks */
47 #include <linux/module.h>
48 #include <linux/kernel.h>
49 #include <linux/init.h>
50 #include <linux/errno.h>
51 #include <linux/kdev_t.h>
52 #include <linux/blkdev.h>
53 #include <linux/delay.h>        /* for mdelay */
54 #include <linux/interrupt.h>    /* needed for in_interrupt() proto */
55 #include <linux/reboot.h>       /* notifier code */
56 #include <linux/sched.h>
57 #include <linux/workqueue.h>
58 #include <linux/sort.h>
59
60 #include <scsi/scsi.h>
61 #include <scsi/scsi_cmnd.h>
62 #include <scsi/scsi_device.h>
63 #include <scsi/scsi_host.h>
64 #include <scsi/scsi_tcq.h>
65 #include <scsi/scsi_transport_fc.h>
66
67 #include "mptbase.h"
68 #include "mptscsih.h"
69
70 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
71 #define my_NAME         "Fusion MPT FC Host driver"
72 #define my_VERSION      MPT_LINUX_VERSION_COMMON
73 #define MYNAM           "mptfc"
74
75 MODULE_AUTHOR(MODULEAUTHOR);
76 MODULE_DESCRIPTION(my_NAME);
77 MODULE_LICENSE("GPL");
78
79 /* Command line args */
80 static int mpt_pq_filter = 0;
81 module_param(mpt_pq_filter, int, 0);
82 MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1  (default=0)");
83
84 #define MPTFC_DEV_LOSS_TMO (60)
85 static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;     /* reasonable default */
86 module_param(mptfc_dev_loss_tmo, int, 0);
87 MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the "
88                                      " transport to wait for an rport to "
89                                      " return following a device loss event."
90                                      "  Default=60.");
91
92 static int      mptfcDoneCtx = -1;
93 static int      mptfcTaskCtx = -1;
94 static int      mptfcInternalCtx = -1; /* Used only for internal commands */
95
96 static int mptfc_target_alloc(struct scsi_target *starget);
97 static int mptfc_slave_alloc(struct scsi_device *sdev);
98 static int mptfc_qcmd(struct scsi_cmnd *SCpnt,
99                       void (*done)(struct scsi_cmnd *));
100 static void mptfc_target_destroy(struct scsi_target *starget);
101 static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);
102 static void __devexit mptfc_remove(struct pci_dev *pdev);
103
104 static struct scsi_host_template mptfc_driver_template = {
105         .module                         = THIS_MODULE,
106         .proc_name                      = "mptfc",
107         .proc_info                      = mptscsih_proc_info,
108         .name                           = "MPT FC Host",
109         .info                           = mptscsih_info,
110         .queuecommand                   = mptfc_qcmd,
111         .target_alloc                   = mptfc_target_alloc,
112         .slave_alloc                    = mptfc_slave_alloc,
113         .slave_configure                = mptscsih_slave_configure,
114         .target_destroy                 = mptfc_target_destroy,
115         .slave_destroy                  = mptscsih_slave_destroy,
116         .change_queue_depth             = mptscsih_change_queue_depth,
117         .eh_abort_handler               = mptscsih_abort,
118         .eh_device_reset_handler        = mptscsih_dev_reset,
119         .eh_bus_reset_handler           = mptscsih_bus_reset,
120         .eh_host_reset_handler          = mptscsih_host_reset,
121         .bios_param                     = mptscsih_bios_param,
122         .can_queue                      = MPT_FC_CAN_QUEUE,
123         .this_id                        = -1,
124         .sg_tablesize                   = MPT_SCSI_SG_DEPTH,
125         .max_sectors                    = 8192,
126         .cmd_per_lun                    = 7,
127         .use_clustering                 = ENABLE_CLUSTERING,
128 };
129
130 /****************************************************************************
131  * Supported hardware
132  */
133
134 static struct pci_device_id mptfc_pci_table[] = {
135         { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909,
136                 PCI_ANY_ID, PCI_ANY_ID },
137         { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919,
138                 PCI_ANY_ID, PCI_ANY_ID },
139         { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929,
140                 PCI_ANY_ID, PCI_ANY_ID },
141         { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X,
142                 PCI_ANY_ID, PCI_ANY_ID },
143         { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X,
144                 PCI_ANY_ID, PCI_ANY_ID },
145         { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC939X,
146                 PCI_ANY_ID, PCI_ANY_ID },
147         { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X,
148                 PCI_ANY_ID, PCI_ANY_ID },
149         { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949ES,
150                 PCI_ANY_ID, PCI_ANY_ID },
151         {0}     /* Terminating entry */
152 };
153 MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
154
155 static struct scsi_transport_template *mptfc_transport_template = NULL;
156
157 static struct fc_function_template mptfc_transport_functions = {
158         .dd_fcrport_size = 8,
159         .show_host_node_name = 1,
160         .show_host_port_name = 1,
161         .show_host_supported_classes = 1,
162         .show_host_port_id = 1,
163         .show_rport_supported_classes = 1,
164         .show_starget_node_name = 1,
165         .show_starget_port_name = 1,
166         .show_starget_port_id = 1,
167         .set_rport_dev_loss_tmo = mptfc_set_rport_loss_tmo,
168         .show_rport_dev_loss_tmo = 1,
169
170 };
171
172 static void
173 mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
174 {
175         if (timeout > 0)
176                 rport->dev_loss_tmo = timeout;
177         else
178                 rport->dev_loss_tmo = mptfc_dev_loss_tmo;
179 }
180
181 static int
182 mptfc_FcDevPage0_cmp_func(const void *a, const void *b)
183 {
184         FCDevicePage0_t **aa = (FCDevicePage0_t **)a;
185         FCDevicePage0_t **bb = (FCDevicePage0_t **)b;
186
187         if ((*aa)->CurrentBus == (*bb)->CurrentBus) {
188                 if ((*aa)->CurrentTargetID == (*bb)->CurrentTargetID)
189                         return 0;
190                 if ((*aa)->CurrentTargetID < (*bb)->CurrentTargetID)
191                         return -1;
192                 return 1;
193         }
194         if ((*aa)->CurrentBus < (*bb)->CurrentBus)
195                 return -1;
196         return 1;
197 }
198
199 static int
200 mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port,
201         void(*func)(MPT_ADAPTER *ioc,int channel, FCDevicePage0_t *arg))
202 {
203         ConfigPageHeader_t       hdr;
204         CONFIGPARMS              cfg;
205         FCDevicePage0_t         *ppage0_alloc, *fc;
206         dma_addr_t               page0_dma;
207         int                      data_sz;
208         int                      ii;
209
210         FCDevicePage0_t         *p0_array=NULL, *p_p0;
211         FCDevicePage0_t         **pp0_array=NULL, **p_pp0;
212
213         int                      rc = -ENOMEM;
214         U32                      port_id = 0xffffff;
215         int                      num_targ = 0;
216         int                      max_bus = ioc->facts.MaxBuses;
217         int                      max_targ = ioc->facts.MaxDevices;
218
219         if (max_bus == 0 || max_targ == 0)
220                 goto out;
221
222         data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;
223         p_p0 = p0_array =  kzalloc(data_sz, GFP_KERNEL);
224         if (!p0_array)
225                 goto out;
226
227         data_sz = sizeof(FCDevicePage0_t *) * max_bus * max_targ;
228         p_pp0 = pp0_array = kzalloc(data_sz, GFP_KERNEL);
229         if (!pp0_array)
230                 goto out;
231
232         do {
233                 /* Get FC Device Page 0 header */
234                 hdr.PageVersion = 0;
235                 hdr.PageLength = 0;
236                 hdr.PageNumber = 0;
237                 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_DEVICE;
238                 cfg.cfghdr.hdr = &hdr;
239                 cfg.physAddr = -1;
240                 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
241                 cfg.dir = 0;
242                 cfg.pageAddr = port_id;
243                 cfg.timeout = 0;
244
245                 if ((rc = mpt_config(ioc, &cfg)) != 0)
246                         break;
247
248                 if (hdr.PageLength <= 0)
249                         break;
250
251                 data_sz = hdr.PageLength * 4;
252                 ppage0_alloc = pci_alloc_consistent(ioc->pcidev, data_sz,
253                                                         &page0_dma);
254                 rc = -ENOMEM;
255                 if (!ppage0_alloc)
256                         break;
257
258                 cfg.physAddr = page0_dma;
259                 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
260
261                 if ((rc = mpt_config(ioc, &cfg)) == 0) {
262                         ppage0_alloc->PortIdentifier =
263                                 le32_to_cpu(ppage0_alloc->PortIdentifier);
264
265                         ppage0_alloc->WWNN.Low =
266                                 le32_to_cpu(ppage0_alloc->WWNN.Low);
267
268                         ppage0_alloc->WWNN.High =
269                                 le32_to_cpu(ppage0_alloc->WWNN.High);
270
271                         ppage0_alloc->WWPN.Low =
272                                 le32_to_cpu(ppage0_alloc->WWPN.Low);
273
274                         ppage0_alloc->WWPN.High =
275                                 le32_to_cpu(ppage0_alloc->WWPN.High);
276
277                         ppage0_alloc->BBCredit =
278                                 le16_to_cpu(ppage0_alloc->BBCredit);
279
280                         ppage0_alloc->MaxRxFrameSize =
281                                 le16_to_cpu(ppage0_alloc->MaxRxFrameSize);
282
283                         port_id = ppage0_alloc->PortIdentifier;
284                         num_targ++;
285                         *p_p0 = *ppage0_alloc;  /* save data */
286                         *p_pp0++ = p_p0++;      /* save addr */
287                 }
288                 pci_free_consistent(ioc->pcidev, data_sz,
289                                         (u8 *) ppage0_alloc, page0_dma);
290                 if (rc != 0)
291                         break;
292
293         } while (port_id <= 0xff0000);
294
295         if (num_targ) {
296                 /* sort array */
297                 if (num_targ > 1)
298                         sort (pp0_array, num_targ, sizeof(FCDevicePage0_t *),
299                                 mptfc_FcDevPage0_cmp_func, NULL);
300                 /* call caller's func for each targ */
301                 for (ii = 0; ii < num_targ;  ii++) {
302                         fc = *(pp0_array+ii);
303                         func(ioc, ioc_port, fc);
304                 }
305         }
306
307  out:
308         kfree(pp0_array);
309         kfree(p0_array);
310         return rc;
311 }
312
313 static int
314 mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
315 {
316         /* not currently usable */
317         if (pg0->Flags & (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID |
318                           MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID))
319                 return -1;
320
321         if (!(pg0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID))
322                 return -1;
323
324         if (!(pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET))
325                 return -1;
326
327         /*
328          * board data structure already normalized to platform endianness
329          * shifted to avoid unaligned access on 64 bit architecture
330          */
331         rid->node_name = ((u64)pg0->WWNN.High) << 32 | (u64)pg0->WWNN.Low;
332         rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;
333         rid->port_id =   pg0->PortIdentifier;
334         rid->roles = FC_RPORT_ROLE_UNKNOWN;
335
336         return 0;
337 }
338
339 static void
340 mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
341 {
342         struct fc_rport_identifiers rport_ids;
343         struct fc_rport         *rport;
344         struct mptfc_rport_info *ri;
345         int                     new_ri = 1;
346         u64                     pn, nn;
347         VirtTarget              *vtarget;
348         u32                     roles = FC_RPORT_ROLE_UNKNOWN;
349
350         if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
351                 return;
352
353         roles |= FC_RPORT_ROLE_FCP_TARGET;
354         if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
355                 roles |= FC_RPORT_ROLE_FCP_INITIATOR;
356
357         /* scan list looking for a match */
358         list_for_each_entry(ri, &ioc->fc_rports, list) {
359                 pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
360                 if (pn == rport_ids.port_name) {        /* match */
361                         list_move_tail(&ri->list, &ioc->fc_rports);
362                         new_ri = 0;
363                         break;
364                 }
365         }
366         if (new_ri) {   /* allocate one */
367                 ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
368                 if (!ri)
369                         return;
370                 list_add_tail(&ri->list, &ioc->fc_rports);
371         }
372
373         ri->pg0 = *pg0; /* add/update pg0 data */
374         ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING;
375
376         /* MPT_RPORT_INFO_FLAGS_REGISTERED - rport not previously deleted */
377         if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
378                 ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
379                 rport = fc_remote_port_add(ioc->sh, channel, &rport_ids);
380                 if (rport) {
381                         ri->rport = rport;
382                         if (new_ri) /* may have been reset by user */
383                                 rport->dev_loss_tmo = mptfc_dev_loss_tmo;
384                         /*
385                          * if already mapped, remap here.  If not mapped,
386                          * target_alloc will allocate vtarget and map,
387                          * slave_alloc will fill in vdev from vtarget.
388                          */
389                         if (ri->starget) {
390                                 vtarget = ri->starget->hostdata;
391                                 if (vtarget) {
392                                         vtarget->target_id = pg0->CurrentTargetID;
393                                         vtarget->bus_id = pg0->CurrentBus;
394                                 }
395                         }
396                         *((struct mptfc_rport_info **)rport->dd_data) = ri;
397                         /* scan will be scheduled once rport becomes a target */
398                         fc_remote_port_rolechg(rport,roles);
399
400                         pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
401                         nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
402                         dfcprintk ((MYIOC_s_INFO_FMT
403                                 "mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
404                                 "rport tid %d, tmo %d\n",
405                                         ioc->name,
406                                         ioc->sh->host_no,
407                                         pg0->PortIdentifier,
408                                         (unsigned long long)nn,
409                                         (unsigned long long)pn,
410                                         pg0->CurrentTargetID,
411                                         ri->rport->scsi_target_id,
412                                         ri->rport->dev_loss_tmo));
413                 } else {
414                         list_del(&ri->list);
415                         kfree(ri);
416                         ri = NULL;
417                 }
418         }
419 }
420
421 /*
422  *      OS entry point to allow for host driver to free allocated memory
423  *      Called if no device present or device being unloaded
424  */
425 static void
426 mptfc_target_destroy(struct scsi_target *starget)
427 {
428         struct fc_rport         *rport;
429         struct mptfc_rport_info *ri;
430
431         rport = starget_to_rport(starget);
432         if (rport) {
433                 ri = *((struct mptfc_rport_info **)rport->dd_data);
434                 if (ri) /* better be! */
435                         ri->starget = NULL;
436         }
437         if (starget->hostdata)
438                 kfree(starget->hostdata);
439         starget->hostdata = NULL;
440 }
441
442 /*
443  *      OS entry point to allow host driver to alloc memory
444  *      for each scsi target. Called once per device the bus scan.
445  *      Return non-zero if allocation fails.
446  */
447 static int
448 mptfc_target_alloc(struct scsi_target *starget)
449 {
450         VirtTarget              *vtarget;
451         struct fc_rport         *rport;
452         struct mptfc_rport_info *ri;
453         int                     rc;
454
455         vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
456         if (!vtarget)
457                 return -ENOMEM;
458         starget->hostdata = vtarget;
459
460         rc = -ENODEV;
461         rport = starget_to_rport(starget);
462         if (rport) {
463                 ri = *((struct mptfc_rport_info **)rport->dd_data);
464                 if (ri) {       /* better be! */
465                         vtarget->target_id = ri->pg0.CurrentTargetID;
466                         vtarget->bus_id = ri->pg0.CurrentBus;
467                         ri->starget = starget;
468                         rc = 0;
469                 }
470         }
471         if (rc != 0) {
472                 kfree(vtarget);
473                 starget->hostdata = NULL;
474         }
475
476         return rc;
477 }
478
479 /*
480  *      OS entry point to allow host driver to alloc memory
481  *      for each scsi device. Called once per device the bus scan.
482  *      Return non-zero if allocation fails.
483  *      Init memory once per LUN.
484  */
485 static int
486 mptfc_slave_alloc(struct scsi_device *sdev)
487 {
488         MPT_SCSI_HOST           *hd;
489         VirtTarget              *vtarget;
490         VirtDevice              *vdev;
491         struct scsi_target      *starget;
492         struct fc_rport         *rport;
493
494
495         starget = scsi_target(sdev);
496         rport = starget_to_rport(starget);
497
498         if (!rport || fc_remote_port_chkready(rport))
499                 return -ENXIO;
500
501         hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
502
503         vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
504         if (!vdev) {
505                 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
506                                 hd->ioc->name, sizeof(VirtDevice));
507                 return -ENOMEM;
508         }
509
510
511         sdev->hostdata = vdev;
512         vtarget = starget->hostdata;
513
514         if (vtarget->num_luns == 0) {
515                 vtarget->ioc_id = hd->ioc->id;
516                 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES |
517                                   MPT_TARGET_FLAGS_VALID_INQUIRY;
518                 hd->Targets[sdev->id] = vtarget;
519         }
520
521         vdev->vtarget = vtarget;
522         vdev->lun = sdev->lun;
523
524         vtarget->num_luns++;
525
526
527 #ifdef DMPT_DEBUG_FC
528         {
529         u64 nn, pn;
530         struct mptfc_rport_info *ri;
531         ri = *((struct mptfc_rport_info **)rport->dd_data);
532         pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
533         nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
534         dfcprintk ((MYIOC_s_INFO_FMT
535                 "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
536                 "CurrentTargetID %d, %x %llx %llx\n",
537                 hd->ioc->name,
538                 sdev->host->host_no,
539                 vtarget->num_luns,
540                 sdev->id, ri->pg0.CurrentTargetID,
541                 ri->pg0.PortIdentifier,
542                 (unsigned long long)pn,
543                 (unsigned long long)nn));
544         }
545 #endif
546
547         return 0;
548 }
549
550 static int
551 mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
552 {
553         struct mptfc_rport_info *ri;
554         struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
555         int             err;
556
557         err = fc_remote_port_chkready(rport);
558         if (unlikely(err)) {
559                 SCpnt->result = err;
560                 done(SCpnt);
561                 return 0;
562         }
563
564         /* dd_data is null until finished adding target */
565         ri = *((struct mptfc_rport_info **)rport->dd_data);
566         if (unlikely(!ri)) {
567                 dfcprintk ((MYIOC_s_INFO_FMT
568                         "mptfc_qcmd.%d: %d:%d, dd_data is null.\n",
569                         ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
570                         ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
571                         SCpnt->device->id,SCpnt->device->lun));
572                 SCpnt->result = DID_IMM_RETRY << 16;
573                 done(SCpnt);
574                 return 0;
575         }
576
577         err = mptscsih_qcmd(SCpnt,done);
578 #ifdef DMPT_DEBUG_FC
579         if (unlikely(err)) {
580                 dfcprintk ((MYIOC_s_INFO_FMT
581                         "mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero, (%x).\n",
582                         ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
583                         ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
584                         SCpnt->device->id,SCpnt->device->lun,err));
585         }
586 #endif
587         return err;
588 }
589
590 /*
591  *      mptfc_GetFcPortPage0 - Fetch FCPort config Page0.
592  *      @ioc: Pointer to MPT_ADAPTER structure
593  *      @portnum: IOC Port number
594  *
595  *      Return: 0 for success
596  *      -ENOMEM if no memory available
597  *              -EPERM if not allowed due to ISR context
598  *              -EAGAIN if no msg frames currently available
599  *              -EFAULT for non-successful reply or no reply (timeout)
600  *              -EINVAL portnum arg out of range (hardwired to two elements)
601  */
602 static int
603 mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
604 {
605         ConfigPageHeader_t       hdr;
606         CONFIGPARMS              cfg;
607         FCPortPage0_t           *ppage0_alloc;
608         FCPortPage0_t           *pp0dest;
609         dma_addr_t               page0_dma;
610         int                      data_sz;
611         int                      copy_sz;
612         int                      rc;
613         int                      count = 400;
614
615         if (portnum > 1)
616                 return -EINVAL;
617
618         /* Get FCPort Page 0 header */
619         hdr.PageVersion = 0;
620         hdr.PageLength = 0;
621         hdr.PageNumber = 0;
622         hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
623         cfg.cfghdr.hdr = &hdr;
624         cfg.physAddr = -1;
625         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
626         cfg.dir = 0;
627         cfg.pageAddr = portnum;
628         cfg.timeout = 0;
629
630         if ((rc = mpt_config(ioc, &cfg)) != 0)
631                 return rc;
632
633         if (hdr.PageLength == 0)
634                 return 0;
635
636         data_sz = hdr.PageLength * 4;
637         rc = -ENOMEM;
638         ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
639         if (ppage0_alloc) {
640
641  try_again:
642                 memset((u8 *)ppage0_alloc, 0, data_sz);
643                 cfg.physAddr = page0_dma;
644                 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
645
646                 if ((rc = mpt_config(ioc, &cfg)) == 0) {
647                         /* save the data */
648                         pp0dest = &ioc->fc_port_page0[portnum];
649                         copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
650                         memcpy(pp0dest, ppage0_alloc, copy_sz);
651
652                         /*
653                          *      Normalize endianness of structure data,
654                          *      by byte-swapping all > 1 byte fields!
655                          */
656                         pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
657                         pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
658                         pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
659                         pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
660                         pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
661                         pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
662                         pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
663                         pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
664                         pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
665                         pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
666                         pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
667                         pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
668                         pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
669                         pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
670                         pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
671                         pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
672
673                         /*
674                          * if still doing discovery,
675                          * hang loose a while until finished
676                          */
677                         if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {
678                                 if (count-- > 0) {
679                                         msleep(100);
680                                         goto try_again;
681                                 }
682                                 printk(MYIOC_s_INFO_FMT "Firmware discovery not"
683                                                         " complete.\n",
684                                                 ioc->name);
685                         }
686                 }
687
688                 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
689         }
690
691         return rc;
692 }
693
694 static int
695 mptfc_WriteFcPortPage1(MPT_ADAPTER *ioc, int portnum)
696 {
697         ConfigPageHeader_t       hdr;
698         CONFIGPARMS              cfg;
699         int                      rc;
700
701         if (portnum > 1)
702                 return -EINVAL;
703
704         if (!(ioc->fc_data.fc_port_page1[portnum].data))
705                 return -EINVAL;
706
707         /* get fcport page 1 header */
708         hdr.PageVersion = 0;
709         hdr.PageLength = 0;
710         hdr.PageNumber = 1;
711         hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
712         cfg.cfghdr.hdr = &hdr;
713         cfg.physAddr = -1;
714         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
715         cfg.dir = 0;
716         cfg.pageAddr = portnum;
717         cfg.timeout = 0;
718
719         if ((rc = mpt_config(ioc, &cfg)) != 0)
720                 return rc;
721
722         if (hdr.PageLength == 0)
723                 return -ENODEV;
724
725         if (hdr.PageLength*4 != ioc->fc_data.fc_port_page1[portnum].pg_sz)
726                 return -EINVAL;
727
728         cfg.physAddr = ioc->fc_data.fc_port_page1[portnum].dma;
729         cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
730         cfg.dir = 1;
731
732         rc = mpt_config(ioc, &cfg);
733
734         return rc;
735 }
736
737 static int
738 mptfc_GetFcPortPage1(MPT_ADAPTER *ioc, int portnum)
739 {
740         ConfigPageHeader_t       hdr;
741         CONFIGPARMS              cfg;
742         FCPortPage1_t           *page1_alloc;
743         dma_addr_t               page1_dma;
744         int                      data_sz;
745         int                      rc;
746
747         if (portnum > 1)
748                 return -EINVAL;
749
750         /* get fcport page 1 header */
751         hdr.PageVersion = 0;
752         hdr.PageLength = 0;
753         hdr.PageNumber = 1;
754         hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
755         cfg.cfghdr.hdr = &hdr;
756         cfg.physAddr = -1;
757         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
758         cfg.dir = 0;
759         cfg.pageAddr = portnum;
760         cfg.timeout = 0;
761
762         if ((rc = mpt_config(ioc, &cfg)) != 0)
763                 return rc;
764
765         if (hdr.PageLength == 0)
766                 return -ENODEV;
767
768 start_over:
769
770         if (ioc->fc_data.fc_port_page1[portnum].data == NULL) {
771                 data_sz = hdr.PageLength * 4;
772                 if (data_sz < sizeof(FCPortPage1_t))
773                         data_sz = sizeof(FCPortPage1_t);
774
775                 page1_alloc = (FCPortPage1_t *) pci_alloc_consistent(ioc->pcidev,
776                                                 data_sz,
777                                                 &page1_dma);
778                 if (!page1_alloc)
779                         return -ENOMEM;
780         }
781         else {
782                 page1_alloc = ioc->fc_data.fc_port_page1[portnum].data;
783                 page1_dma = ioc->fc_data.fc_port_page1[portnum].dma;
784                 data_sz = ioc->fc_data.fc_port_page1[portnum].pg_sz;
785                 if (hdr.PageLength * 4 > data_sz) {
786                         ioc->fc_data.fc_port_page1[portnum].data = NULL;
787                         pci_free_consistent(ioc->pcidev, data_sz, (u8 *)
788                                 page1_alloc, page1_dma);
789                         goto start_over;
790                 }
791         }
792
793         memset(page1_alloc,0,data_sz);
794
795         cfg.physAddr = page1_dma;
796         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
797
798         if ((rc = mpt_config(ioc, &cfg)) == 0) {
799                 ioc->fc_data.fc_port_page1[portnum].data = page1_alloc;
800                 ioc->fc_data.fc_port_page1[portnum].pg_sz = data_sz;
801                 ioc->fc_data.fc_port_page1[portnum].dma = page1_dma;
802         }
803         else {
804                 ioc->fc_data.fc_port_page1[portnum].data = NULL;
805                 pci_free_consistent(ioc->pcidev, data_sz, (u8 *)
806                         page1_alloc, page1_dma);
807         }
808
809         return rc;
810 }
811
812 static void
813 mptfc_SetFcPortPage1_defaults(MPT_ADAPTER *ioc)
814 {
815         int             ii;
816         FCPortPage1_t   *pp1;
817
818         #define MPTFC_FW_DEVICE_TIMEOUT (1)
819         #define MPTFC_FW_IO_PEND_TIMEOUT (1)
820         #define ON_FLAGS  (MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY)
821         #define OFF_FLAGS (MPI_FCPORTPAGE1_FLAGS_VERBOSE_RESCAN_EVENTS)
822
823         for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
824                 if (mptfc_GetFcPortPage1(ioc, ii) != 0)
825                         continue;
826                 pp1 = ioc->fc_data.fc_port_page1[ii].data;
827                 if ((pp1->InitiatorDeviceTimeout == MPTFC_FW_DEVICE_TIMEOUT)
828                  && (pp1->InitiatorIoPendTimeout == MPTFC_FW_IO_PEND_TIMEOUT)
829                  && ((pp1->Flags & ON_FLAGS) == ON_FLAGS)
830                  && ((pp1->Flags & OFF_FLAGS) == 0))
831                         continue;
832                 pp1->InitiatorDeviceTimeout = MPTFC_FW_DEVICE_TIMEOUT;
833                 pp1->InitiatorIoPendTimeout = MPTFC_FW_IO_PEND_TIMEOUT;
834                 pp1->Flags &= ~OFF_FLAGS;
835                 pp1->Flags |= ON_FLAGS;
836                 mptfc_WriteFcPortPage1(ioc, ii);
837         }
838 }
839
840
841 static void
842 mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
843 {
844         unsigned class = 0, cos = 0;
845
846         /* don't know what to do as only one scsi (fc) host was allocated */
847         if (portnum != 0)
848                 return;
849
850         class = ioc->fc_port_page0[portnum].SupportedServiceClass;
851         if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1)
852                 cos |= FC_COS_CLASS1;
853         if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2)
854                 cos |= FC_COS_CLASS2;
855         if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3)
856                 cos |= FC_COS_CLASS3;
857
858         fc_host_node_name(ioc->sh) =
859                 (u64)ioc->fc_port_page0[portnum].WWNN.High << 32
860                     | (u64)ioc->fc_port_page0[portnum].WWNN.Low;
861
862         fc_host_port_name(ioc->sh) =
863                 (u64)ioc->fc_port_page0[portnum].WWPN.High << 32
864                     | (u64)ioc->fc_port_page0[portnum].WWPN.Low;
865
866         fc_host_port_id(ioc->sh) = ioc->fc_port_page0[portnum].PortIdentifier;
867
868         fc_host_supported_classes(ioc->sh) = cos;
869
870         fc_host_tgtid_bind_type(ioc->sh) = FC_TGTID_BIND_BY_WWPN;
871 }
872
873 static void
874 mptfc_setup_reset(void *arg)
875 {
876         MPT_ADAPTER             *ioc = (MPT_ADAPTER *)arg;
877         u64                     pn;
878         struct mptfc_rport_info *ri;
879
880         /* reset about to happen, delete (block) all rports */
881         list_for_each_entry(ri, &ioc->fc_rports, list) {
882                 if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
883                         ri->flags &= ~MPT_RPORT_INFO_FLAGS_REGISTERED;
884                         fc_remote_port_delete(ri->rport);       /* won't sleep */
885                         ri->rport = NULL;
886
887                         pn = (u64)ri->pg0.WWPN.High << 32 |
888                              (u64)ri->pg0.WWPN.Low;
889                         dfcprintk ((MYIOC_s_INFO_FMT
890                                 "mptfc_setup_reset.%d: %llx deleted\n",
891                                 ioc->name,
892                                 ioc->sh->host_no,
893                                 (unsigned long long)pn));
894                 }
895         }
896 }
897
898 static void
899 mptfc_rescan_devices(void *arg)
900 {
901         MPT_ADAPTER             *ioc = (MPT_ADAPTER *)arg;
902         int                     ii;
903         int                     work_to_do;
904         u64                     pn;
905         unsigned long           flags;
906         struct mptfc_rport_info *ri;
907
908         do {
909                 /* start by tagging all ports as missing */
910                 list_for_each_entry(ri, &ioc->fc_rports, list) {
911                         if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
912                                 ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
913                         }
914                 }
915
916                 /*
917                  * now rescan devices known to adapter,
918                  * will reregister existing rports
919                  */
920                 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
921                         (void) mptfc_GetFcPortPage0(ioc, ii);
922                         mptfc_init_host_attr(ioc,ii);   /* refresh */
923                         mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
924                 }
925
926                 /* delete devices still missing */
927                 list_for_each_entry(ri, &ioc->fc_rports, list) {
928                         /* if newly missing, delete it */
929                         if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) {
930
931                                 ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
932                                                MPT_RPORT_INFO_FLAGS_MISSING);
933                                 fc_remote_port_delete(ri->rport);       /* won't sleep */
934                                 ri->rport = NULL;
935
936                                 pn = (u64)ri->pg0.WWPN.High << 32 |
937                                      (u64)ri->pg0.WWPN.Low;
938                                 dfcprintk ((MYIOC_s_INFO_FMT
939                                         "mptfc_rescan.%d: %llx deleted\n",
940                                         ioc->name,
941                                         ioc->sh->host_no,
942                                         (unsigned long long)pn));
943                         }
944                 }
945
946                 /*
947                  * allow multiple passes as target state
948                  * might have changed during scan
949                  */
950                 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
951                 if (ioc->fc_rescan_work_count > 2)      /* only need one more */
952                         ioc->fc_rescan_work_count = 2;
953                 work_to_do = --ioc->fc_rescan_work_count;
954                 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
955         } while (work_to_do);
956 }
957
958 static int
959 mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
960 {
961         struct Scsi_Host        *sh;
962         MPT_SCSI_HOST           *hd;
963         MPT_ADAPTER             *ioc;
964         unsigned long            flags;
965         int                      ii;
966         int                      numSGE = 0;
967         int                      scale;
968         int                      ioc_cap;
969         int                     error=0;
970         int                     r;
971
972         if ((r = mpt_attach(pdev,id)) != 0)
973                 return r;
974
975         ioc = pci_get_drvdata(pdev);
976         ioc->DoneCtx = mptfcDoneCtx;
977         ioc->TaskCtx = mptfcTaskCtx;
978         ioc->InternalCtx = mptfcInternalCtx;
979
980         /*  Added sanity check on readiness of the MPT adapter.
981          */
982         if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
983                 printk(MYIOC_s_WARN_FMT
984                   "Skipping because it's not operational!\n",
985                   ioc->name);
986                 error = -ENODEV;
987                 goto out_mptfc_probe;
988         }
989
990         if (!ioc->active) {
991                 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
992                   ioc->name);
993                 error = -ENODEV;
994                 goto out_mptfc_probe;
995         }
996
997         /*  Sanity check - ensure at least 1 port is INITIATOR capable
998          */
999         ioc_cap = 0;
1000         for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1001                 if (ioc->pfacts[ii].ProtocolFlags &
1002                     MPI_PORTFACTS_PROTOCOL_INITIATOR)
1003                         ioc_cap ++;
1004         }
1005
1006         if (!ioc_cap) {
1007                 printk(MYIOC_s_WARN_FMT
1008                         "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
1009                         ioc->name, ioc);
1010                 return -ENODEV;
1011         }
1012
1013         sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
1014
1015         if (!sh) {
1016                 printk(MYIOC_s_WARN_FMT
1017                         "Unable to register controller with SCSI subsystem\n",
1018                         ioc->name);
1019                 error = -1;
1020                 goto out_mptfc_probe;
1021         }
1022
1023         spin_lock_init(&ioc->fc_rescan_work_lock);
1024         INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc);
1025         INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset, (void *)ioc);
1026
1027         spin_lock_irqsave(&ioc->FreeQlock, flags);
1028
1029         /* Attach the SCSI Host to the IOC structure
1030          */
1031         ioc->sh = sh;
1032
1033         sh->io_port = 0;
1034         sh->n_io_port = 0;
1035         sh->irq = 0;
1036
1037         /* set 16 byte cdb's */
1038         sh->max_cmd_len = 16;
1039
1040         sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
1041
1042         sh->max_lun = MPT_LAST_LUN + 1;
1043         sh->max_channel = 0;
1044         sh->this_id = ioc->pfacts[0].PortSCSIID;
1045
1046         /* Required entry.
1047          */
1048         sh->unique_id = ioc->id;
1049
1050         /* Verify that we won't exceed the maximum
1051          * number of chain buffers
1052          * We can optimize:  ZZ = req_sz/sizeof(SGE)
1053          * For 32bit SGE's:
1054          *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1055          *               + (req_sz - 64)/sizeof(SGE)
1056          * A slightly different algorithm is required for
1057          * 64bit SGEs.
1058          */
1059         scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1060         if (sizeof(dma_addr_t) == sizeof(u64)) {
1061                 numSGE = (scale - 1) *
1062                   (ioc->facts.MaxChainDepth-1) + scale +
1063                   (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
1064                   sizeof(u32));
1065         } else {
1066                 numSGE = 1 + (scale - 1) *
1067                   (ioc->facts.MaxChainDepth-1) + scale +
1068                   (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
1069                   sizeof(u32));
1070         }
1071
1072         if (numSGE < sh->sg_tablesize) {
1073                 /* Reset this value */
1074                 dprintk((MYIOC_s_INFO_FMT
1075                   "Resetting sg_tablesize to %d from %d\n",
1076                   ioc->name, numSGE, sh->sg_tablesize));
1077                 sh->sg_tablesize = numSGE;
1078         }
1079
1080         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1081
1082         hd = (MPT_SCSI_HOST *) sh->hostdata;
1083         hd->ioc = ioc;
1084
1085         /* SCSI needs scsi_cmnd lookup table!
1086          * (with size equal to req_depth*PtrSz!)
1087          */
1088         hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
1089         if (!hd->ScsiLookup) {
1090                 error = -ENOMEM;
1091                 goto out_mptfc_probe;
1092         }
1093
1094         dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
1095                  ioc->name, hd->ScsiLookup));
1096
1097         /* Allocate memory for the device structures.
1098          * A non-Null pointer at an offset
1099          * indicates a device exists.
1100          * max_id = 1 + maximum id (hosts.h)
1101          */
1102         hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
1103         if (!hd->Targets) {
1104                 error = -ENOMEM;
1105                 goto out_mptfc_probe;
1106         }
1107
1108         dprintk((KERN_INFO "  vdev @ %p\n", hd->Targets));
1109
1110         /* Clear the TM flags
1111          */
1112         hd->tmPending = 0;
1113         hd->tmState = TM_STATE_NONE;
1114         hd->resetPending = 0;
1115         hd->abortSCpnt = NULL;
1116
1117         /* Clear the pointer used to store
1118          * single-threaded commands, i.e., those
1119          * issued during a bus scan, dv and
1120          * configuration pages.
1121          */
1122         hd->cmdPtr = NULL;
1123
1124         /* Initialize this SCSI Hosts' timers
1125          * To use, set the timer expires field
1126          * and add_timer
1127          */
1128         init_timer(&hd->timer);
1129         hd->timer.data = (unsigned long) hd;
1130         hd->timer.function = mptscsih_timer_expired;
1131
1132         hd->mpt_pq_filter = mpt_pq_filter;
1133
1134         ddvprintk((MYIOC_s_INFO_FMT
1135                 "mpt_pq_filter %x\n",
1136                 ioc->name, 
1137                 mpt_pq_filter));
1138
1139         init_waitqueue_head(&hd->scandv_waitq);
1140         hd->scandv_wait_done = 0;
1141         hd->last_queue_full = 0;
1142
1143         sh->transportt = mptfc_transport_template;
1144         error = scsi_add_host (sh, &ioc->pcidev->dev);
1145         if(error) {
1146                 dprintk((KERN_ERR MYNAM
1147                   "scsi_add_host failed\n"));
1148                 goto out_mptfc_probe;
1149         }
1150
1151         /* initialize workqueue */
1152
1153         snprintf(ioc->fc_rescan_work_q_name, KOBJ_NAME_LEN, "mptfc_wq_%d",
1154                 sh->host_no);
1155         ioc->fc_rescan_work_q =
1156                 create_singlethread_workqueue(ioc->fc_rescan_work_q_name);
1157         if (!ioc->fc_rescan_work_q)
1158                 goto out_mptfc_probe;
1159
1160         /*
1161          *  Pre-fetch FC port WWN and stuff...
1162          *  (FCPortPage0_t stuff)
1163          */
1164         for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1165                 (void) mptfc_GetFcPortPage0(ioc, ii);
1166         }
1167         mptfc_SetFcPortPage1_defaults(ioc);
1168
1169         /*
1170          * scan for rports -
1171          *      by doing it via the workqueue, some locking is eliminated
1172          */
1173
1174         ioc->fc_rescan_work_count = 1;
1175         queue_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work);
1176         flush_workqueue(ioc->fc_rescan_work_q);
1177
1178         return 0;
1179
1180 out_mptfc_probe:
1181
1182         mptscsih_remove(pdev);
1183         return error;
1184 }
1185
1186 static struct pci_driver mptfc_driver = {
1187         .name           = "mptfc",
1188         .id_table       = mptfc_pci_table,
1189         .probe          = mptfc_probe,
1190         .remove         = __devexit_p(mptfc_remove),
1191         .shutdown       = mptscsih_shutdown,
1192 #ifdef CONFIG_PM
1193         .suspend        = mptscsih_suspend,
1194         .resume         = mptscsih_resume,
1195 #endif
1196 };
1197
1198 static int
1199 mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
1200 {
1201         MPT_SCSI_HOST *hd;
1202         u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
1203         unsigned long flags;
1204         int rc=1;
1205
1206         devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
1207                         ioc->name, event));
1208
1209         if (ioc->sh == NULL ||
1210                 ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
1211                 return 1;
1212
1213         switch (event) {
1214         case MPI_EVENT_RESCAN:
1215                 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1216                 if (ioc->fc_rescan_work_q) {
1217                         if (ioc->fc_rescan_work_count++ == 0) {
1218                                 queue_work(ioc->fc_rescan_work_q,
1219                                            &ioc->fc_rescan_work);
1220                         }
1221                 }
1222                 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1223                 break;
1224         default:
1225                 rc = mptscsih_event_process(ioc,pEvReply);
1226                 break;
1227         }
1228         return rc;
1229 }
1230
1231 static int
1232 mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
1233 {
1234         int             rc;
1235         unsigned long   flags;
1236
1237         rc = mptscsih_ioc_reset(ioc,reset_phase);
1238         if (rc == 0)
1239                 return rc;
1240
1241
1242         dtmprintk((KERN_WARNING MYNAM
1243                 ": IOC %s_reset routed to FC host driver!\n",
1244                 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
1245                 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
1246
1247         if (reset_phase == MPT_IOC_SETUP_RESET) {
1248                 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1249                 if (ioc->fc_rescan_work_q) {
1250                         queue_work(ioc->fc_rescan_work_q,
1251                                    &ioc->fc_setup_reset_work);
1252                 }
1253                 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1254         }
1255
1256         else if (reset_phase == MPT_IOC_PRE_RESET) {
1257         }
1258
1259         else {  /* MPT_IOC_POST_RESET */
1260                 mptfc_SetFcPortPage1_defaults(ioc);
1261                 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1262                 if (ioc->fc_rescan_work_q) {
1263                         if (ioc->fc_rescan_work_count++ == 0) {
1264                                 queue_work(ioc->fc_rescan_work_q,
1265                                            &ioc->fc_rescan_work);
1266                         }
1267                 }
1268                 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1269         }
1270         return 1;
1271 }
1272
1273 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1274 /**
1275  *      mptfc_init - Register MPT adapter(s) as SCSI host(s) with
1276  *      linux scsi mid-layer.
1277  *
1278  *      Returns 0 for success, non-zero for failure.
1279  */
1280 static int __init
1281 mptfc_init(void)
1282 {
1283         int error;
1284
1285         show_mptmod_ver(my_NAME, my_VERSION);
1286
1287         /* sanity check module parameters */
1288         if (mptfc_dev_loss_tmo <= 0)
1289                 mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
1290
1291         mptfc_transport_template =
1292                 fc_attach_transport(&mptfc_transport_functions);
1293
1294         if (!mptfc_transport_template)
1295                 return -ENODEV;
1296
1297         mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);
1298         mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
1299         mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
1300
1301         if (mpt_event_register(mptfcDoneCtx, mptfc_event_process) == 0) {
1302                 devtverboseprintk((KERN_INFO MYNAM
1303                   ": Registered for IOC event notifications\n"));
1304         }
1305
1306         if (mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset) == 0) {
1307                 dprintk((KERN_INFO MYNAM
1308                   ": Registered for IOC reset notifications\n"));
1309         }
1310
1311         error = pci_register_driver(&mptfc_driver);
1312         if (error)
1313                 fc_release_transport(mptfc_transport_template);
1314
1315         return error;
1316 }
1317
1318 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1319 /**
1320  *      mptfc_remove - Removed fc infrastructure for devices
1321  *      @pdev: Pointer to pci_dev structure
1322  *
1323  */
1324 static void __devexit
1325 mptfc_remove(struct pci_dev *pdev)
1326 {
1327         MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
1328         struct mptfc_rport_info *p, *n;
1329         struct workqueue_struct *work_q;
1330         unsigned long           flags;
1331         int                     ii;
1332
1333         /* destroy workqueue */
1334         if ((work_q=ioc->fc_rescan_work_q)) {
1335                 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1336                 ioc->fc_rescan_work_q = NULL;
1337                 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1338                 destroy_workqueue(work_q);
1339         }
1340
1341         fc_remove_host(ioc->sh);
1342
1343         list_for_each_entry_safe(p, n, &ioc->fc_rports, list) {
1344                 list_del(&p->list);
1345                 kfree(p);
1346         }
1347
1348         for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
1349                 if (ioc->fc_data.fc_port_page1[ii].data) {
1350                         pci_free_consistent(ioc->pcidev,
1351                                 ioc->fc_data.fc_port_page1[ii].pg_sz,
1352                                 (u8 *) ioc->fc_data.fc_port_page1[ii].data,
1353                                 ioc->fc_data.fc_port_page1[ii].dma);
1354                         ioc->fc_data.fc_port_page1[ii].data = NULL;
1355                 }
1356         }
1357
1358         mptscsih_remove(pdev);
1359 }
1360
1361 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1362 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1363 /**
1364  *      mptfc_exit - Unregisters MPT adapter(s)
1365  *
1366  */
1367 static void __exit
1368 mptfc_exit(void)
1369 {
1370         pci_unregister_driver(&mptfc_driver);
1371         fc_release_transport(mptfc_transport_template);
1372
1373         mpt_reset_deregister(mptfcDoneCtx);
1374         dprintk((KERN_INFO MYNAM
1375           ": Deregistered for IOC reset notifications\n"));
1376
1377         mpt_event_deregister(mptfcDoneCtx);
1378         dprintk((KERN_INFO MYNAM
1379           ": Deregistered for IOC event notifications\n"));
1380
1381         mpt_deregister(mptfcInternalCtx);
1382         mpt_deregister(mptfcTaskCtx);
1383         mpt_deregister(mptfcDoneCtx);
1384 }
1385
1386 module_init(mptfc_init);
1387 module_exit(mptfc_exit);