xref: /linux/drivers/message/fusion/mptfc.c (revision d67b569f5f620c0fb95d5212642746b7ba9d29e4)
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 device_attribute mptfc_queue_depth_attr = {
87 	.attr = {
88 		.name = 	"queue_depth",
89 		.mode =		S_IWUSR,
90 	},
91 	.store = mptscsih_store_queue_depth,
92 };
93 
94 static struct device_attribute *mptfc_dev_attrs[] = {
95 	&mptfc_queue_depth_attr,
96 	NULL,
97 };
98 
99 static struct scsi_host_template mptfc_driver_template = {
100 	.proc_name			= "mptfc",
101 	.proc_info			= mptscsih_proc_info,
102 	.name				= "MPT FC Host",
103 	.info				= mptscsih_info,
104 	.queuecommand			= mptscsih_qcmd,
105 	.slave_alloc			= mptscsih_slave_alloc,
106 	.slave_configure		= mptscsih_slave_configure,
107 	.slave_destroy			= mptscsih_slave_destroy,
108 	.eh_abort_handler		= mptscsih_abort,
109 	.eh_device_reset_handler	= mptscsih_dev_reset,
110 	.eh_bus_reset_handler		= mptscsih_bus_reset,
111 	.eh_host_reset_handler		= mptscsih_host_reset,
112 	.bios_param			= mptscsih_bios_param,
113 	.can_queue			= MPT_FC_CAN_QUEUE,
114 	.this_id			= -1,
115 	.sg_tablesize			= MPT_SCSI_SG_DEPTH,
116 	.max_sectors			= 8192,
117 	.cmd_per_lun			= 7,
118 	.use_clustering			= ENABLE_CLUSTERING,
119 	.sdev_attrs			= mptfc_dev_attrs,
120 };
121 
122 /****************************************************************************
123  * Supported hardware
124  */
125 
126 static struct pci_device_id mptfc_pci_table[] = {
127 	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909,
128 		PCI_ANY_ID, PCI_ANY_ID },
129 	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919,
130 		PCI_ANY_ID, PCI_ANY_ID },
131 	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929,
132 		PCI_ANY_ID, PCI_ANY_ID },
133 	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X,
134 		PCI_ANY_ID, PCI_ANY_ID },
135 	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X,
136 		PCI_ANY_ID, PCI_ANY_ID },
137 	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC939X,
138 		PCI_ANY_ID, PCI_ANY_ID },
139 	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X,
140 		PCI_ANY_ID, PCI_ANY_ID },
141 	{0}	/* Terminating entry */
142 };
143 MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
144 
145 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
146 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
147 /*
148  *	mptfc_probe - Installs scsi devices per bus.
149  *	@pdev: Pointer to pci_dev structure
150  *
151  *	Returns 0 for success, non-zero for failure.
152  *
153  */
154 static int
155 mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
156 {
157 	struct Scsi_Host	*sh;
158 	MPT_SCSI_HOST		*hd;
159 	MPT_ADAPTER 		*ioc;
160 	unsigned long		 flags;
161 	int			 sz, ii;
162 	int			 numSGE = 0;
163 	int			 scale;
164 	int			 ioc_cap;
165 	u8			*mem;
166 	int			error=0;
167 	int			r;
168 
169 	if ((r = mpt_attach(pdev,id)) != 0)
170 		return r;
171 
172 	ioc = pci_get_drvdata(pdev);
173 	ioc->DoneCtx = mptfcDoneCtx;
174 	ioc->TaskCtx = mptfcTaskCtx;
175 	ioc->InternalCtx = mptfcInternalCtx;
176 
177 	/*  Added sanity check on readiness of the MPT adapter.
178 	 */
179 	if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
180 		printk(MYIOC_s_WARN_FMT
181 		  "Skipping because it's not operational!\n",
182 		  ioc->name);
183 		return -ENODEV;
184 	}
185 
186 	if (!ioc->active) {
187 		printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
188 		  ioc->name);
189 		return -ENODEV;
190 	}
191 
192 	/*  Sanity check - ensure at least 1 port is INITIATOR capable
193 	 */
194 	ioc_cap = 0;
195 	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
196 		if (ioc->pfacts[ii].ProtocolFlags &
197 		    MPI_PORTFACTS_PROTOCOL_INITIATOR)
198 			ioc_cap ++;
199 	}
200 
201 	if (!ioc_cap) {
202 		printk(MYIOC_s_WARN_FMT
203 			"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
204 			ioc->name, ioc);
205 		return -ENODEV;
206 	}
207 
208 	sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
209 
210 	if (!sh) {
211 		printk(MYIOC_s_WARN_FMT
212 			"Unable to register controller with SCSI subsystem\n",
213 			ioc->name);
214                 return -1;
215         }
216 
217 	spin_lock_irqsave(&ioc->FreeQlock, flags);
218 
219 	/* Attach the SCSI Host to the IOC structure
220 	 */
221 	ioc->sh = sh;
222 
223 	sh->io_port = 0;
224 	sh->n_io_port = 0;
225 	sh->irq = 0;
226 
227 	/* set 16 byte cdb's */
228 	sh->max_cmd_len = 16;
229 
230 	sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
231 
232 	sh->max_lun = MPT_LAST_LUN + 1;
233 	sh->max_channel = 0;
234 	sh->this_id = ioc->pfacts[0].PortSCSIID;
235 
236 	/* Required entry.
237 	 */
238 	sh->unique_id = ioc->id;
239 
240 	/* Verify that we won't exceed the maximum
241 	 * number of chain buffers
242 	 * We can optimize:  ZZ = req_sz/sizeof(SGE)
243 	 * For 32bit SGE's:
244 	 *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
245 	 *               + (req_sz - 64)/sizeof(SGE)
246 	 * A slightly different algorithm is required for
247 	 * 64bit SGEs.
248 	 */
249 	scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
250 	if (sizeof(dma_addr_t) == sizeof(u64)) {
251 		numSGE = (scale - 1) *
252 		  (ioc->facts.MaxChainDepth-1) + scale +
253 		  (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
254 		  sizeof(u32));
255 	} else {
256 		numSGE = 1 + (scale - 1) *
257 		  (ioc->facts.MaxChainDepth-1) + scale +
258 		  (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
259 		  sizeof(u32));
260 	}
261 
262 	if (numSGE < sh->sg_tablesize) {
263 		/* Reset this value */
264 		dprintk((MYIOC_s_INFO_FMT
265 		  "Resetting sg_tablesize to %d from %d\n",
266 		  ioc->name, numSGE, sh->sg_tablesize));
267 		sh->sg_tablesize = numSGE;
268 	}
269 
270 	/* Set the pci device pointer in Scsi_Host structure.
271 	 */
272 	scsi_set_device(sh, &ioc->pcidev->dev);
273 
274 	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
275 
276 	hd = (MPT_SCSI_HOST *) sh->hostdata;
277 	hd->ioc = ioc;
278 
279 	/* SCSI needs scsi_cmnd lookup table!
280 	 * (with size equal to req_depth*PtrSz!)
281 	 */
282 	sz = ioc->req_depth * sizeof(void *);
283 	mem = kmalloc(sz, GFP_ATOMIC);
284 	if (mem == NULL) {
285 		error = -ENOMEM;
286 		goto mptfc_probe_failed;
287 	}
288 
289 	memset(mem, 0, sz);
290 	hd->ScsiLookup = (struct scsi_cmnd **) mem;
291 
292 	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
293 		 ioc->name, hd->ScsiLookup, sz));
294 
295 	/* Allocate memory for the device structures.
296 	 * A non-Null pointer at an offset
297 	 * indicates a device exists.
298 	 * max_id = 1 + maximum id (hosts.h)
299 	 */
300 	sz = sh->max_id * sizeof(void *);
301 	mem = kmalloc(sz, GFP_ATOMIC);
302 	if (mem == NULL) {
303 		error = -ENOMEM;
304 		goto mptfc_probe_failed;
305 	}
306 
307 	memset(mem, 0, sz);
308 	hd->Targets = (VirtDevice **) mem;
309 
310 	dprintk((KERN_INFO
311 	  "  Targets @ %p, sz=%d\n", hd->Targets, sz));
312 
313 	/* Clear the TM flags
314 	 */
315 	hd->tmPending = 0;
316 	hd->tmState = TM_STATE_NONE;
317 	hd->resetPending = 0;
318 	hd->abortSCpnt = NULL;
319 
320 	/* Clear the pointer used to store
321 	 * single-threaded commands, i.e., those
322 	 * issued during a bus scan, dv and
323 	 * configuration pages.
324 	 */
325 	hd->cmdPtr = NULL;
326 
327 	/* Initialize this SCSI Hosts' timers
328 	 * To use, set the timer expires field
329 	 * and add_timer
330 	 */
331 	init_timer(&hd->timer);
332 	hd->timer.data = (unsigned long) hd;
333 	hd->timer.function = mptscsih_timer_expired;
334 
335 	hd->mpt_pq_filter = mpt_pq_filter;
336 
337 	ddvprintk((MYIOC_s_INFO_FMT
338 		"mpt_pq_filter %x\n",
339 		ioc->name,
340 		mpt_pq_filter));
341 
342 	init_waitqueue_head(&hd->scandv_waitq);
343 	hd->scandv_wait_done = 0;
344 	hd->last_queue_full = 0;
345 
346 	error = scsi_add_host (sh, &ioc->pcidev->dev);
347 	if(error) {
348 		dprintk((KERN_ERR MYNAM
349 		  "scsi_add_host failed\n"));
350 		goto mptfc_probe_failed;
351 	}
352 
353 	scsi_scan_host(sh);
354 	return 0;
355 
356 mptfc_probe_failed:
357 
358 	mptscsih_remove(pdev);
359 	return error;
360 }
361 
362 static struct pci_driver mptfc_driver = {
363 	.name		= "mptfc",
364 	.id_table	= mptfc_pci_table,
365 	.probe		= mptfc_probe,
366 	.remove		= __devexit_p(mptscsih_remove),
367 	.shutdown	= mptscsih_shutdown,
368 #ifdef CONFIG_PM
369 	.suspend	= mptscsih_suspend,
370 	.resume		= mptscsih_resume,
371 #endif
372 };
373 
374 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
375 /**
376  *	mptfc_init - Register MPT adapter(s) as SCSI host(s) with
377  *	linux scsi mid-layer.
378  *
379  *	Returns 0 for success, non-zero for failure.
380  */
381 static int __init
382 mptfc_init(void)
383 {
384 
385 	show_mptmod_ver(my_NAME, my_VERSION);
386 
387 	mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);
388 	mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
389 	mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
390 
391 	if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) {
392 		devtprintk((KERN_INFO MYNAM
393 		  ": Registered for IOC event notifications\n"));
394 	}
395 
396 	if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) {
397 		dprintk((KERN_INFO MYNAM
398 		  ": Registered for IOC reset notifications\n"));
399 	}
400 
401 	return pci_register_driver(&mptfc_driver);
402 }
403 
404 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
405 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
406 /**
407  *	mptfc_exit - Unregisters MPT adapter(s)
408  *
409  */
410 static void __exit
411 mptfc_exit(void)
412 {
413 	pci_unregister_driver(&mptfc_driver);
414 
415 	mpt_reset_deregister(mptfcDoneCtx);
416 	dprintk((KERN_INFO MYNAM
417 	  ": Deregistered for IOC reset notifications\n"));
418 
419 	mpt_event_deregister(mptfcDoneCtx);
420 	dprintk((KERN_INFO MYNAM
421 	  ": Deregistered for IOC event notifications\n"));
422 
423 	mpt_deregister(mptfcInternalCtx);
424 	mpt_deregister(mptfcTaskCtx);
425 	mpt_deregister(mptfcDoneCtx);
426 }
427 
428 module_init(mptfc_init);
429 module_exit(mptfc_exit);
430