[SCSI] - fusion - mptfc bug fix's to prevent deadlock situations
[linux-2.6] / drivers / message / fusion / mptfc.c
1 /*
2  *  linux/drivers/message/fusion/mptfc.c
3  *      For use with LSI Logic PCI chip/adapter(s)
4  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
5  *
6  *  Copyright (c) 1999-2005 LSI Logic Corporation
7  *  (mailto:mpt_linux_developer@lsil.com)
8  *
9  */
10 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11 /*
12     This program is free software; you can redistribute it and/or modify
13     it under the terms of the GNU General Public License as published by
14     the Free Software Foundation; version 2 of the License.
15
16     This program is distributed in the hope that it will be useful,
17     but WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19     GNU General Public License for more details.
20
21     NO WARRANTY
22     THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
23     CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
24     LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
25     MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
26     solely responsible for determining the appropriateness of using and
27     distributing the Program and assumes all risks associated with its
28     exercise of rights under this Agreement, including but not limited to
29     the risks and costs of program errors, damage to or loss of data,
30     programs or equipment, and unavailability or interruption of operations.
31
32     DISCLAIMER OF LIABILITY
33     NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
34     DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35     DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
36     ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37     TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38     USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
39     HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
40
41     You should have received a copy of the GNU General Public License
42     along with this program; if not, write to the Free Software
43     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
44 */
45 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
46 #include "linux_compat.h"       /* linux-2.6 tweaks */
47 #include <linux/module.h>
48 #include <linux/kernel.h>
49 #include <linux/init.h>
50 #include <linux/errno.h>
51 #include <linux/kdev_t.h>
52 #include <linux/blkdev.h>
53 #include <linux/delay.h>        /* for mdelay */
54 #include <linux/interrupt.h>    /* needed for in_interrupt() proto */
55 #include <linux/reboot.h>       /* notifier code */
56 #include <linux/sched.h>
57 #include <linux/workqueue.h>
58 #include <linux/sort.h>
59
60 #include <scsi/scsi.h>
61 #include <scsi/scsi_cmnd.h>
62 #include <scsi/scsi_device.h>
63 #include <scsi/scsi_host.h>
64 #include <scsi/scsi_tcq.h>
65 #include <scsi/scsi_transport_fc.h>
66
67 #include "mptbase.h"
68 #include "mptscsih.h"
69
70 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
71 #define my_NAME         "Fusion MPT FC Host driver"
72 #define my_VERSION      MPT_LINUX_VERSION_COMMON
73 #define MYNAM           "mptfc"
74
75 MODULE_AUTHOR(MODULEAUTHOR);
76 MODULE_DESCRIPTION(my_NAME);
77 MODULE_LICENSE("GPL");
78
79 /* Command line args */
80 static int mpt_pq_filter = 0;
81 module_param(mpt_pq_filter, int, 0);
82 MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1  (default=0)");
83
84 #define MPTFC_DEV_LOSS_TMO (60)
85 static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;     /* reasonable default */
86 module_param(mptfc_dev_loss_tmo, int, 0);
87 MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the "
88                                      " transport to wait for an rport to "
89                                      " return following a device loss event."
90                                      "  Default=60.");
91
92 static int      mptfcDoneCtx = -1;
93 static int      mptfcTaskCtx = -1;
94 static int      mptfcInternalCtx = -1; /* Used only for internal commands */
95
96 static int mptfc_target_alloc(struct scsi_target *starget);
97 static int mptfc_slave_alloc(struct scsi_device *sdev);
98 static int mptfc_qcmd(struct scsi_cmnd *SCpnt,
99                       void (*done)(struct scsi_cmnd *));
100 static void mptfc_target_destroy(struct scsi_target *starget);
101 static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);
102 static void __devexit mptfc_remove(struct pci_dev *pdev);
103
104 static struct scsi_host_template mptfc_driver_template = {
105         .module                         = THIS_MODULE,
106         .proc_name                      = "mptfc",
107         .proc_info                      = mptscsih_proc_info,
108         .name                           = "MPT FC Host",
109         .info                           = mptscsih_info,
110         .queuecommand                   = mptfc_qcmd,
111         .target_alloc                   = mptfc_target_alloc,
112         .slave_alloc                    = mptfc_slave_alloc,
113         .slave_configure                = mptscsih_slave_configure,
114         .target_destroy                 = mptfc_target_destroy,
115         .slave_destroy                  = mptscsih_slave_destroy,
116         .change_queue_depth             = mptscsih_change_queue_depth,
117         .eh_abort_handler               = mptscsih_abort,
118         .eh_device_reset_handler        = mptscsih_dev_reset,
119         .eh_bus_reset_handler           = mptscsih_bus_reset,
120         .eh_host_reset_handler          = mptscsih_host_reset,
121         .bios_param                     = mptscsih_bios_param,
122         .can_queue                      = MPT_FC_CAN_QUEUE,
123         .this_id                        = -1,
124         .sg_tablesize                   = MPT_SCSI_SG_DEPTH,
125         .max_sectors                    = 8192,
126         .cmd_per_lun                    = 7,
127         .use_clustering                 = ENABLE_CLUSTERING,
128 };
129
130 /****************************************************************************
131  * Supported hardware
132  */
133
134 static struct pci_device_id mptfc_pci_table[] = {
135         { PCI_VENDOR_ID_LSI_LOGIC, 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 /* FIXME! values controlling firmware RESCAN event
173  * need to be set low to allow dev_loss_tmo to
174  * work as expected.  Currently, firmware doesn't
175  * notify driver of RESCAN event until some number
176  * of seconds elapse.  This value can be set via
177  * lsiutil.
178  */
179 static void
180 mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
181 {
182         if (timeout > 0)
183                 rport->dev_loss_tmo = timeout;
184         else
185                 rport->dev_loss_tmo = mptfc_dev_loss_tmo;
186 }
187
188 static int
189 mptfc_FcDevPage0_cmp_func(const void *a, const void *b)
190 {
191         FCDevicePage0_t **aa = (FCDevicePage0_t **)a;
192         FCDevicePage0_t **bb = (FCDevicePage0_t **)b;
193
194         if ((*aa)->CurrentBus == (*bb)->CurrentBus) {
195                 if ((*aa)->CurrentTargetID == (*bb)->CurrentTargetID)
196                         return 0;
197                 if ((*aa)->CurrentTargetID < (*bb)->CurrentTargetID)
198                         return -1;
199                 return 1;
200         }
201         if ((*aa)->CurrentBus < (*bb)->CurrentBus)
202                 return -1;
203         return 1;
204 }
205
206 static int
207 mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port,
208         void(*func)(MPT_ADAPTER *ioc,int channel, FCDevicePage0_t *arg))
209 {
210         ConfigPageHeader_t       hdr;
211         CONFIGPARMS              cfg;
212         FCDevicePage0_t         *ppage0_alloc, *fc;
213         dma_addr_t               page0_dma;
214         int                      data_sz;
215         int                      ii;
216
217         FCDevicePage0_t         *p0_array=NULL, *p_p0;
218         FCDevicePage0_t         **pp0_array=NULL, **p_pp0;
219
220         int                      rc = -ENOMEM;
221         U32                      port_id = 0xffffff;
222         int                      num_targ = 0;
223         int                      max_bus = ioc->facts.MaxBuses;
224         int                      max_targ = ioc->facts.MaxDevices;
225
226         if (max_bus == 0 || max_targ == 0)
227                 goto out;
228
229         data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;
230         p_p0 = p0_array =  kzalloc(data_sz, GFP_KERNEL);
231         if (!p0_array)
232                 goto out;
233
234         data_sz = sizeof(FCDevicePage0_t *) * max_bus * max_targ;
235         p_pp0 = pp0_array = kzalloc(data_sz, GFP_KERNEL);
236         if (!pp0_array)
237                 goto out;
238
239         do {
240                 /* Get FC Device Page 0 header */
241                 hdr.PageVersion = 0;
242                 hdr.PageLength = 0;
243                 hdr.PageNumber = 0;
244                 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_DEVICE;
245                 cfg.cfghdr.hdr = &hdr;
246                 cfg.physAddr = -1;
247                 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
248                 cfg.dir = 0;
249                 cfg.pageAddr = port_id;
250                 cfg.timeout = 0;
251
252                 if ((rc = mpt_config(ioc, &cfg)) != 0)
253                         break;
254
255                 if (hdr.PageLength <= 0)
256                         break;
257
258                 data_sz = hdr.PageLength * 4;
259                 ppage0_alloc = pci_alloc_consistent(ioc->pcidev, data_sz,
260                                                         &page0_dma);
261                 rc = -ENOMEM;
262                 if (!ppage0_alloc)
263                         break;
264
265                 cfg.physAddr = page0_dma;
266                 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
267
268                 if ((rc = mpt_config(ioc, &cfg)) == 0) {
269                         ppage0_alloc->PortIdentifier =
270                                 le32_to_cpu(ppage0_alloc->PortIdentifier);
271
272                         ppage0_alloc->WWNN.Low =
273                                 le32_to_cpu(ppage0_alloc->WWNN.Low);
274
275                         ppage0_alloc->WWNN.High =
276                                 le32_to_cpu(ppage0_alloc->WWNN.High);
277
278                         ppage0_alloc->WWPN.Low =
279                                 le32_to_cpu(ppage0_alloc->WWPN.Low);
280
281                         ppage0_alloc->WWPN.High =
282                                 le32_to_cpu(ppage0_alloc->WWPN.High);
283
284                         ppage0_alloc->BBCredit =
285                                 le16_to_cpu(ppage0_alloc->BBCredit);
286
287                         ppage0_alloc->MaxRxFrameSize =
288                                 le16_to_cpu(ppage0_alloc->MaxRxFrameSize);
289
290                         port_id = ppage0_alloc->PortIdentifier;
291                         num_targ++;
292                         *p_p0 = *ppage0_alloc;  /* save data */
293                         *p_pp0++ = p_p0++;      /* save addr */
294                 }
295                 pci_free_consistent(ioc->pcidev, data_sz,
296                                         (u8 *) ppage0_alloc, page0_dma);
297                 if (rc != 0)
298                         break;
299
300         } while (port_id <= 0xff0000);
301
302         if (num_targ) {
303                 /* sort array */
304                 if (num_targ > 1)
305                         sort (pp0_array, num_targ, sizeof(FCDevicePage0_t *),
306                                 mptfc_FcDevPage0_cmp_func, NULL);
307                 /* call caller's func for each targ */
308                 for (ii = 0; ii < num_targ;  ii++) {
309                         fc = *(pp0_array+ii);
310                         func(ioc, ioc_port, fc);
311                 }
312         }
313
314  out:
315         if (pp0_array)
316                 kfree(pp0_array);
317         if (p0_array)
318                 kfree(p0_array);
319         return rc;
320 }
321
322 static int
323 mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
324 {
325         /* not currently usable */
326         if (pg0->Flags & (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID |
327                           MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID))
328                 return -1;
329
330         if (!(pg0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID))
331                 return -1;
332
333         if (!(pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET))
334                 return -1;
335
336         /*
337          * board data structure already normalized to platform endianness
338          * shifted to avoid unaligned access on 64 bit architecture
339          */
340         rid->node_name = ((u64)pg0->WWNN.High) << 32 | (u64)pg0->WWNN.Low;
341         rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;
342         rid->port_id =   pg0->PortIdentifier;
343         rid->roles = FC_RPORT_ROLE_UNKNOWN;
344         rid->roles |= FC_RPORT_ROLE_FCP_TARGET;
345         if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
346                 rid->roles |= FC_RPORT_ROLE_FCP_INITIATOR;
347
348         return 0;
349 }
350
351 static void
352 mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
353 {
354         struct fc_rport_identifiers rport_ids;
355         struct fc_rport         *rport;
356         struct mptfc_rport_info *ri;
357         int                     new_ri = 1;
358         u64                     pn, nn;
359         VirtTarget              *vtarget;
360
361         if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
362                 return;
363
364         /* scan list looking for a match */
365         list_for_each_entry(ri, &ioc->fc_rports, list) {
366                 pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
367                 if (pn == rport_ids.port_name) {        /* match */
368                         list_move_tail(&ri->list, &ioc->fc_rports);
369                         new_ri = 0;
370                         break;
371                 }
372         }
373         if (new_ri) {   /* allocate one */
374                 ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
375                 if (!ri)
376                         return;
377                 list_add_tail(&ri->list, &ioc->fc_rports);
378         }
379
380         ri->pg0 = *pg0; /* add/update pg0 data */
381         ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING;
382
383         /* MPT_RPORT_INFO_FLAGS_REGISTERED - rport not previously deleted */
384         if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
385                 ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
386                 rport = fc_remote_port_add(ioc->sh, channel, &rport_ids);
387                 if (rport) {
388                         ri->rport = rport;
389                         if (new_ri) /* may have been reset by user */
390                                 rport->dev_loss_tmo = mptfc_dev_loss_tmo;
391                         /*
392                          * if already mapped, remap here.  If not mapped,
393                          * target_alloc will allocate vtarget and map,
394                          * slave_alloc will fill in vdev from vtarget.
395                          */
396                         if (ri->starget) {
397                                 vtarget = ri->starget->hostdata;
398                                 if (vtarget) {
399                                         vtarget->target_id = pg0->CurrentTargetID;
400                                         vtarget->bus_id = pg0->CurrentBus;
401                                 }
402                         }
403                         /* once dd_data is filled in, commands will issue to hardware */
404                         *((struct mptfc_rport_info **)rport->dd_data) = ri;
405
406                         pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
407                         nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
408                         dfcprintk ((MYIOC_s_INFO_FMT
409                                 "mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
410                                 "rport tid %d, tmo %d\n",
411                                         ioc->name,
412                                         ioc->sh->host_no,
413                                         pg0->PortIdentifier,
414                                         (unsigned long long)nn,
415                                         (unsigned long long)pn,
416                                         pg0->CurrentTargetID,
417                                         ri->rport->scsi_target_id,
418                                         ri->rport->dev_loss_tmo));
419                 } else {
420                         list_del(&ri->list);
421                         kfree(ri);
422                         ri = NULL;
423                 }
424         }
425 }
426
427 /*
428  *      OS entry point to allow for host driver to free allocated memory
429  *      Called if no device present or device being unloaded
430  */
431 static void
432 mptfc_target_destroy(struct scsi_target *starget)
433 {
434         struct fc_rport         *rport;
435         struct mptfc_rport_info *ri;
436
437         rport = starget_to_rport(starget);
438         if (rport) {
439                 ri = *((struct mptfc_rport_info **)rport->dd_data);
440                 if (ri) /* better be! */
441                         ri->starget = NULL;
442         }
443         if (starget->hostdata)
444                 kfree(starget->hostdata);
445         starget->hostdata = NULL;
446 }
447
448 /*
449  *      OS entry point to allow host driver to alloc memory
450  *      for each scsi target. Called once per device the bus scan.
451  *      Return non-zero if allocation fails.
452  */
453 static int
454 mptfc_target_alloc(struct scsi_target *starget)
455 {
456         VirtTarget              *vtarget;
457         struct fc_rport         *rport;
458         struct mptfc_rport_info *ri;
459         int                     rc;
460
461         vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
462         if (!vtarget)
463                 return -ENOMEM;
464         starget->hostdata = vtarget;
465
466         rc = -ENODEV;
467         rport = starget_to_rport(starget);
468         if (rport) {
469                 ri = *((struct mptfc_rport_info **)rport->dd_data);
470                 if (ri) {       /* better be! */
471                         vtarget->target_id = ri->pg0.CurrentTargetID;
472                         vtarget->bus_id = ri->pg0.CurrentBus;
473                         ri->starget = starget;
474                         rc = 0;
475                 }
476         }
477         if (rc != 0) {
478                 kfree(vtarget);
479                 starget->hostdata = NULL;
480         }
481
482         return rc;
483 }
484
485 /*
486  *      OS entry point to allow host driver to alloc memory
487  *      for each scsi device. Called once per device the bus scan.
488  *      Return non-zero if allocation fails.
489  *      Init memory once per LUN.
490  */
491 static int
492 mptfc_slave_alloc(struct scsi_device *sdev)
493 {
494         MPT_SCSI_HOST           *hd;
495         VirtTarget              *vtarget;
496         VirtDevice              *vdev;
497         struct scsi_target      *starget;
498         struct fc_rport         *rport;
499
500
501         starget = scsi_target(sdev);
502         rport = starget_to_rport(starget);
503
504         if (!rport || fc_remote_port_chkready(rport))
505                 return -ENXIO;
506
507         hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
508
509         vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
510         if (!vdev) {
511                 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
512                                 hd->ioc->name, sizeof(VirtDevice));
513                 return -ENOMEM;
514         }
515
516
517         sdev->hostdata = vdev;
518         vtarget = starget->hostdata;
519
520         if (vtarget->num_luns == 0) {
521                 vtarget->ioc_id = hd->ioc->id;
522                 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES |
523                                   MPT_TARGET_FLAGS_VALID_INQUIRY;
524                 hd->Targets[sdev->id] = vtarget;
525         }
526
527         vdev->vtarget = vtarget;
528         vdev->lun = sdev->lun;
529
530         vtarget->num_luns++;
531
532
533 #ifdef DMPT_DEBUG_FC
534         {
535         u64 nn, pn;
536         struct mptfc_rport_info *ri;
537         ri = *((struct mptfc_rport_info **)rport->dd_data);
538         pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
539         nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
540         dfcprintk ((MYIOC_s_INFO_FMT
541                 "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
542                 "CurrentTargetID %d, %x %llx %llx\n",
543                 hd->ioc->name,
544                 sdev->host->host_no,
545                 vtarget->num_luns,
546                 sdev->id, ri->pg0.CurrentTargetID,
547                 ri->pg0.PortIdentifier,
548                 (unsigned long long)pn,
549                 (unsigned long long)nn));
550         }
551 #endif
552
553         return 0;
554 }
555
556 static int
557 mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
558 {
559         struct mptfc_rport_info *ri;
560         struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
561         int             err;
562
563         err = fc_remote_port_chkready(rport);
564         if (unlikely(err)) {
565                 SCpnt->result = err;
566                 done(SCpnt);
567                 return 0;
568         }
569
570         /* dd_data is null until finished adding target */
571         ri = *((struct mptfc_rport_info **)rport->dd_data);
572         if (unlikely(!ri)) {
573                 dfcprintk ((MYIOC_s_INFO_FMT
574                         "mptfc_qcmd.%d: %d:%d, dd_data is null.\n",
575                         ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
576                         ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
577                         SCpnt->device->id,SCpnt->device->lun));
578                 SCpnt->result = DID_IMM_RETRY << 16;
579                 done(SCpnt);
580                 return 0;
581         }
582
583         err = mptscsih_qcmd(SCpnt,done);
584 #ifdef DMPT_DEBUG_FC
585         if (unlikely(err)) {
586                 dfcprintk ((MYIOC_s_INFO_FMT
587                         "mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero.\n",
588                         ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
589                         ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
590                         SCpnt->device->id,SCpnt->device->lun));
591         }
592 #endif
593         return err;
594 }
595
596 static void
597 mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
598 {
599         unsigned class = 0, cos = 0;
600
601         /* don't know what to do as only one scsi (fc) host was allocated */
602         if (portnum != 0)
603                 return;
604
605         class = ioc->fc_port_page0[portnum].SupportedServiceClass;
606         if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1)
607                 cos |= FC_COS_CLASS1;
608         if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2)
609                 cos |= FC_COS_CLASS2;
610         if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3)
611                 cos |= FC_COS_CLASS3;
612
613         fc_host_node_name(ioc->sh) =
614                 (u64)ioc->fc_port_page0[portnum].WWNN.High << 32
615                     | (u64)ioc->fc_port_page0[portnum].WWNN.Low;
616
617         fc_host_port_name(ioc->sh) =
618                 (u64)ioc->fc_port_page0[portnum].WWPN.High << 32
619                     | (u64)ioc->fc_port_page0[portnum].WWPN.Low;
620
621         fc_host_port_id(ioc->sh) = ioc->fc_port_page0[portnum].PortIdentifier;
622
623         fc_host_supported_classes(ioc->sh) = cos;
624
625         fc_host_tgtid_bind_type(ioc->sh) = FC_TGTID_BIND_BY_WWPN;
626 }
627
628 static void
629 mptfc_rescan_devices(void *arg)
630 {
631         MPT_ADAPTER             *ioc = (MPT_ADAPTER *)arg;
632         int                     ii;
633         int                     work_to_do;
634         u64                     pn;
635         unsigned long           flags;
636         struct mptfc_rport_info *ri;
637
638         do {
639                 /* start by tagging all ports as missing */
640                 list_for_each_entry(ri, &ioc->fc_rports, list) {
641                         if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
642                                 ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
643                         }
644                 }
645
646                 /*
647                  * now rescan devices known to adapter,
648                  * will reregister existing rports
649                  */
650                 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
651                         (void) mptbase_GetFcPortPage0(ioc, ii);
652                         mptfc_init_host_attr(ioc,ii);   /* refresh */
653                         mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
654                 }
655
656                 /* delete devices still missing */
657                 list_for_each_entry(ri, &ioc->fc_rports, list) {
658                         /* if newly missing, delete it */
659                         if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) {
660
661                                 ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
662                                                MPT_RPORT_INFO_FLAGS_MISSING);
663                                 fc_remote_port_delete(ri->rport);       /* won't sleep */
664                                 ri->rport = NULL;
665
666                                 pn = (u64)ri->pg0.WWPN.High << 32 |
667                                      (u64)ri->pg0.WWPN.Low;
668                                 dfcprintk ((MYIOC_s_INFO_FMT
669                                         "mptfc_rescan.%d: %llx deleted\n",
670                                         ioc->name,
671                                         ioc->sh->host_no,
672                                         (unsigned long long)pn));
673                         }
674                 }
675
676                 /*
677                  * allow multiple passes as target state
678                  * might have changed during scan
679                  */
680                 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
681                 if (ioc->fc_rescan_work_count > 2)      /* only need one more */
682                         ioc->fc_rescan_work_count = 2;
683                 work_to_do = --ioc->fc_rescan_work_count;
684                 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
685         } while (work_to_do);
686 }
687
688 static int
689 mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
690 {
691         struct Scsi_Host        *sh;
692         MPT_SCSI_HOST           *hd;
693         MPT_ADAPTER             *ioc;
694         unsigned long            flags;
695         int                      ii;
696         int                      numSGE = 0;
697         int                      scale;
698         int                      ioc_cap;
699         int                     error=0;
700         int                     r;
701
702         if ((r = mpt_attach(pdev,id)) != 0)
703                 return r;
704
705         ioc = pci_get_drvdata(pdev);
706         ioc->DoneCtx = mptfcDoneCtx;
707         ioc->TaskCtx = mptfcTaskCtx;
708         ioc->InternalCtx = mptfcInternalCtx;
709
710         /*  Added sanity check on readiness of the MPT adapter.
711          */
712         if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
713                 printk(MYIOC_s_WARN_FMT
714                   "Skipping because it's not operational!\n",
715                   ioc->name);
716                 error = -ENODEV;
717                 goto out_mptfc_probe;
718         }
719
720         if (!ioc->active) {
721                 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
722                   ioc->name);
723                 error = -ENODEV;
724                 goto out_mptfc_probe;
725         }
726
727         /*  Sanity check - ensure at least 1 port is INITIATOR capable
728          */
729         ioc_cap = 0;
730         for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
731                 if (ioc->pfacts[ii].ProtocolFlags &
732                     MPI_PORTFACTS_PROTOCOL_INITIATOR)
733                         ioc_cap ++;
734         }
735
736         if (!ioc_cap) {
737                 printk(MYIOC_s_WARN_FMT
738                         "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
739                         ioc->name, ioc);
740                 return -ENODEV;
741         }
742
743         sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
744
745         if (!sh) {
746                 printk(MYIOC_s_WARN_FMT
747                         "Unable to register controller with SCSI subsystem\n",
748                         ioc->name);
749                 error = -1;
750                 goto out_mptfc_probe;
751         }
752
753         INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc);
754
755         spin_lock_irqsave(&ioc->FreeQlock, flags);
756
757         /* Attach the SCSI Host to the IOC structure
758          */
759         ioc->sh = sh;
760
761         sh->io_port = 0;
762         sh->n_io_port = 0;
763         sh->irq = 0;
764
765         /* set 16 byte cdb's */
766         sh->max_cmd_len = 16;
767
768         sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
769
770         sh->max_lun = MPT_LAST_LUN + 1;
771         sh->max_channel = 0;
772         sh->this_id = ioc->pfacts[0].PortSCSIID;
773
774         /* Required entry.
775          */
776         sh->unique_id = ioc->id;
777
778         /* Verify that we won't exceed the maximum
779          * number of chain buffers
780          * We can optimize:  ZZ = req_sz/sizeof(SGE)
781          * For 32bit SGE's:
782          *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
783          *               + (req_sz - 64)/sizeof(SGE)
784          * A slightly different algorithm is required for
785          * 64bit SGEs.
786          */
787         scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
788         if (sizeof(dma_addr_t) == sizeof(u64)) {
789                 numSGE = (scale - 1) *
790                   (ioc->facts.MaxChainDepth-1) + scale +
791                   (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
792                   sizeof(u32));
793         } else {
794                 numSGE = 1 + (scale - 1) *
795                   (ioc->facts.MaxChainDepth-1) + scale +
796                   (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
797                   sizeof(u32));
798         }
799
800         if (numSGE < sh->sg_tablesize) {
801                 /* Reset this value */
802                 dprintk((MYIOC_s_INFO_FMT
803                   "Resetting sg_tablesize to %d from %d\n",
804                   ioc->name, numSGE, sh->sg_tablesize));
805                 sh->sg_tablesize = numSGE;
806         }
807
808         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
809
810         hd = (MPT_SCSI_HOST *) sh->hostdata;
811         hd->ioc = ioc;
812
813         /* SCSI needs scsi_cmnd lookup table!
814          * (with size equal to req_depth*PtrSz!)
815          */
816         hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
817         if (!hd->ScsiLookup) {
818                 error = -ENOMEM;
819                 goto out_mptfc_probe;
820         }
821
822         dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
823                  ioc->name, hd->ScsiLookup));
824
825         /* Allocate memory for the device structures.
826          * A non-Null pointer at an offset
827          * indicates a device exists.
828          * max_id = 1 + maximum id (hosts.h)
829          */
830         hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
831         if (!hd->Targets) {
832                 error = -ENOMEM;
833                 goto out_mptfc_probe;
834         }
835
836         dprintk((KERN_INFO "  vdev @ %p\n", hd->Targets));
837
838         /* Clear the TM flags
839          */
840         hd->tmPending = 0;
841         hd->tmState = TM_STATE_NONE;
842         hd->resetPending = 0;
843         hd->abortSCpnt = NULL;
844
845         /* Clear the pointer used to store
846          * single-threaded commands, i.e., those
847          * issued during a bus scan, dv and
848          * configuration pages.
849          */
850         hd->cmdPtr = NULL;
851
852         /* Initialize this SCSI Hosts' timers
853          * To use, set the timer expires field
854          * and add_timer
855          */
856         init_timer(&hd->timer);
857         hd->timer.data = (unsigned long) hd;
858         hd->timer.function = mptscsih_timer_expired;
859
860         hd->mpt_pq_filter = mpt_pq_filter;
861
862         ddvprintk((MYIOC_s_INFO_FMT
863                 "mpt_pq_filter %x\n",
864                 ioc->name, 
865                 mpt_pq_filter));
866
867         init_waitqueue_head(&hd->scandv_waitq);
868         hd->scandv_wait_done = 0;
869         hd->last_queue_full = 0;
870
871         sh->transportt = mptfc_transport_template;
872         error = scsi_add_host (sh, &ioc->pcidev->dev);
873         if(error) {
874                 dprintk((KERN_ERR MYNAM
875                   "scsi_add_host failed\n"));
876                 goto out_mptfc_probe;
877         }
878
879         /* initialize workqueue */
880
881         snprintf(ioc->fc_rescan_work_q_name, KOBJ_NAME_LEN, "mptfc_wq_%d",
882                 sh->host_no);
883         ioc->fc_rescan_work_q =
884                 create_singlethread_workqueue(ioc->fc_rescan_work_q_name);
885         if (!ioc->fc_rescan_work_q)
886                 goto out_mptfc_probe;
887
888         /*
889          * scan for rports -
890          *      by doing it via the workqueue, some locking is eliminated
891          */
892
893         ioc->fc_rescan_work_count = 1;
894         queue_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work);
895         flush_workqueue(ioc->fc_rescan_work_q);
896
897         return 0;
898
899 out_mptfc_probe:
900
901         mptscsih_remove(pdev);
902         return error;
903 }
904
905 static struct pci_driver mptfc_driver = {
906         .name           = "mptfc",
907         .id_table       = mptfc_pci_table,
908         .probe          = mptfc_probe,
909         .remove         = __devexit_p(mptfc_remove),
910         .shutdown       = mptscsih_shutdown,
911 #ifdef CONFIG_PM
912         .suspend        = mptscsih_suspend,
913         .resume         = mptscsih_resume,
914 #endif
915 };
916
917 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
918 /**
919  *      mptfc_init - Register MPT adapter(s) as SCSI host(s) with
920  *      linux scsi mid-layer.
921  *
922  *      Returns 0 for success, non-zero for failure.
923  */
924 static int __init
925 mptfc_init(void)
926 {
927         int error;
928
929         show_mptmod_ver(my_NAME, my_VERSION);
930
931         /* sanity check module parameter */
932         if (mptfc_dev_loss_tmo == 0)
933                 mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
934
935         mptfc_transport_template =
936                 fc_attach_transport(&mptfc_transport_functions);
937
938         if (!mptfc_transport_template)
939                 return -ENODEV;
940
941         mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);
942         mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
943         mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
944
945         if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) {
946                 devtverboseprintk((KERN_INFO MYNAM
947                   ": Registered for IOC event notifications\n"));
948         }
949
950         if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) {
951                 dprintk((KERN_INFO MYNAM
952                   ": Registered for IOC reset notifications\n"));
953         }
954
955         error = pci_register_driver(&mptfc_driver);
956         if (error)
957                 fc_release_transport(mptfc_transport_template);
958
959         return error;
960 }
961
962 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
963 /**
964  *      mptfc_remove - Removed fc infrastructure for devices
965  *      @pdev: Pointer to pci_dev structure
966  *
967  */
968 static void __devexit
969 mptfc_remove(struct pci_dev *pdev)
970 {
971         MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
972         struct mptfc_rport_info *p, *n;
973         struct workqueue_struct *work_q;
974         unsigned long           flags;
975
976         /* destroy workqueue */
977         if ((work_q=ioc->fc_rescan_work_q)) {
978                 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
979                 ioc->fc_rescan_work_q = NULL;
980                 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
981                 destroy_workqueue(work_q);
982         }
983
984         fc_remove_host(ioc->sh);
985
986         list_for_each_entry_safe(p, n, &ioc->fc_rports, list) {
987                 list_del(&p->list);
988                 kfree(p);
989         }
990
991         mptscsih_remove(pdev);
992 }
993
994 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
995 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
996 /**
997  *      mptfc_exit - Unregisters MPT adapter(s)
998  *
999  */
1000 static void __exit
1001 mptfc_exit(void)
1002 {
1003         pci_unregister_driver(&mptfc_driver);
1004         fc_release_transport(mptfc_transport_template);
1005
1006         mpt_reset_deregister(mptfcDoneCtx);
1007         dprintk((KERN_INFO MYNAM
1008           ": Deregistered for IOC reset notifications\n"));
1009
1010         mpt_event_deregister(mptfcDoneCtx);
1011         dprintk((KERN_INFO MYNAM
1012           ": Deregistered for IOC event notifications\n"));
1013
1014         mpt_deregister(mptfcInternalCtx);
1015         mpt_deregister(mptfcTaskCtx);
1016         mpt_deregister(mptfcDoneCtx);
1017 }
1018
1019 module_init(mptfc_init);
1020 module_exit(mptfc_exit);