2 * linux/drivers/message/fusion/mptfc.c
3 * For use with LSI PCI chip/adapter(s)
4 * running LSI Fusion MPT (Message Passing Technology) firmware.
6 * Copyright (c) 1999-2008 LSI 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 u8 mptfcDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;
94 static u8 mptfcTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
95 static u8 mptfcInternalCtx = MPT_MAX_PROTOCOL_DRIVERS;
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,
133 .shost_attrs = mptscsih_host_attrs,
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 { PCI_VENDOR_ID_BROCADE, MPI_MANUFACTPAGE_DEVICEID_FC949E,
158 PCI_ANY_ID, PCI_ANY_ID },
159 {0} /* Terminating entry */
161 MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
163 static struct scsi_transport_template *mptfc_transport_template = NULL;
165 static struct fc_function_template mptfc_transport_functions = {
166 .dd_fcrport_size = 8,
167 .show_host_node_name = 1,
168 .show_host_port_name = 1,
169 .show_host_supported_classes = 1,
170 .show_host_port_id = 1,
171 .show_rport_supported_classes = 1,
172 .show_starget_node_name = 1,
173 .show_starget_port_name = 1,
174 .show_starget_port_id = 1,
175 .set_rport_dev_loss_tmo = mptfc_set_rport_loss_tmo,
176 .show_rport_dev_loss_tmo = 1,
177 .show_host_supported_speeds = 1,
178 .show_host_maxframe_size = 1,
179 .show_host_speed = 1,
180 .show_host_fabric_name = 1,
181 .show_host_port_type = 1,
182 .show_host_port_state = 1,
183 .show_host_symbolic_name = 1,
187 mptfc_block_error_handler(struct scsi_cmnd *SCpnt,
188 int (*func)(struct scsi_cmnd *SCpnt),
192 struct scsi_device *sdev = SCpnt->device;
193 struct Scsi_Host *shost = sdev->host;
194 struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
199 hd = shost_priv(SCpnt->device->host);
201 spin_lock_irqsave(shost->host_lock, flags);
202 while ((ready = fc_remote_port_chkready(rport) >> 16) == DID_IMM_RETRY) {
203 spin_unlock_irqrestore(shost->host_lock, flags);
204 dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
205 "mptfc_block_error_handler.%d: %d:%d, port status is "
206 "DID_IMM_RETRY, deferring %s recovery.\n",
207 ioc->name, ioc->sh->host_no,
208 SCpnt->device->id, SCpnt->device->lun, caller));
210 spin_lock_irqsave(shost->host_lock, flags);
212 spin_unlock_irqrestore(shost->host_lock, flags);
214 if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata) {
215 dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
216 "%s.%d: %d:%d, failing recovery, "
217 "port state %d, vdevice %p.\n", caller,
218 ioc->name, ioc->sh->host_no,
219 SCpnt->device->id, SCpnt->device->lun, ready,
220 SCpnt->device->hostdata));
223 dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
224 "%s.%d: %d:%d, executing recovery.\n", caller,
225 ioc->name, ioc->sh->host_no,
226 SCpnt->device->id, SCpnt->device->lun));
227 return (*func)(SCpnt);
231 mptfc_abort(struct scsi_cmnd *SCpnt)
234 mptfc_block_error_handler(SCpnt, mptscsih_abort, __FUNCTION__);
238 mptfc_dev_reset(struct scsi_cmnd *SCpnt)
241 mptfc_block_error_handler(SCpnt, mptscsih_dev_reset, __FUNCTION__);
245 mptfc_bus_reset(struct scsi_cmnd *SCpnt)
248 mptfc_block_error_handler(SCpnt, mptscsih_bus_reset, __FUNCTION__);
252 mptfc_host_reset(struct scsi_cmnd *SCpnt)
255 mptfc_block_error_handler(SCpnt, mptscsih_host_reset, __FUNCTION__);
259 mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
262 rport->dev_loss_tmo = timeout;
264 rport->dev_loss_tmo = mptfc_dev_loss_tmo;
268 mptfc_FcDevPage0_cmp_func(const void *a, const void *b)
270 FCDevicePage0_t **aa = (FCDevicePage0_t **)a;
271 FCDevicePage0_t **bb = (FCDevicePage0_t **)b;
273 if ((*aa)->CurrentBus == (*bb)->CurrentBus) {
274 if ((*aa)->CurrentTargetID == (*bb)->CurrentTargetID)
276 if ((*aa)->CurrentTargetID < (*bb)->CurrentTargetID)
280 if ((*aa)->CurrentBus < (*bb)->CurrentBus)
286 mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port,
287 void(*func)(MPT_ADAPTER *ioc,int channel, FCDevicePage0_t *arg))
289 ConfigPageHeader_t hdr;
291 FCDevicePage0_t *ppage0_alloc, *fc;
292 dma_addr_t page0_dma;
296 FCDevicePage0_t *p0_array=NULL, *p_p0;
297 FCDevicePage0_t **pp0_array=NULL, **p_pp0;
300 U32 port_id = 0xffffff;
302 int max_bus = ioc->facts.MaxBuses;
305 max_targ = (ioc->facts.MaxDevices == 0) ? 256 : ioc->facts.MaxDevices;
307 data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;
308 p_p0 = p0_array = kzalloc(data_sz, GFP_KERNEL);
312 data_sz = sizeof(FCDevicePage0_t *) * max_bus * max_targ;
313 p_pp0 = pp0_array = kzalloc(data_sz, GFP_KERNEL);
318 /* Get FC Device Page 0 header */
322 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_DEVICE;
323 cfg.cfghdr.hdr = &hdr;
325 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
327 cfg.pageAddr = port_id;
330 if ((rc = mpt_config(ioc, &cfg)) != 0)
333 if (hdr.PageLength <= 0)
336 data_sz = hdr.PageLength * 4;
337 ppage0_alloc = pci_alloc_consistent(ioc->pcidev, data_sz,
343 cfg.physAddr = page0_dma;
344 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
346 if ((rc = mpt_config(ioc, &cfg)) == 0) {
347 ppage0_alloc->PortIdentifier =
348 le32_to_cpu(ppage0_alloc->PortIdentifier);
350 ppage0_alloc->WWNN.Low =
351 le32_to_cpu(ppage0_alloc->WWNN.Low);
353 ppage0_alloc->WWNN.High =
354 le32_to_cpu(ppage0_alloc->WWNN.High);
356 ppage0_alloc->WWPN.Low =
357 le32_to_cpu(ppage0_alloc->WWPN.Low);
359 ppage0_alloc->WWPN.High =
360 le32_to_cpu(ppage0_alloc->WWPN.High);
362 ppage0_alloc->BBCredit =
363 le16_to_cpu(ppage0_alloc->BBCredit);
365 ppage0_alloc->MaxRxFrameSize =
366 le16_to_cpu(ppage0_alloc->MaxRxFrameSize);
368 port_id = ppage0_alloc->PortIdentifier;
370 *p_p0 = *ppage0_alloc; /* save data */
371 *p_pp0++ = p_p0++; /* save addr */
373 pci_free_consistent(ioc->pcidev, data_sz,
374 (u8 *) ppage0_alloc, page0_dma);
378 } while (port_id <= 0xff0000);
383 sort (pp0_array, num_targ, sizeof(FCDevicePage0_t *),
384 mptfc_FcDevPage0_cmp_func, NULL);
385 /* call caller's func for each targ */
386 for (ii = 0; ii < num_targ; ii++) {
387 fc = *(pp0_array+ii);
388 func(ioc, ioc_port, fc);
399 mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
401 /* not currently usable */
402 if (pg0->Flags & (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID |
403 MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID))
406 if (!(pg0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID))
409 if (!(pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET))
413 * board data structure already normalized to platform endianness
414 * shifted to avoid unaligned access on 64 bit architecture
416 rid->node_name = ((u64)pg0->WWNN.High) << 32 | (u64)pg0->WWNN.Low;
417 rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;
418 rid->port_id = pg0->PortIdentifier;
419 rid->roles = FC_RPORT_ROLE_UNKNOWN;
425 mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
427 struct fc_rport_identifiers rport_ids;
428 struct fc_rport *rport;
429 struct mptfc_rport_info *ri;
433 u32 roles = FC_RPORT_ROLE_UNKNOWN;
435 if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
438 roles |= FC_RPORT_ROLE_FCP_TARGET;
439 if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
440 roles |= FC_RPORT_ROLE_FCP_INITIATOR;
442 /* scan list looking for a match */
443 list_for_each_entry(ri, &ioc->fc_rports, list) {
444 pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
445 if (pn == rport_ids.port_name) { /* match */
446 list_move_tail(&ri->list, &ioc->fc_rports);
451 if (new_ri) { /* allocate one */
452 ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
455 list_add_tail(&ri->list, &ioc->fc_rports);
458 ri->pg0 = *pg0; /* add/update pg0 data */
459 ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING;
461 /* MPT_RPORT_INFO_FLAGS_REGISTERED - rport not previously deleted */
462 if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
463 ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
464 rport = fc_remote_port_add(ioc->sh, channel, &rport_ids);
467 if (new_ri) /* may have been reset by user */
468 rport->dev_loss_tmo = mptfc_dev_loss_tmo;
470 * if already mapped, remap here. If not mapped,
471 * target_alloc will allocate vtarget and map,
472 * slave_alloc will fill in vdevice from vtarget.
475 vtarget = ri->starget->hostdata;
477 vtarget->id = pg0->CurrentTargetID;
478 vtarget->channel = pg0->CurrentBus;
481 *((struct mptfc_rport_info **)rport->dd_data) = ri;
482 /* scan will be scheduled once rport becomes a target */
483 fc_remote_port_rolechg(rport,roles);
485 pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
486 nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
487 dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
488 "mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
489 "rport tid %d, tmo %d\n",
493 (unsigned long long)nn,
494 (unsigned long long)pn,
495 pg0->CurrentTargetID,
496 ri->rport->scsi_target_id,
497 ri->rport->dev_loss_tmo));
507 * OS entry point to allow for host driver to free allocated memory
508 * Called if no device present or device being unloaded
511 mptfc_target_destroy(struct scsi_target *starget)
513 struct fc_rport *rport;
514 struct mptfc_rport_info *ri;
516 rport = starget_to_rport(starget);
518 ri = *((struct mptfc_rport_info **)rport->dd_data);
519 if (ri) /* better be! */
522 if (starget->hostdata)
523 kfree(starget->hostdata);
524 starget->hostdata = NULL;
528 * OS entry point to allow host driver to alloc memory
529 * for each scsi target. Called once per device the bus scan.
530 * Return non-zero if allocation fails.
533 mptfc_target_alloc(struct scsi_target *starget)
536 struct fc_rport *rport;
537 struct mptfc_rport_info *ri;
540 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
543 starget->hostdata = vtarget;
546 rport = starget_to_rport(starget);
548 ri = *((struct mptfc_rport_info **)rport->dd_data);
549 if (ri) { /* better be! */
550 vtarget->id = ri->pg0.CurrentTargetID;
551 vtarget->channel = ri->pg0.CurrentBus;
552 ri->starget = starget;
558 starget->hostdata = NULL;
564 * mptfc_dump_lun_info
571 mptfc_dump_lun_info(MPT_ADAPTER *ioc, struct fc_rport *rport, struct scsi_device *sdev,
575 struct mptfc_rport_info *ri;
577 ri = *((struct mptfc_rport_info **)rport->dd_data);
578 pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
579 nn = (u64)ri->pg0.WWNN.High << 32 | (u64)ri->pg0.WWNN.Low;
580 dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
581 "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
582 "CurrentTargetID %d, %x %llx %llx\n",
586 sdev->id, ri->pg0.CurrentTargetID,
587 ri->pg0.PortIdentifier,
588 (unsigned long long)pn,
589 (unsigned long long)nn));
594 * OS entry point to allow host driver to alloc memory
595 * for each scsi device. Called once per device the bus scan.
596 * Return non-zero if allocation fails.
597 * Init memory once per LUN.
600 mptfc_slave_alloc(struct scsi_device *sdev)
605 struct scsi_target *starget;
606 struct fc_rport *rport;
609 starget = scsi_target(sdev);
610 rport = starget_to_rport(starget);
612 if (!rport || fc_remote_port_chkready(rport))
615 hd = shost_priv(sdev->host);
618 vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
620 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
621 ioc->name, sizeof(VirtDevice));
626 sdev->hostdata = vdevice;
627 vtarget = starget->hostdata;
629 if (vtarget->num_luns == 0) {
630 vtarget->ioc_id = ioc->id;
631 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
634 vdevice->vtarget = vtarget;
635 vdevice->lun = sdev->lun;
640 mptfc_dump_lun_info(ioc, rport, sdev, vtarget);
646 mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
648 struct mptfc_rport_info *ri;
649 struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
651 VirtDevice *vdevice = SCpnt->device->hostdata;
653 if (!vdevice || !vdevice->vtarget) {
654 SCpnt->result = DID_NO_CONNECT << 16;
659 err = fc_remote_port_chkready(rport);
666 /* dd_data is null until finished adding target */
667 ri = *((struct mptfc_rport_info **)rport->dd_data);
669 SCpnt->result = DID_IMM_RETRY << 16;
674 return mptscsih_qcmd(SCpnt,done);
678 * mptfc_display_port_link_speed - displaying link speed
679 * @ioc: Pointer to MPT_ADAPTER structure
680 * @portnum: IOC Port number
681 * @pp0dest: port page0 data payload
685 mptfc_display_port_link_speed(MPT_ADAPTER *ioc, int portnum, FCPortPage0_t *pp0dest)
687 u8 old_speed, new_speed, state;
693 old_speed = ioc->fc_link_speed[portnum];
694 new_speed = pp0dest->CurrentSpeed;
695 state = pp0dest->PortState;
697 if (state != MPI_FCPORTPAGE0_PORTSTATE_OFFLINE &&
698 new_speed != MPI_FCPORTPAGE0_CURRENT_SPEED_UKNOWN) {
700 old = old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT ? "1 Gbps" :
701 old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT ? "2 Gbps" :
702 old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT ? "4 Gbps" :
704 new = new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT ? "1 Gbps" :
705 new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT ? "2 Gbps" :
706 new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT ? "4 Gbps" :
709 printk(MYIOC_s_NOTE_FMT
710 "FC Link Established, Speed = %s\n",
712 else if (old_speed != new_speed)
713 printk(MYIOC_s_WARN_FMT
714 "FC Link Speed Change, Old Speed = %s, New Speed = %s\n",
715 ioc->name, old, new);
717 ioc->fc_link_speed[portnum] = new_speed;
722 * mptfc_GetFcPortPage0 - Fetch FCPort config Page0.
723 * @ioc: Pointer to MPT_ADAPTER structure
724 * @portnum: IOC Port number
726 * Return: 0 for success
727 * -ENOMEM if no memory available
728 * -EPERM if not allowed due to ISR context
729 * -EAGAIN if no msg frames currently available
730 * -EFAULT for non-successful reply or no reply (timeout)
731 * -EINVAL portnum arg out of range (hardwired to two elements)
734 mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
736 ConfigPageHeader_t hdr;
738 FCPortPage0_t *ppage0_alloc;
739 FCPortPage0_t *pp0dest;
740 dma_addr_t page0_dma;
749 /* Get FCPort Page 0 header */
753 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
754 cfg.cfghdr.hdr = &hdr;
756 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
758 cfg.pageAddr = portnum;
761 if ((rc = mpt_config(ioc, &cfg)) != 0)
764 if (hdr.PageLength == 0)
767 data_sz = hdr.PageLength * 4;
769 ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
773 memset((u8 *)ppage0_alloc, 0, data_sz);
774 cfg.physAddr = page0_dma;
775 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
777 if ((rc = mpt_config(ioc, &cfg)) == 0) {
779 pp0dest = &ioc->fc_port_page0[portnum];
780 copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
781 memcpy(pp0dest, ppage0_alloc, copy_sz);
784 * Normalize endianness of structure data,
785 * by byte-swapping all > 1 byte fields!
787 pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
788 pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
789 pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
790 pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
791 pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
792 pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
793 pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
794 pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
795 pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
796 pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
797 pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
798 pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
799 pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
800 pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
801 pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
802 pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
805 * if still doing discovery,
806 * hang loose a while until finished
808 if ((pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) ||
809 (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_ONLINE &&
810 (pp0dest->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_TYPE_MASK)
811 == MPI_FCPORTPAGE0_FLAGS_ATTACH_NO_INIT)) {
816 printk(MYIOC_s_INFO_FMT "Firmware discovery not"
820 mptfc_display_port_link_speed(ioc, portnum, pp0dest);
823 pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
830 mptfc_WriteFcPortPage1(MPT_ADAPTER *ioc, int portnum)
832 ConfigPageHeader_t hdr;
839 if (!(ioc->fc_data.fc_port_page1[portnum].data))
842 /* get fcport page 1 header */
846 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
847 cfg.cfghdr.hdr = &hdr;
849 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
851 cfg.pageAddr = portnum;
854 if ((rc = mpt_config(ioc, &cfg)) != 0)
857 if (hdr.PageLength == 0)
860 if (hdr.PageLength*4 != ioc->fc_data.fc_port_page1[portnum].pg_sz)
863 cfg.physAddr = ioc->fc_data.fc_port_page1[portnum].dma;
864 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
867 rc = mpt_config(ioc, &cfg);
873 mptfc_GetFcPortPage1(MPT_ADAPTER *ioc, int portnum)
875 ConfigPageHeader_t hdr;
877 FCPortPage1_t *page1_alloc;
878 dma_addr_t page1_dma;
885 /* get fcport page 1 header */
889 hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
890 cfg.cfghdr.hdr = &hdr;
892 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
894 cfg.pageAddr = portnum;
897 if ((rc = mpt_config(ioc, &cfg)) != 0)
900 if (hdr.PageLength == 0)
905 if (ioc->fc_data.fc_port_page1[portnum].data == NULL) {
906 data_sz = hdr.PageLength * 4;
907 if (data_sz < sizeof(FCPortPage1_t))
908 data_sz = sizeof(FCPortPage1_t);
910 page1_alloc = (FCPortPage1_t *) pci_alloc_consistent(ioc->pcidev,
917 page1_alloc = ioc->fc_data.fc_port_page1[portnum].data;
918 page1_dma = ioc->fc_data.fc_port_page1[portnum].dma;
919 data_sz = ioc->fc_data.fc_port_page1[portnum].pg_sz;
920 if (hdr.PageLength * 4 > data_sz) {
921 ioc->fc_data.fc_port_page1[portnum].data = NULL;
922 pci_free_consistent(ioc->pcidev, data_sz, (u8 *)
923 page1_alloc, page1_dma);
928 memset(page1_alloc,0,data_sz);
930 cfg.physAddr = page1_dma;
931 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
933 if ((rc = mpt_config(ioc, &cfg)) == 0) {
934 ioc->fc_data.fc_port_page1[portnum].data = page1_alloc;
935 ioc->fc_data.fc_port_page1[portnum].pg_sz = data_sz;
936 ioc->fc_data.fc_port_page1[portnum].dma = page1_dma;
939 ioc->fc_data.fc_port_page1[portnum].data = NULL;
940 pci_free_consistent(ioc->pcidev, data_sz, (u8 *)
941 page1_alloc, page1_dma);
948 mptfc_SetFcPortPage1_defaults(MPT_ADAPTER *ioc)
953 #define MPTFC_FW_DEVICE_TIMEOUT (1)
954 #define MPTFC_FW_IO_PEND_TIMEOUT (1)
955 #define ON_FLAGS (MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY)
956 #define OFF_FLAGS (MPI_FCPORTPAGE1_FLAGS_VERBOSE_RESCAN_EVENTS)
958 for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
959 if (mptfc_GetFcPortPage1(ioc, ii) != 0)
961 pp1 = ioc->fc_data.fc_port_page1[ii].data;
962 if ((pp1->InitiatorDeviceTimeout == MPTFC_FW_DEVICE_TIMEOUT)
963 && (pp1->InitiatorIoPendTimeout == MPTFC_FW_IO_PEND_TIMEOUT)
964 && ((pp1->Flags & ON_FLAGS) == ON_FLAGS)
965 && ((pp1->Flags & OFF_FLAGS) == 0))
967 pp1->InitiatorDeviceTimeout = MPTFC_FW_DEVICE_TIMEOUT;
968 pp1->InitiatorIoPendTimeout = MPTFC_FW_IO_PEND_TIMEOUT;
969 pp1->Flags &= ~OFF_FLAGS;
970 pp1->Flags |= ON_FLAGS;
971 mptfc_WriteFcPortPage1(ioc, ii);
977 mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
985 struct Scsi_Host *sh;
988 /* don't know what to do as only one scsi (fc) host was allocated */
992 pp0 = &ioc->fc_port_page0[portnum];
995 sn = fc_host_symbolic_name(sh);
996 snprintf(sn, FC_SYMBOLIC_NAME_SIZE, "%s %s%08xh",
998 MPT_FW_REV_MAGIC_ID_STRING,
999 ioc->facts.FWVersion.Word);
1001 fc_host_tgtid_bind_type(sh) = FC_TGTID_BIND_BY_WWPN;
1003 fc_host_maxframe_size(sh) = pp0->MaxFrameSize;
1005 fc_host_node_name(sh) =
1006 (u64)pp0->WWNN.High << 32 | (u64)pp0->WWNN.Low;
1008 fc_host_port_name(sh) =
1009 (u64)pp0->WWPN.High << 32 | (u64)pp0->WWPN.Low;
1011 fc_host_port_id(sh) = pp0->PortIdentifier;
1013 class = pp0->SupportedServiceClass;
1014 if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1)
1015 cos |= FC_COS_CLASS1;
1016 if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2)
1017 cos |= FC_COS_CLASS2;
1018 if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3)
1019 cos |= FC_COS_CLASS3;
1020 fc_host_supported_classes(sh) = cos;
1022 if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT)
1023 speed = FC_PORTSPEED_1GBIT;
1024 else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT)
1025 speed = FC_PORTSPEED_2GBIT;
1026 else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT)
1027 speed = FC_PORTSPEED_4GBIT;
1028 else if (pp0->CurrentSpeed == MPI_FCPORTPAGE0_CURRENT_SPEED_10GBIT)
1029 speed = FC_PORTSPEED_10GBIT;
1031 speed = FC_PORTSPEED_UNKNOWN;
1032 fc_host_speed(sh) = speed;
1035 if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED)
1036 speed |= FC_PORTSPEED_1GBIT;
1037 if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED)
1038 speed |= FC_PORTSPEED_2GBIT;
1039 if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_4GBIT_SPEED)
1040 speed |= FC_PORTSPEED_4GBIT;
1041 if (pp0->SupportedSpeeds & MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED)
1042 speed |= FC_PORTSPEED_10GBIT;
1043 fc_host_supported_speeds(sh) = speed;
1045 port_state = FC_PORTSTATE_UNKNOWN;
1046 if (pp0->PortState == MPI_FCPORTPAGE0_PORTSTATE_ONLINE)
1047 port_state = FC_PORTSTATE_ONLINE;
1048 else if (pp0->PortState == MPI_FCPORTPAGE0_PORTSTATE_OFFLINE)
1049 port_state = FC_PORTSTATE_LINKDOWN;
1050 fc_host_port_state(sh) = port_state;
1052 port_type = FC_PORTTYPE_UNKNOWN;
1053 if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_POINT_TO_POINT)
1054 port_type = FC_PORTTYPE_PTP;
1055 else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_PRIVATE_LOOP)
1056 port_type = FC_PORTTYPE_LPORT;
1057 else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_PUBLIC_LOOP)
1058 port_type = FC_PORTTYPE_NLPORT;
1059 else if (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_FABRIC_DIRECT)
1060 port_type = FC_PORTTYPE_NPORT;
1061 fc_host_port_type(sh) = port_type;
1063 fc_host_fabric_name(sh) =
1064 (pp0->Flags & MPI_FCPORTPAGE0_FLAGS_FABRIC_WWN_VALID) ?
1065 (u64) pp0->FabricWWNN.High << 32 | (u64) pp0->FabricWWPN.Low :
1066 (u64)pp0->WWNN.High << 32 | (u64)pp0->WWNN.Low;
1071 mptfc_link_status_change(struct work_struct *work)
1074 container_of(work, MPT_ADAPTER, fc_rescan_work);
1077 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++)
1078 (void) mptfc_GetFcPortPage0(ioc, ii);
1083 mptfc_setup_reset(struct work_struct *work)
1086 container_of(work, MPT_ADAPTER, fc_setup_reset_work);
1088 struct mptfc_rport_info *ri;
1090 /* reset about to happen, delete (block) all rports */
1091 list_for_each_entry(ri, &ioc->fc_rports, list) {
1092 if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
1093 ri->flags &= ~MPT_RPORT_INFO_FLAGS_REGISTERED;
1094 fc_remote_port_delete(ri->rport); /* won't sleep */
1097 pn = (u64)ri->pg0.WWPN.High << 32 |
1098 (u64)ri->pg0.WWPN.Low;
1099 dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
1100 "mptfc_setup_reset.%d: %llx deleted\n",
1103 (unsigned long long)pn));
1109 mptfc_rescan_devices(struct work_struct *work)
1112 container_of(work, MPT_ADAPTER, fc_rescan_work);
1115 struct mptfc_rport_info *ri;
1117 /* start by tagging all ports as missing */
1118 list_for_each_entry(ri, &ioc->fc_rports, list) {
1119 if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
1120 ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
1125 * now rescan devices known to adapter,
1126 * will reregister existing rports
1128 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1129 (void) mptfc_GetFcPortPage0(ioc, ii);
1130 mptfc_init_host_attr(ioc, ii); /* refresh */
1131 mptfc_GetFcDevPage0(ioc, ii, mptfc_register_dev);
1134 /* delete devices still missing */
1135 list_for_each_entry(ri, &ioc->fc_rports, list) {
1136 /* if newly missing, delete it */
1137 if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) {
1139 ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
1140 MPT_RPORT_INFO_FLAGS_MISSING);
1141 fc_remote_port_delete(ri->rport); /* won't sleep */
1144 pn = (u64)ri->pg0.WWPN.High << 32 |
1145 (u64)ri->pg0.WWPN.Low;
1146 dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
1147 "mptfc_rescan.%d: %llx deleted\n",
1150 (unsigned long long)pn));
1156 mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1158 struct Scsi_Host *sh;
1161 unsigned long flags;
1169 if ((r = mpt_attach(pdev,id)) != 0)
1172 ioc = pci_get_drvdata(pdev);
1173 ioc->DoneCtx = mptfcDoneCtx;
1174 ioc->TaskCtx = mptfcTaskCtx;
1175 ioc->InternalCtx = mptfcInternalCtx;
1177 /* Added sanity check on readiness of the MPT adapter.
1179 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
1180 printk(MYIOC_s_WARN_FMT
1181 "Skipping because it's not operational!\n",
1184 goto out_mptfc_probe;
1188 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
1191 goto out_mptfc_probe;
1194 /* Sanity check - ensure at least 1 port is INITIATOR capable
1197 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1198 if (ioc->pfacts[ii].ProtocolFlags &
1199 MPI_PORTFACTS_PROTOCOL_INITIATOR)
1204 printk(MYIOC_s_WARN_FMT
1205 "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
1210 sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
1213 printk(MYIOC_s_WARN_FMT
1214 "Unable to register controller with SCSI subsystem\n",
1217 goto out_mptfc_probe;
1220 spin_lock_init(&ioc->fc_rescan_work_lock);
1221 INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices);
1222 INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset);
1223 INIT_WORK(&ioc->fc_lsc_work, mptfc_link_status_change);
1225 spin_lock_irqsave(&ioc->FreeQlock, flags);
1227 /* Attach the SCSI Host to the IOC structure
1235 /* set 16 byte cdb's */
1236 sh->max_cmd_len = 16;
1238 sh->max_id = ioc->pfacts->MaxDevices;
1239 sh->max_lun = max_lun;
1243 sh->unique_id = ioc->id;
1245 /* Verify that we won't exceed the maximum
1246 * number of chain buffers
1247 * We can optimize: ZZ = req_sz/sizeof(SGE)
1249 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1250 * + (req_sz - 64)/sizeof(SGE)
1251 * A slightly different algorithm is required for
1254 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1255 if (sizeof(dma_addr_t) == sizeof(u64)) {
1256 numSGE = (scale - 1) *
1257 (ioc->facts.MaxChainDepth-1) + scale +
1258 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
1261 numSGE = 1 + (scale - 1) *
1262 (ioc->facts.MaxChainDepth-1) + scale +
1263 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
1267 if (numSGE < sh->sg_tablesize) {
1268 /* Reset this value */
1269 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1270 "Resetting sg_tablesize to %d from %d\n",
1271 ioc->name, numSGE, sh->sg_tablesize));
1272 sh->sg_tablesize = numSGE;
1275 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1277 hd = shost_priv(sh);
1280 /* SCSI needs scsi_cmnd lookup table!
1281 * (with size equal to req_depth*PtrSz!)
1283 ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
1284 if (!ioc->ScsiLookup) {
1286 goto out_mptfc_probe;
1288 spin_lock_init(&ioc->scsi_lookup_lock);
1290 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
1291 ioc->name, ioc->ScsiLookup));
1293 /* Clear the TM flags
1296 hd->tmState = TM_STATE_NONE;
1297 hd->resetPending = 0;
1298 hd->abortSCpnt = NULL;
1300 /* Clear the pointer used to store
1301 * single-threaded commands, i.e., those
1302 * issued during a bus scan, dv and
1303 * configuration pages.
1307 /* Initialize this SCSI Hosts' timers
1308 * To use, set the timer expires field
1311 init_timer(&hd->timer);
1312 hd->timer.data = (unsigned long) hd;
1313 hd->timer.function = mptscsih_timer_expired;
1315 init_waitqueue_head(&hd->scandv_waitq);
1316 hd->scandv_wait_done = 0;
1317 hd->last_queue_full = 0;
1319 sh->transportt = mptfc_transport_template;
1320 error = scsi_add_host (sh, &ioc->pcidev->dev);
1322 dprintk(ioc, printk(MYIOC_s_ERR_FMT
1323 "scsi_add_host failed\n", ioc->name));
1324 goto out_mptfc_probe;
1327 /* initialize workqueue */
1329 snprintf(ioc->fc_rescan_work_q_name, sizeof(ioc->fc_rescan_work_q_name),
1330 "mptfc_wq_%d", sh->host_no);
1331 ioc->fc_rescan_work_q =
1332 create_singlethread_workqueue(ioc->fc_rescan_work_q_name);
1333 if (!ioc->fc_rescan_work_q)
1334 goto out_mptfc_probe;
1337 * Pre-fetch FC port WWN and stuff...
1338 * (FCPortPage0_t stuff)
1340 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1341 (void) mptfc_GetFcPortPage0(ioc, ii);
1343 mptfc_SetFcPortPage1_defaults(ioc);
1347 * by doing it via the workqueue, some locking is eliminated
1350 queue_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work);
1351 flush_workqueue(ioc->fc_rescan_work_q);
1357 mptscsih_remove(pdev);
1361 static struct pci_driver mptfc_driver = {
1363 .id_table = mptfc_pci_table,
1364 .probe = mptfc_probe,
1365 .remove = __devexit_p(mptfc_remove),
1366 .shutdown = mptscsih_shutdown,
1368 .suspend = mptscsih_suspend,
1369 .resume = mptscsih_resume,
1374 mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
1377 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
1378 unsigned long flags;
1381 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
1384 if (ioc->sh == NULL ||
1385 ((hd = shost_priv(ioc->sh)) == NULL))
1389 case MPI_EVENT_RESCAN:
1390 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1391 if (ioc->fc_rescan_work_q) {
1392 queue_work(ioc->fc_rescan_work_q,
1393 &ioc->fc_rescan_work);
1395 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1397 case MPI_EVENT_LINK_STATUS_CHANGE:
1398 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1399 if (ioc->fc_rescan_work_q) {
1400 queue_work(ioc->fc_rescan_work_q,
1403 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1406 rc = mptscsih_event_process(ioc,pEvReply);
1413 mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
1416 unsigned long flags;
1418 rc = mptscsih_ioc_reset(ioc,reset_phase);
1423 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1424 ": IOC %s_reset routed to FC host driver!\n",ioc->name,
1425 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
1426 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
1428 if (reset_phase == MPT_IOC_SETUP_RESET) {
1429 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1430 if (ioc->fc_rescan_work_q) {
1431 queue_work(ioc->fc_rescan_work_q,
1432 &ioc->fc_setup_reset_work);
1434 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1437 else if (reset_phase == MPT_IOC_PRE_RESET) {
1440 else { /* MPT_IOC_POST_RESET */
1441 mptfc_SetFcPortPage1_defaults(ioc);
1442 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1443 if (ioc->fc_rescan_work_q) {
1444 queue_work(ioc->fc_rescan_work_q,
1445 &ioc->fc_rescan_work);
1447 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1452 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1454 * mptfc_init - Register MPT adapter(s) as SCSI host(s) with SCSI mid-layer.
1456 * Returns 0 for success, non-zero for failure.
1463 show_mptmod_ver(my_NAME, my_VERSION);
1465 /* sanity check module parameters */
1466 if (mptfc_dev_loss_tmo <= 0)
1467 mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
1469 mptfc_transport_template =
1470 fc_attach_transport(&mptfc_transport_functions);
1472 if (!mptfc_transport_template)
1475 mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);
1476 mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
1477 mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
1479 mpt_event_register(mptfcDoneCtx, mptfc_event_process);
1480 mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset);
1482 error = pci_register_driver(&mptfc_driver);
1484 fc_release_transport(mptfc_transport_template);
1489 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1491 * mptfc_remove - Remove fc infrastructure for devices
1492 * @pdev: Pointer to pci_dev structure
1495 static void __devexit
1496 mptfc_remove(struct pci_dev *pdev)
1498 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1499 struct mptfc_rport_info *p, *n;
1500 struct workqueue_struct *work_q;
1501 unsigned long flags;
1504 /* destroy workqueue */
1505 if ((work_q=ioc->fc_rescan_work_q)) {
1506 spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
1507 ioc->fc_rescan_work_q = NULL;
1508 spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
1509 destroy_workqueue(work_q);
1512 fc_remove_host(ioc->sh);
1514 list_for_each_entry_safe(p, n, &ioc->fc_rports, list) {
1519 for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
1520 if (ioc->fc_data.fc_port_page1[ii].data) {
1521 pci_free_consistent(ioc->pcidev,
1522 ioc->fc_data.fc_port_page1[ii].pg_sz,
1523 (u8 *) ioc->fc_data.fc_port_page1[ii].data,
1524 ioc->fc_data.fc_port_page1[ii].dma);
1525 ioc->fc_data.fc_port_page1[ii].data = NULL;
1529 mptscsih_remove(pdev);
1532 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1533 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1535 * mptfc_exit - Unregisters MPT adapter(s)
1541 pci_unregister_driver(&mptfc_driver);
1542 fc_release_transport(mptfc_transport_template);
1544 mpt_reset_deregister(mptfcDoneCtx);
1545 mpt_event_deregister(mptfcDoneCtx);
1547 mpt_deregister(mptfcInternalCtx);
1548 mpt_deregister(mptfcTaskCtx);
1549 mpt_deregister(mptfcDoneCtx);
1552 module_init(mptfc_init);
1553 module_exit(mptfc_exit);