xref: /openbmc/linux/drivers/message/fusion/mptfc.c (revision 1ca00bb7916cb40b8140173c23481e11d92d6f6a)
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,
93c7c82987SMoore, Eric Dean 	.target_alloc			= mptscsih_target_alloc,
942496af39SMoore, Eric Dean  	.slave_alloc			= mptscsih_slave_alloc,
952496af39SMoore, Eric Dean  	.slave_configure		= mptscsih_slave_configure,
96c7c82987SMoore, 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;
151*1ca00bb7SChristoph Hellwig 	int			 ii;
1522496af39SMoore, Eric Dean  	int			 numSGE = 0;
1532496af39SMoore, Eric Dean  	int			 scale;
1542496af39SMoore, Eric Dean  	int			 ioc_cap;
1552496af39SMoore, Eric Dean  	int			error=0;
1562496af39SMoore, Eric Dean  	int			r;
1572496af39SMoore, Eric Dean  
1582496af39SMoore, Eric Dean  	if ((r = mpt_attach(pdev,id)) != 0)
1592496af39SMoore, Eric Dean  		return r;
1602496af39SMoore, Eric Dean  
1612496af39SMoore, Eric Dean  	ioc = pci_get_drvdata(pdev);
162d335cc38SMoore, Eric Dean  	ioc->DoneCtx = mptfcDoneCtx;
163d335cc38SMoore, Eric Dean  	ioc->TaskCtx = mptfcTaskCtx;
164d335cc38SMoore, Eric Dean  	ioc->InternalCtx = mptfcInternalCtx;
1652496af39SMoore, Eric Dean  
1662496af39SMoore, Eric Dean  	/*  Added sanity check on readiness of the MPT adapter.
1672496af39SMoore, Eric Dean  	 */
1682496af39SMoore, Eric Dean  	if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
1692496af39SMoore, Eric Dean  		printk(MYIOC_s_WARN_FMT
1702496af39SMoore, Eric Dean  		  "Skipping because it's not operational!\n",
1712496af39SMoore, Eric Dean  		  ioc->name);
1727acec1e7SMoore, Eric Dean 		error = -ENODEV;
1737acec1e7SMoore, Eric Dean 		goto out_mptfc_probe;
1742496af39SMoore, Eric Dean  	}
1752496af39SMoore, Eric Dean  
1762496af39SMoore, Eric Dean  	if (!ioc->active) {
1772496af39SMoore, Eric Dean  		printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
1782496af39SMoore, Eric Dean  		  ioc->name);
1797acec1e7SMoore, Eric Dean 		error = -ENODEV;
1807acec1e7SMoore, Eric Dean 		goto out_mptfc_probe;
1812496af39SMoore, Eric Dean  	}
1822496af39SMoore, Eric Dean  
1832496af39SMoore, Eric Dean  	/*  Sanity check - ensure at least 1 port is INITIATOR capable
1842496af39SMoore, Eric Dean  	 */
1852496af39SMoore, Eric Dean  	ioc_cap = 0;
1862496af39SMoore, Eric Dean  	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1872496af39SMoore, Eric Dean  		if (ioc->pfacts[ii].ProtocolFlags &
1882496af39SMoore, Eric Dean  		    MPI_PORTFACTS_PROTOCOL_INITIATOR)
1892496af39SMoore, Eric Dean  			ioc_cap ++;
1902496af39SMoore, Eric Dean  	}
1912496af39SMoore, Eric Dean  
1922496af39SMoore, Eric Dean  	if (!ioc_cap) {
1932496af39SMoore, Eric Dean  		printk(MYIOC_s_WARN_FMT
1942496af39SMoore, Eric Dean  			"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
1952496af39SMoore, Eric Dean  			ioc->name, ioc);
196466544d8SMoore, Eric Dean 		return 0;
1972496af39SMoore, Eric Dean  	}
1982496af39SMoore, Eric Dean  
1992496af39SMoore, Eric Dean  	sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
2002496af39SMoore, Eric Dean  
2012496af39SMoore, Eric Dean  	if (!sh) {
2022496af39SMoore, Eric Dean  		printk(MYIOC_s_WARN_FMT
2032496af39SMoore, Eric Dean  			"Unable to register controller with SCSI subsystem\n",
2042496af39SMoore, Eric Dean  			ioc->name);
2057acec1e7SMoore, Eric Dean 		error = -1;
2067acec1e7SMoore, Eric Dean 		goto out_mptfc_probe;
2072496af39SMoore, Eric Dean          }
2082496af39SMoore, Eric Dean  
2092496af39SMoore, Eric Dean  	spin_lock_irqsave(&ioc->FreeQlock, flags);
2102496af39SMoore, Eric Dean  
2112496af39SMoore, Eric Dean  	/* Attach the SCSI Host to the IOC structure
2122496af39SMoore, Eric Dean  	 */
2132496af39SMoore, Eric Dean  	ioc->sh = sh;
2142496af39SMoore, Eric Dean  
2152496af39SMoore, Eric Dean  	sh->io_port = 0;
2162496af39SMoore, Eric Dean  	sh->n_io_port = 0;
2172496af39SMoore, Eric Dean  	sh->irq = 0;
2182496af39SMoore, Eric Dean  
2192496af39SMoore, Eric Dean  	/* set 16 byte cdb's */
2202496af39SMoore, Eric Dean  	sh->max_cmd_len = 16;
2212496af39SMoore, Eric Dean  
2222496af39SMoore, Eric Dean  	sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
2232496af39SMoore, Eric Dean  
2242496af39SMoore, Eric Dean  	sh->max_lun = MPT_LAST_LUN + 1;
2252496af39SMoore, Eric Dean  	sh->max_channel = 0;
2262496af39SMoore, Eric Dean  	sh->this_id = ioc->pfacts[0].PortSCSIID;
2272496af39SMoore, Eric Dean  
2282496af39SMoore, Eric Dean  	/* Required entry.
2292496af39SMoore, Eric Dean  	 */
2302496af39SMoore, Eric Dean  	sh->unique_id = ioc->id;
2312496af39SMoore, Eric Dean  
2322496af39SMoore, Eric Dean  	/* Verify that we won't exceed the maximum
2332496af39SMoore, Eric Dean  	 * number of chain buffers
2342496af39SMoore, Eric Dean  	 * We can optimize:  ZZ = req_sz/sizeof(SGE)
2352496af39SMoore, Eric Dean  	 * For 32bit SGE's:
2362496af39SMoore, Eric Dean  	 *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
2372496af39SMoore, Eric Dean  	 *               + (req_sz - 64)/sizeof(SGE)
2382496af39SMoore, Eric Dean  	 * A slightly different algorithm is required for
2392496af39SMoore, Eric Dean  	 * 64bit SGEs.
2402496af39SMoore, Eric Dean  	 */
2412496af39SMoore, Eric Dean  	scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
2422496af39SMoore, Eric Dean  	if (sizeof(dma_addr_t) == sizeof(u64)) {
2432496af39SMoore, Eric Dean  		numSGE = (scale - 1) *
2442496af39SMoore, Eric Dean  		  (ioc->facts.MaxChainDepth-1) + scale +
2452496af39SMoore, Eric Dean  		  (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
2462496af39SMoore, Eric Dean  		  sizeof(u32));
2472496af39SMoore, Eric Dean  	} else {
2482496af39SMoore, Eric Dean  		numSGE = 1 + (scale - 1) *
2492496af39SMoore, Eric Dean  		  (ioc->facts.MaxChainDepth-1) + scale +
2502496af39SMoore, Eric Dean  		  (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
2512496af39SMoore, Eric Dean  		  sizeof(u32));
2522496af39SMoore, Eric Dean  	}
2532496af39SMoore, Eric Dean  
2542496af39SMoore, Eric Dean  	if (numSGE < sh->sg_tablesize) {
2552496af39SMoore, Eric Dean  		/* Reset this value */
2562496af39SMoore, Eric Dean  		dprintk((MYIOC_s_INFO_FMT
2572496af39SMoore, Eric Dean  		  "Resetting sg_tablesize to %d from %d\n",
2582496af39SMoore, Eric Dean  		  ioc->name, numSGE, sh->sg_tablesize));
2592496af39SMoore, Eric Dean  		sh->sg_tablesize = numSGE;
2602496af39SMoore, Eric Dean  	}
2612496af39SMoore, Eric Dean  
2622496af39SMoore, Eric Dean  	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2632496af39SMoore, Eric Dean  
2642496af39SMoore, Eric Dean  	hd = (MPT_SCSI_HOST *) sh->hostdata;
2652496af39SMoore, Eric Dean  	hd->ioc = ioc;
2662496af39SMoore, Eric Dean  
2672496af39SMoore, Eric Dean  	/* SCSI needs scsi_cmnd lookup table!
2682496af39SMoore, Eric Dean  	 * (with size equal to req_depth*PtrSz!)
2692496af39SMoore, Eric Dean  	 */
270*1ca00bb7SChristoph Hellwig 	hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
271*1ca00bb7SChristoph Hellwig 	if (!hd->ScsiLookup) {
2722496af39SMoore, Eric Dean  		error = -ENOMEM;
2737acec1e7SMoore, Eric Dean 		goto out_mptfc_probe;
2742496af39SMoore, Eric Dean  	}
2752496af39SMoore, Eric Dean  
276*1ca00bb7SChristoph Hellwig 	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
277*1ca00bb7SChristoph Hellwig 		 ioc->name, hd->ScsiLookup));
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  	 */
284*1ca00bb7SChristoph Hellwig 	hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
285*1ca00bb7SChristoph Hellwig 	if (!hd->Targets) {
2862496af39SMoore, Eric Dean  		error = -ENOMEM;
2877acec1e7SMoore, Eric Dean 		goto out_mptfc_probe;
2882496af39SMoore, Eric Dean  	}
2892496af39SMoore, Eric Dean  
290*1ca00bb7SChristoph Hellwig 	dprintk((KERN_INFO "  vdev @ %p\n", hd->Targets));
2912496af39SMoore, Eric Dean  
2922496af39SMoore, Eric Dean  	/* Clear the TM flags
2932496af39SMoore, Eric Dean  	 */
2942496af39SMoore, Eric Dean  	hd->tmPending = 0;
2952496af39SMoore, Eric Dean  	hd->tmState = TM_STATE_NONE;
2962496af39SMoore, Eric Dean  	hd->resetPending = 0;
2972496af39SMoore, Eric Dean  	hd->abortSCpnt = NULL;
2982496af39SMoore, Eric Dean  
2992496af39SMoore, Eric Dean  	/* Clear the pointer used to store
3002496af39SMoore, Eric Dean  	 * single-threaded commands, i.e., those
3012496af39SMoore, Eric Dean  	 * issued during a bus scan, dv and
3022496af39SMoore, Eric Dean  	 * configuration pages.
3032496af39SMoore, Eric Dean  	 */
3042496af39SMoore, Eric Dean  	hd->cmdPtr = NULL;
3052496af39SMoore, Eric Dean  
3062496af39SMoore, Eric Dean  	/* Initialize this SCSI Hosts' timers
3072496af39SMoore, Eric Dean  	 * To use, set the timer expires field
3082496af39SMoore, Eric Dean  	 * and add_timer
3092496af39SMoore, Eric Dean  	 */
3102496af39SMoore, Eric Dean  	init_timer(&hd->timer);
3112496af39SMoore, Eric Dean  	hd->timer.data = (unsigned long) hd;
3122496af39SMoore, Eric Dean  	hd->timer.function = mptscsih_timer_expired;
3132496af39SMoore, Eric Dean  
3142496af39SMoore, Eric Dean  	hd->mpt_pq_filter = mpt_pq_filter;
3152496af39SMoore, Eric Dean  
3162496af39SMoore, Eric Dean  	ddvprintk((MYIOC_s_INFO_FMT
3172496af39SMoore, Eric Dean  		"mpt_pq_filter %x\n",
3182496af39SMoore, Eric Dean  		ioc->name,
3192496af39SMoore, Eric Dean  		mpt_pq_filter));
3202496af39SMoore, Eric Dean  
3212496af39SMoore, Eric Dean  	init_waitqueue_head(&hd->scandv_waitq);
3222496af39SMoore, Eric Dean  	hd->scandv_wait_done = 0;
3232496af39SMoore, Eric Dean  	hd->last_queue_full = 0;
3242496af39SMoore, Eric Dean  
3252496af39SMoore, Eric Dean  	error = scsi_add_host (sh, &ioc->pcidev->dev);
3262496af39SMoore, Eric Dean  	if(error) {
3272496af39SMoore, Eric Dean  		dprintk((KERN_ERR MYNAM
3282496af39SMoore, Eric Dean  		  "scsi_add_host failed\n"));
3297acec1e7SMoore, Eric Dean 		goto out_mptfc_probe;
3302496af39SMoore, Eric Dean  	}
3312496af39SMoore, Eric Dean  
3322496af39SMoore, Eric Dean  	scsi_scan_host(sh);
3332496af39SMoore, Eric Dean  	return 0;
3342496af39SMoore, Eric Dean  
3357acec1e7SMoore, Eric Dean out_mptfc_probe:
3362496af39SMoore, Eric Dean  
3372496af39SMoore, Eric Dean  	mptscsih_remove(pdev);
3382496af39SMoore, Eric Dean  	return error;
3392496af39SMoore, Eric Dean  }
3402496af39SMoore, Eric Dean  
3412496af39SMoore, Eric Dean  static struct pci_driver mptfc_driver = {
3422496af39SMoore, Eric Dean  	.name		= "mptfc",
3432496af39SMoore, Eric Dean  	.id_table	= mptfc_pci_table,
3442496af39SMoore, Eric Dean  	.probe		= mptfc_probe,
3452496af39SMoore, Eric Dean  	.remove		= __devexit_p(mptscsih_remove),
3462496af39SMoore, Eric Dean  	.shutdown	= mptscsih_shutdown,
3472496af39SMoore, Eric Dean  #ifdef CONFIG_PM
3482496af39SMoore, Eric Dean  	.suspend	= mptscsih_suspend,
3492496af39SMoore, Eric Dean  	.resume		= mptscsih_resume,
3502496af39SMoore, Eric Dean  #endif
3512496af39SMoore, Eric Dean  };
3522496af39SMoore, Eric Dean  
3532496af39SMoore, Eric Dean  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3542496af39SMoore, Eric Dean  /**
3552496af39SMoore, Eric Dean   *	mptfc_init - Register MPT adapter(s) as SCSI host(s) with
3562496af39SMoore, Eric Dean   *	linux scsi mid-layer.
3572496af39SMoore, Eric Dean   *
3582496af39SMoore, Eric Dean   *	Returns 0 for success, non-zero for failure.
3592496af39SMoore, Eric Dean   */
3602496af39SMoore, Eric Dean  static int __init
3612496af39SMoore, Eric Dean  mptfc_init(void)
3622496af39SMoore, Eric Dean  {
3632496af39SMoore, Eric Dean  
3642496af39SMoore, Eric Dean  	show_mptmod_ver(my_NAME, my_VERSION);
3652496af39SMoore, Eric Dean  
3662496af39SMoore, Eric Dean  	mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);
3672496af39SMoore, Eric Dean  	mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
3682496af39SMoore, Eric Dean  	mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
3692496af39SMoore, Eric Dean  
3702496af39SMoore, Eric Dean  	if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) {
3712496af39SMoore, Eric Dean  		devtprintk((KERN_INFO MYNAM
3722496af39SMoore, Eric Dean  		  ": Registered for IOC event notifications\n"));
3732496af39SMoore, Eric Dean  	}
3742496af39SMoore, Eric Dean  
3752496af39SMoore, Eric Dean  	if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) {
3762496af39SMoore, Eric Dean  		dprintk((KERN_INFO MYNAM
3772496af39SMoore, Eric Dean  		  ": Registered for IOC reset notifications\n"));
3782496af39SMoore, Eric Dean  	}
3792496af39SMoore, Eric Dean  
3802496af39SMoore, Eric Dean  	return pci_register_driver(&mptfc_driver);
3812496af39SMoore, Eric Dean  }
3822496af39SMoore, Eric Dean  
3832496af39SMoore, Eric Dean  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3842496af39SMoore, Eric Dean  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3852496af39SMoore, Eric Dean  /**
3862496af39SMoore, Eric Dean   *	mptfc_exit - Unregisters MPT adapter(s)
3872496af39SMoore, Eric Dean   *
3882496af39SMoore, Eric Dean   */
3892496af39SMoore, Eric Dean  static void __exit
3902496af39SMoore, Eric Dean  mptfc_exit(void)
3912496af39SMoore, Eric Dean  {
3922496af39SMoore, Eric Dean  	pci_unregister_driver(&mptfc_driver);
3932496af39SMoore, Eric Dean  
3942496af39SMoore, Eric Dean  	mpt_reset_deregister(mptfcDoneCtx);
3952496af39SMoore, Eric Dean  	dprintk((KERN_INFO MYNAM
3962496af39SMoore, Eric Dean  	  ": Deregistered for IOC reset notifications\n"));
3972496af39SMoore, Eric Dean  
3982496af39SMoore, Eric Dean  	mpt_event_deregister(mptfcDoneCtx);
3992496af39SMoore, Eric Dean  	dprintk((KERN_INFO MYNAM
4002496af39SMoore, Eric Dean  	  ": Deregistered for IOC event notifications\n"));
4012496af39SMoore, Eric Dean  
4022496af39SMoore, Eric Dean  	mpt_deregister(mptfcInternalCtx);
4032496af39SMoore, Eric Dean  	mpt_deregister(mptfcTaskCtx);
4042496af39SMoore, Eric Dean  	mpt_deregister(mptfcDoneCtx);
4052496af39SMoore, Eric Dean  }
4062496af39SMoore, Eric Dean  
4072496af39SMoore, Eric Dean  module_init(mptfc_init);
4082496af39SMoore, Eric Dean  module_exit(mptfc_exit);
409