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