12496af39SMoore, Eric Dean /* 22496af39SMoore, Eric Dean * linux/drivers/message/fusion/mptfc.c 32496af39SMoore, Eric Dean * For use with LSI Logic PCI chip/adapter(s) 42496af39SMoore, Eric Dean * running LSI Logic Fusion MPT (Message Passing Technology) firmware. 52496af39SMoore, Eric Dean * 62496af39SMoore, Eric Dean * Copyright (c) 1999-2005 LSI Logic Corporation 72496af39SMoore, Eric Dean * (mailto:mpt_linux_developer@lsil.com) 82496af39SMoore, Eric Dean * 92496af39SMoore, Eric Dean */ 102496af39SMoore, Eric Dean /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 112496af39SMoore, Eric Dean /* 122496af39SMoore, Eric Dean This program is free software; you can redistribute it and/or modify 132496af39SMoore, Eric Dean it under the terms of the GNU General Public License as published by 142496af39SMoore, Eric Dean the Free Software Foundation; version 2 of the License. 152496af39SMoore, Eric Dean 162496af39SMoore, Eric Dean This program is distributed in the hope that it will be useful, 172496af39SMoore, Eric Dean but WITHOUT ANY WARRANTY; without even the implied warranty of 182496af39SMoore, Eric Dean MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 192496af39SMoore, Eric Dean GNU General Public License for more details. 202496af39SMoore, Eric Dean 212496af39SMoore, Eric Dean NO WARRANTY 222496af39SMoore, Eric Dean THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR 232496af39SMoore, Eric Dean CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT 242496af39SMoore, Eric Dean LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, 252496af39SMoore, Eric Dean MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is 262496af39SMoore, Eric Dean solely responsible for determining the appropriateness of using and 272496af39SMoore, Eric Dean distributing the Program and assumes all risks associated with its 282496af39SMoore, Eric Dean exercise of rights under this Agreement, including but not limited to 292496af39SMoore, Eric Dean the risks and costs of program errors, damage to or loss of data, 302496af39SMoore, Eric Dean programs or equipment, and unavailability or interruption of operations. 312496af39SMoore, Eric Dean 322496af39SMoore, Eric Dean DISCLAIMER OF LIABILITY 332496af39SMoore, Eric Dean NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY 342496af39SMoore, Eric Dean DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 352496af39SMoore, Eric Dean DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND 362496af39SMoore, Eric Dean ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 372496af39SMoore, Eric Dean TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 382496af39SMoore, Eric Dean USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED 392496af39SMoore, Eric Dean HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES 402496af39SMoore, Eric Dean 412496af39SMoore, Eric Dean You should have received a copy of the GNU General Public License 422496af39SMoore, Eric Dean along with this program; if not, write to the Free Software 432496af39SMoore, Eric Dean Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 442496af39SMoore, Eric Dean */ 452496af39SMoore, Eric Dean /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 462496af39SMoore, Eric Dean #include "linux_compat.h" /* linux-2.6 tweaks */ 472496af39SMoore, Eric Dean #include <linux/module.h> 482496af39SMoore, Eric Dean #include <linux/kernel.h> 492496af39SMoore, Eric Dean #include <linux/init.h> 502496af39SMoore, Eric Dean #include <linux/errno.h> 512496af39SMoore, Eric Dean #include <linux/kdev_t.h> 522496af39SMoore, Eric Dean #include <linux/blkdev.h> 532496af39SMoore, Eric Dean #include <linux/delay.h> /* for mdelay */ 542496af39SMoore, Eric Dean #include <linux/interrupt.h> /* needed for in_interrupt() proto */ 552496af39SMoore, Eric Dean #include <linux/reboot.h> /* notifier code */ 562496af39SMoore, Eric Dean #include <linux/sched.h> 572496af39SMoore, Eric Dean #include <linux/workqueue.h> 582496af39SMoore, Eric Dean 592496af39SMoore, Eric Dean #include <scsi/scsi.h> 602496af39SMoore, Eric Dean #include <scsi/scsi_cmnd.h> 612496af39SMoore, Eric Dean #include <scsi/scsi_device.h> 622496af39SMoore, Eric Dean #include <scsi/scsi_host.h> 632496af39SMoore, Eric Dean #include <scsi/scsi_tcq.h> 642496af39SMoore, Eric Dean 652496af39SMoore, Eric Dean #include "mptbase.h" 662496af39SMoore, Eric Dean #include "mptscsih.h" 672496af39SMoore, Eric Dean 682496af39SMoore, Eric Dean /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 692496af39SMoore, Eric Dean #define my_NAME "Fusion MPT FC Host driver" 702496af39SMoore, Eric Dean #define my_VERSION MPT_LINUX_VERSION_COMMON 712496af39SMoore, Eric Dean #define MYNAM "mptfc" 722496af39SMoore, Eric Dean 732496af39SMoore, Eric Dean MODULE_AUTHOR(MODULEAUTHOR); 742496af39SMoore, Eric Dean MODULE_DESCRIPTION(my_NAME); 752496af39SMoore, Eric Dean MODULE_LICENSE("GPL"); 762496af39SMoore, Eric Dean 772496af39SMoore, Eric Dean /* Command line args */ 782496af39SMoore, Eric Dean static int mpt_pq_filter = 0; 792496af39SMoore, Eric Dean module_param(mpt_pq_filter, int, 0); 802496af39SMoore, Eric Dean MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)"); 812496af39SMoore, Eric Dean 822496af39SMoore, Eric Dean static int mptfcDoneCtx = -1; 832496af39SMoore, Eric Dean static int mptfcTaskCtx = -1; 842496af39SMoore, Eric Dean static int mptfcInternalCtx = -1; /* Used only for internal commands */ 852496af39SMoore, Eric Dean 862496af39SMoore, Eric Dean static struct scsi_host_template mptfc_driver_template = { 872496af39SMoore, Eric Dean .proc_name = "mptfc", 882496af39SMoore, Eric Dean .proc_info = mptscsih_proc_info, 892496af39SMoore, Eric Dean .name = "MPT FC Host", 902496af39SMoore, Eric Dean .info = mptscsih_info, 912496af39SMoore, Eric Dean .queuecommand = mptscsih_qcmd, 922496af39SMoore, Eric Dean .slave_alloc = mptscsih_slave_alloc, 932496af39SMoore, Eric Dean .slave_configure = mptscsih_slave_configure, 942496af39SMoore, Eric Dean .slave_destroy = mptscsih_slave_destroy, 956e3815baSMoore, Eric Dean .change_queue_depth = mptscsih_change_queue_depth, 962496af39SMoore, Eric Dean .eh_abort_handler = mptscsih_abort, 972496af39SMoore, Eric Dean .eh_device_reset_handler = mptscsih_dev_reset, 982496af39SMoore, Eric Dean .eh_bus_reset_handler = mptscsih_bus_reset, 992496af39SMoore, Eric Dean .eh_host_reset_handler = mptscsih_host_reset, 1002496af39SMoore, Eric Dean .bios_param = mptscsih_bios_param, 1012496af39SMoore, Eric Dean .can_queue = MPT_FC_CAN_QUEUE, 1022496af39SMoore, Eric Dean .this_id = -1, 1032496af39SMoore, Eric Dean .sg_tablesize = MPT_SCSI_SG_DEPTH, 1042496af39SMoore, Eric Dean .max_sectors = 8192, 1052496af39SMoore, Eric Dean .cmd_per_lun = 7, 1062496af39SMoore, Eric Dean .use_clustering = ENABLE_CLUSTERING, 1072496af39SMoore, Eric Dean }; 1082496af39SMoore, Eric Dean 1092496af39SMoore, Eric Dean /**************************************************************************** 1102496af39SMoore, Eric Dean * Supported hardware 1112496af39SMoore, Eric Dean */ 1122496af39SMoore, Eric Dean 1132496af39SMoore, Eric Dean static struct pci_device_id mptfc_pci_table[] = { 1142496af39SMoore, Eric Dean { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909, 1152496af39SMoore, Eric Dean PCI_ANY_ID, PCI_ANY_ID }, 1162496af39SMoore, Eric Dean { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919, 1172496af39SMoore, Eric Dean PCI_ANY_ID, PCI_ANY_ID }, 1182496af39SMoore, Eric Dean { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929, 1192496af39SMoore, Eric Dean PCI_ANY_ID, PCI_ANY_ID }, 1202496af39SMoore, Eric Dean { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X, 1212496af39SMoore, Eric Dean PCI_ANY_ID, PCI_ANY_ID }, 1222496af39SMoore, Eric Dean { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X, 1232496af39SMoore, Eric Dean PCI_ANY_ID, PCI_ANY_ID }, 1243fadc59dSMoore, Eric Dean { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC939X, 1253fadc59dSMoore, Eric Dean PCI_ANY_ID, PCI_ANY_ID }, 1263fadc59dSMoore, Eric Dean { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X, 1273fadc59dSMoore, Eric Dean PCI_ANY_ID, PCI_ANY_ID }, 1282496af39SMoore, Eric Dean {0} /* Terminating entry */ 1292496af39SMoore, Eric Dean }; 1302496af39SMoore, Eric Dean MODULE_DEVICE_TABLE(pci, mptfc_pci_table); 1312496af39SMoore, Eric Dean 1322496af39SMoore, Eric Dean /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 1332496af39SMoore, Eric Dean /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 1342496af39SMoore, Eric Dean /* 1352496af39SMoore, Eric Dean * mptfc_probe - Installs scsi devices per bus. 1362496af39SMoore, Eric Dean * @pdev: Pointer to pci_dev structure 1372496af39SMoore, Eric Dean * 1382496af39SMoore, Eric Dean * Returns 0 for success, non-zero for failure. 1392496af39SMoore, Eric Dean * 1402496af39SMoore, Eric Dean */ 1412496af39SMoore, Eric Dean static int 1422496af39SMoore, Eric Dean mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) 1432496af39SMoore, Eric Dean { 1442496af39SMoore, Eric Dean struct Scsi_Host *sh; 1452496af39SMoore, Eric Dean MPT_SCSI_HOST *hd; 1462496af39SMoore, Eric Dean MPT_ADAPTER *ioc; 1472496af39SMoore, Eric Dean unsigned long flags; 1482496af39SMoore, Eric Dean int sz, ii; 1492496af39SMoore, Eric Dean int numSGE = 0; 1502496af39SMoore, Eric Dean int scale; 1512496af39SMoore, Eric Dean int ioc_cap; 1522496af39SMoore, Eric Dean u8 *mem; 1532496af39SMoore, Eric Dean int error=0; 1542496af39SMoore, Eric Dean int r; 1552496af39SMoore, Eric Dean 1562496af39SMoore, Eric Dean if ((r = mpt_attach(pdev,id)) != 0) 1572496af39SMoore, Eric Dean return r; 1582496af39SMoore, Eric Dean 1592496af39SMoore, Eric Dean ioc = pci_get_drvdata(pdev); 160d335cc38SMoore, Eric Dean ioc->DoneCtx = mptfcDoneCtx; 161d335cc38SMoore, Eric Dean ioc->TaskCtx = mptfcTaskCtx; 162d335cc38SMoore, Eric Dean ioc->InternalCtx = mptfcInternalCtx; 1632496af39SMoore, Eric Dean 1642496af39SMoore, Eric Dean /* Added sanity check on readiness of the MPT adapter. 1652496af39SMoore, Eric Dean */ 1662496af39SMoore, Eric Dean if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) { 1672496af39SMoore, Eric Dean printk(MYIOC_s_WARN_FMT 1682496af39SMoore, Eric Dean "Skipping because it's not operational!\n", 1692496af39SMoore, Eric Dean ioc->name); 1702496af39SMoore, Eric Dean return -ENODEV; 1712496af39SMoore, Eric Dean } 1722496af39SMoore, Eric Dean 1732496af39SMoore, Eric Dean if (!ioc->active) { 1742496af39SMoore, Eric Dean printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n", 1752496af39SMoore, Eric Dean ioc->name); 1762496af39SMoore, Eric Dean return -ENODEV; 1772496af39SMoore, Eric Dean } 1782496af39SMoore, Eric Dean 1792496af39SMoore, Eric Dean /* Sanity check - ensure at least 1 port is INITIATOR capable 1802496af39SMoore, Eric Dean */ 1812496af39SMoore, Eric Dean ioc_cap = 0; 1822496af39SMoore, Eric Dean for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { 1832496af39SMoore, Eric Dean if (ioc->pfacts[ii].ProtocolFlags & 1842496af39SMoore, Eric Dean MPI_PORTFACTS_PROTOCOL_INITIATOR) 1852496af39SMoore, Eric Dean ioc_cap ++; 1862496af39SMoore, Eric Dean } 1872496af39SMoore, Eric Dean 1882496af39SMoore, Eric Dean if (!ioc_cap) { 1892496af39SMoore, Eric Dean printk(MYIOC_s_WARN_FMT 1902496af39SMoore, Eric Dean "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n", 1912496af39SMoore, Eric Dean ioc->name, ioc); 192*466544d8SMoore, Eric Dean return 0; 1932496af39SMoore, Eric Dean } 1942496af39SMoore, Eric Dean 1952496af39SMoore, Eric Dean sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST)); 1962496af39SMoore, Eric Dean 1972496af39SMoore, Eric Dean if (!sh) { 1982496af39SMoore, Eric Dean printk(MYIOC_s_WARN_FMT 1992496af39SMoore, Eric Dean "Unable to register controller with SCSI subsystem\n", 2002496af39SMoore, Eric Dean ioc->name); 2012496af39SMoore, Eric Dean return -1; 2022496af39SMoore, Eric Dean } 2032496af39SMoore, Eric Dean 2042496af39SMoore, Eric Dean spin_lock_irqsave(&ioc->FreeQlock, flags); 2052496af39SMoore, Eric Dean 2062496af39SMoore, Eric Dean /* Attach the SCSI Host to the IOC structure 2072496af39SMoore, Eric Dean */ 2082496af39SMoore, Eric Dean ioc->sh = sh; 2092496af39SMoore, Eric Dean 2102496af39SMoore, Eric Dean sh->io_port = 0; 2112496af39SMoore, Eric Dean sh->n_io_port = 0; 2122496af39SMoore, Eric Dean sh->irq = 0; 2132496af39SMoore, Eric Dean 2142496af39SMoore, Eric Dean /* set 16 byte cdb's */ 2152496af39SMoore, Eric Dean sh->max_cmd_len = 16; 2162496af39SMoore, Eric Dean 2172496af39SMoore, Eric Dean sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255; 2182496af39SMoore, Eric Dean 2192496af39SMoore, Eric Dean sh->max_lun = MPT_LAST_LUN + 1; 2202496af39SMoore, Eric Dean sh->max_channel = 0; 2212496af39SMoore, Eric Dean sh->this_id = ioc->pfacts[0].PortSCSIID; 2222496af39SMoore, Eric Dean 2232496af39SMoore, Eric Dean /* Required entry. 2242496af39SMoore, Eric Dean */ 2252496af39SMoore, Eric Dean sh->unique_id = ioc->id; 2262496af39SMoore, Eric Dean 2272496af39SMoore, Eric Dean /* Verify that we won't exceed the maximum 2282496af39SMoore, Eric Dean * number of chain buffers 2292496af39SMoore, Eric Dean * We can optimize: ZZ = req_sz/sizeof(SGE) 2302496af39SMoore, Eric Dean * For 32bit SGE's: 2312496af39SMoore, Eric Dean * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ 2322496af39SMoore, Eric Dean * + (req_sz - 64)/sizeof(SGE) 2332496af39SMoore, Eric Dean * A slightly different algorithm is required for 2342496af39SMoore, Eric Dean * 64bit SGEs. 2352496af39SMoore, Eric Dean */ 2362496af39SMoore, Eric Dean scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); 2372496af39SMoore, Eric Dean if (sizeof(dma_addr_t) == sizeof(u64)) { 2382496af39SMoore, Eric Dean numSGE = (scale - 1) * 2392496af39SMoore, Eric Dean (ioc->facts.MaxChainDepth-1) + scale + 2402496af39SMoore, Eric Dean (ioc->req_sz - 60) / (sizeof(dma_addr_t) + 2412496af39SMoore, Eric Dean sizeof(u32)); 2422496af39SMoore, Eric Dean } else { 2432496af39SMoore, Eric Dean numSGE = 1 + (scale - 1) * 2442496af39SMoore, Eric Dean (ioc->facts.MaxChainDepth-1) + scale + 2452496af39SMoore, Eric Dean (ioc->req_sz - 64) / (sizeof(dma_addr_t) + 2462496af39SMoore, Eric Dean sizeof(u32)); 2472496af39SMoore, Eric Dean } 2482496af39SMoore, Eric Dean 2492496af39SMoore, Eric Dean if (numSGE < sh->sg_tablesize) { 2502496af39SMoore, Eric Dean /* Reset this value */ 2512496af39SMoore, Eric Dean dprintk((MYIOC_s_INFO_FMT 2522496af39SMoore, Eric Dean "Resetting sg_tablesize to %d from %d\n", 2532496af39SMoore, Eric Dean ioc->name, numSGE, sh->sg_tablesize)); 2542496af39SMoore, Eric Dean sh->sg_tablesize = numSGE; 2552496af39SMoore, Eric Dean } 2562496af39SMoore, Eric Dean 2572496af39SMoore, Eric Dean spin_unlock_irqrestore(&ioc->FreeQlock, flags); 2582496af39SMoore, Eric Dean 2592496af39SMoore, Eric Dean hd = (MPT_SCSI_HOST *) sh->hostdata; 2602496af39SMoore, Eric Dean hd->ioc = ioc; 2612496af39SMoore, Eric Dean 2622496af39SMoore, Eric Dean /* SCSI needs scsi_cmnd lookup table! 2632496af39SMoore, Eric Dean * (with size equal to req_depth*PtrSz!) 2642496af39SMoore, Eric Dean */ 2652496af39SMoore, Eric Dean sz = ioc->req_depth * sizeof(void *); 2662496af39SMoore, Eric Dean mem = kmalloc(sz, GFP_ATOMIC); 2672496af39SMoore, Eric Dean if (mem == NULL) { 2682496af39SMoore, Eric Dean error = -ENOMEM; 2692496af39SMoore, Eric Dean goto mptfc_probe_failed; 2702496af39SMoore, Eric Dean } 2712496af39SMoore, Eric Dean 2722496af39SMoore, Eric Dean memset(mem, 0, sz); 2732496af39SMoore, Eric Dean hd->ScsiLookup = (struct scsi_cmnd **) mem; 2742496af39SMoore, Eric Dean 2752496af39SMoore, Eric Dean dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", 2762496af39SMoore, Eric Dean ioc->name, hd->ScsiLookup, sz)); 2772496af39SMoore, Eric Dean 2782496af39SMoore, Eric Dean /* Allocate memory for the device structures. 2792496af39SMoore, Eric Dean * A non-Null pointer at an offset 2802496af39SMoore, Eric Dean * indicates a device exists. 2812496af39SMoore, Eric Dean * max_id = 1 + maximum id (hosts.h) 2822496af39SMoore, Eric Dean */ 2832496af39SMoore, Eric Dean sz = sh->max_id * sizeof(void *); 2842496af39SMoore, Eric Dean mem = kmalloc(sz, GFP_ATOMIC); 2852496af39SMoore, Eric Dean if (mem == NULL) { 2862496af39SMoore, Eric Dean error = -ENOMEM; 2872496af39SMoore, Eric Dean goto mptfc_probe_failed; 2882496af39SMoore, Eric Dean } 2892496af39SMoore, Eric Dean 2902496af39SMoore, Eric Dean memset(mem, 0, sz); 2912496af39SMoore, Eric Dean hd->Targets = (VirtDevice **) mem; 2922496af39SMoore, Eric Dean 2932496af39SMoore, Eric Dean dprintk((KERN_INFO 2942496af39SMoore, Eric Dean " Targets @ %p, sz=%d\n", hd->Targets, sz)); 2952496af39SMoore, Eric Dean 2962496af39SMoore, Eric Dean /* Clear the TM flags 2972496af39SMoore, Eric Dean */ 2982496af39SMoore, Eric Dean hd->tmPending = 0; 2992496af39SMoore, Eric Dean hd->tmState = TM_STATE_NONE; 3002496af39SMoore, Eric Dean hd->resetPending = 0; 3012496af39SMoore, Eric Dean hd->abortSCpnt = NULL; 3022496af39SMoore, Eric Dean 3032496af39SMoore, Eric Dean /* Clear the pointer used to store 3042496af39SMoore, Eric Dean * single-threaded commands, i.e., those 3052496af39SMoore, Eric Dean * issued during a bus scan, dv and 3062496af39SMoore, Eric Dean * configuration pages. 3072496af39SMoore, Eric Dean */ 3082496af39SMoore, Eric Dean hd->cmdPtr = NULL; 3092496af39SMoore, Eric Dean 3102496af39SMoore, Eric Dean /* Initialize this SCSI Hosts' timers 3112496af39SMoore, Eric Dean * To use, set the timer expires field 3122496af39SMoore, Eric Dean * and add_timer 3132496af39SMoore, Eric Dean */ 3142496af39SMoore, Eric Dean init_timer(&hd->timer); 3152496af39SMoore, Eric Dean hd->timer.data = (unsigned long) hd; 3162496af39SMoore, Eric Dean hd->timer.function = mptscsih_timer_expired; 3172496af39SMoore, Eric Dean 3182496af39SMoore, Eric Dean hd->mpt_pq_filter = mpt_pq_filter; 3192496af39SMoore, Eric Dean 3202496af39SMoore, Eric Dean ddvprintk((MYIOC_s_INFO_FMT 3212496af39SMoore, Eric Dean "mpt_pq_filter %x\n", 3222496af39SMoore, Eric Dean ioc->name, 3232496af39SMoore, Eric Dean mpt_pq_filter)); 3242496af39SMoore, Eric Dean 3252496af39SMoore, Eric Dean init_waitqueue_head(&hd->scandv_waitq); 3262496af39SMoore, Eric Dean hd->scandv_wait_done = 0; 3272496af39SMoore, Eric Dean hd->last_queue_full = 0; 3282496af39SMoore, Eric Dean 3292496af39SMoore, Eric Dean error = scsi_add_host (sh, &ioc->pcidev->dev); 3302496af39SMoore, Eric Dean if(error) { 3312496af39SMoore, Eric Dean dprintk((KERN_ERR MYNAM 3322496af39SMoore, Eric Dean "scsi_add_host failed\n")); 3332496af39SMoore, Eric Dean goto mptfc_probe_failed; 3342496af39SMoore, Eric Dean } 3352496af39SMoore, Eric Dean 3362496af39SMoore, Eric Dean scsi_scan_host(sh); 3372496af39SMoore, Eric Dean return 0; 3382496af39SMoore, Eric Dean 3392496af39SMoore, Eric Dean mptfc_probe_failed: 3402496af39SMoore, Eric Dean 3412496af39SMoore, Eric Dean mptscsih_remove(pdev); 3422496af39SMoore, Eric Dean return error; 3432496af39SMoore, Eric Dean } 3442496af39SMoore, Eric Dean 3452496af39SMoore, Eric Dean static struct pci_driver mptfc_driver = { 3462496af39SMoore, Eric Dean .name = "mptfc", 3472496af39SMoore, Eric Dean .id_table = mptfc_pci_table, 3482496af39SMoore, Eric Dean .probe = mptfc_probe, 3492496af39SMoore, Eric Dean .remove = __devexit_p(mptscsih_remove), 3502496af39SMoore, Eric Dean .shutdown = mptscsih_shutdown, 3512496af39SMoore, Eric Dean #ifdef CONFIG_PM 3522496af39SMoore, Eric Dean .suspend = mptscsih_suspend, 3532496af39SMoore, Eric Dean .resume = mptscsih_resume, 3542496af39SMoore, Eric Dean #endif 3552496af39SMoore, Eric Dean }; 3562496af39SMoore, Eric Dean 3572496af39SMoore, Eric Dean /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 3582496af39SMoore, Eric Dean /** 3592496af39SMoore, Eric Dean * mptfc_init - Register MPT adapter(s) as SCSI host(s) with 3602496af39SMoore, Eric Dean * linux scsi mid-layer. 3612496af39SMoore, Eric Dean * 3622496af39SMoore, Eric Dean * Returns 0 for success, non-zero for failure. 3632496af39SMoore, Eric Dean */ 3642496af39SMoore, Eric Dean static int __init 3652496af39SMoore, Eric Dean mptfc_init(void) 3662496af39SMoore, Eric Dean { 3672496af39SMoore, Eric Dean 3682496af39SMoore, Eric Dean show_mptmod_ver(my_NAME, my_VERSION); 3692496af39SMoore, Eric Dean 3702496af39SMoore, Eric Dean mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER); 3712496af39SMoore, Eric Dean mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER); 3722496af39SMoore, Eric Dean mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER); 3732496af39SMoore, Eric Dean 3742496af39SMoore, Eric Dean if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) { 3752496af39SMoore, Eric Dean devtprintk((KERN_INFO MYNAM 3762496af39SMoore, Eric Dean ": Registered for IOC event notifications\n")); 3772496af39SMoore, Eric Dean } 3782496af39SMoore, Eric Dean 3792496af39SMoore, Eric Dean if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) { 3802496af39SMoore, Eric Dean dprintk((KERN_INFO MYNAM 3812496af39SMoore, Eric Dean ": Registered for IOC reset notifications\n")); 3822496af39SMoore, Eric Dean } 3832496af39SMoore, Eric Dean 3842496af39SMoore, Eric Dean return pci_register_driver(&mptfc_driver); 3852496af39SMoore, Eric Dean } 3862496af39SMoore, Eric Dean 3872496af39SMoore, Eric Dean /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 3882496af39SMoore, Eric Dean /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 3892496af39SMoore, Eric Dean /** 3902496af39SMoore, Eric Dean * mptfc_exit - Unregisters MPT adapter(s) 3912496af39SMoore, Eric Dean * 3922496af39SMoore, Eric Dean */ 3932496af39SMoore, Eric Dean static void __exit 3942496af39SMoore, Eric Dean mptfc_exit(void) 3952496af39SMoore, Eric Dean { 3962496af39SMoore, Eric Dean pci_unregister_driver(&mptfc_driver); 3972496af39SMoore, Eric Dean 3982496af39SMoore, Eric Dean mpt_reset_deregister(mptfcDoneCtx); 3992496af39SMoore, Eric Dean dprintk((KERN_INFO MYNAM 4002496af39SMoore, Eric Dean ": Deregistered for IOC reset notifications\n")); 4012496af39SMoore, Eric Dean 4022496af39SMoore, Eric Dean mpt_event_deregister(mptfcDoneCtx); 4032496af39SMoore, Eric Dean dprintk((KERN_INFO MYNAM 4042496af39SMoore, Eric Dean ": Deregistered for IOC event notifications\n")); 4052496af39SMoore, Eric Dean 4062496af39SMoore, Eric Dean mpt_deregister(mptfcInternalCtx); 4072496af39SMoore, Eric Dean mpt_deregister(mptfcTaskCtx); 4082496af39SMoore, Eric Dean mpt_deregister(mptfcDoneCtx); 4092496af39SMoore, Eric Dean } 4102496af39SMoore, Eric Dean 4112496af39SMoore, Eric Dean module_init(mptfc_init); 4122496af39SMoore, Eric Dean module_exit(mptfc_exit); 413