xref: /openbmc/linux/drivers/message/fusion/mptfc.c (revision 2496af3945bdcc5fe774b8220a415086a47f40a0)
1*2496af39SMoore, Eric Dean  /*
2*2496af39SMoore, Eric Dean   *  linux/drivers/message/fusion/mptfc.c
3*2496af39SMoore, Eric Dean   *      For use with LSI Logic PCI chip/adapter(s)
4*2496af39SMoore, Eric Dean   *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
5*2496af39SMoore, Eric Dean   *
6*2496af39SMoore, Eric Dean   *  Copyright (c) 1999-2005 LSI Logic Corporation
7*2496af39SMoore, Eric Dean   *  (mailto:mpt_linux_developer@lsil.com)
8*2496af39SMoore, Eric Dean   *
9*2496af39SMoore, Eric Dean   */
10*2496af39SMoore, Eric Dean  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11*2496af39SMoore, Eric Dean  /*
12*2496af39SMoore, Eric Dean      This program is free software; you can redistribute it and/or modify
13*2496af39SMoore, Eric Dean      it under the terms of the GNU General Public License as published by
14*2496af39SMoore, Eric Dean      the Free Software Foundation; version 2 of the License.
15*2496af39SMoore, Eric Dean  
16*2496af39SMoore, Eric Dean      This program is distributed in the hope that it will be useful,
17*2496af39SMoore, Eric Dean      but WITHOUT ANY WARRANTY; without even the implied warranty of
18*2496af39SMoore, Eric Dean      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19*2496af39SMoore, Eric Dean      GNU General Public License for more details.
20*2496af39SMoore, Eric Dean  
21*2496af39SMoore, Eric Dean      NO WARRANTY
22*2496af39SMoore, Eric Dean      THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
23*2496af39SMoore, Eric Dean      CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
24*2496af39SMoore, Eric Dean      LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
25*2496af39SMoore, Eric Dean      MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
26*2496af39SMoore, Eric Dean      solely responsible for determining the appropriateness of using and
27*2496af39SMoore, Eric Dean      distributing the Program and assumes all risks associated with its
28*2496af39SMoore, Eric Dean      exercise of rights under this Agreement, including but not limited to
29*2496af39SMoore, Eric Dean      the risks and costs of program errors, damage to or loss of data,
30*2496af39SMoore, Eric Dean      programs or equipment, and unavailability or interruption of operations.
31*2496af39SMoore, Eric Dean  
32*2496af39SMoore, Eric Dean      DISCLAIMER OF LIABILITY
33*2496af39SMoore, Eric Dean      NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
34*2496af39SMoore, Eric Dean      DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35*2496af39SMoore, Eric Dean      DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
36*2496af39SMoore, Eric Dean      ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37*2496af39SMoore, Eric Dean      TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38*2496af39SMoore, Eric Dean      USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
39*2496af39SMoore, Eric Dean      HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
40*2496af39SMoore, Eric Dean  
41*2496af39SMoore, Eric Dean      You should have received a copy of the GNU General Public License
42*2496af39SMoore, Eric Dean      along with this program; if not, write to the Free Software
43*2496af39SMoore, Eric Dean      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
44*2496af39SMoore, Eric Dean  */
45*2496af39SMoore, Eric Dean  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
46*2496af39SMoore, Eric Dean  #include "linux_compat.h"	/* linux-2.6 tweaks */
47*2496af39SMoore, Eric Dean  #include <linux/module.h>
48*2496af39SMoore, Eric Dean  #include <linux/kernel.h>
49*2496af39SMoore, Eric Dean  #include <linux/init.h>
50*2496af39SMoore, Eric Dean  #include <linux/errno.h>
51*2496af39SMoore, Eric Dean  #include <linux/kdev_t.h>
52*2496af39SMoore, Eric Dean  #include <linux/blkdev.h>
53*2496af39SMoore, Eric Dean  #include <linux/delay.h>	/* for mdelay */
54*2496af39SMoore, Eric Dean  #include <linux/interrupt.h>	/* needed for in_interrupt() proto */
55*2496af39SMoore, Eric Dean  #include <linux/reboot.h>	/* notifier code */
56*2496af39SMoore, Eric Dean  #include <linux/sched.h>
57*2496af39SMoore, Eric Dean  #include <linux/workqueue.h>
58*2496af39SMoore, Eric Dean  
59*2496af39SMoore, Eric Dean  #include <scsi/scsi.h>
60*2496af39SMoore, Eric Dean  #include <scsi/scsi_cmnd.h>
61*2496af39SMoore, Eric Dean  #include <scsi/scsi_device.h>
62*2496af39SMoore, Eric Dean  #include <scsi/scsi_host.h>
63*2496af39SMoore, Eric Dean  #include <scsi/scsi_tcq.h>
64*2496af39SMoore, Eric Dean  
65*2496af39SMoore, Eric Dean  #include "mptbase.h"
66*2496af39SMoore, Eric Dean  #include "mptscsih.h"
67*2496af39SMoore, Eric Dean  
68*2496af39SMoore, Eric Dean  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
69*2496af39SMoore, Eric Dean  #define my_NAME		"Fusion MPT FC Host driver"
70*2496af39SMoore, Eric Dean  #define my_VERSION	MPT_LINUX_VERSION_COMMON
71*2496af39SMoore, Eric Dean  #define MYNAM		"mptfc"
72*2496af39SMoore, Eric Dean  
73*2496af39SMoore, Eric Dean  MODULE_AUTHOR(MODULEAUTHOR);
74*2496af39SMoore, Eric Dean  MODULE_DESCRIPTION(my_NAME);
75*2496af39SMoore, Eric Dean  MODULE_LICENSE("GPL");
76*2496af39SMoore, Eric Dean  
77*2496af39SMoore, Eric Dean  /* Command line args */
78*2496af39SMoore, Eric Dean  static int mpt_pq_filter = 0;
79*2496af39SMoore, Eric Dean  module_param(mpt_pq_filter, int, 0);
80*2496af39SMoore, Eric Dean  MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1  (default=0)");
81*2496af39SMoore, Eric Dean  
82*2496af39SMoore, Eric Dean  static int	mptfcDoneCtx = -1;
83*2496af39SMoore, Eric Dean  static int	mptfcTaskCtx = -1;
84*2496af39SMoore, Eric Dean  static int	mptfcInternalCtx = -1; /* Used only for internal commands */
85*2496af39SMoore, Eric Dean  
86*2496af39SMoore, Eric Dean  static struct device_attribute mptfc_queue_depth_attr = {
87*2496af39SMoore, Eric Dean  	.attr = {
88*2496af39SMoore, Eric Dean  		.name = 	"queue_depth",
89*2496af39SMoore, Eric Dean  		.mode =		S_IWUSR,
90*2496af39SMoore, Eric Dean  	},
91*2496af39SMoore, Eric Dean  	.store = mptscsih_store_queue_depth,
92*2496af39SMoore, Eric Dean  };
93*2496af39SMoore, Eric Dean  
94*2496af39SMoore, Eric Dean  static struct device_attribute *mptfc_dev_attrs[] = {
95*2496af39SMoore, Eric Dean  	&mptfc_queue_depth_attr,
96*2496af39SMoore, Eric Dean  	NULL,
97*2496af39SMoore, Eric Dean  };
98*2496af39SMoore, Eric Dean  
99*2496af39SMoore, Eric Dean  static struct scsi_host_template mptfc_driver_template = {
100*2496af39SMoore, Eric Dean  	.proc_name			= "mptfc",
101*2496af39SMoore, Eric Dean  	.proc_info			= mptscsih_proc_info,
102*2496af39SMoore, Eric Dean  	.name				= "MPT FC Host",
103*2496af39SMoore, Eric Dean  	.info				= mptscsih_info,
104*2496af39SMoore, Eric Dean  	.queuecommand			= mptscsih_qcmd,
105*2496af39SMoore, Eric Dean  	.slave_alloc			= mptscsih_slave_alloc,
106*2496af39SMoore, Eric Dean  	.slave_configure		= mptscsih_slave_configure,
107*2496af39SMoore, Eric Dean  	.slave_destroy			= mptscsih_slave_destroy,
108*2496af39SMoore, Eric Dean  	.eh_abort_handler		= mptscsih_abort,
109*2496af39SMoore, Eric Dean  	.eh_device_reset_handler	= mptscsih_dev_reset,
110*2496af39SMoore, Eric Dean  	.eh_bus_reset_handler		= mptscsih_bus_reset,
111*2496af39SMoore, Eric Dean  	.eh_host_reset_handler		= mptscsih_host_reset,
112*2496af39SMoore, Eric Dean  	.bios_param			= mptscsih_bios_param,
113*2496af39SMoore, Eric Dean  	.can_queue			= MPT_FC_CAN_QUEUE,
114*2496af39SMoore, Eric Dean  	.this_id			= -1,
115*2496af39SMoore, Eric Dean  	.sg_tablesize			= MPT_SCSI_SG_DEPTH,
116*2496af39SMoore, Eric Dean  	.max_sectors			= 8192,
117*2496af39SMoore, Eric Dean  	.cmd_per_lun			= 7,
118*2496af39SMoore, Eric Dean  	.use_clustering			= ENABLE_CLUSTERING,
119*2496af39SMoore, Eric Dean  	.sdev_attrs			= mptfc_dev_attrs,
120*2496af39SMoore, Eric Dean  };
121*2496af39SMoore, Eric Dean  
122*2496af39SMoore, Eric Dean  /****************************************************************************
123*2496af39SMoore, Eric Dean   * Supported hardware
124*2496af39SMoore, Eric Dean   */
125*2496af39SMoore, Eric Dean  
126*2496af39SMoore, Eric Dean  static struct pci_device_id mptfc_pci_table[] = {
127*2496af39SMoore, Eric Dean  	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909,
128*2496af39SMoore, Eric Dean  		PCI_ANY_ID, PCI_ANY_ID },
129*2496af39SMoore, Eric Dean  	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919,
130*2496af39SMoore, Eric Dean  		PCI_ANY_ID, PCI_ANY_ID },
131*2496af39SMoore, Eric Dean  	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929,
132*2496af39SMoore, Eric Dean  		PCI_ANY_ID, PCI_ANY_ID },
133*2496af39SMoore, Eric Dean  	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X,
134*2496af39SMoore, Eric Dean  		PCI_ANY_ID, PCI_ANY_ID },
135*2496af39SMoore, Eric Dean  	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X,
136*2496af39SMoore, Eric Dean  		PCI_ANY_ID, PCI_ANY_ID },
137*2496af39SMoore, Eric Dean  	{0}	/* Terminating entry */
138*2496af39SMoore, Eric Dean  };
139*2496af39SMoore, Eric Dean  MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
140*2496af39SMoore, Eric Dean  
141*2496af39SMoore, Eric Dean  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
142*2496af39SMoore, Eric Dean  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
143*2496af39SMoore, Eric Dean  /*
144*2496af39SMoore, Eric Dean   *	mptfc_probe - Installs scsi devices per bus.
145*2496af39SMoore, Eric Dean   *	@pdev: Pointer to pci_dev structure
146*2496af39SMoore, Eric Dean   *
147*2496af39SMoore, Eric Dean   *	Returns 0 for success, non-zero for failure.
148*2496af39SMoore, Eric Dean   *
149*2496af39SMoore, Eric Dean   */
150*2496af39SMoore, Eric Dean  static int
151*2496af39SMoore, Eric Dean  mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
152*2496af39SMoore, Eric Dean  {
153*2496af39SMoore, Eric Dean  	struct Scsi_Host	*sh;
154*2496af39SMoore, Eric Dean  	MPT_SCSI_HOST		*hd;
155*2496af39SMoore, Eric Dean  	MPT_ADAPTER 		*ioc;
156*2496af39SMoore, Eric Dean  	unsigned long		 flags;
157*2496af39SMoore, Eric Dean  	int			 sz, ii;
158*2496af39SMoore, Eric Dean  	int			 numSGE = 0;
159*2496af39SMoore, Eric Dean  	int			 scale;
160*2496af39SMoore, Eric Dean  	int			 ioc_cap;
161*2496af39SMoore, Eric Dean  	u8			*mem;
162*2496af39SMoore, Eric Dean  	int			error=0;
163*2496af39SMoore, Eric Dean  	int			r;
164*2496af39SMoore, Eric Dean  
165*2496af39SMoore, Eric Dean  	if ((r = mpt_attach(pdev,id)) != 0)
166*2496af39SMoore, Eric Dean  		return r;
167*2496af39SMoore, Eric Dean  
168*2496af39SMoore, Eric Dean  	ioc = pci_get_drvdata(pdev);
169*2496af39SMoore, Eric Dean  
170*2496af39SMoore, Eric Dean  	/*  Added sanity check on readiness of the MPT adapter.
171*2496af39SMoore, Eric Dean  	 */
172*2496af39SMoore, Eric Dean  	if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
173*2496af39SMoore, Eric Dean  		printk(MYIOC_s_WARN_FMT
174*2496af39SMoore, Eric Dean  		  "Skipping because it's not operational!\n",
175*2496af39SMoore, Eric Dean  		  ioc->name);
176*2496af39SMoore, Eric Dean  		return -ENODEV;
177*2496af39SMoore, Eric Dean  	}
178*2496af39SMoore, Eric Dean  
179*2496af39SMoore, Eric Dean  	if (!ioc->active) {
180*2496af39SMoore, Eric Dean  		printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
181*2496af39SMoore, Eric Dean  		  ioc->name);
182*2496af39SMoore, Eric Dean  		return -ENODEV;
183*2496af39SMoore, Eric Dean  	}
184*2496af39SMoore, Eric Dean  
185*2496af39SMoore, Eric Dean  	/*  Sanity check - ensure at least 1 port is INITIATOR capable
186*2496af39SMoore, Eric Dean  	 */
187*2496af39SMoore, Eric Dean  	ioc_cap = 0;
188*2496af39SMoore, Eric Dean  	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
189*2496af39SMoore, Eric Dean  		if (ioc->pfacts[ii].ProtocolFlags &
190*2496af39SMoore, Eric Dean  		    MPI_PORTFACTS_PROTOCOL_INITIATOR)
191*2496af39SMoore, Eric Dean  			ioc_cap ++;
192*2496af39SMoore, Eric Dean  	}
193*2496af39SMoore, Eric Dean  
194*2496af39SMoore, Eric Dean  	if (!ioc_cap) {
195*2496af39SMoore, Eric Dean  		printk(MYIOC_s_WARN_FMT
196*2496af39SMoore, Eric Dean  			"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
197*2496af39SMoore, Eric Dean  			ioc->name, ioc);
198*2496af39SMoore, Eric Dean  		return -ENODEV;
199*2496af39SMoore, Eric Dean  	}
200*2496af39SMoore, Eric Dean  
201*2496af39SMoore, Eric Dean  	sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
202*2496af39SMoore, Eric Dean  
203*2496af39SMoore, Eric Dean  	if (!sh) {
204*2496af39SMoore, Eric Dean  		printk(MYIOC_s_WARN_FMT
205*2496af39SMoore, Eric Dean  			"Unable to register controller with SCSI subsystem\n",
206*2496af39SMoore, Eric Dean  			ioc->name);
207*2496af39SMoore, Eric Dean                  return -1;
208*2496af39SMoore, Eric Dean          }
209*2496af39SMoore, Eric Dean  
210*2496af39SMoore, Eric Dean  	spin_lock_irqsave(&ioc->FreeQlock, flags);
211*2496af39SMoore, Eric Dean  
212*2496af39SMoore, Eric Dean  	/* Attach the SCSI Host to the IOC structure
213*2496af39SMoore, Eric Dean  	 */
214*2496af39SMoore, Eric Dean  	ioc->sh = sh;
215*2496af39SMoore, Eric Dean  
216*2496af39SMoore, Eric Dean  	sh->io_port = 0;
217*2496af39SMoore, Eric Dean  	sh->n_io_port = 0;
218*2496af39SMoore, Eric Dean  	sh->irq = 0;
219*2496af39SMoore, Eric Dean  
220*2496af39SMoore, Eric Dean  	/* set 16 byte cdb's */
221*2496af39SMoore, Eric Dean  	sh->max_cmd_len = 16;
222*2496af39SMoore, Eric Dean  
223*2496af39SMoore, Eric Dean  	sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
224*2496af39SMoore, Eric Dean  
225*2496af39SMoore, Eric Dean  	sh->max_lun = MPT_LAST_LUN + 1;
226*2496af39SMoore, Eric Dean  	sh->max_channel = 0;
227*2496af39SMoore, Eric Dean  	sh->this_id = ioc->pfacts[0].PortSCSIID;
228*2496af39SMoore, Eric Dean  
229*2496af39SMoore, Eric Dean  	/* Required entry.
230*2496af39SMoore, Eric Dean  	 */
231*2496af39SMoore, Eric Dean  	sh->unique_id = ioc->id;
232*2496af39SMoore, Eric Dean  
233*2496af39SMoore, Eric Dean  	/* Verify that we won't exceed the maximum
234*2496af39SMoore, Eric Dean  	 * number of chain buffers
235*2496af39SMoore, Eric Dean  	 * We can optimize:  ZZ = req_sz/sizeof(SGE)
236*2496af39SMoore, Eric Dean  	 * For 32bit SGE's:
237*2496af39SMoore, Eric Dean  	 *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
238*2496af39SMoore, Eric Dean  	 *               + (req_sz - 64)/sizeof(SGE)
239*2496af39SMoore, Eric Dean  	 * A slightly different algorithm is required for
240*2496af39SMoore, Eric Dean  	 * 64bit SGEs.
241*2496af39SMoore, Eric Dean  	 */
242*2496af39SMoore, Eric Dean  	scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
243*2496af39SMoore, Eric Dean  	if (sizeof(dma_addr_t) == sizeof(u64)) {
244*2496af39SMoore, Eric Dean  		numSGE = (scale - 1) *
245*2496af39SMoore, Eric Dean  		  (ioc->facts.MaxChainDepth-1) + scale +
246*2496af39SMoore, Eric Dean  		  (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
247*2496af39SMoore, Eric Dean  		  sizeof(u32));
248*2496af39SMoore, Eric Dean  	} else {
249*2496af39SMoore, Eric Dean  		numSGE = 1 + (scale - 1) *
250*2496af39SMoore, Eric Dean  		  (ioc->facts.MaxChainDepth-1) + scale +
251*2496af39SMoore, Eric Dean  		  (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
252*2496af39SMoore, Eric Dean  		  sizeof(u32));
253*2496af39SMoore, Eric Dean  	}
254*2496af39SMoore, Eric Dean  
255*2496af39SMoore, Eric Dean  	if (numSGE < sh->sg_tablesize) {
256*2496af39SMoore, Eric Dean  		/* Reset this value */
257*2496af39SMoore, Eric Dean  		dprintk((MYIOC_s_INFO_FMT
258*2496af39SMoore, Eric Dean  		  "Resetting sg_tablesize to %d from %d\n",
259*2496af39SMoore, Eric Dean  		  ioc->name, numSGE, sh->sg_tablesize));
260*2496af39SMoore, Eric Dean  		sh->sg_tablesize = numSGE;
261*2496af39SMoore, Eric Dean  	}
262*2496af39SMoore, Eric Dean  
263*2496af39SMoore, Eric Dean  	/* Set the pci device pointer in Scsi_Host structure.
264*2496af39SMoore, Eric Dean  	 */
265*2496af39SMoore, Eric Dean  	scsi_set_device(sh, &ioc->pcidev->dev);
266*2496af39SMoore, Eric Dean  
267*2496af39SMoore, Eric Dean  	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
268*2496af39SMoore, Eric Dean  
269*2496af39SMoore, Eric Dean  	hd = (MPT_SCSI_HOST *) sh->hostdata;
270*2496af39SMoore, Eric Dean  	hd->ioc = ioc;
271*2496af39SMoore, Eric Dean  
272*2496af39SMoore, Eric Dean  	/* SCSI needs scsi_cmnd lookup table!
273*2496af39SMoore, Eric Dean  	 * (with size equal to req_depth*PtrSz!)
274*2496af39SMoore, Eric Dean  	 */
275*2496af39SMoore, Eric Dean  	sz = ioc->req_depth * sizeof(void *);
276*2496af39SMoore, Eric Dean  	mem = kmalloc(sz, GFP_ATOMIC);
277*2496af39SMoore, Eric Dean  	if (mem == NULL) {
278*2496af39SMoore, Eric Dean  		error = -ENOMEM;
279*2496af39SMoore, Eric Dean  		goto mptfc_probe_failed;
280*2496af39SMoore, Eric Dean  	}
281*2496af39SMoore, Eric Dean  
282*2496af39SMoore, Eric Dean  	memset(mem, 0, sz);
283*2496af39SMoore, Eric Dean  	hd->ScsiLookup = (struct scsi_cmnd **) mem;
284*2496af39SMoore, Eric Dean  
285*2496af39SMoore, Eric Dean  	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
286*2496af39SMoore, Eric Dean  		 ioc->name, hd->ScsiLookup, sz));
287*2496af39SMoore, Eric Dean  
288*2496af39SMoore, Eric Dean  	/* Allocate memory for the device structures.
289*2496af39SMoore, Eric Dean  	 * A non-Null pointer at an offset
290*2496af39SMoore, Eric Dean  	 * indicates a device exists.
291*2496af39SMoore, Eric Dean  	 * max_id = 1 + maximum id (hosts.h)
292*2496af39SMoore, Eric Dean  	 */
293*2496af39SMoore, Eric Dean  	sz = sh->max_id * sizeof(void *);
294*2496af39SMoore, Eric Dean  	mem = kmalloc(sz, GFP_ATOMIC);
295*2496af39SMoore, Eric Dean  	if (mem == NULL) {
296*2496af39SMoore, Eric Dean  		error = -ENOMEM;
297*2496af39SMoore, Eric Dean  		goto mptfc_probe_failed;
298*2496af39SMoore, Eric Dean  	}
299*2496af39SMoore, Eric Dean  
300*2496af39SMoore, Eric Dean  	memset(mem, 0, sz);
301*2496af39SMoore, Eric Dean  	hd->Targets = (VirtDevice **) mem;
302*2496af39SMoore, Eric Dean  
303*2496af39SMoore, Eric Dean  	dprintk((KERN_INFO
304*2496af39SMoore, Eric Dean  	  "  Targets @ %p, sz=%d\n", hd->Targets, sz));
305*2496af39SMoore, Eric Dean  
306*2496af39SMoore, Eric Dean  	/* Clear the TM flags
307*2496af39SMoore, Eric Dean  	 */
308*2496af39SMoore, Eric Dean  	hd->tmPending = 0;
309*2496af39SMoore, Eric Dean  	hd->tmState = TM_STATE_NONE;
310*2496af39SMoore, Eric Dean  	hd->resetPending = 0;
311*2496af39SMoore, Eric Dean  	hd->abortSCpnt = NULL;
312*2496af39SMoore, Eric Dean  
313*2496af39SMoore, Eric Dean  	/* Clear the pointer used to store
314*2496af39SMoore, Eric Dean  	 * single-threaded commands, i.e., those
315*2496af39SMoore, Eric Dean  	 * issued during a bus scan, dv and
316*2496af39SMoore, Eric Dean  	 * configuration pages.
317*2496af39SMoore, Eric Dean  	 */
318*2496af39SMoore, Eric Dean  	hd->cmdPtr = NULL;
319*2496af39SMoore, Eric Dean  
320*2496af39SMoore, Eric Dean  	/* Initialize this SCSI Hosts' timers
321*2496af39SMoore, Eric Dean  	 * To use, set the timer expires field
322*2496af39SMoore, Eric Dean  	 * and add_timer
323*2496af39SMoore, Eric Dean  	 */
324*2496af39SMoore, Eric Dean  	init_timer(&hd->timer);
325*2496af39SMoore, Eric Dean  	hd->timer.data = (unsigned long) hd;
326*2496af39SMoore, Eric Dean  	hd->timer.function = mptscsih_timer_expired;
327*2496af39SMoore, Eric Dean  
328*2496af39SMoore, Eric Dean  	ioc->DoneCtx = mptfcDoneCtx;
329*2496af39SMoore, Eric Dean  	ioc->TaskCtx = mptfcTaskCtx;
330*2496af39SMoore, Eric Dean  	ioc->InternalCtx = mptfcInternalCtx;
331*2496af39SMoore, Eric Dean  
332*2496af39SMoore, Eric Dean  	hd->mpt_pq_filter = mpt_pq_filter;
333*2496af39SMoore, Eric Dean  
334*2496af39SMoore, Eric Dean  	ddvprintk((MYIOC_s_INFO_FMT
335*2496af39SMoore, Eric Dean  		"mpt_pq_filter %x\n",
336*2496af39SMoore, Eric Dean  		ioc->name,
337*2496af39SMoore, Eric Dean  		mpt_pq_filter));
338*2496af39SMoore, Eric Dean  
339*2496af39SMoore, Eric Dean  	init_waitqueue_head(&hd->scandv_waitq);
340*2496af39SMoore, Eric Dean  	hd->scandv_wait_done = 0;
341*2496af39SMoore, Eric Dean  	hd->last_queue_full = 0;
342*2496af39SMoore, Eric Dean  
343*2496af39SMoore, Eric Dean  	error = scsi_add_host (sh, &ioc->pcidev->dev);
344*2496af39SMoore, Eric Dean  	if(error) {
345*2496af39SMoore, Eric Dean  		dprintk((KERN_ERR MYNAM
346*2496af39SMoore, Eric Dean  		  "scsi_add_host failed\n"));
347*2496af39SMoore, Eric Dean  		goto mptfc_probe_failed;
348*2496af39SMoore, Eric Dean  	}
349*2496af39SMoore, Eric Dean  
350*2496af39SMoore, Eric Dean  	scsi_scan_host(sh);
351*2496af39SMoore, Eric Dean  	return 0;
352*2496af39SMoore, Eric Dean  
353*2496af39SMoore, Eric Dean  mptfc_probe_failed:
354*2496af39SMoore, Eric Dean  
355*2496af39SMoore, Eric Dean  	mptscsih_remove(pdev);
356*2496af39SMoore, Eric Dean  	return error;
357*2496af39SMoore, Eric Dean  }
358*2496af39SMoore, Eric Dean  
359*2496af39SMoore, Eric Dean  static struct pci_driver mptfc_driver = {
360*2496af39SMoore, Eric Dean  	.name		= "mptfc",
361*2496af39SMoore, Eric Dean  	.id_table	= mptfc_pci_table,
362*2496af39SMoore, Eric Dean  	.probe		= mptfc_probe,
363*2496af39SMoore, Eric Dean  	.remove		= __devexit_p(mptscsih_remove),
364*2496af39SMoore, Eric Dean  	.driver         = {
365*2496af39SMoore, Eric Dean  		.shutdown = mptscsih_shutdown,
366*2496af39SMoore, Eric Dean          },
367*2496af39SMoore, Eric Dean  #ifdef CONFIG_PM
368*2496af39SMoore, Eric Dean  	.suspend	= mptscsih_suspend,
369*2496af39SMoore, Eric Dean  	.resume		= mptscsih_resume,
370*2496af39SMoore, Eric Dean  #endif
371*2496af39SMoore, Eric Dean  };
372*2496af39SMoore, Eric Dean  
373*2496af39SMoore, Eric Dean  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
374*2496af39SMoore, Eric Dean  /**
375*2496af39SMoore, Eric Dean   *	mptfc_init - Register MPT adapter(s) as SCSI host(s) with
376*2496af39SMoore, Eric Dean   *	linux scsi mid-layer.
377*2496af39SMoore, Eric Dean   *
378*2496af39SMoore, Eric Dean   *	Returns 0 for success, non-zero for failure.
379*2496af39SMoore, Eric Dean   */
380*2496af39SMoore, Eric Dean  static int __init
381*2496af39SMoore, Eric Dean  mptfc_init(void)
382*2496af39SMoore, Eric Dean  {
383*2496af39SMoore, Eric Dean  
384*2496af39SMoore, Eric Dean  	show_mptmod_ver(my_NAME, my_VERSION);
385*2496af39SMoore, Eric Dean  
386*2496af39SMoore, Eric Dean  	mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);
387*2496af39SMoore, Eric Dean  	mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
388*2496af39SMoore, Eric Dean  	mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
389*2496af39SMoore, Eric Dean  
390*2496af39SMoore, Eric Dean  	if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) {
391*2496af39SMoore, Eric Dean  		devtprintk((KERN_INFO MYNAM
392*2496af39SMoore, Eric Dean  		  ": Registered for IOC event notifications\n"));
393*2496af39SMoore, Eric Dean  	}
394*2496af39SMoore, Eric Dean  
395*2496af39SMoore, Eric Dean  	if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) {
396*2496af39SMoore, Eric Dean  		dprintk((KERN_INFO MYNAM
397*2496af39SMoore, Eric Dean  		  ": Registered for IOC reset notifications\n"));
398*2496af39SMoore, Eric Dean  	}
399*2496af39SMoore, Eric Dean  
400*2496af39SMoore, Eric Dean  	return pci_register_driver(&mptfc_driver);
401*2496af39SMoore, Eric Dean  }
402*2496af39SMoore, Eric Dean  
403*2496af39SMoore, Eric Dean  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
404*2496af39SMoore, Eric Dean  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
405*2496af39SMoore, Eric Dean  /**
406*2496af39SMoore, Eric Dean   *	mptfc_exit - Unregisters MPT adapter(s)
407*2496af39SMoore, Eric Dean   *
408*2496af39SMoore, Eric Dean   */
409*2496af39SMoore, Eric Dean  static void __exit
410*2496af39SMoore, Eric Dean  mptfc_exit(void)
411*2496af39SMoore, Eric Dean  {
412*2496af39SMoore, Eric Dean  	pci_unregister_driver(&mptfc_driver);
413*2496af39SMoore, Eric Dean  
414*2496af39SMoore, Eric Dean  	mpt_reset_deregister(mptfcDoneCtx);
415*2496af39SMoore, Eric Dean  	dprintk((KERN_INFO MYNAM
416*2496af39SMoore, Eric Dean  	  ": Deregistered for IOC reset notifications\n"));
417*2496af39SMoore, Eric Dean  
418*2496af39SMoore, Eric Dean  	mpt_event_deregister(mptfcDoneCtx);
419*2496af39SMoore, Eric Dean  	dprintk((KERN_INFO MYNAM
420*2496af39SMoore, Eric Dean  	  ": Deregistered for IOC event notifications\n"));
421*2496af39SMoore, Eric Dean  
422*2496af39SMoore, Eric Dean  	mpt_deregister(mptfcInternalCtx);
423*2496af39SMoore, Eric Dean  	mpt_deregister(mptfcTaskCtx);
424*2496af39SMoore, Eric Dean  	mpt_deregister(mptfcDoneCtx);
425*2496af39SMoore, Eric Dean  }
426*2496af39SMoore, Eric Dean  
427*2496af39SMoore, Eric Dean  module_init(mptfc_init);
428*2496af39SMoore, Eric Dean  module_exit(mptfc_exit);
429