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