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-2005 LSI Logic Corporation
7 * (mailto:mpt_linux_developer@lsil.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/sched.h>
57 #include <linux/workqueue.h>
58 #include <linux/sort.h>
60 #include <scsi/scsi.h>
61 #include <scsi/scsi_cmnd.h>
62 #include <scsi/scsi_device.h>
63 #include <scsi/scsi_host.h>
64 #include <scsi/scsi_tcq.h>
65 #include <scsi/scsi_transport_fc.h>
70 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
71 #define my_NAME "Fusion MPT FC Host driver"
72 #define my_VERSION MPT_LINUX_VERSION_COMMON
75 MODULE_AUTHOR(MODULEAUTHOR
);
76 MODULE_DESCRIPTION(my_NAME
);
77 MODULE_LICENSE("GPL");
79 /* Command line args */
80 static int mpt_pq_filter
= 0;
81 module_param(mpt_pq_filter
, int, 0);
82 MODULE_PARM_DESC(mpt_pq_filter
, " Enable peripheral qualifier filter: enable=1 (default=0)");
84 #define MPTFC_DEV_LOSS_TMO (60)
85 static int mptfc_dev_loss_tmo
= MPTFC_DEV_LOSS_TMO
; /* reasonable default */
86 module_param(mptfc_dev_loss_tmo
, int, 0);
87 MODULE_PARM_DESC(mptfc_dev_loss_tmo
, " Initial time the driver programs the "
88 " transport to wait for an rport to "
89 " return following a device loss event."
92 static int mptfcDoneCtx
= -1;
93 static int mptfcTaskCtx
= -1;
94 static int mptfcInternalCtx
= -1; /* Used only for internal commands */
96 int mptfc_slave_alloc(struct scsi_device
*device
);
97 static int mptfc_qcmd(struct scsi_cmnd
*SCpnt
,
98 void (*done
)(struct scsi_cmnd
*));
100 static void mptfc_set_rport_loss_tmo(struct fc_rport
*rport
, uint32_t timeout
);
101 static void __devexit
mptfc_remove(struct pci_dev
*pdev
);
103 static struct scsi_host_template mptfc_driver_template
= {
104 .module
= THIS_MODULE
,
105 .proc_name
= "mptfc",
106 .proc_info
= mptscsih_proc_info
,
107 .name
= "MPT FC Host",
108 .info
= mptscsih_info
,
109 .queuecommand
= mptfc_qcmd
,
110 .target_alloc
= mptscsih_target_alloc
,
111 .slave_alloc
= mptfc_slave_alloc
,
112 .slave_configure
= mptscsih_slave_configure
,
113 .target_destroy
= mptscsih_target_destroy
,
114 .slave_destroy
= mptscsih_slave_destroy
,
115 .change_queue_depth
= mptscsih_change_queue_depth
,
116 .eh_abort_handler
= mptscsih_abort
,
117 .eh_device_reset_handler
= mptscsih_dev_reset
,
118 .eh_bus_reset_handler
= mptscsih_bus_reset
,
119 .eh_host_reset_handler
= mptscsih_host_reset
,
120 .bios_param
= mptscsih_bios_param
,
121 .can_queue
= MPT_FC_CAN_QUEUE
,
123 .sg_tablesize
= MPT_SCSI_SG_DEPTH
,
126 .use_clustering
= ENABLE_CLUSTERING
,
129 /****************************************************************************
133 static struct pci_device_id mptfc_pci_table
[] = {
134 { PCI_VENDOR_ID_LSI_LOGIC
, PCI_DEVICE_ID_LSI_FC909
,
135 PCI_ANY_ID
, PCI_ANY_ID
},
136 { PCI_VENDOR_ID_LSI_LOGIC
, PCI_DEVICE_ID_LSI_FC919
,
137 PCI_ANY_ID
, PCI_ANY_ID
},
138 { PCI_VENDOR_ID_LSI_LOGIC
, PCI_DEVICE_ID_LSI_FC929
,
139 PCI_ANY_ID
, PCI_ANY_ID
},
140 { PCI_VENDOR_ID_LSI_LOGIC
, PCI_DEVICE_ID_LSI_FC919X
,
141 PCI_ANY_ID
, PCI_ANY_ID
},
142 { PCI_VENDOR_ID_LSI_LOGIC
, PCI_DEVICE_ID_LSI_FC929X
,
143 PCI_ANY_ID
, PCI_ANY_ID
},
144 { PCI_VENDOR_ID_LSI_LOGIC
, PCI_DEVICE_ID_LSI_FC939X
,
145 PCI_ANY_ID
, PCI_ANY_ID
},
146 { PCI_VENDOR_ID_LSI_LOGIC
, PCI_DEVICE_ID_LSI_FC949X
,
147 PCI_ANY_ID
, PCI_ANY_ID
},
148 {0} /* Terminating entry */
150 MODULE_DEVICE_TABLE(pci
, mptfc_pci_table
);
152 static struct scsi_transport_template
*mptfc_transport_template
= NULL
;
154 struct fc_function_template mptfc_transport_functions
= {
155 .dd_fcrport_size
= 8,
156 .show_host_node_name
= 1,
157 .show_host_port_name
= 1,
158 .show_host_supported_classes
= 1,
159 .show_host_port_id
= 1,
160 .show_rport_supported_classes
= 1,
161 .show_starget_node_name
= 1,
162 .show_starget_port_name
= 1,
163 .show_starget_port_id
= 1,
164 .set_rport_dev_loss_tmo
= mptfc_set_rport_loss_tmo
,
165 .show_rport_dev_loss_tmo
= 1,
169 /* FIXME! values controlling firmware RESCAN event
170 * need to be set low to allow dev_loss_tmo to
171 * work as expected. Currently, firmware doesn't
172 * notify driver of RESCAN event until some number
173 * of seconds elapse. This value can be set via
177 mptfc_set_rport_loss_tmo(struct fc_rport
*rport
, uint32_t timeout
)
180 rport
->dev_loss_tmo
= timeout
;
182 rport
->dev_loss_tmo
= mptfc_dev_loss_tmo
;
186 mptfc_FcDevPage0_cmp_func(const void *a
, const void *b
)
188 FCDevicePage0_t
**aa
= (FCDevicePage0_t
**)a
;
189 FCDevicePage0_t
**bb
= (FCDevicePage0_t
**)b
;
191 if ((*aa
)->CurrentBus
== (*bb
)->CurrentBus
) {
192 if ((*aa
)->CurrentTargetID
== (*bb
)->CurrentTargetID
)
194 if ((*aa
)->CurrentTargetID
< (*bb
)->CurrentTargetID
)
198 if ((*aa
)->CurrentBus
< (*bb
)->CurrentBus
)
204 mptfc_GetFcDevPage0(MPT_ADAPTER
*ioc
, int ioc_port
,
205 void(*func
)(MPT_ADAPTER
*ioc
,int channel
, FCDevicePage0_t
*arg
))
207 ConfigPageHeader_t hdr
;
209 FCDevicePage0_t
*ppage0_alloc
, *fc
;
210 dma_addr_t page0_dma
;
214 FCDevicePage0_t
*p0_array
=NULL
, *p_p0
;
215 FCDevicePage0_t
**pp0_array
=NULL
, **p_pp0
;
218 U32 port_id
= 0xffffff;
220 int max_bus
= ioc
->facts
.MaxBuses
;
221 int max_targ
= ioc
->facts
.MaxDevices
;
223 if (max_bus
== 0 || max_targ
== 0)
226 data_sz
= sizeof(FCDevicePage0_t
) * max_bus
* max_targ
;
227 p_p0
= p0_array
= kzalloc(data_sz
, GFP_KERNEL
);
231 data_sz
= sizeof(FCDevicePage0_t
*) * max_bus
* max_targ
;
232 p_pp0
= pp0_array
= kzalloc(data_sz
, GFP_KERNEL
);
237 /* Get FC Device Page 0 header */
241 hdr
.PageType
= MPI_CONFIG_PAGETYPE_FC_DEVICE
;
242 cfg
.cfghdr
.hdr
= &hdr
;
244 cfg
.action
= MPI_CONFIG_ACTION_PAGE_HEADER
;
246 cfg
.pageAddr
= port_id
;
249 if ((rc
= mpt_config(ioc
, &cfg
)) != 0)
252 if (hdr
.PageLength
<= 0)
255 data_sz
= hdr
.PageLength
* 4;
256 ppage0_alloc
= pci_alloc_consistent(ioc
->pcidev
, data_sz
,
262 cfg
.physAddr
= page0_dma
;
263 cfg
.action
= MPI_CONFIG_ACTION_PAGE_READ_CURRENT
;
265 if ((rc
= mpt_config(ioc
, &cfg
)) == 0) {
266 ppage0_alloc
->PortIdentifier
=
267 le32_to_cpu(ppage0_alloc
->PortIdentifier
);
269 ppage0_alloc
->WWNN
.Low
=
270 le32_to_cpu(ppage0_alloc
->WWNN
.Low
);
272 ppage0_alloc
->WWNN
.High
=
273 le32_to_cpu(ppage0_alloc
->WWNN
.High
);
275 ppage0_alloc
->WWPN
.Low
=
276 le32_to_cpu(ppage0_alloc
->WWPN
.Low
);
278 ppage0_alloc
->WWPN
.High
=
279 le32_to_cpu(ppage0_alloc
->WWPN
.High
);
281 ppage0_alloc
->BBCredit
=
282 le16_to_cpu(ppage0_alloc
->BBCredit
);
284 ppage0_alloc
->MaxRxFrameSize
=
285 le16_to_cpu(ppage0_alloc
->MaxRxFrameSize
);
287 port_id
= ppage0_alloc
->PortIdentifier
;
289 *p_p0
= *ppage0_alloc
; /* save data */
290 *p_pp0
++ = p_p0
++; /* save addr */
292 pci_free_consistent(ioc
->pcidev
, data_sz
,
293 (u8
*) ppage0_alloc
, page0_dma
);
297 } while (port_id
<= 0xff0000);
302 sort (pp0_array
, num_targ
, sizeof(FCDevicePage0_t
*),
303 mptfc_FcDevPage0_cmp_func
, NULL
);
304 /* call caller's func for each targ */
305 for (ii
= 0; ii
< num_targ
; ii
++) {
306 fc
= *(pp0_array
+ii
);
307 func(ioc
, ioc_port
, fc
);
320 mptfc_generate_rport_ids(FCDevicePage0_t
*pg0
, struct fc_rport_identifiers
*rid
)
322 /* not currently usable */
323 if (pg0
->Flags
& (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID
|
324 MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID
))
327 if (!(pg0
->Flags
& MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID
))
330 if (!(pg0
->Protocol
& MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET
))
334 * board data structure already normalized to platform endianness
335 * shifted to avoid unaligned access on 64 bit architecture
337 rid
->node_name
= ((u64
)pg0
->WWNN
.High
) << 32 | (u64
)pg0
->WWNN
.Low
;
338 rid
->port_name
= ((u64
)pg0
->WWPN
.High
) << 32 | (u64
)pg0
->WWPN
.Low
;
339 rid
->port_id
= pg0
->PortIdentifier
;
340 rid
->roles
= FC_RPORT_ROLE_UNKNOWN
;
341 rid
->roles
|= FC_RPORT_ROLE_FCP_TARGET
;
342 if (pg0
->Protocol
& MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR
)
343 rid
->roles
|= FC_RPORT_ROLE_FCP_INITIATOR
;
349 mptfc_register_dev(MPT_ADAPTER
*ioc
, int channel
, FCDevicePage0_t
*pg0
)
351 struct fc_rport_identifiers rport_ids
;
352 struct fc_rport
*rport
;
353 struct mptfc_rport_info
*ri
;
358 if (mptfc_generate_rport_ids(pg0
, &rport_ids
) < 0)
361 /* scan list looking for a match */
362 spin_lock_irqsave(&ioc
->fc_rport_lock
, flags
);
363 list_for_each_entry(ri
, &ioc
->fc_rports
, list
) {
364 port_name
= (u64
)ri
->pg0
.WWPN
.High
<< 32 | (u64
)ri
->pg0
.WWPN
.Low
;
365 if (port_name
== rport_ids
.port_name
) { /* match */
366 list_move_tail(&ri
->list
, &ioc
->fc_rports
);
371 if (!match
) { /* allocate one */
372 spin_unlock_irqrestore(&ioc
->fc_rport_lock
, flags
);
373 ri
= kzalloc(sizeof(struct mptfc_rport_info
), GFP_KERNEL
);
376 spin_lock_irqsave(&ioc
->fc_rport_lock
, flags
);
377 list_add_tail(&ri
->list
, &ioc
->fc_rports
);
380 ri
->pg0
= *pg0
; /* add/update pg0 data */
381 ri
->flags
&= ~MPT_RPORT_INFO_FLAGS_MISSING
;
383 if (!(ri
->flags
& MPT_RPORT_INFO_FLAGS_REGISTERED
)) {
384 ri
->flags
|= MPT_RPORT_INFO_FLAGS_REGISTERED
;
385 spin_unlock_irqrestore(&ioc
->fc_rport_lock
, flags
);
386 rport
= fc_remote_port_add(ioc
->sh
,channel
, &rport_ids
);
387 spin_lock_irqsave(&ioc
->fc_rport_lock
, flags
);
389 if (*((struct mptfc_rport_info
**)rport
->dd_data
) != ri
) {
390 ri
->flags
&= ~MPT_RPORT_INFO_FLAGS_MAPPED_VDEV
;
393 *((struct mptfc_rport_info
**)rport
->dd_data
) = ri
;
395 rport
->dev_loss_tmo
= mptfc_dev_loss_tmo
;
397 * if already mapped, remap here. If not mapped,
398 * slave_alloc will allocate vdev and map
400 if (ri
->flags
& MPT_RPORT_INFO_FLAGS_MAPPED_VDEV
) {
401 ri
->vdev
->target_id
= ri
->pg0
.CurrentTargetID
;
402 ri
->vdev
->bus_id
= ri
->pg0
.CurrentBus
;
403 ri
->vdev
->vtarget
->target_id
= ri
->vdev
->target_id
;
404 ri
->vdev
->vtarget
->bus_id
= ri
->vdev
->bus_id
;
407 printk ("mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
408 "rport tid %d, tmo %d\n",
413 pg0
->CurrentTargetID
,
414 ri
->rport
->scsi_target_id
,
415 ri
->rport
->dev_loss_tmo
);
423 spin_unlock_irqrestore(&ioc
->fc_rport_lock
,flags
);
428 * OS entry point to allow host driver to alloc memory
429 * for each scsi device. Called once per device the bus scan.
430 * Return non-zero if allocation fails.
431 * Init memory once per LUN.
434 mptfc_slave_alloc(struct scsi_device
*sdev
)
439 struct scsi_target
*starget
;
440 struct fc_rport
*rport
;
441 struct mptfc_rport_info
*ri
;
445 rport
= starget_to_rport(scsi_target(sdev
));
447 if (!rport
|| fc_remote_port_chkready(rport
))
450 hd
= (MPT_SCSI_HOST
*)sdev
->host
->hostdata
;
452 vdev
= kmalloc(sizeof(VirtDevice
), GFP_KERNEL
);
454 printk(MYIOC_s_ERR_FMT
"slave_alloc kmalloc(%zd) FAILED!\n",
455 hd
->ioc
->name
, sizeof(VirtDevice
));
458 memset(vdev
, 0, sizeof(VirtDevice
));
460 spin_lock_irqsave(&hd
->ioc
->fc_rport_lock
,flags
);
462 if (!(ri
= *((struct mptfc_rport_info
**)rport
->dd_data
))) {
463 spin_unlock_irqrestore(&hd
->ioc
->fc_rport_lock
,flags
);
468 sdev
->hostdata
= vdev
;
469 starget
= scsi_target(sdev
);
470 vtarget
= starget
->hostdata
;
471 if (vtarget
->num_luns
== 0) {
472 vtarget
->tflags
= MPT_TARGET_FLAGS_Q_YES
|
473 MPT_TARGET_FLAGS_VALID_INQUIRY
;
474 hd
->Targets
[sdev
->id
] = vtarget
;
477 vtarget
->target_id
= vdev
->target_id
;
478 vtarget
->bus_id
= vdev
->bus_id
;
480 vdev
->vtarget
= vtarget
;
481 vdev
->ioc_id
= hd
->ioc
->id
;
482 vdev
->lun
= sdev
->lun
;
483 vdev
->target_id
= ri
->pg0
.CurrentTargetID
;
484 vdev
->bus_id
= ri
->pg0
.CurrentBus
;
486 ri
->flags
|= MPT_RPORT_INFO_FLAGS_MAPPED_VDEV
;
489 spin_unlock_irqrestore(&hd
->ioc
->fc_rport_lock
,flags
);
494 printk ("mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
495 "CurrentTargetID %d, %x %llx %llx\n",
498 sdev
->id
, ri
->pg0
.CurrentTargetID
,
499 ri
->pg0
.PortIdentifier
, ri
->pg0
.WWPN
, ri
->pg0
.WWNN
);
506 mptfc_qcmd(struct scsi_cmnd
*SCpnt
, void (*done
)(struct scsi_cmnd
*))
508 struct fc_rport
*rport
= starget_to_rport(scsi_target(SCpnt
->device
));
511 err
= fc_remote_port_chkready(rport
);
517 return mptscsih_qcmd(SCpnt
,done
);
521 mptfc_init_host_attr(MPT_ADAPTER
*ioc
,int portnum
)
523 unsigned class = 0, cos
= 0;
525 /* don't know what to do as only one scsi (fc) host was allocated */
529 class = ioc
->fc_port_page0
[portnum
].SupportedServiceClass
;
530 if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1
)
531 cos
|= FC_COS_CLASS1
;
532 if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2
)
533 cos
|= FC_COS_CLASS2
;
534 if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3
)
535 cos
|= FC_COS_CLASS3
;
537 fc_host_node_name(ioc
->sh
) =
538 (u64
)ioc
->fc_port_page0
[portnum
].WWNN
.High
<< 32
539 | (u64
)ioc
->fc_port_page0
[portnum
].WWNN
.Low
;
541 fc_host_port_name(ioc
->sh
) =
542 (u64
)ioc
->fc_port_page0
[portnum
].WWPN
.High
<< 32
543 | (u64
)ioc
->fc_port_page0
[portnum
].WWPN
.Low
;
545 fc_host_port_id(ioc
->sh
) = ioc
->fc_port_page0
[portnum
].PortIdentifier
;
547 fc_host_supported_classes(ioc
->sh
) = cos
;
549 fc_host_tgtid_bind_type(ioc
->sh
) = FC_TGTID_BIND_BY_WWPN
;
553 mptfc_rescan_devices(void *arg
)
555 MPT_ADAPTER
*ioc
= (MPT_ADAPTER
*)arg
;
559 struct mptfc_rport_info
*ri
;
562 /* start by tagging all ports as missing */
563 spin_lock_irqsave(&ioc
->fc_rport_lock
,flags
);
564 list_for_each_entry(ri
, &ioc
->fc_rports
, list
) {
565 if (ri
->flags
& MPT_RPORT_INFO_FLAGS_REGISTERED
) {
566 ri
->flags
|= MPT_RPORT_INFO_FLAGS_MISSING
;
569 spin_unlock_irqrestore(&ioc
->fc_rport_lock
,flags
);
572 * now rescan devices known to adapter,
573 * will reregister existing rports
575 for (ii
=0; ii
< ioc
->facts
.NumberOfPorts
; ii
++) {
576 (void) mptbase_GetFcPortPage0(ioc
, ii
);
577 mptfc_init_host_attr(ioc
,ii
); /* refresh */
578 mptfc_GetFcDevPage0(ioc
,ii
,mptfc_register_dev
);
581 /* delete devices still missing */
582 spin_lock_irqsave(&ioc
->fc_rport_lock
, flags
);
583 list_for_each_entry(ri
, &ioc
->fc_rports
, list
) {
584 /* if newly missing, delete it */
585 if ((ri
->flags
& (MPT_RPORT_INFO_FLAGS_REGISTERED
|
586 MPT_RPORT_INFO_FLAGS_MISSING
))
587 == (MPT_RPORT_INFO_FLAGS_REGISTERED
|
588 MPT_RPORT_INFO_FLAGS_MISSING
)) {
590 ri
->flags
&= ~(MPT_RPORT_INFO_FLAGS_REGISTERED
|
591 MPT_RPORT_INFO_FLAGS_MISSING
);
592 fc_remote_port_delete(ri
->rport
);
594 * remote port not really deleted 'cause
595 * binding is by WWPN and driver only
596 * registers FCP_TARGETs
599 printk ("mptfc_rescan.%d: %llx deleted\n",
600 ioc
->sh
->host_no
, ri
->pg0
.WWPN
);
604 spin_unlock_irqrestore(&ioc
->fc_rport_lock
,flags
);
607 * allow multiple passes as target state
608 * might have changed during scan
610 spin_lock_irqsave(&ioc
->fc_rescan_work_lock
, flags
);
611 if (ioc
->fc_rescan_work_count
> 2) /* only need one more */
612 ioc
->fc_rescan_work_count
= 2;
613 work_to_do
= --ioc
->fc_rescan_work_count
;
614 spin_unlock_irqrestore(&ioc
->fc_rescan_work_lock
, flags
);
615 } while (work_to_do
);
619 mptfc_probe(struct pci_dev
*pdev
, const struct pci_device_id
*id
)
621 struct Scsi_Host
*sh
;
632 if ((r
= mpt_attach(pdev
,id
)) != 0)
635 ioc
= pci_get_drvdata(pdev
);
636 ioc
->DoneCtx
= mptfcDoneCtx
;
637 ioc
->TaskCtx
= mptfcTaskCtx
;
638 ioc
->InternalCtx
= mptfcInternalCtx
;
640 /* Added sanity check on readiness of the MPT adapter.
642 if (ioc
->last_state
!= MPI_IOC_STATE_OPERATIONAL
) {
643 printk(MYIOC_s_WARN_FMT
644 "Skipping because it's not operational!\n",
647 goto out_mptfc_probe
;
651 printk(MYIOC_s_WARN_FMT
"Skipping because it's disabled!\n",
654 goto out_mptfc_probe
;
657 /* Sanity check - ensure at least 1 port is INITIATOR capable
660 for (ii
=0; ii
< ioc
->facts
.NumberOfPorts
; ii
++) {
661 if (ioc
->pfacts
[ii
].ProtocolFlags
&
662 MPI_PORTFACTS_PROTOCOL_INITIATOR
)
667 printk(MYIOC_s_WARN_FMT
668 "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
673 sh
= scsi_host_alloc(&mptfc_driver_template
, sizeof(MPT_SCSI_HOST
));
676 printk(MYIOC_s_WARN_FMT
677 "Unable to register controller with SCSI subsystem\n",
680 goto out_mptfc_probe
;
683 INIT_WORK(&ioc
->fc_rescan_work
, mptfc_rescan_devices
,(void *)ioc
);
685 spin_lock_irqsave(&ioc
->FreeQlock
, flags
);
687 /* Attach the SCSI Host to the IOC structure
695 /* set 16 byte cdb's */
696 sh
->max_cmd_len
= 16;
698 sh
->max_id
= MPT_MAX_FC_DEVICES
<256 ? MPT_MAX_FC_DEVICES
: 255;
700 sh
->max_lun
= MPT_LAST_LUN
+ 1;
702 sh
->this_id
= ioc
->pfacts
[0].PortSCSIID
;
706 sh
->unique_id
= ioc
->id
;
708 /* Verify that we won't exceed the maximum
709 * number of chain buffers
710 * We can optimize: ZZ = req_sz/sizeof(SGE)
712 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
713 * + (req_sz - 64)/sizeof(SGE)
714 * A slightly different algorithm is required for
717 scale
= ioc
->req_sz
/(sizeof(dma_addr_t
) + sizeof(u32
));
718 if (sizeof(dma_addr_t
) == sizeof(u64
)) {
719 numSGE
= (scale
- 1) *
720 (ioc
->facts
.MaxChainDepth
-1) + scale
+
721 (ioc
->req_sz
- 60) / (sizeof(dma_addr_t
) +
724 numSGE
= 1 + (scale
- 1) *
725 (ioc
->facts
.MaxChainDepth
-1) + scale
+
726 (ioc
->req_sz
- 64) / (sizeof(dma_addr_t
) +
730 if (numSGE
< sh
->sg_tablesize
) {
731 /* Reset this value */
732 dprintk((MYIOC_s_INFO_FMT
733 "Resetting sg_tablesize to %d from %d\n",
734 ioc
->name
, numSGE
, sh
->sg_tablesize
));
735 sh
->sg_tablesize
= numSGE
;
738 spin_unlock_irqrestore(&ioc
->FreeQlock
, flags
);
740 hd
= (MPT_SCSI_HOST
*) sh
->hostdata
;
743 /* SCSI needs scsi_cmnd lookup table!
744 * (with size equal to req_depth*PtrSz!)
746 hd
->ScsiLookup
= kcalloc(ioc
->req_depth
, sizeof(void *), GFP_ATOMIC
);
747 if (!hd
->ScsiLookup
) {
749 goto out_mptfc_probe
;
752 dprintk((MYIOC_s_INFO_FMT
"ScsiLookup @ %p\n",
753 ioc
->name
, hd
->ScsiLookup
));
755 /* Allocate memory for the device structures.
756 * A non-Null pointer at an offset
757 * indicates a device exists.
758 * max_id = 1 + maximum id (hosts.h)
760 hd
->Targets
= kcalloc(sh
->max_id
, sizeof(void *), GFP_ATOMIC
);
763 goto out_mptfc_probe
;
766 dprintk((KERN_INFO
" vdev @ %p\n", hd
->Targets
));
768 /* Clear the TM flags
771 hd
->tmState
= TM_STATE_NONE
;
772 hd
->resetPending
= 0;
773 hd
->abortSCpnt
= NULL
;
775 /* Clear the pointer used to store
776 * single-threaded commands, i.e., those
777 * issued during a bus scan, dv and
778 * configuration pages.
782 /* Initialize this SCSI Hosts' timers
783 * To use, set the timer expires field
786 init_timer(&hd
->timer
);
787 hd
->timer
.data
= (unsigned long) hd
;
788 hd
->timer
.function
= mptscsih_timer_expired
;
790 hd
->mpt_pq_filter
= mpt_pq_filter
;
792 ddvprintk((MYIOC_s_INFO_FMT
793 "mpt_pq_filter %x\n",
797 init_waitqueue_head(&hd
->scandv_waitq
);
798 hd
->scandv_wait_done
= 0;
799 hd
->last_queue_full
= 0;
801 sh
->transportt
= mptfc_transport_template
;
802 error
= scsi_add_host (sh
, &ioc
->pcidev
->dev
);
804 dprintk((KERN_ERR MYNAM
805 "scsi_add_host failed\n"));
806 goto out_mptfc_probe
;
809 for (ii
=0; ii
< ioc
->facts
.NumberOfPorts
; ii
++) {
810 mptfc_init_host_attr(ioc
,ii
);
811 mptfc_GetFcDevPage0(ioc
,ii
,mptfc_register_dev
);
818 mptscsih_remove(pdev
);
822 static struct pci_driver mptfc_driver
= {
824 .id_table
= mptfc_pci_table
,
825 .probe
= mptfc_probe
,
826 .remove
= __devexit_p(mptfc_remove
),
827 .shutdown
= mptscsih_shutdown
,
829 .suspend
= mptscsih_suspend
,
830 .resume
= mptscsih_resume
,
834 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
836 * mptfc_init - Register MPT adapter(s) as SCSI host(s) with
837 * linux scsi mid-layer.
839 * Returns 0 for success, non-zero for failure.
846 show_mptmod_ver(my_NAME
, my_VERSION
);
848 /* sanity check module parameter */
849 if (mptfc_dev_loss_tmo
== 0)
850 mptfc_dev_loss_tmo
= MPTFC_DEV_LOSS_TMO
;
852 mptfc_transport_template
=
853 fc_attach_transport(&mptfc_transport_functions
);
855 if (!mptfc_transport_template
)
858 mptfcDoneCtx
= mpt_register(mptscsih_io_done
, MPTFC_DRIVER
);
859 mptfcTaskCtx
= mpt_register(mptscsih_taskmgmt_complete
, MPTFC_DRIVER
);
860 mptfcInternalCtx
= mpt_register(mptscsih_scandv_complete
, MPTFC_DRIVER
);
862 if (mpt_event_register(mptfcDoneCtx
, mptscsih_event_process
) == 0) {
863 devtprintk((KERN_INFO MYNAM
864 ": Registered for IOC event notifications\n"));
867 if (mpt_reset_register(mptfcDoneCtx
, mptscsih_ioc_reset
) == 0) {
868 dprintk((KERN_INFO MYNAM
869 ": Registered for IOC reset notifications\n"));
872 error
= pci_register_driver(&mptfc_driver
);
874 fc_release_transport(mptfc_transport_template
);
880 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
882 * mptfc_remove - Removed fc infrastructure for devices
883 * @pdev: Pointer to pci_dev structure
886 static void __devexit
mptfc_remove(struct pci_dev
*pdev
)
888 MPT_ADAPTER
*ioc
= pci_get_drvdata(pdev
);
889 struct mptfc_rport_info
*p
, *n
;
891 fc_remove_host(ioc
->sh
);
893 list_for_each_entry_safe(p
, n
, &ioc
->fc_rports
, list
) {
898 mptscsih_remove(pdev
);
901 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
902 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
904 * mptfc_exit - Unregisters MPT adapter(s)
910 pci_unregister_driver(&mptfc_driver
);
911 fc_release_transport(mptfc_transport_template
);
913 mpt_reset_deregister(mptfcDoneCtx
);
914 dprintk((KERN_INFO MYNAM
915 ": Deregistered for IOC reset notifications\n"));
917 mpt_event_deregister(mptfcDoneCtx
);
918 dprintk((KERN_INFO MYNAM
919 ": Deregistered for IOC event notifications\n"));
921 mpt_deregister(mptfcInternalCtx
);
922 mpt_deregister(mptfcTaskCtx
);
923 mpt_deregister(mptfcDoneCtx
);
926 module_init(mptfc_init
);
927 module_exit(mptfc_exit
);