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:DL-MPTFusionLinux@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/module.h>
47 #include <linux/kernel.h>
48 #include <linux/init.h>
49 #include <linux/errno.h>
50 #include <linux/kdev_t.h>
51 #include <linux/blkdev.h>
52 #include <linux/delay.h> /* for mdelay */
53 #include <linux/interrupt.h> /* needed for in_interrupt() proto */
54 #include <linux/reboot.h> /* notifier code */
55 #include <linux/workqueue.h>
56 #include <linux/sort.h>
58 #include <scsi/scsi.h>
59 #include <scsi/scsi_cmnd.h>
60 #include <scsi/scsi_device.h>
61 #include <scsi/scsi_host.h>
62 #include <scsi/scsi_tcq.h>
63 #include <scsi/scsi_transport_fc.h>
68 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
69 #define my_NAME "Fusion MPT FC Host driver"
70 #define my_VERSION MPT_LINUX_VERSION_COMMON
73 MODULE_AUTHOR(MODULEAUTHOR);
74 MODULE_DESCRIPTION(my_NAME);
75 MODULE_LICENSE("GPL");
76 MODULE_VERSION(my_VERSION);
78 /* Command line args */
79 #define MPTFC_DEV_LOSS_TMO (60)
80 static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; /* reasonable default */
81 module_param(mptfc_dev_loss_tmo, int, 0);
82 MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the "
83 " transport to wait for an rport to "
84 " return following a device loss event."
87 /* scsi-mid layer global parmeter is max_report_luns, which is 511 */
88 #define MPTFC_MAX_LUN (16895)
89 static int max_lun = MPTFC_MAX_LUN;
90 module_param(max_lun, int, 0);
91 MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
93 static int mptfcDoneCtx = -1;
94 static int mptfcTaskCtx = -1;
95 static int mptfcInternalCtx = -1; /* Used only for internal commands */
97 static int mptfc_target_alloc(struct scsi_target *starget);
98 static int mptfc_slave_alloc(struct scsi_device *sdev);
99 static int mptfc_qcmd(struct scsi_cmnd *SCpnt,
100 void (*done)(struct scsi_cmnd *));
101 static void mptfc_target_destroy(struct scsi_target *starget);
102 static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);
103 static void __devexit mptfc_remove(struct pci_dev *pdev);
104 static int mptfc_abort(struct scsi_cmnd *SCpnt);
105 static int mptfc_dev_reset(struct scsi_cmnd *SCpnt);
106 static int mptfc_bus_reset(struct scsi_cmnd *SCpnt);
107 static int mptfc_host_reset(struct scsi_cmnd *SCpnt);
109 static struct scsi_host_template mptfc_driver_template = {
110 .module = THIS_MODULE,
111 .proc_name = "mptfc",
112 .proc_info = mptscsih_proc_info,
113 .name = "MPT FC Host",
114 .info = mptscsih_info,
115 .queuecommand = mptfc_qcmd,
116 .target_alloc = mptfc_target_alloc,
117 .slave_alloc = mptfc_slave_alloc,
118 .slave_configure = mptscsih_slave_configure,
119 .target_destroy = mptfc_target_destroy,
120 .slave_destroy = mptscsih_slave_destroy,
121 .change_queue_depth = mptscsih_change_queue_depth,
122 .eh_abort_handler = mptfc_abort,
123 .eh_device_reset_handler = mptfc_dev_reset,
124 .eh_bus_reset_handler = mptfc_bus_reset,
125 .eh_host_reset_handler = mptfc_host_reset,
126 .bios_param = mptscsih_bios_param,
127 .can_queue = MPT_FC_CAN_QUEUE,
129 .sg_tablesize = MPT_SCSI_SG_DEPTH,
132 .use_clustering = ENABLE_CLUSTERING,
135 /****************************************************************************
139 static struct pci_device_id mptfc_pci_table[] = {
140 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC909,
141 PCI_ANY_ID, PCI_ANY_ID },
142 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC919,
143 PCI_ANY_ID, PCI_ANY_ID },
144 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC929,
145 PCI_ANY_ID, PCI_ANY_ID },
146 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC919X,
147 PCI_ANY_ID, PCI_ANY_ID },
148 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC929X,
149 PCI_ANY_ID, PCI_ANY_ID },
150 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC939X,
151 PCI_ANY_ID, PCI_ANY_ID },
152 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949X,
153 PCI_ANY_ID, PCI_ANY_ID },
154 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC949E,
155 PCI_ANY_ID, PCI_ANY_ID },
156 {0} /* Terminating entry */
158 MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
160 static struct scsi_transport_template *mptfc_transport_template = NULL;
162 static struct fc_function_template mptfc_transport_functions = {
163 .dd_fcrport_size = 8,
164 .show_host_node_name = 1,
165 .show_host_port_name = 1,
166 .show_host_supported_classes = 1,
167 .show_host_port_id = 1,
168 .show_rport_supported_classes = 1,
169 .show_starget_node_name = 1,
170 .show_starget_port_name = 1,
171 .show_starget_port_id = 1,
172 .set_rport_dev_loss_tmo = mptfc_set_rport_loss_tmo,
173 .show_rport_dev_loss_tmo = 1,
174 .show_host_supported_speeds = 1,
175 .show_host_maxframe_size = 1,
176 .show_host_speed = 1,
177 .show_host_fabric_name = 1,
178 .show_host_port_type = 1,
179 .show_host_port_state = 1,
180 .show_host_symbolic_name = 1,
184 mptfc_block_error_handler(struct scsi_cmnd *SCpnt,
185 int (*func)(struct scsi_cmnd *SCpnt),
188 struct scsi_device *sdev = SCpnt->device;
189 struct Scsi_Host *shost = sdev->host;
190 struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
194 spin_lock_irqsave(shost->host_lock, flags);
195 while ((ready = fc_remote_port_chkready(rport) >> 16) == DID_IMM_RETRY) {
196 spin_unlock_irqrestore(shost->host_lock, flags);
197 dfcprintk ((MYIOC_s_INFO_FMT
198 "mptfc_block_error_handler.%d: %d:%d, port status is "
199 "DID_IMM_RETRY, deferring %s recovery.\n",
200 ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name,
201 ((MPT_SCSI_HOST *) shost->hostdata)->ioc->sh->host_no,
202 SCpnt->device->id,SCpnt->device->lun,caller));
204 spin_lock_irqsave(shost->host_lock, flags);
206 spin_unlock_irqrestore(shost->host_lock, flags);
208 if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata) {
209 dfcprintk ((MYIOC_s_INFO_FMT
210 "%s.%d: %d:%d, failing recovery, "
211 "port state %d, vdev %p.\n", caller,
212 ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name,
213 ((MPT_SCSI_HOST *) shost->hostdata)->ioc->sh->host_no,
214 SCpnt->device->id,SCpnt->device->lun,ready,
215 SCpnt->device->hostdata));
218 dfcprintk ((MYIOC_s_INFO_FMT
219 "%s.%d: %d:%d, executing recovery.\n", caller,
220 ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name,
221 ((MPT_SCSI_HOST *) shost->hostdata)->ioc->sh->host_no,
222 SCpnt->device->id,SCpnt->device->lun));
223 return (*func)(SCpnt);
227 mptfc_abort(struct scsi_cmnd *SCpnt)
230 mptfc_block_error_handler(SCpnt, mptscsih_abort, __FUNCTION__);
234 mptfc_dev_reset(struct scsi_cmnd *SCpnt)
237 mptfc_block_error_handler(SCpnt, mptscsih_dev_reset, __FUNCTION__);
241 mptfc_bus_reset(struct scsi_cmnd *SCpnt)
244 mptfc_block_error_handler(SCpnt, mptscsih_bus_reset, __FUNCTION__);
248 mptfc_host_reset(struct scsi_cmnd *SCpnt)
251 mptfc_block_error_handler(SCpnt, mptscsih_host_reset, __FUNCTION__);
255 mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
258 rport->dev_loss_tmo = timeout;
260 rport->dev_loss_tmo = mptfc_dev_loss_tmo;
264 mptfc_FcDevPage0_cmp_func(const void *a, const void *b)
266 FCDevicePage0_t **aa = (FCDevicePage0_t **)a;
267 FCDevicePage0_t **bb = (FCDevicePage0_t **)b;
269 if ((*aa)->CurrentBus == (*bb)->CurrentBus) {
270 if ((*aa)->CurrentTargetID == (*bb)->CurrentTargetID)
272 if ((*aa)->CurrentTargetID < (*bb)->CurrentTargetID)
276 if ((*aa)->CurrentBus < (*bb)->CurrentBus)
282 mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port,
283 void(*func)(MPT_ADAPTER *ioc,int channel, FCDevicePage0_t *arg))
285 ConfigPageHeader_t hdr;
287 FCDevicePage0_t *ppage0_alloc, *fc;
288 dma_addr_t page0_dma;
292 FCDevicePage0_t *p0_array=NULL, *p_p0;
293 FCDevicePage0_t **pp0_array=NULL, **p_pp0;
296 U32 port_id = 0xffffff;
298 int max_bus = ioc->facts.MaxBuses;
301 max_targ = (ioc->facts.MaxDevices == 0) ? 256 : ioc->facts.MaxDevices;
303 data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;
304 p_p0 = p0_array = kzalloc(data_sz, GFP_KERNEL);
308 data_sz = sizeof(FCDevicePage0_t *) * max_bus * max_targ;
309 p_pp0 = pp0_array = kzalloc(data_sz, GFP_KERNEL);
314 /* Get FC Device Page 0 header */
318 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_DEVICE;
319 cfg.cfghdr.hdr = &hdr;
321 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
323 cfg.pageAddr = port_id;
326 if ((rc = mpt_config(ioc, &cfg)) != 0)
329 if (hdr.PageLength <= 0)
332 data_sz = hdr.PageLength * 4;
333 ppage0_alloc = pci_alloc_consistent(ioc->pcidev, data_sz,
339 cfg.physAddr = page0_dma;
340 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
342 if ((rc = mpt_config(ioc, &cfg)) == 0) {
343 ppage0_alloc->PortIdentifier =
344 le32_to_cpu(ppage0_alloc->PortIdentifier);
346 ppage0_alloc->WWNN.Low =
347 le32_to_cpu(ppage0_alloc->WWNN.Low);
349 ppage0_alloc->WWNN.High =
350 le32_to_cpu(ppage0_alloc->WWNN.High);
352 ppage0_alloc->WWPN.Low =
353 le32_to_cpu(ppage0_alloc->WWPN.Low);
355 ppage0_alloc->WWPN.High =
356 le32_to_cpu(ppage0_alloc->WWPN.High);
358 ppage0_alloc->BBCredit =
359 le16_to_cpu(ppage0_alloc->BBCredit);
361 ppage0_alloc->MaxRxFrameSize =
362 le16_to_cpu(ppage0_alloc->MaxRxFrameSize);
364 port_id = ppage0_alloc->PortIdentifier;
366 *p_p0 = *ppage0_alloc; /* save data */
367 *p_pp0++ = p_p0++; /* save addr */
369 pci_free_consistent(ioc->pcidev, data_sz,
370 (u8 *) ppage0_alloc, page0_dma);
374 } while (port_id <= 0xff0000);
379 sort (pp0_array, num_targ, sizeof(FCDevicePage0_t *),
380 mptfc_FcDevPage0_cmp_func, NULL);
381 /* call caller's func for each targ */
382 for (ii = 0; ii < num_targ; ii++) {
383 fc = *(pp0_array+ii);
384 func(ioc, ioc_port, fc);
395 mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
397 /* not currently usable */
398 if (pg0->Flags & (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID |
399 MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID))
402 if (!(pg0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID))
405 if (!(pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET))
409 * board data structure already normalized to platform endianness
410 * shifted to avoid unaligned access on 64 bit architecture
412 rid->node_name = ((u64)pg0->WWNN.High) << 32 | (u64)pg0->WWNN.Low;
413 rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;
414 rid->port_id = pg0->PortIdentifier;
415 rid->roles = FC_RPORT_ROLE_UNKNOWN;
421 mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
423 struct fc_rport_identifiers rport_ids;
424 struct fc_rport *rport;
425 struct mptfc_rport_info *ri;
429 u32 roles = FC_RPORT_ROLE_UNKNOWN;
431 if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
434 roles |= FC_RPORT_ROLE_FCP_TARGET;
435 if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
436 roles |= FC_RPORT_ROLE_FCP_INITIATOR;
438 /* scan list looking for a match */
439 list_for_each_entry(ri, &ioc->fc_rports, list) {
440 pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
441 if (pn == rport_ids.port_name) { /* match */
442 list_move_tail(&ri->list, &ioc->fc_rports);
447 if (new_ri) { /* allocate one */
448 ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
451 list_add_tail(&ri->list, &ioc->fc_rports);
454 ri->pg0 = *pg0; /* add/update pg0 data */
455 ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING;
457 /* MPT_RPORT_INFO_FLAGS_REGISTERED - rport not previously deleted */
458 if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
459 ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
460 rport = fc_remote_port_add(ioc->sh, channel, &rport_ids);
463 if (new_ri) /* may have been reset by user */
464 rport->dev_loss_tmo = mptfc_dev_loss_tmo;
466 * if already mapped, remap here. If not mapped,
467 * target_alloc will allocate vtarget and map,
468 * slave_alloc will fill in vdev from vtarget.
471 vtarget = ri->starget->hostdata;
473 vtarget->id = pg0->CurrentTargetID;
474 vtarget->channel = pg0->CurrentBus;
477 *((struct mptfc_rport_info **)rport->dd_data) = ri;
478 /* scan will be scheduled once rport becomes a target */
479 fc_remote_port_rolechg(rport,roles);
481 pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
482 nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
483 dfcprintk ((MYIOC_s_INFO_FMT
484 "mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
485 "rport tid %d, tmo %d\n",
489 (unsigned long long)nn,
490 (unsigned long long)pn,
491 pg0->CurrentTargetID,
492 ri->rport->scsi_target_id,
493 ri->rport->dev_loss_tmo));
503 * OS entry point to allow for host driver to free allocated memory
504 * Called if no device present or device being unloaded
507 mptfc_target_destroy(struct scsi_target *starget)
509 struct fc_rport *rport;
510 struct mptfc_rport_info *ri;
512 rport = starget_to_rport(starget);
514 ri = *((struct mptfc_rport_info **)rport->dd_data);
515 if (ri) /* better be! */
518 if (starget->hostdata)
519 kfree(starget->hostdata);
520 starget->hostdata = NULL;
524 * OS entry point to allow host driver to alloc memory
525 * for each scsi target. Called once per device the bus scan.
526 * Return non-zero if allocation fails.
529 mptfc_target_alloc(struct scsi_target *starget)
532 struct fc_rport *rport;
533 struct mptfc_rport_info *ri;
536 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
539 starget->hostdata = vtarget;
542 rport = starget_to_rport(starget);
544 ri = *((struct mptfc_rport_info **)rport->dd_data);
545 if (ri) { /* better be! */
546 vtarget->id = ri->pg0.CurrentTargetID;
547 vtarget->channel = ri->pg0.CurrentBus;
548 ri->starget = starget;
554 starget->hostdata = NULL;
561 * OS entry point to allow host driver to alloc memory
562 * for each scsi device. Called once per device the bus scan.
563 * Return non-zero if allocation fails.
564 * Init memory once per LUN.
567 mptfc_slave_alloc(struct scsi_device *sdev)
572 struct scsi_target *starget;
573 struct fc_rport *rport;
576 starget = scsi_target(sdev);
577 rport = starget_to_rport(starget);
579 if (!rport || fc_remote_port_chkready(rport))
582 hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
584 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
586 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
587 hd->ioc->name, sizeof(VirtDevice));
592 sdev->hostdata = vdev;
593 vtarget = starget->hostdata;
595 if (vtarget->num_luns == 0) {
596 vtarget->ioc_id = hd->ioc->id;
597 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
600 vdev->vtarget = vtarget;
601 vdev->lun = sdev->lun;
609 struct mptfc_rport_info *ri;
610 ri = *((struct mptfc_rport_info **)rport->dd_data);
611 pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
612 nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
613 dfcprintk ((MYIOC_s_INFO_FMT
614 "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
615 "CurrentTargetID %d, %x %llx %llx\n",
619 sdev->id, ri->pg0.CurrentTargetID,
620 ri->pg0.PortIdentifier,
621 (unsigned long long)pn,
622 (unsigned long long)nn));
630 mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
632 struct mptfc_rport_info *ri;
633 struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
635 VirtDevice *vdev = SCpnt->device->hostdata;
637 if (!vdev || !vdev->vtarget) {
638 SCpnt->result = DID_NO_CONNECT << 16;
643 err = fc_remote_port_chkready(rport);
650 /* dd_data is null until finished adding target */
651 ri = *((struct mptfc_rport_info **)rport->dd_data);
653 dfcprintk ((MYIOC_s_INFO_FMT
654 "mptfc_qcmd.%d: %d:%d, dd_data is null.\n",
655 ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
656 ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
657 SCpnt->device->id,SCpnt->device->lun));
658 SCpnt->result = DID_IMM_RETRY << 16;
663 err = mptscsih_qcmd(SCpnt,done);
666 dfcprintk ((MYIOC_s_INFO_FMT
667 "mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero, (%x).\n",
668 ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
669 ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
670 SCpnt->device->id,SCpnt->device->lun,err));
677 * mptfc_GetFcPortPage0 - Fetch FCPort config Page0.
678 * @ioc: Pointer to MPT_ADAPTER structure
679 * @portnum: IOC Port number
681 * Return: 0 for success
682 * -ENOMEM if no memory available
683 * -EPERM if not allowed due to ISR context
684 * -EAGAIN if no msg frames currently available
685 * -EFAULT for non-successful reply or no reply (timeout)
686 * -EINVAL portnum arg out of range (hardwired to two elements)
689 mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
691 ConfigPageHeader_t hdr;
693 FCPortPage0_t *ppage0_alloc;
694 FCPortPage0_t *pp0dest;
695 dma_addr_t page0_dma;
704 /* Get FCPort Page 0 header */
708 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
709 cfg.cfghdr.hdr = &hdr;
711 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
713 cfg.pageAddr = portnum;
716 if ((rc = mpt_config(ioc, &cfg)) != 0)
719 if (hdr.PageLength == 0)
722 data_sz = hdr.PageLength * 4;
724 ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
728 memset((u8 *)ppage0_alloc, 0, data_sz);
729 cfg.physAddr = page0_dma;
730 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
732 if ((rc = mpt_config(ioc, &cfg)) == 0) {
734 pp0dest = &ioc->fc_port_page0[portnum];
735 copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
736 memcpy(pp0dest, ppage0_alloc, copy_sz);
739 * Normalize endianness of structure data,
740 * by byte-swapping all > 1 byte fields!
742 pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
743 pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
744 pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
745 pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
746 pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
747 pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
748 pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
749 pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
750 pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
751 pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
752 pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
753 pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
754 pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
755 pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
756 pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
757 pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
760 * if still doing discovery,
761 * hang loose a while until finished
763 if ((pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) ||
764 (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_ONLINE &&
765 (pp0dest->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_TYPE_MASK)
766 == MPI_FCPORTPAGE0_FLAGS_ATTACH_NO_INIT)) {
771 printk(MYIOC_s_INFO_FMT "Firmware discovery not"
777 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
784 mptfc_WriteFcPortPage1(MPT_ADAPTER *ioc, int portnum)
786 ConfigPageHeader_t hdr;
793 if (!(ioc->fc_data.fc_port_page1[portnum].data))
796 /* get fcport page 1 header */
800 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
801 cfg.cfghdr.hdr = &hdr;
803 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
805 cfg.pageAddr = portnum;
808 if ((rc = mpt_config(ioc, &cfg)) != 0)
811 if (hdr.PageLength == 0)
814 if (hdr.PageLength*4 != ioc->fc_data.fc_port_page1[portnum].pg_sz)
817 cfg.physAddr = ioc->fc_data.fc_port_page1[portnum].dma;
818 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
821 rc = mpt_config(ioc, &cfg);
827 mptfc_GetFcPortPage1(MPT_ADAPTER *ioc, int portnum)
829 ConfigPageHeader_t hdr;
831 FCPortPage1_t *page1_alloc;
832 dma_addr_t page1_dma;
839 /* get fcport page 1 header */
843 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
844 cfg.cfghdr.hdr = &hdr;
846 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
848 cfg.pageAddr = portnum;
851 if ((rc = mpt_config(ioc, &cfg)) != 0)
854 if (hdr.PageLength == 0)
859 if (ioc->fc_data.fc_port_page1[portnum].data == NULL) {
860 data_sz = hdr.PageLength * 4;
861 if (data_sz < sizeof(FCPortPage1_t))
862 data_sz = sizeof(FCPortPage1_t);
864 page1_alloc = (FCPortPage1_t *) pci_alloc_consistent(ioc->pcidev,
871 page1_alloc = ioc->fc_data.fc_port_page1[portnum].data;
872 page1_dma = ioc->fc_data.fc_port_page1[portnum].dma;
873 data_sz = ioc->fc_data.fc_port_page1[portnum].pg_sz;
874 if (hdr.PageLength * 4 > data_sz) {
875 ioc->fc_data.fc_port_page1[portnum].data = NULL;
876 pci_free_consistent(ioc->pcidev, data_sz, (u8 *)
877 page1_alloc, page1_dma);
882 memset(page1_alloc,0,data_sz);
884 cfg.physAddr = page1_dma;
885 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
887 if ((rc = mpt_config(ioc, &cfg)) == 0) {
888 ioc->fc_data.fc_port_page1[portnum].data = page1_alloc;
889 ioc->fc_data.fc_port_page1[portnum].pg_sz = data_sz;
890 ioc->fc_data.fc_port_page1[portnum].dma = page1_dma;
893 ioc->fc_data.fc_port_page1[portnum].data = NULL;
894 pci_free_consistent(ioc->pcidev, data_sz, (u8 *)
895 page1_alloc, page1_dma);
902 mptfc_SetFcPortPage1_defaults(MPT_ADAPTER *ioc)
907 #define MPTFC_FW_DEVICE_TIMEOUT (1)
908 #define MPTFC_FW_IO_PEND_TIMEOUT (1)
909 #define ON_FLAGS (MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY)
910 #define OFF_FLAGS (MPI_FCPORTPAGE1_FLAGS_VERBOSE_RESCAN_EVENTS)
912 for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
913 if (mptfc_GetFcPortPage1(ioc, ii) != 0)
915 pp1 = ioc->fc_data.fc_port_page1[ii].data;
916 if ((pp1->InitiatorDeviceTimeout == MPTFC_FW_DEVICE_TIMEOUT)
917 && (pp1->InitiatorIoPendTimeout == MPTFC_FW_IO_PEND_TIMEOUT)
918 && ((pp1->Flags & ON_FLAGS) == ON_FLAGS)
919 && ((pp1->Flags & OFF_FLAGS) == 0))
921 pp1->InitiatorDeviceTimeout = MPTFC_FW_DEVICE_TIMEOUT;
922 pp1->InitiatorIoPendTimeout = MPTFC_FW_IO_PEND_TIMEOUT;
923 pp1->Flags &= ~OFF_FLAGS;
924 pp1->Flags |= ON_FLAGS;
925 mptfc_WriteFcPortPage1(ioc, ii);
931 mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
939 struct Scsi_Host *sh;
942 /* don't know what to do as only one scsi (fc) host was allocated */
946 pp0 = &ioc->fc_port_page0[portnum];
949 sn = fc_host_symbolic_name(sh);
950 snprintf(sn, FC_SYMBOLIC_NAME_SIZE, "%s %s%08xh",
952 MPT_FW_REV_MAGIC_ID_STRING,
953 ioc->facts.FWVersion.Word);
955 fc_host_tgtid_bind_type(sh) = FC_TGTID_BIND_BY_WWPN;
957 fc_host_maxframe_size(sh) = pp0->MaxFrameSize;
959 fc_host_node_name(sh) =
960 (u64)pp0->WWNN.High << 32 | (u64)pp0->WWNN.Low;
962 fc_host_port_name(sh) =
963 (u64)pp0->WWPN.High << 32 | (u64)pp0->WWPN.Low;
965 fc_host_port_id(sh) = pp0->PortIdentifier;
967 class = pp0->SupportedServiceClass;
968 if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1)
969 cos |= FC_COS_CLASS1;
970 if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2)
971 cos |= FC_COS_CLASS2;
972 if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3)
973 cos |= FC_COS_CLASS3;
974 fc_host_supported_classes(sh) = cos;
976 if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT)
977 speed = FC_PORTSPEED_1GBIT;
978 else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT)
979 speed = FC_PORTSPEED_2GBIT;
980 else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT)
981 speed = FC_PORTSPEED_4GBIT;
982 else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_10GBIT)
983 speed = FC_PORTSPEED_10GBIT;
985 speed = FC_PORTSPEED_UNKNOWN;
986 fc_host_speed(sh) = speed;
989 if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED)
990 speed |= FC_PORTSPEED_1GBIT;
991 if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED)
992 speed |= FC_PORTSPEED_2GBIT;
993 if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_4GBIT_SPEED)
994 speed |= FC_PORTSPEED_4GBIT;
995 if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED)
996 speed |= FC_PORTSPEED_10GBIT;
997 fc_host_supported_speeds(sh) = speed;
999 port_state = FC_PORTSTATE_UNKNOWN;
1000 if (pp0->PortState == MPI_FCPORTPAGE0_PORTSTATE_ONLINE)
1001 port_state = FC_PORTSTATE_ONLINE;
1002 else if (pp0->PortState == MPI_FCPORTPAGE0_PORTSTATE_OFFLINE)
1003 port_state = FC_PORTSTATE_LINKDOWN;
1004 fc_host_port_state(sh) = port_state;
1006 port_type = FC_PORTTYPE_UNKNOWN;
1007 if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_POINT_TO_POINT)
1008 port_type = FC_PORTTYPE_PTP;
1009 else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_PRIVATE_LOOP)
1010 port_type = FC_PORTTYPE_LPORT;
1011 else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_PUBLIC_LOOP)
1012 port_type = FC_PORTTYPE_NLPORT;
1013 else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_FABRIC_DIRECT)
1014 port_type = FC_PORTTYPE_NPORT;
1015 fc_host_port_type(sh) = port_type;
1017 fc_host_fabric_name(sh) =
1018 (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_FABRIC_WWN_VALID) ?
1019 (u64) pp0->FabricWWNN.High << 32 | (u64) pp0->FabricWWPN.Low :
1020 (u64)pp0->WWNN.High << 32 | (u64)pp0->WWNN.Low;
1025 mptfc_setup_reset(struct work_struct *work)
1028 container_of(work, MPT_ADAPTER, fc_setup_reset_work);
1030 struct mptfc_rport_info *ri;
1032 /* reset about to happen, delete (block) all rports */
1033 list_for_each_entry(ri, &ioc->fc_rports, list) {
1034 if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
1035 ri->flags &= ~MPT_RPORT_INFO_FLAGS_REGISTERED;
1036 fc_remote_port_delete(ri->rport); /* won't sleep */
1039 pn = (u64)ri->pg0.WWPN.High << 32 |
1040 (u64)ri->pg0.WWPN.Low;
1041 dfcprintk ((MYIOC_s_INFO_FMT
1042 "mptfc_setup_reset.%d: %llx deleted\n",
1045 (unsigned long long)pn));
1051 mptfc_rescan_devices(struct work_struct *work)
1054 container_of(work, MPT_ADAPTER, fc_rescan_work);
1057 struct mptfc_rport_info *ri;
1059 /* start by tagging all ports as missing */
1060 list_for_each_entry(ri, &ioc->fc_rports, list) {
1061 if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
1062 ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
1067 * now rescan devices known to adapter,
1068 * will reregister existing rports
1070 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1071 (void) mptfc_GetFcPortPage0(ioc, ii);
1072 mptfc_init_host_attr(ioc, ii); /* refresh */
1073 mptfc_GetFcDevPage0(ioc, ii, mptfc_register_dev);
1076 /* delete devices still missing */
1077 list_for_each_entry(ri, &ioc->fc_rports, list) {
1078 /* if newly missing, delete it */
1079 if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) {
1081 ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
1082 MPT_RPORT_INFO_FLAGS_MISSING);
1083 fc_remote_port_delete(ri->rport); /* won't sleep */
1086 pn = (u64)ri->pg0.WWPN.High << 32 |
1087 (u64)ri->pg0.WWPN.Low;
1088 dfcprintk ((MYIOC_s_INFO_FMT
1089 "mptfc_rescan.%d: %llx deleted\n",
1092 (unsigned long long)pn));
1098 mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1100 struct Scsi_Host *sh;
1103 unsigned long flags;
1111 if ((r = mpt_attach(pdev,id)) != 0)
1114 ioc = pci_get_drvdata(pdev);
1115 ioc->DoneCtx = mptfcDoneCtx;
1116 ioc->TaskCtx = mptfcTaskCtx;
1117 ioc->InternalCtx = mptfcInternalCtx;
1119 /* Added sanity check on readiness of the MPT adapter.
1121 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
1122 printk(MYIOC_s_WARN_FMT
1123 "Skipping because it's not operational!\n",
1126 goto out_mptfc_probe;
1130 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
1133 goto out_mptfc_probe;
1136 /* Sanity check - ensure at least 1 port is INITIATOR capable
1139 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1140 if (ioc->pfacts[ii].ProtocolFlags &
1141 MPI_PORTFACTS_PROTOCOL_INITIATOR)
1146 printk(MYIOC_s_WARN_FMT
1147 "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
1152 sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
1155 printk(MYIOC_s_WARN_FMT
1156 "Unable to register controller with SCSI subsystem\n",
1159 goto out_mptfc_probe;
1162 spin_lock_init(&ioc->fc_rescan_work_lock);
1163 INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices);
1164 INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset);
1166 spin_lock_irqsave(&ioc->FreeQlock, flags);
1168 /* Attach the SCSI Host to the IOC structure
1176 /* set 16 byte cdb's */
1177 sh->max_cmd_len = 16;
1179 sh->max_id = ioc->pfacts->MaxDevices;
1180 sh->max_lun = max_lun;
1182 sh->this_id = ioc->pfacts[0].PortSCSIID;
1186 sh->unique_id = ioc->id;
1188 /* Verify that we won't exceed the maximum
1189 * number of chain buffers
1190 * We can optimize: ZZ = req_sz/sizeof(SGE)
1192 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1193 * + (req_sz - 64)/sizeof(SGE)
1194 * A slightly different algorithm is required for
1197 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1198 if (sizeof(dma_addr_t) == sizeof(u64)) {
1199 numSGE = (scale - 1) *
1200 (ioc->facts.MaxChainDepth-1) + scale +
1201 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
1204 numSGE = 1 + (scale - 1) *
1205 (ioc->facts.MaxChainDepth-1) + scale +
1206 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
1210 if (numSGE < sh->sg_tablesize) {
1211 /* Reset this value */
1212 dprintk((MYIOC_s_INFO_FMT
1213 "Resetting sg_tablesize to %d from %d\n",
1214 ioc->name, numSGE, sh->sg_tablesize));
1215 sh->sg_tablesize = numSGE;
1218 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1220 hd = (MPT_SCSI_HOST *) sh->hostdata;
1223 /* SCSI needs scsi_cmnd lookup table!
1224 * (with size equal to req_depth*PtrSz!)
1226 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
1227 if (!hd->ScsiLookup) {
1229 goto out_mptfc_probe;
1232 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
1233 ioc->name, hd->ScsiLookup));
1235 /* Clear the TM flags
1238 hd->tmState = TM_STATE_NONE;
1239 hd->resetPending = 0;
1240 hd->abortSCpnt = NULL;
1242 /* Clear the pointer used to store
1243 * single-threaded commands, i.e., those
1244 * issued during a bus scan, dv and
1245 * configuration pages.
1249 /* Initialize this SCSI Hosts' timers
1250 * To use, set the timer expires field
1253 init_timer(&hd->timer);
1254 hd->timer.data = (unsigned long) hd;
1255 hd->timer.function = mptscsih_timer_expired;
1257 init_waitqueue_head(&hd->scandv_waitq);
1258 hd->scandv_wait_done = 0;
1259 hd->last_queue_full = 0;
1261 sh->transportt = mptfc_transport_template;
1262 error = scsi_add_host (sh, &ioc->pcidev->dev);
1264 dprintk((KERN_ERR MYNAM
1265 "scsi_add_host failed\n"));
1266 goto out_mptfc_probe;
1269 /* initialize workqueue */
1271 snprintf(ioc->fc_rescan_work_q_name, KOBJ_NAME_LEN, "mptfc_wq_%d",
1273 ioc->fc_rescan_work_q =
1274 create_singlethread_workqueue(ioc->fc_rescan_work_q_name);
1275 if (!ioc->fc_rescan_work_q)
1276 goto out_mptfc_probe;
1279 * Pre-fetch FC port WWN and stuff...
1280 * (FCPortPage0_t stuff)
1282 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1283 (void) mptfc_GetFcPortPage0(ioc, ii);
1285 mptfc_SetFcPortPage1_defaults(ioc);
1289 * by doing it via the workqueue, some locking is eliminated
1292 queue_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work);
1293 flush_workqueue(ioc->fc_rescan_work_q);
1299 mptscsih_remove(pdev);
1303 static struct pci_driver mptfc_driver = {
1305 .id_table = mptfc_pci_table,
1306 .probe = mptfc_probe,
1307 .remove = __devexit_p(mptfc_remove),
1308 .shutdown = mptscsih_shutdown,
1310 .suspend = mptscsih_suspend,
1311 .resume = mptscsih_resume,
1316 mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
1319 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
1320 unsigned long flags;
1323 devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
1326 if (ioc->sh == NULL ||
1327 ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
1331 case MPI_EVENT_RESCAN:
1332 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1333 if (ioc->fc_rescan_work_q) {
1334 queue_work(ioc->fc_rescan_work_q,
1335 &ioc->fc_rescan_work);
1337 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1340 rc = mptscsih_event_process(ioc,pEvReply);
1347 mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
1350 unsigned long flags;
1352 rc = mptscsih_ioc_reset(ioc,reset_phase);
1357 dtmprintk((KERN_WARNING MYNAM
1358 ": IOC %s_reset routed to FC host driver!\n",
1359 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
1360 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
1362 if (reset_phase == MPT_IOC_SETUP_RESET) {
1363 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1364 if (ioc->fc_rescan_work_q) {
1365 queue_work(ioc->fc_rescan_work_q,
1366 &ioc->fc_setup_reset_work);
1368 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1371 else if (reset_phase == MPT_IOC_PRE_RESET) {
1374 else { /* MPT_IOC_POST_RESET */
1375 mptfc_SetFcPortPage1_defaults(ioc);
1376 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1377 if (ioc->fc_rescan_work_q) {
1378 queue_work(ioc->fc_rescan_work_q,
1379 &ioc->fc_rescan_work);
1381 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1386 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1388 * mptfc_init - Register MPT adapter(s) as SCSI host(s) with SCSI mid-layer.
1390 * Returns 0 for success, non-zero for failure.
1397 show_mptmod_ver(my_NAME, my_VERSION);
1399 /* sanity check module parameters */
1400 if (mptfc_dev_loss_tmo <= 0)
1401 mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
1403 mptfc_transport_template =
1404 fc_attach_transport(&mptfc_transport_functions);
1406 if (!mptfc_transport_template)
1409 mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);
1410 mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
1411 mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
1413 if (mpt_event_register(mptfcDoneCtx, mptfc_event_process) == 0) {
1414 devtverboseprintk((KERN_INFO MYNAM
1415 ": Registered for IOC event notifications\n"));
1418 if (mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset) == 0) {
1419 dprintk((KERN_INFO MYNAM
1420 ": Registered for IOC reset notifications\n"));
1423 error = pci_register_driver(&mptfc_driver);
1425 fc_release_transport(mptfc_transport_template);
1430 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1432 * mptfc_remove - Remove fc infrastructure for devices
1433 * @pdev: Pointer to pci_dev structure
1436 static void __devexit
1437 mptfc_remove(struct pci_dev *pdev)
1439 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1440 struct mptfc_rport_info *p, *n;
1441 struct workqueue_struct *work_q;
1442 unsigned long flags;
1445 /* destroy workqueue */
1446 if ((work_q=ioc->fc_rescan_work_q)) {
1447 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1448 ioc->fc_rescan_work_q = NULL;
1449 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1450 destroy_workqueue(work_q);
1453 fc_remove_host(ioc->sh);
1455 list_for_each_entry_safe(p, n, &ioc->fc_rports, list) {
1460 for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
1461 if (ioc->fc_data.fc_port_page1[ii].data) {
1462 pci_free_consistent(ioc->pcidev,
1463 ioc->fc_data.fc_port_page1[ii].pg_sz,
1464 (u8 *) ioc->fc_data.fc_port_page1[ii].data,
1465 ioc->fc_data.fc_port_page1[ii].dma);
1466 ioc->fc_data.fc_port_page1[ii].data = NULL;
1470 mptscsih_remove(pdev);
1473 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1474 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1476 * mptfc_exit - Unregisters MPT adapter(s)
1482 pci_unregister_driver(&mptfc_driver);
1483 fc_release_transport(mptfc_transport_template);
1485 mpt_reset_deregister(mptfcDoneCtx);
1486 dprintk((KERN_INFO MYNAM
1487 ": Deregistered for IOC reset notifications\n"));
1489 mpt_event_deregister(mptfcDoneCtx);
1490 dprintk((KERN_INFO MYNAM
1491 ": Deregistered for IOC event notifications\n"));
1493 mpt_deregister(mptfcInternalCtx);
1494 mpt_deregister(mptfcTaskCtx);
1495 mpt_deregister(mptfcDoneCtx);
1498 module_init(mptfc_init);
1499 module_exit(mptfc_exit);