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.
6 * Copyright (c) 1999-2005 LSI Logic Corporation
7 * (mailto:mpt_linux_developer@lsil.com)
10 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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.
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.
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.
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
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
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>
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>
68 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
69 #define my_NAME "Fusion MPT FC Host driver"
70 #define my_VERSION MPT_LINUX_VERSION_COMMON
73 MODULE_AUTHOR(MODULEAUTHOR);
74 MODULE_DESCRIPTION(my_NAME);
75 MODULE_LICENSE("GPL");
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)");
82 static int mptfcDoneCtx = -1;
83 static int mptfcTaskCtx = -1;
84 static int mptfcInternalCtx = -1; /* Used only for internal commands */
86 static struct scsi_host_template mptfc_driver_template = {
87 .module = THIS_MODULE,
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,
106 .sg_tablesize = MPT_SCSI_SG_DEPTH,
109 .use_clustering = ENABLE_CLUSTERING,
112 /****************************************************************************
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 */
133 MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
135 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
136 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
138 * mptfc_probe - Installs scsi devices per bus.
139 * @pdev: Pointer to pci_dev structure
141 * Returns 0 for success, non-zero for failure.
145 mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
147 struct Scsi_Host *sh;
159 if ((r = mpt_attach(pdev,id)) != 0)
162 ioc = pci_get_drvdata(pdev);
163 ioc->DoneCtx = mptfcDoneCtx;
164 ioc->TaskCtx = mptfcTaskCtx;
165 ioc->InternalCtx = mptfcInternalCtx;
167 /* Added sanity check on readiness of the MPT adapter.
169 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
170 printk(MYIOC_s_WARN_FMT
171 "Skipping because it's not operational!\n",
174 goto out_mptfc_probe;
178 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
181 goto out_mptfc_probe;
184 /* Sanity check - ensure at least 1 port is INITIATOR capable
187 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
188 if (ioc->pfacts[ii].ProtocolFlags &
189 MPI_PORTFACTS_PROTOCOL_INITIATOR)
194 printk(MYIOC_s_WARN_FMT
195 "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
200 sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
203 printk(MYIOC_s_WARN_FMT
204 "Unable to register controller with SCSI subsystem\n",
207 goto out_mptfc_probe;
210 spin_lock_irqsave(&ioc->FreeQlock, flags);
212 /* Attach the SCSI Host to the IOC structure
220 /* set 16 byte cdb's */
221 sh->max_cmd_len = 16;
223 sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
225 sh->max_lun = MPT_LAST_LUN + 1;
227 sh->this_id = ioc->pfacts[0].PortSCSIID;
231 sh->unique_id = ioc->id;
233 /* Verify that we won't exceed the maximum
234 * number of chain buffers
235 * We can optimize: ZZ = req_sz/sizeof(SGE)
237 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
238 * + (req_sz - 64)/sizeof(SGE)
239 * A slightly different algorithm is required for
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) +
249 numSGE = 1 + (scale - 1) *
250 (ioc->facts.MaxChainDepth-1) + scale +
251 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
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;
263 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
265 hd = (MPT_SCSI_HOST *) sh->hostdata;
268 /* SCSI needs scsi_cmnd lookup table!
269 * (with size equal to req_depth*PtrSz!)
271 sz = ioc->req_depth * sizeof(void *);
272 mem = kmalloc(sz, GFP_ATOMIC);
275 goto out_mptfc_probe;
279 hd->ScsiLookup = (struct scsi_cmnd **) mem;
281 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
282 ioc->name, hd->ScsiLookup, sz));
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)
289 sz = sh->max_id * sizeof(void *);
290 mem = kmalloc(sz, GFP_ATOMIC);
293 goto out_mptfc_probe;
297 hd->Targets = (VirtTarget **) mem;
300 " vdev @ %p, sz=%d\n", hd->Targets, sz));
302 /* Clear the TM flags
305 hd->tmState = TM_STATE_NONE;
306 hd->resetPending = 0;
307 hd->abortSCpnt = NULL;
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.
316 /* Initialize this SCSI Hosts' timers
317 * To use, set the timer expires field
320 init_timer(&hd->timer);
321 hd->timer.data = (unsigned long) hd;
322 hd->timer.function = mptscsih_timer_expired;
324 hd->mpt_pq_filter = mpt_pq_filter;
326 ddvprintk((MYIOC_s_INFO_FMT
327 "mpt_pq_filter %x\n",
331 init_waitqueue_head(&hd->scandv_waitq);
332 hd->scandv_wait_done = 0;
333 hd->last_queue_full = 0;
335 error = scsi_add_host (sh, &ioc->pcidev->dev);
337 dprintk((KERN_ERR MYNAM
338 "scsi_add_host failed\n"));
339 goto out_mptfc_probe;
347 mptscsih_remove(pdev);
351 static struct pci_driver mptfc_driver = {
353 .id_table = mptfc_pci_table,
354 .probe = mptfc_probe,
355 .remove = __devexit_p(mptscsih_remove),
356 .shutdown = mptscsih_shutdown,
358 .suspend = mptscsih_suspend,
359 .resume = mptscsih_resume,
363 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
365 * mptfc_init - Register MPT adapter(s) as SCSI host(s) with
366 * linux scsi mid-layer.
368 * Returns 0 for success, non-zero for failure.
374 show_mptmod_ver(my_NAME, my_VERSION);
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);
380 if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) {
381 devtprintk((KERN_INFO MYNAM
382 ": Registered for IOC event notifications\n"));
385 if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) {
386 dprintk((KERN_INFO MYNAM
387 ": Registered for IOC reset notifications\n"));
390 return pci_register_driver(&mptfc_driver);
393 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
394 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
396 * mptfc_exit - Unregisters MPT adapter(s)
402 pci_unregister_driver(&mptfc_driver);
404 mpt_reset_deregister(mptfcDoneCtx);
405 dprintk((KERN_INFO MYNAM
406 ": Deregistered for IOC reset notifications\n"));
408 mpt_event_deregister(mptfcDoneCtx);
409 dprintk((KERN_INFO MYNAM
410 ": Deregistered for IOC event notifications\n"));
412 mpt_deregister(mptfcInternalCtx);
413 mpt_deregister(mptfcTaskCtx);
414 mpt_deregister(mptfcDoneCtx);
417 module_init(mptfc_init);
418 module_exit(mptfc_exit);