[SCSI] mptsas: Adding 1078 ROC support
[linux-2.6] / 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, MPI_MANUFACTPAGE_DEVICEID_FC909,
136                 PCI_ANY_ID, PCI_ANY_ID },
137         { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC919,
138                 PCI_ANY_ID, PCI_ANY_ID },
139         { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC929,
140                 PCI_ANY_ID, PCI_ANY_ID },
141         { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC919X,
142                 PCI_ANY_ID, PCI_ANY_ID },
143         { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC929X,
144                 PCI_ANY_ID, PCI_ANY_ID },
145         { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC939X,
146                 PCI_ANY_ID, PCI_ANY_ID },
147         { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949X,
148                 PCI_ANY_ID, PCI_ANY_ID },
149         { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949E,
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         if (pp0_array)
309                 kfree(pp0_array);
310         if (p0_array)
311                 kfree(p0_array);
312         return rc;
313 }
314
315 static int
316 mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
317 {
318         /* not currently usable */
319         if (pg0->Flags & (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID |
320                           MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID))
321                 return -1;
322
323         if (!(pg0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID))
324                 return -1;
325
326         if (!(pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET))
327                 return -1;
328
329         /*
330          * board data structure already normalized to platform endianness
331          * shifted to avoid unaligned access on 64 bit architecture
332          */
333         rid->node_name = ((u64)pg0->WWNN.High) << 32 | (u64)pg0->WWNN.Low;
334         rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;
335         rid->port_id =   pg0->PortIdentifier;
336         rid->roles = FC_RPORT_ROLE_UNKNOWN;
337
338         return 0;
339 }
340
341 static void
342 mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
343 {
344         struct fc_rport_identifiers rport_ids;
345         struct fc_rport         *rport;
346         struct mptfc_rport_info *ri;
347         int                     new_ri = 1;
348         u64                     pn, nn;
349         VirtTarget              *vtarget;
350         u32                     roles = FC_RPORT_ROLE_UNKNOWN;
351
352         if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
353                 return;
354
355         roles |= FC_RPORT_ROLE_FCP_TARGET;
356         if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
357                 roles |= FC_RPORT_ROLE_FCP_INITIATOR;
358
359         /* scan list looking for a match */
360         list_for_each_entry(ri, &ioc->fc_rports, list) {
361                 pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
362                 if (pn == rport_ids.port_name) {        /* match */
363                         list_move_tail(&ri->list, &ioc->fc_rports);
364                         new_ri = 0;
365                         break;
366                 }
367         }
368         if (new_ri) {   /* allocate one */
369                 ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
370                 if (!ri)
371                         return;
372                 list_add_tail(&ri->list, &ioc->fc_rports);
373         }
374
375         ri->pg0 = *pg0; /* add/update pg0 data */
376         ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING;
377
378         /* MPT_RPORT_INFO_FLAGS_REGISTERED - rport not previously deleted */
379         if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
380                 ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
381                 rport = fc_remote_port_add(ioc->sh, channel, &rport_ids);
382                 if (rport) {
383                         ri->rport = rport;
384                         if (new_ri) /* may have been reset by user */
385                                 rport->dev_loss_tmo = mptfc_dev_loss_tmo;
386                         /*
387                          * if already mapped, remap here.  If not mapped,
388                          * target_alloc will allocate vtarget and map,
389                          * slave_alloc will fill in vdev from vtarget.
390                          */
391                         if (ri->starget) {
392                                 vtarget = ri->starget->hostdata;
393                                 if (vtarget) {
394                                         vtarget->target_id = pg0->CurrentTargetID;
395                                         vtarget->bus_id = pg0->CurrentBus;
396                                 }
397                         }
398                         *((struct mptfc_rport_info **)rport->dd_data) = ri;
399                         /* scan will be scheduled once rport becomes a target */
400                         fc_remote_port_rolechg(rport,roles);
401
402                         pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
403                         nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
404                         dfcprintk ((MYIOC_s_INFO_FMT
405                                 "mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
406                                 "rport tid %d, tmo %d\n",
407                                         ioc->name,
408                                         ioc->sh->host_no,
409                                         pg0->PortIdentifier,
410                                         (unsigned long long)nn,
411                                         (unsigned long long)pn,
412                                         pg0->CurrentTargetID,
413                                         ri->rport->scsi_target_id,
414                                         ri->rport->dev_loss_tmo));
415                 } else {
416                         list_del(&ri->list);
417                         kfree(ri);
418                         ri = NULL;
419                 }
420         }
421 }
422
423 /*
424  *      OS entry point to allow for host driver to free allocated memory
425  *      Called if no device present or device being unloaded
426  */
427 static void
428 mptfc_target_destroy(struct scsi_target *starget)
429 {
430         struct fc_rport         *rport;
431         struct mptfc_rport_info *ri;
432
433         rport = starget_to_rport(starget);
434         if (rport) {
435                 ri = *((struct mptfc_rport_info **)rport->dd_data);
436                 if (ri) /* better be! */
437                         ri->starget = NULL;
438         }
439         if (starget->hostdata)
440                 kfree(starget->hostdata);
441         starget->hostdata = NULL;
442 }
443
444 /*
445  *      OS entry point to allow host driver to alloc memory
446  *      for each scsi target. Called once per device the bus scan.
447  *      Return non-zero if allocation fails.
448  */
449 static int
450 mptfc_target_alloc(struct scsi_target *starget)
451 {
452         VirtTarget              *vtarget;
453         struct fc_rport         *rport;
454         struct mptfc_rport_info *ri;
455         int                     rc;
456
457         vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
458         if (!vtarget)
459                 return -ENOMEM;
460         starget->hostdata = vtarget;
461
462         rc = -ENODEV;
463         rport = starget_to_rport(starget);
464         if (rport) {
465                 ri = *((struct mptfc_rport_info **)rport->dd_data);
466                 if (ri) {       /* better be! */
467                         vtarget->target_id = ri->pg0.CurrentTargetID;
468                         vtarget->bus_id = ri->pg0.CurrentBus;
469                         ri->starget = starget;
470                         rc = 0;
471                 }
472         }
473         if (rc != 0) {
474                 kfree(vtarget);
475                 starget->hostdata = NULL;
476         }
477
478         return rc;
479 }
480
481 /*
482  *      OS entry point to allow host driver to alloc memory
483  *      for each scsi device. Called once per device the bus scan.
484  *      Return non-zero if allocation fails.
485  *      Init memory once per LUN.
486  */
487 static int
488 mptfc_slave_alloc(struct scsi_device *sdev)
489 {
490         MPT_SCSI_HOST           *hd;
491         VirtTarget              *vtarget;
492         VirtDevice              *vdev;
493         struct scsi_target      *starget;
494         struct fc_rport         *rport;
495
496
497         starget = scsi_target(sdev);
498         rport = starget_to_rport(starget);
499
500         if (!rport || fc_remote_port_chkready(rport))
501                 return -ENXIO;
502
503         hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
504
505         vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
506         if (!vdev) {
507                 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
508                                 hd->ioc->name, sizeof(VirtDevice));
509                 return -ENOMEM;
510         }
511
512
513         sdev->hostdata = vdev;
514         vtarget = starget->hostdata;
515
516         if (vtarget->num_luns == 0) {
517                 vtarget->ioc_id = hd->ioc->id;
518                 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES |
519                                   MPT_TARGET_FLAGS_VALID_INQUIRY;
520                 hd->Targets[sdev->id] = vtarget;
521         }
522
523         vdev->vtarget = vtarget;
524         vdev->lun = sdev->lun;
525
526         vtarget->num_luns++;
527
528
529 #ifdef DMPT_DEBUG_FC
530         {
531         u64 nn, pn;
532         struct mptfc_rport_info *ri;
533         ri = *((struct mptfc_rport_info **)rport->dd_data);
534         pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
535         nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
536         dfcprintk ((MYIOC_s_INFO_FMT
537                 "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
538                 "CurrentTargetID %d, %x %llx %llx\n",
539                 hd->ioc->name,
540                 sdev->host->host_no,
541                 vtarget->num_luns,
542                 sdev->id, ri->pg0.CurrentTargetID,
543                 ri->pg0.PortIdentifier,
544                 (unsigned long long)pn,
545                 (unsigned long long)nn));
546         }
547 #endif
548
549         return 0;
550 }
551
552 static int
553 mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
554 {
555         struct mptfc_rport_info *ri;
556         struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
557         int             err;
558
559         err = fc_remote_port_chkready(rport);
560         if (unlikely(err)) {
561                 SCpnt->result = err;
562                 done(SCpnt);
563                 return 0;
564         }
565
566         /* dd_data is null until finished adding target */
567         ri = *((struct mptfc_rport_info **)rport->dd_data);
568         if (unlikely(!ri)) {
569                 dfcprintk ((MYIOC_s_INFO_FMT
570                         "mptfc_qcmd.%d: %d:%d, dd_data is null.\n",
571                         ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
572                         ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
573                         SCpnt->device->id,SCpnt->device->lun));
574                 SCpnt->result = DID_IMM_RETRY << 16;
575                 done(SCpnt);
576                 return 0;
577         }
578
579         err = mptscsih_qcmd(SCpnt,done);
580 #ifdef DMPT_DEBUG_FC
581         if (unlikely(err)) {
582                 dfcprintk ((MYIOC_s_INFO_FMT
583                         "mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero, (%x).\n",
584                         ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
585                         ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
586                         SCpnt->device->id,SCpnt->device->lun,err));
587         }
588 #endif
589         return err;
590 }
591
592 /*
593  *      mptfc_GetFcPortPage0 - Fetch FCPort config Page0.
594  *      @ioc: Pointer to MPT_ADAPTER structure
595  *      @portnum: IOC Port number
596  *
597  *      Return: 0 for success
598  *      -ENOMEM if no memory available
599  *              -EPERM if not allowed due to ISR context
600  *              -EAGAIN if no msg frames currently available
601  *              -EFAULT for non-successful reply or no reply (timeout)
602  *              -EINVAL portnum arg out of range (hardwired to two elements)
603  */
604 static int
605 mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
606 {
607         ConfigPageHeader_t       hdr;
608         CONFIGPARMS              cfg;
609         FCPortPage0_t           *ppage0_alloc;
610         FCPortPage0_t           *pp0dest;
611         dma_addr_t               page0_dma;
612         int                      data_sz;
613         int                      copy_sz;
614         int                      rc;
615         int                      count = 400;
616
617         if (portnum > 1)
618                 return -EINVAL;
619
620         /* Get FCPort Page 0 header */
621         hdr.PageVersion = 0;
622         hdr.PageLength = 0;
623         hdr.PageNumber = 0;
624         hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
625         cfg.cfghdr.hdr = &hdr;
626         cfg.physAddr = -1;
627         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
628         cfg.dir = 0;
629         cfg.pageAddr = portnum;
630         cfg.timeout = 0;
631
632         if ((rc = mpt_config(ioc, &cfg)) != 0)
633                 return rc;
634
635         if (hdr.PageLength == 0)
636                 return 0;
637
638         data_sz = hdr.PageLength * 4;
639         rc = -ENOMEM;
640         ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
641         if (ppage0_alloc) {
642
643  try_again:
644                 memset((u8 *)ppage0_alloc, 0, data_sz);
645                 cfg.physAddr = page0_dma;
646                 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
647
648                 if ((rc = mpt_config(ioc, &cfg)) == 0) {
649                         /* save the data */
650                         pp0dest = &ioc->fc_port_page0[portnum];
651                         copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
652                         memcpy(pp0dest, ppage0_alloc, copy_sz);
653
654                         /*
655                          *      Normalize endianness of structure data,
656                          *      by byte-swapping all > 1 byte fields!
657                          */
658                         pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
659                         pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
660                         pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
661                         pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
662                         pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
663                         pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
664                         pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
665                         pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
666                         pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
667                         pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
668                         pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
669                         pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
670                         pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
671                         pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
672                         pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
673                         pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
674
675                         /*
676                          * if still doing discovery,
677                          * hang loose a while until finished
678                          */
679                         if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {
680                                 if (count-- > 0) {
681                                         msleep(100);
682                                         goto try_again;
683                                 }
684                                 printk(MYIOC_s_INFO_FMT "Firmware discovery not"
685                                                         " complete.\n",
686                                                 ioc->name);
687                         }
688                 }
689
690                 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
691         }
692
693         return rc;
694 }
695
696 static int
697 mptfc_WriteFcPortPage1(MPT_ADAPTER *ioc, int portnum)
698 {
699         ConfigPageHeader_t       hdr;
700         CONFIGPARMS              cfg;
701         int                      rc;
702
703         if (portnum > 1)
704                 return -EINVAL;
705
706         if (!(ioc->fc_data.fc_port_page1[portnum].data))
707                 return -EINVAL;
708
709         /* get fcport page 1 header */
710         hdr.PageVersion = 0;
711         hdr.PageLength = 0;
712         hdr.PageNumber = 1;
713         hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
714         cfg.cfghdr.hdr = &hdr;
715         cfg.physAddr = -1;
716         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
717         cfg.dir = 0;
718         cfg.pageAddr = portnum;
719         cfg.timeout = 0;
720
721         if ((rc = mpt_config(ioc, &cfg)) != 0)
722                 return rc;
723
724         if (hdr.PageLength == 0)
725                 return -ENODEV;
726
727         if (hdr.PageLength*4 != ioc->fc_data.fc_port_page1[portnum].pg_sz)
728                 return -EINVAL;
729
730         cfg.physAddr = ioc->fc_data.fc_port_page1[portnum].dma;
731         cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
732         cfg.dir = 1;
733
734         rc = mpt_config(ioc, &cfg);
735
736         return rc;
737 }
738
739 static int
740 mptfc_GetFcPortPage1(MPT_ADAPTER *ioc, int portnum)
741 {
742         ConfigPageHeader_t       hdr;
743         CONFIGPARMS              cfg;
744         FCPortPage1_t           *page1_alloc;
745         dma_addr_t               page1_dma;
746         int                      data_sz;
747         int                      rc;
748
749         if (portnum > 1)
750                 return -EINVAL;
751
752         /* get fcport page 1 header */
753         hdr.PageVersion = 0;
754         hdr.PageLength = 0;
755         hdr.PageNumber = 1;
756         hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
757         cfg.cfghdr.hdr = &hdr;
758         cfg.physAddr = -1;
759         cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
760         cfg.dir = 0;
761         cfg.pageAddr = portnum;
762         cfg.timeout = 0;
763
764         if ((rc = mpt_config(ioc, &cfg)) != 0)
765                 return rc;
766
767         if (hdr.PageLength == 0)
768                 return -ENODEV;
769
770 start_over:
771
772         if (ioc->fc_data.fc_port_page1[portnum].data == NULL) {
773                 data_sz = hdr.PageLength * 4;
774                 if (data_sz < sizeof(FCPortPage1_t))
775                         data_sz = sizeof(FCPortPage1_t);
776
777                 page1_alloc = (FCPortPage1_t *) pci_alloc_consistent(ioc->pcidev,
778                                                 data_sz,
779                                                 &page1_dma);
780                 if (!page1_alloc)
781                         return -ENOMEM;
782         }
783         else {
784                 page1_alloc = ioc->fc_data.fc_port_page1[portnum].data;
785                 page1_dma = ioc->fc_data.fc_port_page1[portnum].dma;
786                 data_sz = ioc->fc_data.fc_port_page1[portnum].pg_sz;
787                 if (hdr.PageLength * 4 > data_sz) {
788                         ioc->fc_data.fc_port_page1[portnum].data = NULL;
789                         pci_free_consistent(ioc->pcidev, data_sz, (u8 *)
790                                 page1_alloc, page1_dma);
791                         goto start_over;
792                 }
793         }
794
795         memset(page1_alloc,0,data_sz);
796
797         cfg.physAddr = page1_dma;
798         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
799
800         if ((rc = mpt_config(ioc, &cfg)) == 0) {
801                 ioc->fc_data.fc_port_page1[portnum].data = page1_alloc;
802                 ioc->fc_data.fc_port_page1[portnum].pg_sz = data_sz;
803                 ioc->fc_data.fc_port_page1[portnum].dma = page1_dma;
804         }
805         else {
806                 ioc->fc_data.fc_port_page1[portnum].data = NULL;
807                 pci_free_consistent(ioc->pcidev, data_sz, (u8 *)
808                         page1_alloc, page1_dma);
809         }
810
811         return rc;
812 }
813
814 static void
815 mptfc_SetFcPortPage1_defaults(MPT_ADAPTER *ioc)
816 {
817         int             ii;
818         FCPortPage1_t   *pp1;
819
820         #define MPTFC_FW_DEVICE_TIMEOUT (1)
821         #define MPTFC_FW_IO_PEND_TIMEOUT (1)
822         #define ON_FLAGS  (MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY)
823         #define OFF_FLAGS (MPI_FCPORTPAGE1_FLAGS_VERBOSE_RESCAN_EVENTS)
824
825         for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
826                 if (mptfc_GetFcPortPage1(ioc, ii) != 0)
827                         continue;
828                 pp1 = ioc->fc_data.fc_port_page1[ii].data;
829                 if ((pp1->InitiatorDeviceTimeout == MPTFC_FW_DEVICE_TIMEOUT)
830                  && (pp1->InitiatorIoPendTimeout == MPTFC_FW_IO_PEND_TIMEOUT)
831                  && ((pp1->Flags & ON_FLAGS) == ON_FLAGS)
832                  && ((pp1->Flags & OFF_FLAGS) == 0))
833                         continue;
834                 pp1->InitiatorDeviceTimeout = MPTFC_FW_DEVICE_TIMEOUT;
835                 pp1->InitiatorIoPendTimeout = MPTFC_FW_IO_PEND_TIMEOUT;
836                 pp1->Flags &= ~OFF_FLAGS;
837                 pp1->Flags |= ON_FLAGS;
838                 mptfc_WriteFcPortPage1(ioc, ii);
839         }
840 }
841
842
843 static void
844 mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
845 {
846         unsigned class = 0, cos = 0;
847
848         /* don't know what to do as only one scsi (fc) host was allocated */
849         if (portnum != 0)
850                 return;
851
852         class = ioc->fc_port_page0[portnum].SupportedServiceClass;
853         if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1)
854                 cos |= FC_COS_CLASS1;
855         if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2)
856                 cos |= FC_COS_CLASS2;
857         if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3)
858                 cos |= FC_COS_CLASS3;
859
860         fc_host_node_name(ioc->sh) =
861                 (u64)ioc->fc_port_page0[portnum].WWNN.High << 32
862                     | (u64)ioc->fc_port_page0[portnum].WWNN.Low;
863
864         fc_host_port_name(ioc->sh) =
865                 (u64)ioc->fc_port_page0[portnum].WWPN.High << 32
866                     | (u64)ioc->fc_port_page0[portnum].WWPN.Low;
867
868         fc_host_port_id(ioc->sh) = ioc->fc_port_page0[portnum].PortIdentifier;
869
870         fc_host_supported_classes(ioc->sh) = cos;
871
872         fc_host_tgtid_bind_type(ioc->sh) = FC_TGTID_BIND_BY_WWPN;
873 }
874
875 static void
876 mptfc_setup_reset(void *arg)
877 {
878         MPT_ADAPTER             *ioc = (MPT_ADAPTER *)arg;
879         u64                     pn;
880         struct mptfc_rport_info *ri;
881
882         /* reset about to happen, delete (block) all rports */
883         list_for_each_entry(ri, &ioc->fc_rports, list) {
884                 if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
885                         ri->flags &= ~MPT_RPORT_INFO_FLAGS_REGISTERED;
886                         fc_remote_port_delete(ri->rport);       /* won't sleep */
887                         ri->rport = NULL;
888
889                         pn = (u64)ri->pg0.WWPN.High << 32 |
890                              (u64)ri->pg0.WWPN.Low;
891                         dfcprintk ((MYIOC_s_INFO_FMT
892                                 "mptfc_setup_reset.%d: %llx deleted\n",
893                                 ioc->name,
894                                 ioc->sh->host_no,
895                                 (unsigned long long)pn));
896                 }
897         }
898 }
899
900 static void
901 mptfc_rescan_devices(void *arg)
902 {
903         MPT_ADAPTER             *ioc = (MPT_ADAPTER *)arg;
904         int                     ii;
905         int                     work_to_do;
906         u64                     pn;
907         unsigned long           flags;
908         struct mptfc_rport_info *ri;
909
910         do {
911                 /* start by tagging all ports as missing */
912                 list_for_each_entry(ri, &ioc->fc_rports, list) {
913                         if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
914                                 ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
915                         }
916                 }
917
918                 /*
919                  * now rescan devices known to adapter,
920                  * will reregister existing rports
921                  */
922                 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
923                         (void) mptfc_GetFcPortPage0(ioc, ii);
924                         mptfc_init_host_attr(ioc,ii);   /* refresh */
925                         mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
926                 }
927
928                 /* delete devices still missing */
929                 list_for_each_entry(ri, &ioc->fc_rports, list) {
930                         /* if newly missing, delete it */
931                         if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) {
932
933                                 ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
934                                                MPT_RPORT_INFO_FLAGS_MISSING);
935                                 fc_remote_port_delete(ri->rport);       /* won't sleep */
936                                 ri->rport = NULL;
937
938                                 pn = (u64)ri->pg0.WWPN.High << 32 |
939                                      (u64)ri->pg0.WWPN.Low;
940                                 dfcprintk ((MYIOC_s_INFO_FMT
941                                         "mptfc_rescan.%d: %llx deleted\n",
942                                         ioc->name,
943                                         ioc->sh->host_no,
944                                         (unsigned long long)pn));
945                         }
946                 }
947
948                 /*
949                  * allow multiple passes as target state
950                  * might have changed during scan
951                  */
952                 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
953                 if (ioc->fc_rescan_work_count > 2)      /* only need one more */
954                         ioc->fc_rescan_work_count = 2;
955                 work_to_do = --ioc->fc_rescan_work_count;
956                 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
957         } while (work_to_do);
958 }
959
960 static int
961 mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
962 {
963         struct Scsi_Host        *sh;
964         MPT_SCSI_HOST           *hd;
965         MPT_ADAPTER             *ioc;
966         unsigned long            flags;
967         int                      ii;
968         int                      numSGE = 0;
969         int                      scale;
970         int                      ioc_cap;
971         int                     error=0;
972         int                     r;
973
974         if ((r = mpt_attach(pdev,id)) != 0)
975                 return r;
976
977         ioc = pci_get_drvdata(pdev);
978         ioc->DoneCtx = mptfcDoneCtx;
979         ioc->TaskCtx = mptfcTaskCtx;
980         ioc->InternalCtx = mptfcInternalCtx;
981
982         /*  Added sanity check on readiness of the MPT adapter.
983          */
984         if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
985                 printk(MYIOC_s_WARN_FMT
986                   "Skipping because it's not operational!\n",
987                   ioc->name);
988                 error = -ENODEV;
989                 goto out_mptfc_probe;
990         }
991
992         if (!ioc->active) {
993                 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
994                   ioc->name);
995                 error = -ENODEV;
996                 goto out_mptfc_probe;
997         }
998
999         /*  Sanity check - ensure at least 1 port is INITIATOR capable
1000          */
1001         ioc_cap = 0;
1002         for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1003                 if (ioc->pfacts[ii].ProtocolFlags &
1004                     MPI_PORTFACTS_PROTOCOL_INITIATOR)
1005                         ioc_cap ++;
1006         }
1007
1008         if (!ioc_cap) {
1009                 printk(MYIOC_s_WARN_FMT
1010                         "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
1011                         ioc->name, ioc);
1012                 return -ENODEV;
1013         }
1014
1015         sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
1016
1017         if (!sh) {
1018                 printk(MYIOC_s_WARN_FMT
1019                         "Unable to register controller with SCSI subsystem\n",
1020                         ioc->name);
1021                 error = -1;
1022                 goto out_mptfc_probe;
1023         }
1024
1025         spin_lock_init(&ioc->fc_rescan_work_lock);
1026         INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc);
1027         INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset, (void *)ioc);
1028
1029         spin_lock_irqsave(&ioc->FreeQlock, flags);
1030
1031         /* Attach the SCSI Host to the IOC structure
1032          */
1033         ioc->sh = sh;
1034
1035         sh->io_port = 0;
1036         sh->n_io_port = 0;
1037         sh->irq = 0;
1038
1039         /* set 16 byte cdb's */
1040         sh->max_cmd_len = 16;
1041
1042         sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
1043
1044         sh->max_lun = MPT_LAST_LUN + 1;
1045         sh->max_channel = 0;
1046         sh->this_id = ioc->pfacts[0].PortSCSIID;
1047
1048         /* Required entry.
1049          */
1050         sh->unique_id = ioc->id;
1051
1052         /* Verify that we won't exceed the maximum
1053          * number of chain buffers
1054          * We can optimize:  ZZ = req_sz/sizeof(SGE)
1055          * For 32bit SGE's:
1056          *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1057          *               + (req_sz - 64)/sizeof(SGE)
1058          * A slightly different algorithm is required for
1059          * 64bit SGEs.
1060          */
1061         scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1062         if (sizeof(dma_addr_t) == sizeof(u64)) {
1063                 numSGE = (scale - 1) *
1064                   (ioc->facts.MaxChainDepth-1) + scale +
1065                   (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
1066                   sizeof(u32));
1067         } else {
1068                 numSGE = 1 + (scale - 1) *
1069                   (ioc->facts.MaxChainDepth-1) + scale +
1070                   (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
1071                   sizeof(u32));
1072         }
1073
1074         if (numSGE < sh->sg_tablesize) {
1075                 /* Reset this value */
1076                 dprintk((MYIOC_s_INFO_FMT
1077                   "Resetting sg_tablesize to %d from %d\n",
1078                   ioc->name, numSGE, sh->sg_tablesize));
1079                 sh->sg_tablesize = numSGE;
1080         }
1081
1082         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1083
1084         hd = (MPT_SCSI_HOST *) sh->hostdata;
1085         hd->ioc = ioc;
1086
1087         /* SCSI needs scsi_cmnd lookup table!
1088          * (with size equal to req_depth*PtrSz!)
1089          */
1090         hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
1091         if (!hd->ScsiLookup) {
1092                 error = -ENOMEM;
1093                 goto out_mptfc_probe;
1094         }
1095
1096         dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
1097                  ioc->name, hd->ScsiLookup));
1098
1099         /* Allocate memory for the device structures.
1100          * A non-Null pointer at an offset
1101          * indicates a device exists.
1102          * max_id = 1 + maximum id (hosts.h)
1103          */
1104         hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
1105         if (!hd->Targets) {
1106                 error = -ENOMEM;
1107                 goto out_mptfc_probe;
1108         }
1109
1110         dprintk((KERN_INFO "  vdev @ %p\n", hd->Targets));
1111
1112         /* Clear the TM flags
1113          */
1114         hd->tmPending = 0;
1115         hd->tmState = TM_STATE_NONE;
1116         hd->resetPending = 0;
1117         hd->abortSCpnt = NULL;
1118
1119         /* Clear the pointer used to store
1120          * single-threaded commands, i.e., those
1121          * issued during a bus scan, dv and
1122          * configuration pages.
1123          */
1124         hd->cmdPtr = NULL;
1125
1126         /* Initialize this SCSI Hosts' timers
1127          * To use, set the timer expires field
1128          * and add_timer
1129          */
1130         init_timer(&hd->timer);
1131         hd->timer.data = (unsigned long) hd;
1132         hd->timer.function = mptscsih_timer_expired;
1133
1134         hd->mpt_pq_filter = mpt_pq_filter;
1135
1136         ddvprintk((MYIOC_s_INFO_FMT
1137                 "mpt_pq_filter %x\n",
1138                 ioc->name, 
1139                 mpt_pq_filter));
1140
1141         init_waitqueue_head(&hd->scandv_waitq);
1142         hd->scandv_wait_done = 0;
1143         hd->last_queue_full = 0;
1144
1145         sh->transportt = mptfc_transport_template;
1146         error = scsi_add_host (sh, &ioc->pcidev->dev);
1147         if(error) {
1148                 dprintk((KERN_ERR MYNAM
1149                   "scsi_add_host failed\n"));
1150                 goto out_mptfc_probe;
1151         }
1152
1153         /* initialize workqueue */
1154
1155         snprintf(ioc->fc_rescan_work_q_name, KOBJ_NAME_LEN, "mptfc_wq_%d",
1156                 sh->host_no);
1157         ioc->fc_rescan_work_q =
1158                 create_singlethread_workqueue(ioc->fc_rescan_work_q_name);
1159         if (!ioc->fc_rescan_work_q)
1160                 goto out_mptfc_probe;
1161
1162         /*
1163          *  Pre-fetch FC port WWN and stuff...
1164          *  (FCPortPage0_t stuff)
1165          */
1166         for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1167                 (void) mptfc_GetFcPortPage0(ioc, ii);
1168         }
1169         mptfc_SetFcPortPage1_defaults(ioc);
1170
1171         /*
1172          * scan for rports -
1173          *      by doing it via the workqueue, some locking is eliminated
1174          */
1175
1176         ioc->fc_rescan_work_count = 1;
1177         queue_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work);
1178         flush_workqueue(ioc->fc_rescan_work_q);
1179
1180         return 0;
1181
1182 out_mptfc_probe:
1183
1184         mptscsih_remove(pdev);
1185         return error;
1186 }
1187
1188 static struct pci_driver mptfc_driver = {
1189         .name           = "mptfc",
1190         .id_table       = mptfc_pci_table,
1191         .probe          = mptfc_probe,
1192         .remove         = __devexit_p(mptfc_remove),
1193         .shutdown       = mptscsih_shutdown,
1194 #ifdef CONFIG_PM
1195         .suspend        = mptscsih_suspend,
1196         .resume         = mptscsih_resume,
1197 #endif
1198 };
1199
1200 static int
1201 mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
1202 {
1203         MPT_SCSI_HOST *hd;
1204         u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
1205         unsigned long flags;
1206         int rc=1;
1207
1208         devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
1209                         ioc->name, event));
1210
1211         if (ioc->sh == NULL ||
1212                 ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
1213                 return 1;
1214
1215         switch (event) {
1216         case MPI_EVENT_RESCAN:
1217                 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1218                 if (ioc->fc_rescan_work_q) {
1219                         if (ioc->fc_rescan_work_count++ == 0) {
1220                                 queue_work(ioc->fc_rescan_work_q,
1221                                            &ioc->fc_rescan_work);
1222                         }
1223                 }
1224                 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1225                 break;
1226         default:
1227                 rc = mptscsih_event_process(ioc,pEvReply);
1228                 break;
1229         }
1230         return rc;
1231 }
1232
1233 static int
1234 mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
1235 {
1236         int             rc;
1237         unsigned long   flags;
1238
1239         rc = mptscsih_ioc_reset(ioc,reset_phase);
1240         if (rc == 0)
1241                 return rc;
1242
1243
1244         dtmprintk((KERN_WARNING MYNAM
1245                 ": IOC %s_reset routed to FC host driver!\n",
1246                 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
1247                 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
1248
1249         if (reset_phase == MPT_IOC_SETUP_RESET) {
1250                 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1251                 if (ioc->fc_rescan_work_q) {
1252                         queue_work(ioc->fc_rescan_work_q,
1253                                    &ioc->fc_setup_reset_work);
1254                 }
1255                 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1256         }
1257
1258         else if (reset_phase == MPT_IOC_PRE_RESET) {
1259         }
1260
1261         else {  /* MPT_IOC_POST_RESET */
1262                 mptfc_SetFcPortPage1_defaults(ioc);
1263                 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1264                 if (ioc->fc_rescan_work_q) {
1265                         if (ioc->fc_rescan_work_count++ == 0) {
1266                                 queue_work(ioc->fc_rescan_work_q,
1267                                            &ioc->fc_rescan_work);
1268                         }
1269                 }
1270                 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1271         }
1272         return 1;
1273 }
1274
1275 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1276 /**
1277  *      mptfc_init - Register MPT adapter(s) as SCSI host(s) with
1278  *      linux scsi mid-layer.
1279  *
1280  *      Returns 0 for success, non-zero for failure.
1281  */
1282 static int __init
1283 mptfc_init(void)
1284 {
1285         int error;
1286
1287         show_mptmod_ver(my_NAME, my_VERSION);
1288
1289         /* sanity check module parameters */
1290         if (mptfc_dev_loss_tmo <= 0)
1291                 mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
1292
1293         mptfc_transport_template =
1294                 fc_attach_transport(&mptfc_transport_functions);
1295
1296         if (!mptfc_transport_template)
1297                 return -ENODEV;
1298
1299         mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);
1300         mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
1301         mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
1302
1303         if (mpt_event_register(mptfcDoneCtx, mptfc_event_process) == 0) {
1304                 devtverboseprintk((KERN_INFO MYNAM
1305                   ": Registered for IOC event notifications\n"));
1306         }
1307
1308         if (mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset) == 0) {
1309                 dprintk((KERN_INFO MYNAM
1310                   ": Registered for IOC reset notifications\n"));
1311         }
1312
1313         error = pci_register_driver(&mptfc_driver);
1314         if (error)
1315                 fc_release_transport(mptfc_transport_template);
1316
1317         return error;
1318 }
1319
1320 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1321 /**
1322  *      mptfc_remove - Removed fc infrastructure for devices
1323  *      @pdev: Pointer to pci_dev structure
1324  *
1325  */
1326 static void __devexit
1327 mptfc_remove(struct pci_dev *pdev)
1328 {
1329         MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
1330         struct mptfc_rport_info *p, *n;
1331         struct workqueue_struct *work_q;
1332         unsigned long           flags;
1333         int                     ii;
1334
1335         /* destroy workqueue */
1336         if ((work_q=ioc->fc_rescan_work_q)) {
1337                 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1338                 ioc->fc_rescan_work_q = NULL;
1339                 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1340                 destroy_workqueue(work_q);
1341         }
1342
1343         fc_remove_host(ioc->sh);
1344
1345         list_for_each_entry_safe(p, n, &ioc->fc_rports, list) {
1346                 list_del(&p->list);
1347                 kfree(p);
1348         }
1349
1350         for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
1351                 if (ioc->fc_data.fc_port_page1[ii].data) {
1352                         pci_free_consistent(ioc->pcidev,
1353                                 ioc->fc_data.fc_port_page1[ii].pg_sz,
1354                                 (u8 *) ioc->fc_data.fc_port_page1[ii].data,
1355                                 ioc->fc_data.fc_port_page1[ii].dma);
1356                         ioc->fc_data.fc_port_page1[ii].data = NULL;
1357                 }
1358         }
1359
1360         mptscsih_remove(pdev);
1361 }
1362
1363 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1364 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1365 /**
1366  *      mptfc_exit - Unregisters MPT adapter(s)
1367  *
1368  */
1369 static void __exit
1370 mptfc_exit(void)
1371 {
1372         pci_unregister_driver(&mptfc_driver);
1373         fc_release_transport(mptfc_transport_template);
1374
1375         mpt_reset_deregister(mptfcDoneCtx);
1376         dprintk((KERN_INFO MYNAM
1377           ": Deregistered for IOC reset notifications\n"));
1378
1379         mpt_event_deregister(mptfcDoneCtx);
1380         dprintk((KERN_INFO MYNAM
1381           ": Deregistered for IOC event notifications\n"));
1382
1383         mpt_deregister(mptfcInternalCtx);
1384         mpt_deregister(mptfcTaskCtx);
1385         mpt_deregister(mptfcDoneCtx);
1386 }
1387
1388 module_init(mptfc_init);
1389 module_exit(mptfc_exit);