[SCSI] mptfc: set fibre channel fw target missing timers to one second
[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         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.\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));
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_interruptible(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_rescan_devices(void *arg)
877 {
878         MPT_ADAPTER             *ioc = (MPT_ADAPTER *)arg;
879         int                     ii;
880         int                     work_to_do;
881         u64                     pn;
882         unsigned long           flags;
883         struct mptfc_rport_info *ri;
884
885         do {
886                 /* start by tagging all ports as missing */
887                 list_for_each_entry(ri, &ioc->fc_rports, list) {
888                         if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
889                                 ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
890                         }
891                 }
892
893                 /*
894                  * now rescan devices known to adapter,
895                  * will reregister existing rports
896                  */
897                 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
898                         (void) mptfc_GetFcPortPage0(ioc, ii);
899                         mptfc_init_host_attr(ioc,ii);   /* refresh */
900                         mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
901                 }
902
903                 /* delete devices still missing */
904                 list_for_each_entry(ri, &ioc->fc_rports, list) {
905                         /* if newly missing, delete it */
906                         if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) {
907
908                                 ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
909                                                MPT_RPORT_INFO_FLAGS_MISSING);
910                                 fc_remote_port_delete(ri->rport);       /* won't sleep */
911                                 ri->rport = NULL;
912
913                                 pn = (u64)ri->pg0.WWPN.High << 32 |
914                                      (u64)ri->pg0.WWPN.Low;
915                                 dfcprintk ((MYIOC_s_INFO_FMT
916                                         "mptfc_rescan.%d: %llx deleted\n",
917                                         ioc->name,
918                                         ioc->sh->host_no,
919                                         (unsigned long long)pn));
920                         }
921                 }
922
923                 /*
924                  * allow multiple passes as target state
925                  * might have changed during scan
926                  */
927                 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
928                 if (ioc->fc_rescan_work_count > 2)      /* only need one more */
929                         ioc->fc_rescan_work_count = 2;
930                 work_to_do = --ioc->fc_rescan_work_count;
931                 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
932         } while (work_to_do);
933 }
934
935 static int
936 mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
937 {
938         struct Scsi_Host        *sh;
939         MPT_SCSI_HOST           *hd;
940         MPT_ADAPTER             *ioc;
941         unsigned long            flags;
942         int                      ii;
943         int                      numSGE = 0;
944         int                      scale;
945         int                      ioc_cap;
946         int                     error=0;
947         int                     r;
948
949         if ((r = mpt_attach(pdev,id)) != 0)
950                 return r;
951
952         ioc = pci_get_drvdata(pdev);
953         ioc->DoneCtx = mptfcDoneCtx;
954         ioc->TaskCtx = mptfcTaskCtx;
955         ioc->InternalCtx = mptfcInternalCtx;
956
957         /*  Added sanity check on readiness of the MPT adapter.
958          */
959         if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
960                 printk(MYIOC_s_WARN_FMT
961                   "Skipping because it's not operational!\n",
962                   ioc->name);
963                 error = -ENODEV;
964                 goto out_mptfc_probe;
965         }
966
967         if (!ioc->active) {
968                 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
969                   ioc->name);
970                 error = -ENODEV;
971                 goto out_mptfc_probe;
972         }
973
974         /*  Sanity check - ensure at least 1 port is INITIATOR capable
975          */
976         ioc_cap = 0;
977         for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
978                 if (ioc->pfacts[ii].ProtocolFlags &
979                     MPI_PORTFACTS_PROTOCOL_INITIATOR)
980                         ioc_cap ++;
981         }
982
983         if (!ioc_cap) {
984                 printk(MYIOC_s_WARN_FMT
985                         "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
986                         ioc->name, ioc);
987                 return -ENODEV;
988         }
989
990         sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
991
992         if (!sh) {
993                 printk(MYIOC_s_WARN_FMT
994                         "Unable to register controller with SCSI subsystem\n",
995                         ioc->name);
996                 error = -1;
997                 goto out_mptfc_probe;
998         }
999
1000         spin_lock_init(&ioc->fc_rescan_work_lock);
1001         INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc);
1002
1003         spin_lock_irqsave(&ioc->FreeQlock, flags);
1004
1005         /* Attach the SCSI Host to the IOC structure
1006          */
1007         ioc->sh = sh;
1008
1009         sh->io_port = 0;
1010         sh->n_io_port = 0;
1011         sh->irq = 0;
1012
1013         /* set 16 byte cdb's */
1014         sh->max_cmd_len = 16;
1015
1016         sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
1017
1018         sh->max_lun = MPT_LAST_LUN + 1;
1019         sh->max_channel = 0;
1020         sh->this_id = ioc->pfacts[0].PortSCSIID;
1021
1022         /* Required entry.
1023          */
1024         sh->unique_id = ioc->id;
1025
1026         /* Verify that we won't exceed the maximum
1027          * number of chain buffers
1028          * We can optimize:  ZZ = req_sz/sizeof(SGE)
1029          * For 32bit SGE's:
1030          *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1031          *               + (req_sz - 64)/sizeof(SGE)
1032          * A slightly different algorithm is required for
1033          * 64bit SGEs.
1034          */
1035         scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1036         if (sizeof(dma_addr_t) == sizeof(u64)) {
1037                 numSGE = (scale - 1) *
1038                   (ioc->facts.MaxChainDepth-1) + scale +
1039                   (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
1040                   sizeof(u32));
1041         } else {
1042                 numSGE = 1 + (scale - 1) *
1043                   (ioc->facts.MaxChainDepth-1) + scale +
1044                   (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
1045                   sizeof(u32));
1046         }
1047
1048         if (numSGE < sh->sg_tablesize) {
1049                 /* Reset this value */
1050                 dprintk((MYIOC_s_INFO_FMT
1051                   "Resetting sg_tablesize to %d from %d\n",
1052                   ioc->name, numSGE, sh->sg_tablesize));
1053                 sh->sg_tablesize = numSGE;
1054         }
1055
1056         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1057
1058         hd = (MPT_SCSI_HOST *) sh->hostdata;
1059         hd->ioc = ioc;
1060
1061         /* SCSI needs scsi_cmnd lookup table!
1062          * (with size equal to req_depth*PtrSz!)
1063          */
1064         hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
1065         if (!hd->ScsiLookup) {
1066                 error = -ENOMEM;
1067                 goto out_mptfc_probe;
1068         }
1069
1070         dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
1071                  ioc->name, hd->ScsiLookup));
1072
1073         /* Allocate memory for the device structures.
1074          * A non-Null pointer at an offset
1075          * indicates a device exists.
1076          * max_id = 1 + maximum id (hosts.h)
1077          */
1078         hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
1079         if (!hd->Targets) {
1080                 error = -ENOMEM;
1081                 goto out_mptfc_probe;
1082         }
1083
1084         dprintk((KERN_INFO "  vdev @ %p\n", hd->Targets));
1085
1086         /* Clear the TM flags
1087          */
1088         hd->tmPending = 0;
1089         hd->tmState = TM_STATE_NONE;
1090         hd->resetPending = 0;
1091         hd->abortSCpnt = NULL;
1092
1093         /* Clear the pointer used to store
1094          * single-threaded commands, i.e., those
1095          * issued during a bus scan, dv and
1096          * configuration pages.
1097          */
1098         hd->cmdPtr = NULL;
1099
1100         /* Initialize this SCSI Hosts' timers
1101          * To use, set the timer expires field
1102          * and add_timer
1103          */
1104         init_timer(&hd->timer);
1105         hd->timer.data = (unsigned long) hd;
1106         hd->timer.function = mptscsih_timer_expired;
1107
1108         hd->mpt_pq_filter = mpt_pq_filter;
1109
1110         ddvprintk((MYIOC_s_INFO_FMT
1111                 "mpt_pq_filter %x\n",
1112                 ioc->name, 
1113                 mpt_pq_filter));
1114
1115         init_waitqueue_head(&hd->scandv_waitq);
1116         hd->scandv_wait_done = 0;
1117         hd->last_queue_full = 0;
1118
1119         sh->transportt = mptfc_transport_template;
1120         error = scsi_add_host (sh, &ioc->pcidev->dev);
1121         if(error) {
1122                 dprintk((KERN_ERR MYNAM
1123                   "scsi_add_host failed\n"));
1124                 goto out_mptfc_probe;
1125         }
1126
1127         /* initialize workqueue */
1128
1129         snprintf(ioc->fc_rescan_work_q_name, KOBJ_NAME_LEN, "mptfc_wq_%d",
1130                 sh->host_no);
1131         ioc->fc_rescan_work_q =
1132                 create_singlethread_workqueue(ioc->fc_rescan_work_q_name);
1133         if (!ioc->fc_rescan_work_q)
1134                 goto out_mptfc_probe;
1135
1136         /*
1137          *  Pre-fetch FC port WWN and stuff...
1138          *  (FCPortPage0_t stuff)
1139          */
1140         for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1141                 (void) mptfc_GetFcPortPage0(ioc, ii);
1142         }
1143         mptfc_SetFcPortPage1_defaults(ioc);
1144
1145         /*
1146          * scan for rports -
1147          *      by doing it via the workqueue, some locking is eliminated
1148          */
1149
1150         ioc->fc_rescan_work_count = 1;
1151         queue_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work);
1152         flush_workqueue(ioc->fc_rescan_work_q);
1153
1154         return 0;
1155
1156 out_mptfc_probe:
1157
1158         mptscsih_remove(pdev);
1159         return error;
1160 }
1161
1162 static struct pci_driver mptfc_driver = {
1163         .name           = "mptfc",
1164         .id_table       = mptfc_pci_table,
1165         .probe          = mptfc_probe,
1166         .remove         = __devexit_p(mptfc_remove),
1167         .shutdown       = mptscsih_shutdown,
1168 #ifdef CONFIG_PM
1169         .suspend        = mptscsih_suspend,
1170         .resume         = mptscsih_resume,
1171 #endif
1172 };
1173
1174 static int
1175 mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
1176 {
1177         MPT_SCSI_HOST *hd;
1178         u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
1179         unsigned long flags;
1180         int rc=1;
1181
1182         devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
1183                         ioc->name, event));
1184
1185         if (ioc->sh == NULL ||
1186                 ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
1187                 return 1;
1188
1189         switch (event) {
1190         case MPI_EVENT_RESCAN:
1191                 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1192                 if (ioc->fc_rescan_work_q) {
1193                         if (ioc->fc_rescan_work_count++ == 0) {
1194                                 queue_work(ioc->fc_rescan_work_q,
1195                                            &ioc->fc_rescan_work);
1196                         }
1197                 }
1198                 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1199                 break;
1200         default:
1201                 rc = mptscsih_event_process(ioc,pEvReply);
1202                 break;
1203         }
1204         return rc;
1205 }
1206
1207 static int
1208 mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
1209 {
1210         int             rc;
1211         unsigned long   flags;
1212
1213         rc = mptscsih_ioc_reset(ioc,reset_phase);
1214         if (rc == 0)
1215                 return rc;
1216
1217
1218         dtmprintk((KERN_WARNING MYNAM
1219                 ": IOC %s_reset routed to FC host driver!\n",
1220                 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
1221                 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
1222
1223         if (reset_phase == MPT_IOC_SETUP_RESET) {
1224         }
1225
1226         else if (reset_phase == MPT_IOC_PRE_RESET) {
1227         }
1228
1229         else {  /* MPT_IOC_POST_RESET */
1230                 mptfc_SetFcPortPage1_defaults(ioc);
1231                 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1232                 if (ioc->fc_rescan_work_q) {
1233                         if (ioc->fc_rescan_work_count++ == 0) {
1234                                 queue_work(ioc->fc_rescan_work_q,
1235                                            &ioc->fc_rescan_work);
1236                         }
1237                 }
1238                 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1239         }
1240         return 1;
1241 }
1242
1243 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1244 /**
1245  *      mptfc_init - Register MPT adapter(s) as SCSI host(s) with
1246  *      linux scsi mid-layer.
1247  *
1248  *      Returns 0 for success, non-zero for failure.
1249  */
1250 static int __init
1251 mptfc_init(void)
1252 {
1253         int error;
1254
1255         show_mptmod_ver(my_NAME, my_VERSION);
1256
1257         /* sanity check module parameters */
1258         if (mptfc_dev_loss_tmo <= 0)
1259                 mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
1260
1261         mptfc_transport_template =
1262                 fc_attach_transport(&mptfc_transport_functions);
1263
1264         if (!mptfc_transport_template)
1265                 return -ENODEV;
1266
1267         mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);
1268         mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
1269         mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
1270
1271         if (mpt_event_register(mptfcDoneCtx, mptfc_event_process) == 0) {
1272                 devtverboseprintk((KERN_INFO MYNAM
1273                   ": Registered for IOC event notifications\n"));
1274         }
1275
1276         if (mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset) == 0) {
1277                 dprintk((KERN_INFO MYNAM
1278                   ": Registered for IOC reset notifications\n"));
1279         }
1280
1281         error = pci_register_driver(&mptfc_driver);
1282         if (error)
1283                 fc_release_transport(mptfc_transport_template);
1284
1285         return error;
1286 }
1287
1288 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1289 /**
1290  *      mptfc_remove - Removed fc infrastructure for devices
1291  *      @pdev: Pointer to pci_dev structure
1292  *
1293  */
1294 static void __devexit
1295 mptfc_remove(struct pci_dev *pdev)
1296 {
1297         MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
1298         struct mptfc_rport_info *p, *n;
1299         struct workqueue_struct *work_q;
1300         unsigned long           flags;
1301         int                     ii;
1302
1303         /* destroy workqueue */
1304         if ((work_q=ioc->fc_rescan_work_q)) {
1305                 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1306                 ioc->fc_rescan_work_q = NULL;
1307                 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1308                 destroy_workqueue(work_q);
1309         }
1310
1311         fc_remove_host(ioc->sh);
1312
1313         list_for_each_entry_safe(p, n, &ioc->fc_rports, list) {
1314                 list_del(&p->list);
1315                 kfree(p);
1316         }
1317
1318         for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
1319                 if (ioc->fc_data.fc_port_page1[ii].data) {
1320                         pci_free_consistent(ioc->pcidev,
1321                                 ioc->fc_data.fc_port_page1[ii].pg_sz,
1322                                 (u8 *) ioc->fc_data.fc_port_page1[ii].data,
1323                                 ioc->fc_data.fc_port_page1[ii].dma);
1324                         ioc->fc_data.fc_port_page1[ii].data = NULL;
1325                 }
1326         }
1327
1328         mptscsih_remove(pdev);
1329 }
1330
1331 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1332 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1333 /**
1334  *      mptfc_exit - Unregisters MPT adapter(s)
1335  *
1336  */
1337 static void __exit
1338 mptfc_exit(void)
1339 {
1340         pci_unregister_driver(&mptfc_driver);
1341         fc_release_transport(mptfc_transport_template);
1342
1343         mpt_reset_deregister(mptfcDoneCtx);
1344         dprintk((KERN_INFO MYNAM
1345           ": Deregistered for IOC reset notifications\n"));
1346
1347         mpt_event_deregister(mptfcDoneCtx);
1348         dprintk((KERN_INFO MYNAM
1349           ": Deregistered for IOC event notifications\n"));
1350
1351         mpt_deregister(mptfcInternalCtx);
1352         mpt_deregister(mptfcTaskCtx);
1353         mpt_deregister(mptfcDoneCtx);
1354 }
1355
1356 module_init(mptfc_init);
1357 module_exit(mptfc_exit);