blob: ba61e18288585679d4915c9ec22abd82804496b7 [file] [log] [blame]
Moore, Eric Dean 2496af32005-04-22 18:02:41 -04001/*
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
73MODULE_AUTHOR(MODULEAUTHOR);
74MODULE_DESCRIPTION(my_NAME);
75MODULE_LICENSE("GPL");
76
77/* Command line args */
78static int mpt_pq_filter = 0;
79module_param(mpt_pq_filter, int, 0);
80MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
81
82static int mptfcDoneCtx = -1;
83static int mptfcTaskCtx = -1;
84static int mptfcInternalCtx = -1; /* Used only for internal commands */
85
Moore, Eric Dean 2496af32005-04-22 18:02:41 -040086static struct scsi_host_template mptfc_driver_template = {
Moore, Eric Deanf78496d2005-11-16 18:54:14 -070087 .module = THIS_MODULE,
Moore, Eric Dean 2496af32005-04-22 18:02:41 -040088 .proc_name = "mptfc",
89 .proc_info = mptscsih_proc_info,
90 .name = "MPT FC Host",
91 .info = mptscsih_info,
92 .queuecommand = mptscsih_qcmd,
Moore, Eric Deanc7c82982005-11-16 18:54:25 -070093 .target_alloc = mptscsih_target_alloc,
Moore, Eric Dean 2496af32005-04-22 18:02:41 -040094 .slave_alloc = mptscsih_slave_alloc,
95 .slave_configure = mptscsih_slave_configure,
Moore, Eric Deanc7c82982005-11-16 18:54:25 -070096 .target_destroy = mptscsih_target_destroy,
Moore, Eric Dean 2496af32005-04-22 18:02:41 -040097 .slave_destroy = mptscsih_slave_destroy,
Moore, Eric Dean6e3815b2005-06-24 12:18:57 -060098 .change_queue_depth = mptscsih_change_queue_depth,
Moore, Eric Dean 2496af32005-04-22 18:02:41 -040099 .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,
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400110};
111
112/****************************************************************************
113 * Supported hardware
114 */
115
116static 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 },
Moore, Eric Dean 3fadc592005-05-11 17:46:52 -0600127 { 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 },
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400131 {0} /* Terminating entry */
132};
133MODULE_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 */
144static int
145mptfc_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);
Moore, Eric Dean d335cc32005-04-30 17:09:38 -0500163 ioc->DoneCtx = mptfcDoneCtx;
164 ioc->TaskCtx = mptfcTaskCtx;
165 ioc->InternalCtx = mptfcInternalCtx;
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400166
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);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -0700173 error = -ENODEV;
174 goto out_mptfc_probe;
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400175 }
176
177 if (!ioc->active) {
178 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
179 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -0700180 error = -ENODEV;
181 goto out_mptfc_probe;
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400182 }
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);
Moore, Eric Dean466544d2005-09-14 18:09:10 -0600197 return 0;
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400198 }
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);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -0700206 error = -1;
207 goto out_mptfc_probe;
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400208 }
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
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400263 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;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -0700275 goto out_mptfc_probe;
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400276 }
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;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -0700293 goto out_mptfc_probe;
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400294 }
295
296 memset(mem, 0, sz);
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700297 hd->Targets = (VirtTarget **) mem;
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400298
299 dprintk((KERN_INFO
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700300 " vdev @ %p, sz=%d\n", hd->Targets, sz));
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400301
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
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400324 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"));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -0700339 goto out_mptfc_probe;
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400340 }
341
342 scsi_scan_host(sh);
343 return 0;
344
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -0700345out_mptfc_probe:
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400346
347 mptscsih_remove(pdev);
348 return error;
349}
350
351static struct pci_driver mptfc_driver = {
352 .name = "mptfc",
353 .id_table = mptfc_pci_table,
354 .probe = mptfc_probe,
355 .remove = __devexit_p(mptscsih_remove),
Greg Kroah-Hartmand18c3db2005-06-23 17:35:56 -0700356 .shutdown = mptscsih_shutdown,
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400357#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 */
370static int __init
371mptfc_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 */
399static void __exit
400mptfc_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
417module_init(mptfc_init);
418module_exit(mptfc_exit);