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 device_attribute mptfc_queue_depth_attr = { 872496af39SMoore, Eric Dean .attr = { 882496af39SMoore, Eric Dean .name = "queue_depth", 892496af39SMoore, Eric Dean .mode = S_IWUSR, 902496af39SMoore, Eric Dean }, 912496af39SMoore, Eric Dean .store = mptscsih_store_queue_depth, 922496af39SMoore, Eric Dean }; 932496af39SMoore, Eric Dean 942496af39SMoore, Eric Dean static struct device_attribute *mptfc_dev_attrs[] = { 952496af39SMoore, Eric Dean &mptfc_queue_depth_attr, 962496af39SMoore, Eric Dean NULL, 972496af39SMoore, Eric Dean }; 982496af39SMoore, Eric Dean 992496af39SMoore, Eric Dean static struct scsi_host_template mptfc_driver_template = { 1002496af39SMoore, Eric Dean .proc_name = "mptfc", 1012496af39SMoore, Eric Dean .proc_info = mptscsih_proc_info, 1022496af39SMoore, Eric Dean .name = "MPT FC Host", 1032496af39SMoore, Eric Dean .info = mptscsih_info, 1042496af39SMoore, Eric Dean .queuecommand = mptscsih_qcmd, 1052496af39SMoore, Eric Dean .slave_alloc = mptscsih_slave_alloc, 1062496af39SMoore, Eric Dean .slave_configure = mptscsih_slave_configure, 1072496af39SMoore, Eric Dean .slave_destroy = mptscsih_slave_destroy, 1082496af39SMoore, Eric Dean .eh_abort_handler = mptscsih_abort, 1092496af39SMoore, Eric Dean .eh_device_reset_handler = mptscsih_dev_reset, 1102496af39SMoore, Eric Dean .eh_bus_reset_handler = mptscsih_bus_reset, 1112496af39SMoore, Eric Dean .eh_host_reset_handler = mptscsih_host_reset, 1122496af39SMoore, Eric Dean .bios_param = mptscsih_bios_param, 1132496af39SMoore, Eric Dean .can_queue = MPT_FC_CAN_QUEUE, 1142496af39SMoore, Eric Dean .this_id = -1, 1152496af39SMoore, Eric Dean .sg_tablesize = MPT_SCSI_SG_DEPTH, 1162496af39SMoore, Eric Dean .max_sectors = 8192, 1172496af39SMoore, Eric Dean .cmd_per_lun = 7, 1182496af39SMoore, Eric Dean .use_clustering = ENABLE_CLUSTERING, 1192496af39SMoore, Eric Dean .sdev_attrs = mptfc_dev_attrs, 1202496af39SMoore, Eric Dean }; 1212496af39SMoore, Eric Dean 1222496af39SMoore, Eric Dean /**************************************************************************** 1232496af39SMoore, Eric Dean * Supported hardware 1242496af39SMoore, Eric Dean */ 1252496af39SMoore, Eric Dean 1262496af39SMoore, Eric Dean static struct pci_device_id mptfc_pci_table[] = { 1272496af39SMoore, Eric Dean { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909, 1282496af39SMoore, Eric Dean PCI_ANY_ID, PCI_ANY_ID }, 1292496af39SMoore, Eric Dean { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919, 1302496af39SMoore, Eric Dean PCI_ANY_ID, PCI_ANY_ID }, 1312496af39SMoore, Eric Dean { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929, 1322496af39SMoore, Eric Dean PCI_ANY_ID, PCI_ANY_ID }, 1332496af39SMoore, Eric Dean { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X, 1342496af39SMoore, Eric Dean PCI_ANY_ID, PCI_ANY_ID }, 1352496af39SMoore, Eric Dean { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X, 1362496af39SMoore, Eric Dean PCI_ANY_ID, PCI_ANY_ID }, 1372496af39SMoore, Eric Dean {0} /* Terminating entry */ 1382496af39SMoore, Eric Dean }; 1392496af39SMoore, Eric Dean MODULE_DEVICE_TABLE(pci, mptfc_pci_table); 1402496af39SMoore, Eric Dean 1412496af39SMoore, Eric Dean /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 1422496af39SMoore, Eric Dean /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 1432496af39SMoore, Eric Dean /* 1442496af39SMoore, Eric Dean * mptfc_probe - Installs scsi devices per bus. 1452496af39SMoore, Eric Dean * @pdev: Pointer to pci_dev structure 1462496af39SMoore, Eric Dean * 1472496af39SMoore, Eric Dean * Returns 0 for success, non-zero for failure. 1482496af39SMoore, Eric Dean * 1492496af39SMoore, Eric Dean */ 1502496af39SMoore, Eric Dean static int 1512496af39SMoore, Eric Dean mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) 1522496af39SMoore, Eric Dean { 1532496af39SMoore, Eric Dean struct Scsi_Host *sh; 1542496af39SMoore, Eric Dean MPT_SCSI_HOST *hd; 1552496af39SMoore, Eric Dean MPT_ADAPTER *ioc; 1562496af39SMoore, Eric Dean unsigned long flags; 1572496af39SMoore, Eric Dean int sz, ii; 1582496af39SMoore, Eric Dean int numSGE = 0; 1592496af39SMoore, Eric Dean int scale; 1602496af39SMoore, Eric Dean int ioc_cap; 1612496af39SMoore, Eric Dean u8 *mem; 1622496af39SMoore, Eric Dean int error=0; 1632496af39SMoore, Eric Dean int r; 1642496af39SMoore, Eric Dean 1652496af39SMoore, Eric Dean if ((r = mpt_attach(pdev,id)) != 0) 1662496af39SMoore, Eric Dean return r; 1672496af39SMoore, Eric Dean 1682496af39SMoore, Eric Dean ioc = pci_get_drvdata(pdev); 169*d335cc38SMoore, Eric Dean ioc->DoneCtx = mptfcDoneCtx; 170*d335cc38SMoore, Eric Dean ioc->TaskCtx = mptfcTaskCtx; 171*d335cc38SMoore, Eric Dean ioc->InternalCtx = mptfcInternalCtx; 1722496af39SMoore, Eric Dean 1732496af39SMoore, Eric Dean /* Added sanity check on readiness of the MPT adapter. 1742496af39SMoore, Eric Dean */ 1752496af39SMoore, Eric Dean if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) { 1762496af39SMoore, Eric Dean printk(MYIOC_s_WARN_FMT 1772496af39SMoore, Eric Dean "Skipping because it's not operational!\n", 1782496af39SMoore, Eric Dean ioc->name); 1792496af39SMoore, Eric Dean return -ENODEV; 1802496af39SMoore, Eric Dean } 1812496af39SMoore, Eric Dean 1822496af39SMoore, Eric Dean if (!ioc->active) { 1832496af39SMoore, Eric Dean printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n", 1842496af39SMoore, Eric Dean ioc->name); 1852496af39SMoore, Eric Dean return -ENODEV; 1862496af39SMoore, Eric Dean } 1872496af39SMoore, Eric Dean 1882496af39SMoore, Eric Dean /* Sanity check - ensure at least 1 port is INITIATOR capable 1892496af39SMoore, Eric Dean */ 1902496af39SMoore, Eric Dean ioc_cap = 0; 1912496af39SMoore, Eric Dean for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { 1922496af39SMoore, Eric Dean if (ioc->pfacts[ii].ProtocolFlags & 1932496af39SMoore, Eric Dean MPI_PORTFACTS_PROTOCOL_INITIATOR) 1942496af39SMoore, Eric Dean ioc_cap ++; 1952496af39SMoore, Eric Dean } 1962496af39SMoore, Eric Dean 1972496af39SMoore, Eric Dean if (!ioc_cap) { 1982496af39SMoore, Eric Dean printk(MYIOC_s_WARN_FMT 1992496af39SMoore, Eric Dean "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n", 2002496af39SMoore, Eric Dean ioc->name, ioc); 2012496af39SMoore, Eric Dean return -ENODEV; 2022496af39SMoore, Eric Dean } 2032496af39SMoore, Eric Dean 2042496af39SMoore, Eric Dean sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST)); 2052496af39SMoore, Eric Dean 2062496af39SMoore, Eric Dean if (!sh) { 2072496af39SMoore, Eric Dean printk(MYIOC_s_WARN_FMT 2082496af39SMoore, Eric Dean "Unable to register controller with SCSI subsystem\n", 2092496af39SMoore, Eric Dean ioc->name); 2102496af39SMoore, Eric Dean return -1; 2112496af39SMoore, Eric Dean } 2122496af39SMoore, Eric Dean 2132496af39SMoore, Eric Dean spin_lock_irqsave(&ioc->FreeQlock, flags); 2142496af39SMoore, Eric Dean 2152496af39SMoore, Eric Dean /* Attach the SCSI Host to the IOC structure 2162496af39SMoore, Eric Dean */ 2172496af39SMoore, Eric Dean ioc->sh = sh; 2182496af39SMoore, Eric Dean 2192496af39SMoore, Eric Dean sh->io_port = 0; 2202496af39SMoore, Eric Dean sh->n_io_port = 0; 2212496af39SMoore, Eric Dean sh->irq = 0; 2222496af39SMoore, Eric Dean 2232496af39SMoore, Eric Dean /* set 16 byte cdb's */ 2242496af39SMoore, Eric Dean sh->max_cmd_len = 16; 2252496af39SMoore, Eric Dean 2262496af39SMoore, Eric Dean sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255; 2272496af39SMoore, Eric Dean 2282496af39SMoore, Eric Dean sh->max_lun = MPT_LAST_LUN + 1; 2292496af39SMoore, Eric Dean sh->max_channel = 0; 2302496af39SMoore, Eric Dean sh->this_id = ioc->pfacts[0].PortSCSIID; 2312496af39SMoore, Eric Dean 2322496af39SMoore, Eric Dean /* Required entry. 2332496af39SMoore, Eric Dean */ 2342496af39SMoore, Eric Dean sh->unique_id = ioc->id; 2352496af39SMoore, Eric Dean 2362496af39SMoore, Eric Dean /* Verify that we won't exceed the maximum 2372496af39SMoore, Eric Dean * number of chain buffers 2382496af39SMoore, Eric Dean * We can optimize: ZZ = req_sz/sizeof(SGE) 2392496af39SMoore, Eric Dean * For 32bit SGE's: 2402496af39SMoore, Eric Dean * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ 2412496af39SMoore, Eric Dean * + (req_sz - 64)/sizeof(SGE) 2422496af39SMoore, Eric Dean * A slightly different algorithm is required for 2432496af39SMoore, Eric Dean * 64bit SGEs. 2442496af39SMoore, Eric Dean */ 2452496af39SMoore, Eric Dean scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); 2462496af39SMoore, Eric Dean if (sizeof(dma_addr_t) == sizeof(u64)) { 2472496af39SMoore, Eric Dean numSGE = (scale - 1) * 2482496af39SMoore, Eric Dean (ioc->facts.MaxChainDepth-1) + scale + 2492496af39SMoore, Eric Dean (ioc->req_sz - 60) / (sizeof(dma_addr_t) + 2502496af39SMoore, Eric Dean sizeof(u32)); 2512496af39SMoore, Eric Dean } else { 2522496af39SMoore, Eric Dean numSGE = 1 + (scale - 1) * 2532496af39SMoore, Eric Dean (ioc->facts.MaxChainDepth-1) + scale + 2542496af39SMoore, Eric Dean (ioc->req_sz - 64) / (sizeof(dma_addr_t) + 2552496af39SMoore, Eric Dean sizeof(u32)); 2562496af39SMoore, Eric Dean } 2572496af39SMoore, Eric Dean 2582496af39SMoore, Eric Dean if (numSGE < sh->sg_tablesize) { 2592496af39SMoore, Eric Dean /* Reset this value */ 2602496af39SMoore, Eric Dean dprintk((MYIOC_s_INFO_FMT 2612496af39SMoore, Eric Dean "Resetting sg_tablesize to %d from %d\n", 2622496af39SMoore, Eric Dean ioc->name, numSGE, sh->sg_tablesize)); 2632496af39SMoore, Eric Dean sh->sg_tablesize = numSGE; 2642496af39SMoore, Eric Dean } 2652496af39SMoore, Eric Dean 2662496af39SMoore, Eric Dean /* Set the pci device pointer in Scsi_Host structure. 2672496af39SMoore, Eric Dean */ 2682496af39SMoore, Eric Dean scsi_set_device(sh, &ioc->pcidev->dev); 2692496af39SMoore, Eric Dean 2702496af39SMoore, Eric Dean spin_unlock_irqrestore(&ioc->FreeQlock, flags); 2712496af39SMoore, Eric Dean 2722496af39SMoore, Eric Dean hd = (MPT_SCSI_HOST *) sh->hostdata; 2732496af39SMoore, Eric Dean hd->ioc = ioc; 2742496af39SMoore, Eric Dean 2752496af39SMoore, Eric Dean /* SCSI needs scsi_cmnd lookup table! 2762496af39SMoore, Eric Dean * (with size equal to req_depth*PtrSz!) 2772496af39SMoore, Eric Dean */ 2782496af39SMoore, Eric Dean sz = ioc->req_depth * sizeof(void *); 2792496af39SMoore, Eric Dean mem = kmalloc(sz, GFP_ATOMIC); 2802496af39SMoore, Eric Dean if (mem == NULL) { 2812496af39SMoore, Eric Dean error = -ENOMEM; 2822496af39SMoore, Eric Dean goto mptfc_probe_failed; 2832496af39SMoore, Eric Dean } 2842496af39SMoore, Eric Dean 2852496af39SMoore, Eric Dean memset(mem, 0, sz); 2862496af39SMoore, Eric Dean hd->ScsiLookup = (struct scsi_cmnd **) mem; 2872496af39SMoore, Eric Dean 2882496af39SMoore, Eric Dean dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", 2892496af39SMoore, Eric Dean ioc->name, hd->ScsiLookup, sz)); 2902496af39SMoore, Eric Dean 2912496af39SMoore, Eric Dean /* Allocate memory for the device structures. 2922496af39SMoore, Eric Dean * A non-Null pointer at an offset 2932496af39SMoore, Eric Dean * indicates a device exists. 2942496af39SMoore, Eric Dean * max_id = 1 + maximum id (hosts.h) 2952496af39SMoore, Eric Dean */ 2962496af39SMoore, Eric Dean sz = sh->max_id * sizeof(void *); 2972496af39SMoore, Eric Dean mem = kmalloc(sz, GFP_ATOMIC); 2982496af39SMoore, Eric Dean if (mem == NULL) { 2992496af39SMoore, Eric Dean error = -ENOMEM; 3002496af39SMoore, Eric Dean goto mptfc_probe_failed; 3012496af39SMoore, Eric Dean } 3022496af39SMoore, Eric Dean 3032496af39SMoore, Eric Dean memset(mem, 0, sz); 3042496af39SMoore, Eric Dean hd->Targets = (VirtDevice **) mem; 3052496af39SMoore, Eric Dean 3062496af39SMoore, Eric Dean dprintk((KERN_INFO 3072496af39SMoore, Eric Dean " Targets @ %p, sz=%d\n", hd->Targets, sz)); 3082496af39SMoore, Eric Dean 3092496af39SMoore, Eric Dean /* Clear the TM flags 3102496af39SMoore, Eric Dean */ 3112496af39SMoore, Eric Dean hd->tmPending = 0; 3122496af39SMoore, Eric Dean hd->tmState = TM_STATE_NONE; 3132496af39SMoore, Eric Dean hd->resetPending = 0; 3142496af39SMoore, Eric Dean hd->abortSCpnt = NULL; 3152496af39SMoore, Eric Dean 3162496af39SMoore, Eric Dean /* Clear the pointer used to store 3172496af39SMoore, Eric Dean * single-threaded commands, i.e., those 3182496af39SMoore, Eric Dean * issued during a bus scan, dv and 3192496af39SMoore, Eric Dean * configuration pages. 3202496af39SMoore, Eric Dean */ 3212496af39SMoore, Eric Dean hd->cmdPtr = NULL; 3222496af39SMoore, Eric Dean 3232496af39SMoore, Eric Dean /* Initialize this SCSI Hosts' timers 3242496af39SMoore, Eric Dean * To use, set the timer expires field 3252496af39SMoore, Eric Dean * and add_timer 3262496af39SMoore, Eric Dean */ 3272496af39SMoore, Eric Dean init_timer(&hd->timer); 3282496af39SMoore, Eric Dean hd->timer.data = (unsigned long) hd; 3292496af39SMoore, Eric Dean hd->timer.function = mptscsih_timer_expired; 3302496af39SMoore, Eric Dean 3312496af39SMoore, Eric Dean hd->mpt_pq_filter = mpt_pq_filter; 3322496af39SMoore, Eric Dean 3332496af39SMoore, Eric Dean ddvprintk((MYIOC_s_INFO_FMT 3342496af39SMoore, Eric Dean "mpt_pq_filter %x\n", 3352496af39SMoore, Eric Dean ioc->name, 3362496af39SMoore, Eric Dean mpt_pq_filter)); 3372496af39SMoore, Eric Dean 3382496af39SMoore, Eric Dean init_waitqueue_head(&hd->scandv_waitq); 3392496af39SMoore, Eric Dean hd->scandv_wait_done = 0; 3402496af39SMoore, Eric Dean hd->last_queue_full = 0; 3412496af39SMoore, Eric Dean 3422496af39SMoore, Eric Dean error = scsi_add_host (sh, &ioc->pcidev->dev); 3432496af39SMoore, Eric Dean if(error) { 3442496af39SMoore, Eric Dean dprintk((KERN_ERR MYNAM 3452496af39SMoore, Eric Dean "scsi_add_host failed\n")); 3462496af39SMoore, Eric Dean goto mptfc_probe_failed; 3472496af39SMoore, Eric Dean } 3482496af39SMoore, Eric Dean 3492496af39SMoore, Eric Dean scsi_scan_host(sh); 3502496af39SMoore, Eric Dean return 0; 3512496af39SMoore, Eric Dean 3522496af39SMoore, Eric Dean mptfc_probe_failed: 3532496af39SMoore, Eric Dean 3542496af39SMoore, Eric Dean mptscsih_remove(pdev); 3552496af39SMoore, Eric Dean return error; 3562496af39SMoore, Eric Dean } 3572496af39SMoore, Eric Dean 3582496af39SMoore, Eric Dean static struct pci_driver mptfc_driver = { 3592496af39SMoore, Eric Dean .name = "mptfc", 3602496af39SMoore, Eric Dean .id_table = mptfc_pci_table, 3612496af39SMoore, Eric Dean .probe = mptfc_probe, 3622496af39SMoore, Eric Dean .remove = __devexit_p(mptscsih_remove), 3632496af39SMoore, Eric Dean .driver = { 3642496af39SMoore, Eric Dean .shutdown = mptscsih_shutdown, 3652496af39SMoore, Eric Dean }, 3662496af39SMoore, Eric Dean #ifdef CONFIG_PM 3672496af39SMoore, Eric Dean .suspend = mptscsih_suspend, 3682496af39SMoore, Eric Dean .resume = mptscsih_resume, 3692496af39SMoore, Eric Dean #endif 3702496af39SMoore, Eric Dean }; 3712496af39SMoore, Eric Dean 3722496af39SMoore, Eric Dean /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 3732496af39SMoore, Eric Dean /** 3742496af39SMoore, Eric Dean * mptfc_init - Register MPT adapter(s) as SCSI host(s) with 3752496af39SMoore, Eric Dean * linux scsi mid-layer. 3762496af39SMoore, Eric Dean * 3772496af39SMoore, Eric Dean * Returns 0 for success, non-zero for failure. 3782496af39SMoore, Eric Dean */ 3792496af39SMoore, Eric Dean static int __init 3802496af39SMoore, Eric Dean mptfc_init(void) 3812496af39SMoore, Eric Dean { 3822496af39SMoore, Eric Dean 3832496af39SMoore, Eric Dean show_mptmod_ver(my_NAME, my_VERSION); 3842496af39SMoore, Eric Dean 3852496af39SMoore, Eric Dean mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER); 3862496af39SMoore, Eric Dean mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER); 3872496af39SMoore, Eric Dean mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER); 3882496af39SMoore, Eric Dean 3892496af39SMoore, Eric Dean if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) { 3902496af39SMoore, Eric Dean devtprintk((KERN_INFO MYNAM 3912496af39SMoore, Eric Dean ": Registered for IOC event notifications\n")); 3922496af39SMoore, Eric Dean } 3932496af39SMoore, Eric Dean 3942496af39SMoore, Eric Dean if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) { 3952496af39SMoore, Eric Dean dprintk((KERN_INFO MYNAM 3962496af39SMoore, Eric Dean ": Registered for IOC reset notifications\n")); 3972496af39SMoore, Eric Dean } 3982496af39SMoore, Eric Dean 3992496af39SMoore, Eric Dean return pci_register_driver(&mptfc_driver); 4002496af39SMoore, Eric Dean } 4012496af39SMoore, Eric Dean 4022496af39SMoore, Eric Dean /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 4032496af39SMoore, Eric Dean /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 4042496af39SMoore, Eric Dean /** 4052496af39SMoore, Eric Dean * mptfc_exit - Unregisters MPT adapter(s) 4062496af39SMoore, Eric Dean * 4072496af39SMoore, Eric Dean */ 4082496af39SMoore, Eric Dean static void __exit 4092496af39SMoore, Eric Dean mptfc_exit(void) 4102496af39SMoore, Eric Dean { 4112496af39SMoore, Eric Dean pci_unregister_driver(&mptfc_driver); 4122496af39SMoore, Eric Dean 4132496af39SMoore, Eric Dean mpt_reset_deregister(mptfcDoneCtx); 4142496af39SMoore, Eric Dean dprintk((KERN_INFO MYNAM 4152496af39SMoore, Eric Dean ": Deregistered for IOC reset notifications\n")); 4162496af39SMoore, Eric Dean 4172496af39SMoore, Eric Dean mpt_event_deregister(mptfcDoneCtx); 4182496af39SMoore, Eric Dean dprintk((KERN_INFO MYNAM 4192496af39SMoore, Eric Dean ": Deregistered for IOC event notifications\n")); 4202496af39SMoore, Eric Dean 4212496af39SMoore, Eric Dean mpt_deregister(mptfcInternalCtx); 4222496af39SMoore, Eric Dean mpt_deregister(mptfcTaskCtx); 4232496af39SMoore, Eric Dean mpt_deregister(mptfcDoneCtx); 4242496af39SMoore, Eric Dean } 4252496af39SMoore, Eric Dean 4262496af39SMoore, Eric Dean module_init(mptfc_init); 4272496af39SMoore, Eric Dean module_exit(mptfc_exit); 428