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.
6 * Copyright (c) 1999-2007 LSI Logic Corporation
7 * (mailto:mpt_linux_developer@lsi.com)
10 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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.
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.
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.
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
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
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/workqueue.h>
57 #include <linux/sort.h>
59 #include <scsi/scsi.h>
60 #include <scsi/scsi_cmnd.h>
61 #include <scsi/scsi_device.h>
62 #include <scsi/scsi_host.h>
63 #include <scsi/scsi_tcq.h>
64 #include <scsi/scsi_transport_fc.h>
69 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
70 #define my_NAME "Fusion MPT FC Host driver"
71 #define my_VERSION MPT_LINUX_VERSION_COMMON
74 MODULE_AUTHOR(MODULEAUTHOR);
75 MODULE_DESCRIPTION(my_NAME);
76 MODULE_LICENSE("GPL");
77 MODULE_VERSION(my_VERSION);
79 /* Command line args */
80 #define MPTFC_DEV_LOSS_TMO (60)
81 static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; /* reasonable default */
82 module_param(mptfc_dev_loss_tmo, int, 0);
83 MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the "
84 " transport to wait for an rport to "
85 " return following a device loss event."
88 /* scsi-mid layer global parmeter is max_report_luns, which is 511 */
89 #define MPTFC_MAX_LUN (16895)
90 static int max_lun = MPTFC_MAX_LUN;
91 module_param(max_lun, int, 0);
92 MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
94 static int mptfcDoneCtx = -1;
95 static int mptfcTaskCtx = -1;
96 static int mptfcInternalCtx = -1; /* Used only for internal commands */
98 static int mptfc_target_alloc(struct scsi_target *starget);
99 static int mptfc_slave_alloc(struct scsi_device *sdev);
100 static int mptfc_qcmd(struct scsi_cmnd *SCpnt,
101 void (*done)(struct scsi_cmnd *));
102 static void mptfc_target_destroy(struct scsi_target *starget);
103 static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);
104 static void __devexit mptfc_remove(struct pci_dev *pdev);
105 static int mptfc_abort(struct scsi_cmnd *SCpnt);
106 static int mptfc_dev_reset(struct scsi_cmnd *SCpnt);
107 static int mptfc_bus_reset(struct scsi_cmnd *SCpnt);
108 static int mptfc_host_reset(struct scsi_cmnd *SCpnt);
110 static struct scsi_host_template mptfc_driver_template = {
111 .module = THIS_MODULE,
112 .proc_name = "mptfc",
113 .proc_info = mptscsih_proc_info,
114 .name = "MPT FC Host",
115 .info = mptscsih_info,
116 .queuecommand = mptfc_qcmd,
117 .target_alloc = mptfc_target_alloc,
118 .slave_alloc = mptfc_slave_alloc,
119 .slave_configure = mptscsih_slave_configure,
120 .target_destroy = mptfc_target_destroy,
121 .slave_destroy = mptscsih_slave_destroy,
122 .change_queue_depth = mptscsih_change_queue_depth,
123 .eh_abort_handler = mptfc_abort,
124 .eh_device_reset_handler = mptfc_dev_reset,
125 .eh_bus_reset_handler = mptfc_bus_reset,
126 .eh_host_reset_handler = mptfc_host_reset,
127 .bios_param = mptscsih_bios_param,
128 .can_queue = MPT_FC_CAN_QUEUE,
130 .sg_tablesize = MPT_SCSI_SG_DEPTH,
133 .use_clustering = ENABLE_CLUSTERING,
136 /****************************************************************************
140 static struct pci_device_id mptfc_pci_table[] = {
141 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC909,
142 PCI_ANY_ID, PCI_ANY_ID },
143 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC919,
144 PCI_ANY_ID, PCI_ANY_ID },
145 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC929,
146 PCI_ANY_ID, PCI_ANY_ID },
147 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC919X,
148 PCI_ANY_ID, PCI_ANY_ID },
149 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC929X,
150 PCI_ANY_ID, PCI_ANY_ID },
151 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC939X,
152 PCI_ANY_ID, PCI_ANY_ID },
153 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949X,
154 PCI_ANY_ID, PCI_ANY_ID },
155 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949E,
156 PCI_ANY_ID, PCI_ANY_ID },
157 {0} /* Terminating entry */
159 MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
161 static struct scsi_transport_template *mptfc_transport_template = NULL;
163 static struct fc_function_template mptfc_transport_functions = {
164 .dd_fcrport_size = 8,
165 .show_host_node_name = 1,
166 .show_host_port_name = 1,
167 .show_host_supported_classes = 1,
168 .show_host_port_id = 1,
169 .show_rport_supported_classes = 1,
170 .show_starget_node_name = 1,
171 .show_starget_port_name = 1,
172 .show_starget_port_id = 1,
173 .set_rport_dev_loss_tmo = mptfc_set_rport_loss_tmo,
174 .show_rport_dev_loss_tmo = 1,
175 .show_host_supported_speeds = 1,
176 .show_host_maxframe_size = 1,
177 .show_host_speed = 1,
178 .show_host_fabric_name = 1,
179 .show_host_port_type = 1,
180 .show_host_port_state = 1,
181 .show_host_symbolic_name = 1,
185 mptfc_block_error_handler(struct scsi_cmnd *SCpnt,
186 int (*func)(struct scsi_cmnd *SCpnt),
189 struct scsi_device *sdev = SCpnt->device;
190 struct Scsi_Host *shost = sdev->host;
191 struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
195 spin_lock_irqsave(shost->host_lock, flags);
196 while ((ready = fc_remote_port_chkready(rport) >> 16) == DID_IMM_RETRY) {
197 spin_unlock_irqrestore(shost->host_lock, flags);
198 dfcprintk ((MYIOC_s_INFO_FMT
199 "mptfc_block_error_handler.%d: %d:%d, port status is "
200 "DID_IMM_RETRY, deferring %s recovery.\n",
201 ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name,
202 ((MPT_SCSI_HOST *) shost->hostdata)->ioc->sh->host_no,
203 SCpnt->device->id,SCpnt->device->lun,caller));
205 spin_lock_irqsave(shost->host_lock, flags);
207 spin_unlock_irqrestore(shost->host_lock, flags);
209 if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata) {
210 dfcprintk ((MYIOC_s_INFO_FMT
211 "%s.%d: %d:%d, failing recovery, "
212 "port state %d, vdev %p.\n", caller,
213 ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name,
214 ((MPT_SCSI_HOST *) shost->hostdata)->ioc->sh->host_no,
215 SCpnt->device->id,SCpnt->device->lun,ready,
216 SCpnt->device->hostdata));
219 dfcprintk ((MYIOC_s_INFO_FMT
220 "%s.%d: %d:%d, executing recovery.\n", caller,
221 ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name,
222 ((MPT_SCSI_HOST *) shost->hostdata)->ioc->sh->host_no,
223 SCpnt->device->id,SCpnt->device->lun));
224 return (*func)(SCpnt);
228 mptfc_abort(struct scsi_cmnd *SCpnt)
231 mptfc_block_error_handler(SCpnt, mptscsih_abort, __FUNCTION__);
235 mptfc_dev_reset(struct scsi_cmnd *SCpnt)
238 mptfc_block_error_handler(SCpnt, mptscsih_dev_reset, __FUNCTION__);
242 mptfc_bus_reset(struct scsi_cmnd *SCpnt)
245 mptfc_block_error_handler(SCpnt, mptscsih_bus_reset, __FUNCTION__);
249 mptfc_host_reset(struct scsi_cmnd *SCpnt)
252 mptfc_block_error_handler(SCpnt, mptscsih_host_reset, __FUNCTION__);
256 mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
259 rport->dev_loss_tmo = timeout;
261 rport->dev_loss_tmo = mptfc_dev_loss_tmo;
265 mptfc_FcDevPage0_cmp_func(const void *a, const void *b)
267 FCDevicePage0_t **aa = (FCDevicePage0_t **)a;
268 FCDevicePage0_t **bb = (FCDevicePage0_t **)b;
270 if ((*aa)->CurrentBus == (*bb)->CurrentBus) {
271 if ((*aa)->CurrentTargetID == (*bb)->CurrentTargetID)
273 if ((*aa)->CurrentTargetID < (*bb)->CurrentTargetID)
277 if ((*aa)->CurrentBus < (*bb)->CurrentBus)
283 mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port,
284 void(*func)(MPT_ADAPTER *ioc,int channel, FCDevicePage0_t *arg))
286 ConfigPageHeader_t hdr;
288 FCDevicePage0_t *ppage0_alloc, *fc;
289 dma_addr_t page0_dma;
293 FCDevicePage0_t *p0_array=NULL, *p_p0;
294 FCDevicePage0_t **pp0_array=NULL, **p_pp0;
297 U32 port_id = 0xffffff;
299 int max_bus = ioc->facts.MaxBuses;
302 max_targ = (ioc->facts.MaxDevices == 0) ? 256 : ioc->facts.MaxDevices;
304 data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;
305 p_p0 = p0_array = kzalloc(data_sz, GFP_KERNEL);
309 data_sz = sizeof(FCDevicePage0_t *) * max_bus * max_targ;
310 p_pp0 = pp0_array = kzalloc(data_sz, GFP_KERNEL);
315 /* Get FC Device Page 0 header */
319 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_DEVICE;
320 cfg.cfghdr.hdr = &hdr;
322 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
324 cfg.pageAddr = port_id;
327 if ((rc = mpt_config(ioc, &cfg)) != 0)
330 if (hdr.PageLength <= 0)
333 data_sz = hdr.PageLength * 4;
334 ppage0_alloc = pci_alloc_consistent(ioc->pcidev, data_sz,
340 cfg.physAddr = page0_dma;
341 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
343 if ((rc = mpt_config(ioc, &cfg)) == 0) {
344 ppage0_alloc->PortIdentifier =
345 le32_to_cpu(ppage0_alloc->PortIdentifier);
347 ppage0_alloc->WWNN.Low =
348 le32_to_cpu(ppage0_alloc->WWNN.Low);
350 ppage0_alloc->WWNN.High =
351 le32_to_cpu(ppage0_alloc->WWNN.High);
353 ppage0_alloc->WWPN.Low =
354 le32_to_cpu(ppage0_alloc->WWPN.Low);
356 ppage0_alloc->WWPN.High =
357 le32_to_cpu(ppage0_alloc->WWPN.High);
359 ppage0_alloc->BBCredit =
360 le16_to_cpu(ppage0_alloc->BBCredit);
362 ppage0_alloc->MaxRxFrameSize =
363 le16_to_cpu(ppage0_alloc->MaxRxFrameSize);
365 port_id = ppage0_alloc->PortIdentifier;
367 *p_p0 = *ppage0_alloc; /* save data */
368 *p_pp0++ = p_p0++; /* save addr */
370 pci_free_consistent(ioc->pcidev, data_sz,
371 (u8 *) ppage0_alloc, page0_dma);
375 } while (port_id <= 0xff0000);
380 sort (pp0_array, num_targ, sizeof(FCDevicePage0_t *),
381 mptfc_FcDevPage0_cmp_func, NULL);
382 /* call caller's func for each targ */
383 for (ii = 0; ii < num_targ; ii++) {
384 fc = *(pp0_array+ii);
385 func(ioc, ioc_port, fc);
396 mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
398 /* not currently usable */
399 if (pg0->Flags & (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID |
400 MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID))
403 if (!(pg0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID))
406 if (!(pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET))
410 * board data structure already normalized to platform endianness
411 * shifted to avoid unaligned access on 64 bit architecture
413 rid->node_name = ((u64)pg0->WWNN.High) << 32 | (u64)pg0->WWNN.Low;
414 rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;
415 rid->port_id = pg0->PortIdentifier;
416 rid->roles = FC_RPORT_ROLE_UNKNOWN;
422 mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
424 struct fc_rport_identifiers rport_ids;
425 struct fc_rport *rport;
426 struct mptfc_rport_info *ri;
430 u32 roles = FC_RPORT_ROLE_UNKNOWN;
432 if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
435 roles |= FC_RPORT_ROLE_FCP_TARGET;
436 if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
437 roles |= FC_RPORT_ROLE_FCP_INITIATOR;
439 /* scan list looking for a match */
440 list_for_each_entry(ri, &ioc->fc_rports, list) {
441 pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
442 if (pn == rport_ids.port_name) { /* match */
443 list_move_tail(&ri->list, &ioc->fc_rports);
448 if (new_ri) { /* allocate one */
449 ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
452 list_add_tail(&ri->list, &ioc->fc_rports);
455 ri->pg0 = *pg0; /* add/update pg0 data */
456 ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING;
458 /* MPT_RPORT_INFO_FLAGS_REGISTERED - rport not previously deleted */
459 if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
460 ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
461 rport = fc_remote_port_add(ioc->sh, channel, &rport_ids);
464 if (new_ri) /* may have been reset by user */
465 rport->dev_loss_tmo = mptfc_dev_loss_tmo;
467 * if already mapped, remap here. If not mapped,
468 * target_alloc will allocate vtarget and map,
469 * slave_alloc will fill in vdev from vtarget.
472 vtarget = ri->starget->hostdata;
474 vtarget->id = pg0->CurrentTargetID;
475 vtarget->channel = pg0->CurrentBus;
478 *((struct mptfc_rport_info **)rport->dd_data) = ri;
479 /* scan will be scheduled once rport becomes a target */
480 fc_remote_port_rolechg(rport,roles);
482 pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
483 nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
484 dfcprintk ((MYIOC_s_INFO_FMT
485 "mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
486 "rport tid %d, tmo %d\n",
490 (unsigned long long)nn,
491 (unsigned long long)pn,
492 pg0->CurrentTargetID,
493 ri->rport->scsi_target_id,
494 ri->rport->dev_loss_tmo));
504 * OS entry point to allow for host driver to free allocated memory
505 * Called if no device present or device being unloaded
508 mptfc_target_destroy(struct scsi_target *starget)
510 struct fc_rport *rport;
511 struct mptfc_rport_info *ri;
513 rport = starget_to_rport(starget);
515 ri = *((struct mptfc_rport_info **)rport->dd_data);
516 if (ri) /* better be! */
519 if (starget->hostdata)
520 kfree(starget->hostdata);
521 starget->hostdata = NULL;
525 * OS entry point to allow host driver to alloc memory
526 * for each scsi target. Called once per device the bus scan.
527 * Return non-zero if allocation fails.
530 mptfc_target_alloc(struct scsi_target *starget)
533 struct fc_rport *rport;
534 struct mptfc_rport_info *ri;
537 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
540 starget->hostdata = vtarget;
543 rport = starget_to_rport(starget);
545 ri = *((struct mptfc_rport_info **)rport->dd_data);
546 if (ri) { /* better be! */
547 vtarget->id = ri->pg0.CurrentTargetID;
548 vtarget->channel = ri->pg0.CurrentBus;
549 ri->starget = starget;
555 starget->hostdata = NULL;
562 * OS entry point to allow host driver to alloc memory
563 * for each scsi device. Called once per device the bus scan.
564 * Return non-zero if allocation fails.
565 * Init memory once per LUN.
568 mptfc_slave_alloc(struct scsi_device *sdev)
573 struct scsi_target *starget;
574 struct fc_rport *rport;
577 starget = scsi_target(sdev);
578 rport = starget_to_rport(starget);
580 if (!rport || fc_remote_port_chkready(rport))
583 hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
585 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
587 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
588 hd->ioc->name, sizeof(VirtDevice));
593 sdev->hostdata = vdev;
594 vtarget = starget->hostdata;
596 if (vtarget->num_luns == 0) {
597 vtarget->ioc_id = hd->ioc->id;
598 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
601 vdev->vtarget = vtarget;
602 vdev->lun = sdev->lun;
610 struct mptfc_rport_info *ri;
611 ri = *((struct mptfc_rport_info **)rport->dd_data);
612 pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
613 nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
614 dfcprintk ((MYIOC_s_INFO_FMT
615 "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
616 "CurrentTargetID %d, %x %llx %llx\n",
620 sdev->id, ri->pg0.CurrentTargetID,
621 ri->pg0.PortIdentifier,
622 (unsigned long long)pn,
623 (unsigned long long)nn));
631 mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
633 struct mptfc_rport_info *ri;
634 struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
636 VirtDevice *vdev = SCpnt->device->hostdata;
638 if (!vdev || !vdev->vtarget) {
639 SCpnt->result = DID_NO_CONNECT << 16;
644 err = fc_remote_port_chkready(rport);
651 /* dd_data is null until finished adding target */
652 ri = *((struct mptfc_rport_info **)rport->dd_data);
654 dfcprintk ((MYIOC_s_INFO_FMT
655 "mptfc_qcmd.%d: %d:%d, dd_data is null.\n",
656 ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
657 ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
658 SCpnt->device->id,SCpnt->device->lun));
659 SCpnt->result = DID_IMM_RETRY << 16;
664 err = mptscsih_qcmd(SCpnt,done);
667 dfcprintk ((MYIOC_s_INFO_FMT
668 "mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero, (%x).\n",
669 ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
670 ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
671 SCpnt->device->id,SCpnt->device->lun,err));
678 * mptfc_GetFcPortPage0 - Fetch FCPort config Page0.
679 * @ioc: Pointer to MPT_ADAPTER structure
680 * @portnum: IOC Port number
682 * Return: 0 for success
683 * -ENOMEM if no memory available
684 * -EPERM if not allowed due to ISR context
685 * -EAGAIN if no msg frames currently available
686 * -EFAULT for non-successful reply or no reply (timeout)
687 * -EINVAL portnum arg out of range (hardwired to two elements)
690 mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
692 ConfigPageHeader_t hdr;
694 FCPortPage0_t *ppage0_alloc;
695 FCPortPage0_t *pp0dest;
696 dma_addr_t page0_dma;
705 /* Get FCPort Page 0 header */
709 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
710 cfg.cfghdr.hdr = &hdr;
712 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
714 cfg.pageAddr = portnum;
717 if ((rc = mpt_config(ioc, &cfg)) != 0)
720 if (hdr.PageLength == 0)
723 data_sz = hdr.PageLength * 4;
725 ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
729 memset((u8 *)ppage0_alloc, 0, data_sz);
730 cfg.physAddr = page0_dma;
731 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
733 if ((rc = mpt_config(ioc, &cfg)) == 0) {
735 pp0dest = &ioc->fc_port_page0[portnum];
736 copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
737 memcpy(pp0dest, ppage0_alloc, copy_sz);
740 * Normalize endianness of structure data,
741 * by byte-swapping all > 1 byte fields!
743 pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
744 pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
745 pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
746 pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
747 pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
748 pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
749 pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
750 pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
751 pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
752 pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
753 pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
754 pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
755 pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
756 pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
757 pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
758 pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
761 * if still doing discovery,
762 * hang loose a while until finished
764 if ((pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) ||
765 (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_ONLINE &&
766 (pp0dest->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_TYPE_MASK)
767 == MPI_FCPORTPAGE0_FLAGS_ATTACH_NO_INIT)) {
772 printk(MYIOC_s_INFO_FMT "Firmware discovery not"
778 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
785 mptfc_WriteFcPortPage1(MPT_ADAPTER *ioc, int portnum)
787 ConfigPageHeader_t hdr;
794 if (!(ioc->fc_data.fc_port_page1[portnum].data))
797 /* get fcport page 1 header */
801 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
802 cfg.cfghdr.hdr = &hdr;
804 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
806 cfg.pageAddr = portnum;
809 if ((rc = mpt_config(ioc, &cfg)) != 0)
812 if (hdr.PageLength == 0)
815 if (hdr.PageLength*4 != ioc->fc_data.fc_port_page1[portnum].pg_sz)
818 cfg.physAddr = ioc->fc_data.fc_port_page1[portnum].dma;
819 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
822 rc = mpt_config(ioc, &cfg);
828 mptfc_GetFcPortPage1(MPT_ADAPTER *ioc, int portnum)
830 ConfigPageHeader_t hdr;
832 FCPortPage1_t *page1_alloc;
833 dma_addr_t page1_dma;
840 /* get fcport page 1 header */
844 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
845 cfg.cfghdr.hdr = &hdr;
847 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
849 cfg.pageAddr = portnum;
852 if ((rc = mpt_config(ioc, &cfg)) != 0)
855 if (hdr.PageLength == 0)
860 if (ioc->fc_data.fc_port_page1[portnum].data == NULL) {
861 data_sz = hdr.PageLength * 4;
862 if (data_sz < sizeof(FCPortPage1_t))
863 data_sz = sizeof(FCPortPage1_t);
865 page1_alloc = (FCPortPage1_t *) pci_alloc_consistent(ioc->pcidev,
872 page1_alloc = ioc->fc_data.fc_port_page1[portnum].data;
873 page1_dma = ioc->fc_data.fc_port_page1[portnum].dma;
874 data_sz = ioc->fc_data.fc_port_page1[portnum].pg_sz;
875 if (hdr.PageLength * 4 > data_sz) {
876 ioc->fc_data.fc_port_page1[portnum].data = NULL;
877 pci_free_consistent(ioc->pcidev, data_sz, (u8 *)
878 page1_alloc, page1_dma);
883 memset(page1_alloc,0,data_sz);
885 cfg.physAddr = page1_dma;
886 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
888 if ((rc = mpt_config(ioc, &cfg)) == 0) {
889 ioc->fc_data.fc_port_page1[portnum].data = page1_alloc;
890 ioc->fc_data.fc_port_page1[portnum].pg_sz = data_sz;
891 ioc->fc_data.fc_port_page1[portnum].dma = page1_dma;
894 ioc->fc_data.fc_port_page1[portnum].data = NULL;
895 pci_free_consistent(ioc->pcidev, data_sz, (u8 *)
896 page1_alloc, page1_dma);
903 mptfc_SetFcPortPage1_defaults(MPT_ADAPTER *ioc)
908 #define MPTFC_FW_DEVICE_TIMEOUT (1)
909 #define MPTFC_FW_IO_PEND_TIMEOUT (1)
910 #define ON_FLAGS (MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY)
911 #define OFF_FLAGS (MPI_FCPORTPAGE1_FLAGS_VERBOSE_RESCAN_EVENTS)
913 for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
914 if (mptfc_GetFcPortPage1(ioc, ii) != 0)
916 pp1 = ioc->fc_data.fc_port_page1[ii].data;
917 if ((pp1->InitiatorDeviceTimeout == MPTFC_FW_DEVICE_TIMEOUT)
918 && (pp1->InitiatorIoPendTimeout == MPTFC_FW_IO_PEND_TIMEOUT)
919 && ((pp1->Flags & ON_FLAGS) == ON_FLAGS)
920 && ((pp1->Flags & OFF_FLAGS) == 0))
922 pp1->InitiatorDeviceTimeout = MPTFC_FW_DEVICE_TIMEOUT;
923 pp1->InitiatorIoPendTimeout = MPTFC_FW_IO_PEND_TIMEOUT;
924 pp1->Flags &= ~OFF_FLAGS;
925 pp1->Flags |= ON_FLAGS;
926 mptfc_WriteFcPortPage1(ioc, ii);
932 mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
940 struct Scsi_Host *sh;
943 /* don't know what to do as only one scsi (fc) host was allocated */
947 pp0 = &ioc->fc_port_page0[portnum];
950 sn = fc_host_symbolic_name(sh);
951 snprintf(sn, FC_SYMBOLIC_NAME_SIZE, "%s %s%08xh",
953 MPT_FW_REV_MAGIC_ID_STRING,
954 ioc->facts.FWVersion.Word);
956 fc_host_tgtid_bind_type(sh) = FC_TGTID_BIND_BY_WWPN;
958 fc_host_maxframe_size(sh) = pp0->MaxFrameSize;
960 fc_host_node_name(sh) =
961 (u64)pp0->WWNN.High << 32 | (u64)pp0->WWNN.Low;
963 fc_host_port_name(sh) =
964 (u64)pp0->WWPN.High << 32 | (u64)pp0->WWPN.Low;
966 fc_host_port_id(sh) = pp0->PortIdentifier;
968 class = pp0->SupportedServiceClass;
969 if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1)
970 cos |= FC_COS_CLASS1;
971 if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2)
972 cos |= FC_COS_CLASS2;
973 if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3)
974 cos |= FC_COS_CLASS3;
975 fc_host_supported_classes(sh) = cos;
977 if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT)
978 speed = FC_PORTSPEED_1GBIT;
979 else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT)
980 speed = FC_PORTSPEED_2GBIT;
981 else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT)
982 speed = FC_PORTSPEED_4GBIT;
983 else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_10GBIT)
984 speed = FC_PORTSPEED_10GBIT;
986 speed = FC_PORTSPEED_UNKNOWN;
987 fc_host_speed(sh) = speed;
990 if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED)
991 speed |= FC_PORTSPEED_1GBIT;
992 if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED)
993 speed |= FC_PORTSPEED_2GBIT;
994 if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_4GBIT_SPEED)
995 speed |= FC_PORTSPEED_4GBIT;
996 if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED)
997 speed |= FC_PORTSPEED_10GBIT;
998 fc_host_supported_speeds(sh) = speed;
1000 port_state = FC_PORTSTATE_UNKNOWN;
1001 if (pp0->PortState == MPI_FCPORTPAGE0_PORTSTATE_ONLINE)
1002 port_state = FC_PORTSTATE_ONLINE;
1003 else if (pp0->PortState == MPI_FCPORTPAGE0_PORTSTATE_OFFLINE)
1004 port_state = FC_PORTSTATE_LINKDOWN;
1005 fc_host_port_state(sh) = port_state;
1007 port_type = FC_PORTTYPE_UNKNOWN;
1008 if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_POINT_TO_POINT)
1009 port_type = FC_PORTTYPE_PTP;
1010 else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_PRIVATE_LOOP)
1011 port_type = FC_PORTTYPE_LPORT;
1012 else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_PUBLIC_LOOP)
1013 port_type = FC_PORTTYPE_NLPORT;
1014 else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_FABRIC_DIRECT)
1015 port_type = FC_PORTTYPE_NPORT;
1016 fc_host_port_type(sh) = port_type;
1018 fc_host_fabric_name(sh) =
1019 (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_FABRIC_WWN_VALID) ?
1020 (u64) pp0->FabricWWNN.High << 32 | (u64) pp0->FabricWWPN.Low :
1021 (u64)pp0->WWNN.High << 32 | (u64)pp0->WWNN.Low;
1026 mptfc_setup_reset(struct work_struct *work)
1029 container_of(work, MPT_ADAPTER, fc_setup_reset_work);
1031 struct mptfc_rport_info *ri;
1033 /* reset about to happen, delete (block) all rports */
1034 list_for_each_entry(ri, &ioc->fc_rports, list) {
1035 if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
1036 ri->flags &= ~MPT_RPORT_INFO_FLAGS_REGISTERED;
1037 fc_remote_port_delete(ri->rport); /* won't sleep */
1040 pn = (u64)ri->pg0.WWPN.High << 32 |
1041 (u64)ri->pg0.WWPN.Low;
1042 dfcprintk ((MYIOC_s_INFO_FMT
1043 "mptfc_setup_reset.%d: %llx deleted\n",
1046 (unsigned long long)pn));
1052 mptfc_rescan_devices(struct work_struct *work)
1055 container_of(work, MPT_ADAPTER, fc_rescan_work);
1058 struct mptfc_rport_info *ri;
1060 /* start by tagging all ports as missing */
1061 list_for_each_entry(ri, &ioc->fc_rports, list) {
1062 if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
1063 ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
1068 * now rescan devices known to adapter,
1069 * will reregister existing rports
1071 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1072 (void) mptfc_GetFcPortPage0(ioc, ii);
1073 mptfc_init_host_attr(ioc, ii); /* refresh */
1074 mptfc_GetFcDevPage0(ioc, ii, mptfc_register_dev);
1077 /* delete devices still missing */
1078 list_for_each_entry(ri, &ioc->fc_rports, list) {
1079 /* if newly missing, delete it */
1080 if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) {
1082 ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
1083 MPT_RPORT_INFO_FLAGS_MISSING);
1084 fc_remote_port_delete(ri->rport); /* won't sleep */
1087 pn = (u64)ri->pg0.WWPN.High << 32 |
1088 (u64)ri->pg0.WWPN.Low;
1089 dfcprintk ((MYIOC_s_INFO_FMT
1090 "mptfc_rescan.%d: %llx deleted\n",
1093 (unsigned long long)pn));
1099 mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1101 struct Scsi_Host *sh;
1104 unsigned long flags;
1112 if ((r = mpt_attach(pdev,id)) != 0)
1115 ioc = pci_get_drvdata(pdev);
1116 ioc->DoneCtx = mptfcDoneCtx;
1117 ioc->TaskCtx = mptfcTaskCtx;
1118 ioc->InternalCtx = mptfcInternalCtx;
1120 /* Added sanity check on readiness of the MPT adapter.
1122 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
1123 printk(MYIOC_s_WARN_FMT
1124 "Skipping because it's not operational!\n",
1127 goto out_mptfc_probe;
1131 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
1134 goto out_mptfc_probe;
1137 /* Sanity check - ensure at least 1 port is INITIATOR capable
1140 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1141 if (ioc->pfacts[ii].ProtocolFlags &
1142 MPI_PORTFACTS_PROTOCOL_INITIATOR)
1147 printk(MYIOC_s_WARN_FMT
1148 "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
1153 sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
1156 printk(MYIOC_s_WARN_FMT
1157 "Unable to register controller with SCSI subsystem\n",
1160 goto out_mptfc_probe;
1163 spin_lock_init(&ioc->fc_rescan_work_lock);
1164 INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices);
1165 INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset);
1167 spin_lock_irqsave(&ioc->FreeQlock, flags);
1169 /* Attach the SCSI Host to the IOC structure
1177 /* set 16 byte cdb's */
1178 sh->max_cmd_len = 16;
1180 sh->max_id = ioc->pfacts->MaxDevices;
1181 sh->max_lun = max_lun;
1183 sh->this_id = ioc->pfacts[0].PortSCSIID;
1187 sh->unique_id = ioc->id;
1189 /* Verify that we won't exceed the maximum
1190 * number of chain buffers
1191 * We can optimize: ZZ = req_sz/sizeof(SGE)
1193 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1194 * + (req_sz - 64)/sizeof(SGE)
1195 * A slightly different algorithm is required for
1198 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1199 if (sizeof(dma_addr_t) == sizeof(u64)) {
1200 numSGE = (scale - 1) *
1201 (ioc->facts.MaxChainDepth-1) + scale +
1202 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
1205 numSGE = 1 + (scale - 1) *
1206 (ioc->facts.MaxChainDepth-1) + scale +
1207 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
1211 if (numSGE < sh->sg_tablesize) {
1212 /* Reset this value */
1213 dprintk((MYIOC_s_INFO_FMT
1214 "Resetting sg_tablesize to %d from %d\n",
1215 ioc->name, numSGE, sh->sg_tablesize));
1216 sh->sg_tablesize = numSGE;
1219 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1221 hd = (MPT_SCSI_HOST *) sh->hostdata;
1224 /* SCSI needs scsi_cmnd lookup table!
1225 * (with size equal to req_depth*PtrSz!)
1227 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
1228 if (!hd->ScsiLookup) {
1230 goto out_mptfc_probe;
1233 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
1234 ioc->name, hd->ScsiLookup));
1236 /* Clear the TM flags
1239 hd->tmState = TM_STATE_NONE;
1240 hd->resetPending = 0;
1241 hd->abortSCpnt = NULL;
1243 /* Clear the pointer used to store
1244 * single-threaded commands, i.e., those
1245 * issued during a bus scan, dv and
1246 * configuration pages.
1250 /* Initialize this SCSI Hosts' timers
1251 * To use, set the timer expires field
1254 init_timer(&hd->timer);
1255 hd->timer.data = (unsigned long) hd;
1256 hd->timer.function = mptscsih_timer_expired;
1258 init_waitqueue_head(&hd->scandv_waitq);
1259 hd->scandv_wait_done = 0;
1260 hd->last_queue_full = 0;
1262 sh->transportt = mptfc_transport_template;
1263 error = scsi_add_host (sh, &ioc->pcidev->dev);
1265 dprintk((KERN_ERR MYNAM
1266 "scsi_add_host failed\n"));
1267 goto out_mptfc_probe;
1270 /* initialize workqueue */
1272 snprintf(ioc->fc_rescan_work_q_name, KOBJ_NAME_LEN, "mptfc_wq_%d",
1274 ioc->fc_rescan_work_q =
1275 create_singlethread_workqueue(ioc->fc_rescan_work_q_name);
1276 if (!ioc->fc_rescan_work_q)
1277 goto out_mptfc_probe;
1280 * Pre-fetch FC port WWN and stuff...
1281 * (FCPortPage0_t stuff)
1283 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1284 (void) mptfc_GetFcPortPage0(ioc, ii);
1286 mptfc_SetFcPortPage1_defaults(ioc);
1290 * by doing it via the workqueue, some locking is eliminated
1293 queue_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work);
1294 flush_workqueue(ioc->fc_rescan_work_q);
1300 mptscsih_remove(pdev);
1304 static struct pci_driver mptfc_driver = {
1306 .id_table = mptfc_pci_table,
1307 .probe = mptfc_probe,
1308 .remove = __devexit_p(mptfc_remove),
1309 .shutdown = mptscsih_shutdown,
1311 .suspend = mptscsih_suspend,
1312 .resume = mptscsih_resume,
1317 mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
1320 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
1321 unsigned long flags;
1324 devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
1327 if (ioc->sh == NULL ||
1328 ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
1332 case MPI_EVENT_RESCAN:
1333 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1334 if (ioc->fc_rescan_work_q) {
1335 queue_work(ioc->fc_rescan_work_q,
1336 &ioc->fc_rescan_work);
1338 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1341 rc = mptscsih_event_process(ioc,pEvReply);
1348 mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
1351 unsigned long flags;
1353 rc = mptscsih_ioc_reset(ioc,reset_phase);
1358 dtmprintk((KERN_WARNING MYNAM
1359 ": IOC %s_reset routed to FC host driver!\n",
1360 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
1361 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
1363 if (reset_phase == MPT_IOC_SETUP_RESET) {
1364 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1365 if (ioc->fc_rescan_work_q) {
1366 queue_work(ioc->fc_rescan_work_q,
1367 &ioc->fc_setup_reset_work);
1369 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1372 else if (reset_phase == MPT_IOC_PRE_RESET) {
1375 else { /* MPT_IOC_POST_RESET */
1376 mptfc_SetFcPortPage1_defaults(ioc);
1377 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1378 if (ioc->fc_rescan_work_q) {
1379 queue_work(ioc->fc_rescan_work_q,
1380 &ioc->fc_rescan_work);
1382 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1387 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1389 * mptfc_init - Register MPT adapter(s) as SCSI host(s) with SCSI mid-layer.
1391 * Returns 0 for success, non-zero for failure.
1398 show_mptmod_ver(my_NAME, my_VERSION);
1400 /* sanity check module parameters */
1401 if (mptfc_dev_loss_tmo <= 0)
1402 mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
1404 mptfc_transport_template =
1405 fc_attach_transport(&mptfc_transport_functions);
1407 if (!mptfc_transport_template)
1410 mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);
1411 mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
1412 mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
1414 if (mpt_event_register(mptfcDoneCtx, mptfc_event_process) == 0) {
1415 devtverboseprintk((KERN_INFO MYNAM
1416 ": Registered for IOC event notifications\n"));
1419 if (mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset) == 0) {
1420 dprintk((KERN_INFO MYNAM
1421 ": Registered for IOC reset notifications\n"));
1424 error = pci_register_driver(&mptfc_driver);
1426 fc_release_transport(mptfc_transport_template);
1431 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1433 * mptfc_remove - Remove fc infrastructure for devices
1434 * @pdev: Pointer to pci_dev structure
1437 static void __devexit
1438 mptfc_remove(struct pci_dev *pdev)
1440 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1441 struct mptfc_rport_info *p, *n;
1442 struct workqueue_struct *work_q;
1443 unsigned long flags;
1446 /* destroy workqueue */
1447 if ((work_q=ioc->fc_rescan_work_q)) {
1448 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1449 ioc->fc_rescan_work_q = NULL;
1450 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1451 destroy_workqueue(work_q);
1454 fc_remove_host(ioc->sh);
1456 list_for_each_entry_safe(p, n, &ioc->fc_rports, list) {
1461 for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
1462 if (ioc->fc_data.fc_port_page1[ii].data) {
1463 pci_free_consistent(ioc->pcidev,
1464 ioc->fc_data.fc_port_page1[ii].pg_sz,
1465 (u8 *) ioc->fc_data.fc_port_page1[ii].data,
1466 ioc->fc_data.fc_port_page1[ii].dma);
1467 ioc->fc_data.fc_port_page1[ii].data = NULL;
1471 mptscsih_remove(pdev);
1474 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1475 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1477 * mptfc_exit - Unregisters MPT adapter(s)
1483 pci_unregister_driver(&mptfc_driver);
1484 fc_release_transport(mptfc_transport_template);
1486 mpt_reset_deregister(mptfcDoneCtx);
1487 dprintk((KERN_INFO MYNAM
1488 ": Deregistered for IOC reset notifications\n"));
1490 mpt_event_deregister(mptfcDoneCtx);
1491 dprintk((KERN_INFO MYNAM
1492 ": Deregistered for IOC event notifications\n"));
1494 mpt_deregister(mptfcInternalCtx);
1495 mpt_deregister(mptfcTaskCtx);
1496 mpt_deregister(mptfcDoneCtx);
1499 module_init(mptfc_init);
1500 module_exit(mptfc_exit);