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