Merge with /home/shaggy/git/linus-clean/
[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 int mptfc_slave_alloc(struct scsi_device *device);
97 static int mptfc_qcmd(struct scsi_cmnd *SCpnt,
98     void (*done)(struct scsi_cmnd *));
99
100 static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);
101 static void __devexit mptfc_remove(struct pci_dev *pdev);
102
103 static struct scsi_host_template mptfc_driver_template = {
104         .module                         = THIS_MODULE,
105         .proc_name                      = "mptfc",
106         .proc_info                      = mptscsih_proc_info,
107         .name                           = "MPT FC Host",
108         .info                           = mptscsih_info,
109         .queuecommand                   = mptfc_qcmd,
110         .target_alloc                   = mptscsih_target_alloc,
111         .slave_alloc                    = mptfc_slave_alloc,
112         .slave_configure                = mptscsih_slave_configure,
113         .target_destroy                 = mptscsih_target_destroy,
114         .slave_destroy                  = mptscsih_slave_destroy,
115         .change_queue_depth             = mptscsih_change_queue_depth,
116         .eh_abort_handler               = mptscsih_abort,
117         .eh_device_reset_handler        = mptscsih_dev_reset,
118         .eh_bus_reset_handler           = mptscsih_bus_reset,
119         .eh_host_reset_handler          = mptscsih_host_reset,
120         .bios_param                     = mptscsih_bios_param,
121         .can_queue                      = MPT_FC_CAN_QUEUE,
122         .this_id                        = -1,
123         .sg_tablesize                   = MPT_SCSI_SG_DEPTH,
124         .max_sectors                    = 8192,
125         .cmd_per_lun                    = 7,
126         .use_clustering                 = ENABLE_CLUSTERING,
127 };
128
129 /****************************************************************************
130  * Supported hardware
131  */
132
133 static struct pci_device_id mptfc_pci_table[] = {
134         { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909,
135                 PCI_ANY_ID, PCI_ANY_ID },
136         { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919,
137                 PCI_ANY_ID, PCI_ANY_ID },
138         { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929,
139                 PCI_ANY_ID, PCI_ANY_ID },
140         { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X,
141                 PCI_ANY_ID, PCI_ANY_ID },
142         { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X,
143                 PCI_ANY_ID, PCI_ANY_ID },
144         { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC939X,
145                 PCI_ANY_ID, PCI_ANY_ID },
146         { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X,
147                 PCI_ANY_ID, PCI_ANY_ID },
148         { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949ES,
149                 PCI_ANY_ID, PCI_ANY_ID },
150         {0}     /* Terminating entry */
151 };
152 MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
153
154 static struct scsi_transport_template *mptfc_transport_template = NULL;
155
156 struct fc_function_template mptfc_transport_functions = {
157         .dd_fcrport_size = 8,
158         .show_host_node_name = 1,
159         .show_host_port_name = 1,
160         .show_host_supported_classes = 1,
161         .show_host_port_id = 1,
162         .show_rport_supported_classes = 1,
163         .show_starget_node_name = 1,
164         .show_starget_port_name = 1,
165         .show_starget_port_id = 1,
166         .set_rport_dev_loss_tmo = mptfc_set_rport_loss_tmo,
167         .show_rport_dev_loss_tmo = 1,
168
169 };
170
171 /* FIXME! values controlling firmware RESCAN event
172  * need to be set low to allow dev_loss_tmo to
173  * work as expected.  Currently, firmware doesn't
174  * notify driver of RESCAN event until some number
175  * of seconds elapse.  This value can be set via
176  * lsiutil.
177  */
178 static void
179 mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
180 {
181         if (timeout > 0)
182                 rport->dev_loss_tmo = timeout;
183         else
184                 rport->dev_loss_tmo = mptfc_dev_loss_tmo;
185 }
186
187 static int
188 mptfc_FcDevPage0_cmp_func(const void *a, const void *b)
189 {
190         FCDevicePage0_t **aa = (FCDevicePage0_t **)a;
191         FCDevicePage0_t **bb = (FCDevicePage0_t **)b;
192
193         if ((*aa)->CurrentBus == (*bb)->CurrentBus) {
194                 if ((*aa)->CurrentTargetID == (*bb)->CurrentTargetID)
195                         return 0;
196                 if ((*aa)->CurrentTargetID < (*bb)->CurrentTargetID)
197                         return -1;
198                 return 1;
199         }
200         if ((*aa)->CurrentBus < (*bb)->CurrentBus)
201                 return -1;
202         return 1;
203 }
204
205 static int
206 mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port,
207         void(*func)(MPT_ADAPTER *ioc,int channel, FCDevicePage0_t *arg))
208 {
209         ConfigPageHeader_t       hdr;
210         CONFIGPARMS              cfg;
211         FCDevicePage0_t         *ppage0_alloc, *fc;
212         dma_addr_t               page0_dma;
213         int                      data_sz;
214         int                      ii;
215
216         FCDevicePage0_t         *p0_array=NULL, *p_p0;
217         FCDevicePage0_t         **pp0_array=NULL, **p_pp0;
218
219         int                      rc = -ENOMEM;
220         U32                      port_id = 0xffffff;
221         int                      num_targ = 0;
222         int                      max_bus = ioc->facts.MaxBuses;
223         int                      max_targ = ioc->facts.MaxDevices;
224
225         if (max_bus == 0 || max_targ == 0)
226                 goto out;
227
228         data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;
229         p_p0 = p0_array =  kzalloc(data_sz, GFP_KERNEL);
230         if (!p0_array)
231                 goto out;
232
233         data_sz = sizeof(FCDevicePage0_t *) * max_bus * max_targ;
234         p_pp0 = pp0_array = kzalloc(data_sz, GFP_KERNEL);
235         if (!pp0_array)
236                 goto out;
237
238         do {
239                 /* Get FC Device Page 0 header */
240                 hdr.PageVersion = 0;
241                 hdr.PageLength = 0;
242                 hdr.PageNumber = 0;
243                 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_DEVICE;
244                 cfg.cfghdr.hdr = &hdr;
245                 cfg.physAddr = -1;
246                 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
247                 cfg.dir = 0;
248                 cfg.pageAddr = port_id;
249                 cfg.timeout = 0;
250
251                 if ((rc = mpt_config(ioc, &cfg)) != 0)
252                         break;
253
254                 if (hdr.PageLength <= 0)
255                         break;
256
257                 data_sz = hdr.PageLength * 4;
258                 ppage0_alloc = pci_alloc_consistent(ioc->pcidev, data_sz,
259                                                         &page0_dma);
260                 rc = -ENOMEM;
261                 if (!ppage0_alloc)
262                         break;
263
264                 cfg.physAddr = page0_dma;
265                 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
266
267                 if ((rc = mpt_config(ioc, &cfg)) == 0) {
268                         ppage0_alloc->PortIdentifier =
269                                 le32_to_cpu(ppage0_alloc->PortIdentifier);
270
271                         ppage0_alloc->WWNN.Low =
272                                 le32_to_cpu(ppage0_alloc->WWNN.Low);
273
274                         ppage0_alloc->WWNN.High =
275                                 le32_to_cpu(ppage0_alloc->WWNN.High);
276
277                         ppage0_alloc->WWPN.Low =
278                                 le32_to_cpu(ppage0_alloc->WWPN.Low);
279
280                         ppage0_alloc->WWPN.High =
281                                 le32_to_cpu(ppage0_alloc->WWPN.High);
282
283                         ppage0_alloc->BBCredit =
284                                 le16_to_cpu(ppage0_alloc->BBCredit);
285
286                         ppage0_alloc->MaxRxFrameSize =
287                                 le16_to_cpu(ppage0_alloc->MaxRxFrameSize);
288
289                         port_id = ppage0_alloc->PortIdentifier;
290                         num_targ++;
291                         *p_p0 = *ppage0_alloc;  /* save data */
292                         *p_pp0++ = p_p0++;      /* save addr */
293                 }
294                 pci_free_consistent(ioc->pcidev, data_sz,
295                                         (u8 *) ppage0_alloc, page0_dma);
296                 if (rc != 0)
297                         break;
298
299         } while (port_id <= 0xff0000);
300
301         if (num_targ) {
302                 /* sort array */
303                 if (num_targ > 1)
304                         sort (pp0_array, num_targ, sizeof(FCDevicePage0_t *),
305                                 mptfc_FcDevPage0_cmp_func, NULL);
306                 /* call caller's func for each targ */
307                 for (ii = 0; ii < num_targ;  ii++) {
308                         fc = *(pp0_array+ii);
309                         func(ioc, ioc_port, fc);
310                 }
311         }
312
313  out:
314         if (pp0_array)
315                 kfree(pp0_array);
316         if (p0_array)
317                 kfree(p0_array);
318         return rc;
319 }
320
321 static int
322 mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
323 {
324         /* not currently usable */
325         if (pg0->Flags & (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID |
326                           MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID))
327                 return -1;
328
329         if (!(pg0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID))
330                 return -1;
331
332         if (!(pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET))
333                 return -1;
334
335         /*
336          * board data structure already normalized to platform endianness
337          * shifted to avoid unaligned access on 64 bit architecture
338          */
339         rid->node_name = ((u64)pg0->WWNN.High) << 32 | (u64)pg0->WWNN.Low;
340         rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;
341         rid->port_id =   pg0->PortIdentifier;
342         rid->roles = FC_RPORT_ROLE_UNKNOWN;
343         rid->roles |= FC_RPORT_ROLE_FCP_TARGET;
344         if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
345                 rid->roles |= FC_RPORT_ROLE_FCP_INITIATOR;
346
347         return 0;
348 }
349
350 static void
351 mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
352 {
353         struct fc_rport_identifiers rport_ids;
354         struct fc_rport         *rport;
355         struct mptfc_rport_info *ri;
356         int                     match = 0;
357         u64                     port_name;
358         unsigned long           flags;
359
360         if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
361                 return;
362
363         /* scan list looking for a match */
364         spin_lock_irqsave(&ioc->fc_rport_lock, flags);
365         list_for_each_entry(ri, &ioc->fc_rports, list) {
366                 port_name = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
367                 if (port_name == rport_ids.port_name) { /* match */
368                         list_move_tail(&ri->list, &ioc->fc_rports);
369                         match = 1;
370                         break;
371                 }
372         }
373         if (!match) {   /* allocate one */
374                 spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
375                 ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
376                 if (!ri)
377                         return;
378                 spin_lock_irqsave(&ioc->fc_rport_lock, flags);
379                 list_add_tail(&ri->list, &ioc->fc_rports);
380         }
381
382         ri->pg0 = *pg0; /* add/update pg0 data */
383         ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING;
384
385         if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
386                 ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
387                 spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
388                 rport = fc_remote_port_add(ioc->sh,channel, &rport_ids);
389                 spin_lock_irqsave(&ioc->fc_rport_lock, flags);
390                 if (rport) {
391                         if (*((struct mptfc_rport_info **)rport->dd_data) != ri) {
392                                 ri->flags &= ~MPT_RPORT_INFO_FLAGS_MAPPED_VDEV;
393                                 ri->vdev = NULL;
394                                 ri->rport = rport;
395                                 *((struct mptfc_rport_info **)rport->dd_data) = ri;
396                         }
397                         rport->dev_loss_tmo = mptfc_dev_loss_tmo;
398                         /*
399                          * if already mapped, remap here.  If not mapped,
400                          * slave_alloc will allocate vdev and map
401                          */
402                         if (ri->flags & MPT_RPORT_INFO_FLAGS_MAPPED_VDEV) {
403                                 ri->vdev->target_id = ri->pg0.CurrentTargetID;
404                                 ri->vdev->bus_id = ri->pg0.CurrentBus;
405                                 ri->vdev->vtarget->target_id = ri->vdev->target_id;
406                                 ri->vdev->vtarget->bus_id = ri->vdev->bus_id;
407                         }
408                         #ifdef MPT_DEBUG
409                         printk ("mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
410                                 "rport tid %d, tmo %d\n",
411                                         ioc->sh->host_no,
412                                         pg0->PortIdentifier,
413                                         pg0->WWNN,
414                                         pg0->WWPN,
415                                         pg0->CurrentTargetID,
416                                         ri->rport->scsi_target_id,
417                                         ri->rport->dev_loss_tmo);
418                         #endif
419                 } else {
420                         list_del(&ri->list);
421                         kfree(ri);
422                         ri = NULL;
423                 }
424         }
425         spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
426
427 }
428
429 /*
430  *      OS entry point to allow host driver to alloc memory
431  *      for each scsi device. Called once per device the bus scan.
432  *      Return non-zero if allocation fails.
433  *      Init memory once per LUN.
434  */
435 int
436 mptfc_slave_alloc(struct scsi_device *sdev)
437 {
438         MPT_SCSI_HOST           *hd;
439         VirtTarget              *vtarget;
440         VirtDevice              *vdev;
441         struct scsi_target      *starget;
442         struct fc_rport         *rport;
443         struct mptfc_rport_info *ri;
444         unsigned long           flags;
445
446
447         rport = starget_to_rport(scsi_target(sdev));
448
449         if (!rport || fc_remote_port_chkready(rport))
450                 return -ENXIO;
451
452         hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
453
454         vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
455         if (!vdev) {
456                 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
457                                 hd->ioc->name, sizeof(VirtDevice));
458                 return -ENOMEM;
459         }
460         memset(vdev, 0, sizeof(VirtDevice));
461
462         spin_lock_irqsave(&hd->ioc->fc_rport_lock,flags);
463
464         if (!(ri = *((struct mptfc_rport_info **)rport->dd_data))) {
465                 spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
466                 kfree(vdev);
467                 return -ENODEV;
468         }
469
470         sdev->hostdata = vdev;
471         starget = scsi_target(sdev);
472         vtarget = starget->hostdata;
473         if (vtarget->num_luns == 0) {
474                 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES |
475                                   MPT_TARGET_FLAGS_VALID_INQUIRY;
476                 hd->Targets[sdev->id] = vtarget;
477         }
478
479         vtarget->target_id = vdev->target_id;
480         vtarget->bus_id = vdev->bus_id;
481
482         vdev->vtarget = vtarget;
483         vdev->ioc_id = hd->ioc->id;
484         vdev->lun = sdev->lun;
485         vdev->target_id = ri->pg0.CurrentTargetID;
486         vdev->bus_id = ri->pg0.CurrentBus;
487
488         ri->flags |= MPT_RPORT_INFO_FLAGS_MAPPED_VDEV;
489         ri->vdev = vdev;
490
491         spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
492
493         vtarget->num_luns++;
494
495 #ifdef MPT_DEBUG
496         printk ("mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
497                 "CurrentTargetID %d, %x %llx %llx\n",
498                         sdev->host->host_no,
499                         vtarget->num_luns,
500                         sdev->id, ri->pg0.CurrentTargetID,
501                         ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN);
502 #endif
503
504         return 0;
505 }
506
507 static int
508 mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
509 {
510         struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
511         int             err;
512
513         err = fc_remote_port_chkready(rport);
514         if (unlikely(err)) {
515                 SCpnt->result = err;
516                 done(SCpnt);
517                 return 0;
518         }
519         return mptscsih_qcmd(SCpnt,done);
520 }
521
522 static void
523 mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
524 {
525         unsigned class = 0, cos = 0;
526
527         /* don't know what to do as only one scsi (fc) host was allocated */
528         if (portnum != 0)
529                 return;
530
531         class = ioc->fc_port_page0[portnum].SupportedServiceClass;
532         if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1)
533                 cos |= FC_COS_CLASS1;
534         if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2)
535                 cos |= FC_COS_CLASS2;
536         if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3)
537                 cos |= FC_COS_CLASS3;
538
539         fc_host_node_name(ioc->sh) =
540                 (u64)ioc->fc_port_page0[portnum].WWNN.High << 32
541                     | (u64)ioc->fc_port_page0[portnum].WWNN.Low;
542
543         fc_host_port_name(ioc->sh) =
544                 (u64)ioc->fc_port_page0[portnum].WWPN.High << 32
545                     | (u64)ioc->fc_port_page0[portnum].WWPN.Low;
546
547         fc_host_port_id(ioc->sh) = ioc->fc_port_page0[portnum].PortIdentifier;
548
549         fc_host_supported_classes(ioc->sh) = cos;
550
551         fc_host_tgtid_bind_type(ioc->sh) = FC_TGTID_BIND_BY_WWPN;
552 }
553
554 static void
555 mptfc_rescan_devices(void *arg)
556 {
557         MPT_ADAPTER             *ioc = (MPT_ADAPTER *)arg;
558         int                     ii;
559         int                     work_to_do;
560         unsigned long           flags;
561         struct mptfc_rport_info *ri;
562
563         do {
564                 /* start by tagging all ports as missing */
565                 spin_lock_irqsave(&ioc->fc_rport_lock,flags);
566                 list_for_each_entry(ri, &ioc->fc_rports, list) {
567                         if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
568                                 ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
569                         }
570                 }
571                 spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
572
573                 /*
574                  * now rescan devices known to adapter,
575                  * will reregister existing rports
576                  */
577                 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
578                         (void) mptbase_GetFcPortPage0(ioc, ii);
579                         mptfc_init_host_attr(ioc,ii);   /* refresh */
580                         mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
581                 }
582
583                 /* delete devices still missing */
584                 spin_lock_irqsave(&ioc->fc_rport_lock, flags);
585                 list_for_each_entry(ri, &ioc->fc_rports, list) {
586                         /* if newly missing, delete it */
587                         if ((ri->flags & (MPT_RPORT_INFO_FLAGS_REGISTERED |
588                                           MPT_RPORT_INFO_FLAGS_MISSING))
589                           == (MPT_RPORT_INFO_FLAGS_REGISTERED |
590                               MPT_RPORT_INFO_FLAGS_MISSING)) {
591
592                                 ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
593                                                MPT_RPORT_INFO_FLAGS_MISSING);
594                                 fc_remote_port_delete(ri->rport);
595                                 /*
596                                  * remote port not really deleted 'cause
597                                  * binding is by WWPN and driver only
598                                  * registers FCP_TARGETs
599                                  */
600                                 #ifdef MPT_DEBUG
601                                 printk ("mptfc_rescan.%d: %llx deleted\n",
602                                         ioc->sh->host_no, ri->pg0.WWPN);
603                                 #endif
604                         }
605                 }
606                 spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
607
608                 /*
609                  * allow multiple passes as target state
610                  * might have changed during scan
611                  */
612                 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
613                 if (ioc->fc_rescan_work_count > 2)      /* only need one more */
614                         ioc->fc_rescan_work_count = 2;
615                 work_to_do = --ioc->fc_rescan_work_count;
616                 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
617         } while (work_to_do);
618 }
619
620 static int
621 mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
622 {
623         struct Scsi_Host        *sh;
624         MPT_SCSI_HOST           *hd;
625         MPT_ADAPTER             *ioc;
626         unsigned long            flags;
627         int                      ii;
628         int                      numSGE = 0;
629         int                      scale;
630         int                      ioc_cap;
631         int                     error=0;
632         int                     r;
633
634         if ((r = mpt_attach(pdev,id)) != 0)
635                 return r;
636
637         ioc = pci_get_drvdata(pdev);
638         ioc->DoneCtx = mptfcDoneCtx;
639         ioc->TaskCtx = mptfcTaskCtx;
640         ioc->InternalCtx = mptfcInternalCtx;
641
642         /*  Added sanity check on readiness of the MPT adapter.
643          */
644         if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
645                 printk(MYIOC_s_WARN_FMT
646                   "Skipping because it's not operational!\n",
647                   ioc->name);
648                 error = -ENODEV;
649                 goto out_mptfc_probe;
650         }
651
652         if (!ioc->active) {
653                 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
654                   ioc->name);
655                 error = -ENODEV;
656                 goto out_mptfc_probe;
657         }
658
659         /*  Sanity check - ensure at least 1 port is INITIATOR capable
660          */
661         ioc_cap = 0;
662         for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
663                 if (ioc->pfacts[ii].ProtocolFlags &
664                     MPI_PORTFACTS_PROTOCOL_INITIATOR)
665                         ioc_cap ++;
666         }
667
668         if (!ioc_cap) {
669                 printk(MYIOC_s_WARN_FMT
670                         "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
671                         ioc->name, ioc);
672                 return -ENODEV;
673         }
674
675         sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
676
677         if (!sh) {
678                 printk(MYIOC_s_WARN_FMT
679                         "Unable to register controller with SCSI subsystem\n",
680                         ioc->name);
681                 error = -1;
682                 goto out_mptfc_probe;
683         }
684
685         INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc);
686
687         spin_lock_irqsave(&ioc->FreeQlock, flags);
688
689         /* Attach the SCSI Host to the IOC structure
690          */
691         ioc->sh = sh;
692
693         sh->io_port = 0;
694         sh->n_io_port = 0;
695         sh->irq = 0;
696
697         /* set 16 byte cdb's */
698         sh->max_cmd_len = 16;
699
700         sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
701
702         sh->max_lun = MPT_LAST_LUN + 1;
703         sh->max_channel = 0;
704         sh->this_id = ioc->pfacts[0].PortSCSIID;
705
706         /* Required entry.
707          */
708         sh->unique_id = ioc->id;
709
710         /* Verify that we won't exceed the maximum
711          * number of chain buffers
712          * We can optimize:  ZZ = req_sz/sizeof(SGE)
713          * For 32bit SGE's:
714          *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
715          *               + (req_sz - 64)/sizeof(SGE)
716          * A slightly different algorithm is required for
717          * 64bit SGEs.
718          */
719         scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
720         if (sizeof(dma_addr_t) == sizeof(u64)) {
721                 numSGE = (scale - 1) *
722                   (ioc->facts.MaxChainDepth-1) + scale +
723                   (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
724                   sizeof(u32));
725         } else {
726                 numSGE = 1 + (scale - 1) *
727                   (ioc->facts.MaxChainDepth-1) + scale +
728                   (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
729                   sizeof(u32));
730         }
731
732         if (numSGE < sh->sg_tablesize) {
733                 /* Reset this value */
734                 dprintk((MYIOC_s_INFO_FMT
735                   "Resetting sg_tablesize to %d from %d\n",
736                   ioc->name, numSGE, sh->sg_tablesize));
737                 sh->sg_tablesize = numSGE;
738         }
739
740         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
741
742         hd = (MPT_SCSI_HOST *) sh->hostdata;
743         hd->ioc = ioc;
744
745         /* SCSI needs scsi_cmnd lookup table!
746          * (with size equal to req_depth*PtrSz!)
747          */
748         hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
749         if (!hd->ScsiLookup) {
750                 error = -ENOMEM;
751                 goto out_mptfc_probe;
752         }
753
754         dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
755                  ioc->name, hd->ScsiLookup));
756
757         /* Allocate memory for the device structures.
758          * A non-Null pointer at an offset
759          * indicates a device exists.
760          * max_id = 1 + maximum id (hosts.h)
761          */
762         hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
763         if (!hd->Targets) {
764                 error = -ENOMEM;
765                 goto out_mptfc_probe;
766         }
767
768         dprintk((KERN_INFO "  vdev @ %p\n", hd->Targets));
769
770         /* Clear the TM flags
771          */
772         hd->tmPending = 0;
773         hd->tmState = TM_STATE_NONE;
774         hd->resetPending = 0;
775         hd->abortSCpnt = NULL;
776
777         /* Clear the pointer used to store
778          * single-threaded commands, i.e., those
779          * issued during a bus scan, dv and
780          * configuration pages.
781          */
782         hd->cmdPtr = NULL;
783
784         /* Initialize this SCSI Hosts' timers
785          * To use, set the timer expires field
786          * and add_timer
787          */
788         init_timer(&hd->timer);
789         hd->timer.data = (unsigned long) hd;
790         hd->timer.function = mptscsih_timer_expired;
791
792         hd->mpt_pq_filter = mpt_pq_filter;
793
794         ddvprintk((MYIOC_s_INFO_FMT
795                 "mpt_pq_filter %x\n",
796                 ioc->name, 
797                 mpt_pq_filter));
798
799         init_waitqueue_head(&hd->scandv_waitq);
800         hd->scandv_wait_done = 0;
801         hd->last_queue_full = 0;
802
803         sh->transportt = mptfc_transport_template;
804         error = scsi_add_host (sh, &ioc->pcidev->dev);
805         if(error) {
806                 dprintk((KERN_ERR MYNAM
807                   "scsi_add_host failed\n"));
808                 goto out_mptfc_probe;
809         }
810
811         for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
812                 mptfc_init_host_attr(ioc,ii);
813                 mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
814         }
815
816         return 0;
817
818 out_mptfc_probe:
819
820         mptscsih_remove(pdev);
821         return error;
822 }
823
824 static struct pci_driver mptfc_driver = {
825         .name           = "mptfc",
826         .id_table       = mptfc_pci_table,
827         .probe          = mptfc_probe,
828         .remove         = __devexit_p(mptfc_remove),
829         .shutdown       = mptscsih_shutdown,
830 #ifdef CONFIG_PM
831         .suspend        = mptscsih_suspend,
832         .resume         = mptscsih_resume,
833 #endif
834 };
835
836 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
837 /**
838  *      mptfc_init - Register MPT adapter(s) as SCSI host(s) with
839  *      linux scsi mid-layer.
840  *
841  *      Returns 0 for success, non-zero for failure.
842  */
843 static int __init
844 mptfc_init(void)
845 {
846         int error;
847
848         show_mptmod_ver(my_NAME, my_VERSION);
849
850         /* sanity check module parameter */
851         if (mptfc_dev_loss_tmo == 0)
852                 mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
853
854         mptfc_transport_template =
855                 fc_attach_transport(&mptfc_transport_functions);
856
857         if (!mptfc_transport_template)
858                 return -ENODEV;
859
860         mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);
861         mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
862         mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
863
864         if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) {
865                 devtprintk((KERN_INFO MYNAM
866                   ": Registered for IOC event notifications\n"));
867         }
868
869         if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) {
870                 dprintk((KERN_INFO MYNAM
871                   ": Registered for IOC reset notifications\n"));
872         }
873
874         error = pci_register_driver(&mptfc_driver);
875         if (error) {
876                 fc_release_transport(mptfc_transport_template);
877         }
878
879         return error;
880 }
881
882 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
883 /**
884  *      mptfc_remove - Removed fc infrastructure for devices
885  *      @pdev: Pointer to pci_dev structure
886  *
887  */
888 static void __devexit mptfc_remove(struct pci_dev *pdev)
889 {
890         MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
891         struct mptfc_rport_info *p, *n;
892
893         fc_remove_host(ioc->sh);
894
895         list_for_each_entry_safe(p, n, &ioc->fc_rports, list) {
896                 list_del(&p->list);
897                 kfree(p);
898         }
899
900         mptscsih_remove(pdev);
901 }
902
903 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
904 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
905 /**
906  *      mptfc_exit - Unregisters MPT adapter(s)
907  *
908  */
909 static void __exit
910 mptfc_exit(void)
911 {
912         pci_unregister_driver(&mptfc_driver);
913         fc_release_transport(mptfc_transport_template);
914
915         mpt_reset_deregister(mptfcDoneCtx);
916         dprintk((KERN_INFO MYNAM
917           ": Deregistered for IOC reset notifications\n"));
918
919         mpt_event_deregister(mptfcDoneCtx);
920         dprintk((KERN_INFO MYNAM
921           ": Deregistered for IOC event notifications\n"));
922
923         mpt_deregister(mptfcInternalCtx);
924         mpt_deregister(mptfcTaskCtx);
925         mpt_deregister(mptfcDoneCtx);
926 }
927
928 module_init(mptfc_init);
929 module_exit(mptfc_exit);