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