xref: /openbmc/linux/drivers/message/fusion/mptfc.c (revision 466544d8898fc87ed6e2e62ac14af7c50ab7a1a4)
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