blob: 5083a556a2584f1cdf8ec437d84b3ba22d0fbbd8 [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;
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +0100151 int ii;
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400152 int numSGE = 0;
153 int scale;
154 int ioc_cap;
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400155 int error=0;
156 int r;
157
158 if ((r = mpt_attach(pdev,id)) != 0)
159 return r;
160
161 ioc = pci_get_drvdata(pdev);
Moore, Eric Dean d335cc32005-04-30 17:09:38 -0500162 ioc->DoneCtx = mptfcDoneCtx;
163 ioc->TaskCtx = mptfcTaskCtx;
164 ioc->InternalCtx = mptfcInternalCtx;
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400165
166 /* Added sanity check on readiness of the MPT adapter.
167 */
168 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
169 printk(MYIOC_s_WARN_FMT
170 "Skipping because it's not operational!\n",
171 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -0700172 error = -ENODEV;
173 goto out_mptfc_probe;
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400174 }
175
176 if (!ioc->active) {
177 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
178 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -0700179 error = -ENODEV;
180 goto out_mptfc_probe;
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400181 }
182
183 /* Sanity check - ensure at least 1 port is INITIATOR capable
184 */
185 ioc_cap = 0;
186 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
187 if (ioc->pfacts[ii].ProtocolFlags &
188 MPI_PORTFACTS_PROTOCOL_INITIATOR)
189 ioc_cap ++;
190 }
191
192 if (!ioc_cap) {
193 printk(MYIOC_s_WARN_FMT
194 "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
195 ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -0600196 return 0;
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400197 }
198
199 sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
200
201 if (!sh) {
202 printk(MYIOC_s_WARN_FMT
203 "Unable to register controller with SCSI subsystem\n",
204 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -0700205 error = -1;
206 goto out_mptfc_probe;
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400207 }
208
209 spin_lock_irqsave(&ioc->FreeQlock, flags);
210
211 /* Attach the SCSI Host to the IOC structure
212 */
213 ioc->sh = sh;
214
215 sh->io_port = 0;
216 sh->n_io_port = 0;
217 sh->irq = 0;
218
219 /* set 16 byte cdb's */
220 sh->max_cmd_len = 16;
221
222 sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
223
224 sh->max_lun = MPT_LAST_LUN + 1;
225 sh->max_channel = 0;
226 sh->this_id = ioc->pfacts[0].PortSCSIID;
227
228 /* Required entry.
229 */
230 sh->unique_id = ioc->id;
231
232 /* Verify that we won't exceed the maximum
233 * number of chain buffers
234 * We can optimize: ZZ = req_sz/sizeof(SGE)
235 * For 32bit SGE's:
236 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
237 * + (req_sz - 64)/sizeof(SGE)
238 * A slightly different algorithm is required for
239 * 64bit SGEs.
240 */
241 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
242 if (sizeof(dma_addr_t) == sizeof(u64)) {
243 numSGE = (scale - 1) *
244 (ioc->facts.MaxChainDepth-1) + scale +
245 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
246 sizeof(u32));
247 } else {
248 numSGE = 1 + (scale - 1) *
249 (ioc->facts.MaxChainDepth-1) + scale +
250 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
251 sizeof(u32));
252 }
253
254 if (numSGE < sh->sg_tablesize) {
255 /* Reset this value */
256 dprintk((MYIOC_s_INFO_FMT
257 "Resetting sg_tablesize to %d from %d\n",
258 ioc->name, numSGE, sh->sg_tablesize));
259 sh->sg_tablesize = numSGE;
260 }
261
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400262 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
263
264 hd = (MPT_SCSI_HOST *) sh->hostdata;
265 hd->ioc = ioc;
266
267 /* SCSI needs scsi_cmnd lookup table!
268 * (with size equal to req_depth*PtrSz!)
269 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +0100270 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
271 if (!hd->ScsiLookup) {
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400272 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -0700273 goto out_mptfc_probe;
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400274 }
275
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +0100276 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
277 ioc->name, hd->ScsiLookup));
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400278
279 /* Allocate memory for the device structures.
280 * A non-Null pointer at an offset
281 * indicates a device exists.
282 * max_id = 1 + maximum id (hosts.h)
283 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +0100284 hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
285 if (!hd->Targets) {
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400286 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -0700287 goto out_mptfc_probe;
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400288 }
289
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +0100290 dprintk((KERN_INFO " vdev @ %p\n", hd->Targets));
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400291
292 /* Clear the TM flags
293 */
294 hd->tmPending = 0;
295 hd->tmState = TM_STATE_NONE;
296 hd->resetPending = 0;
297 hd->abortSCpnt = NULL;
298
299 /* Clear the pointer used to store
300 * single-threaded commands, i.e., those
301 * issued during a bus scan, dv and
302 * configuration pages.
303 */
304 hd->cmdPtr = NULL;
305
306 /* Initialize this SCSI Hosts' timers
307 * To use, set the timer expires field
308 * and add_timer
309 */
310 init_timer(&hd->timer);
311 hd->timer.data = (unsigned long) hd;
312 hd->timer.function = mptscsih_timer_expired;
313
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400314 hd->mpt_pq_filter = mpt_pq_filter;
315
316 ddvprintk((MYIOC_s_INFO_FMT
317 "mpt_pq_filter %x\n",
318 ioc->name,
319 mpt_pq_filter));
320
321 init_waitqueue_head(&hd->scandv_waitq);
322 hd->scandv_wait_done = 0;
323 hd->last_queue_full = 0;
324
325 error = scsi_add_host (sh, &ioc->pcidev->dev);
326 if(error) {
327 dprintk((KERN_ERR MYNAM
328 "scsi_add_host failed\n"));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -0700329 goto out_mptfc_probe;
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400330 }
331
332 scsi_scan_host(sh);
333 return 0;
334
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -0700335out_mptfc_probe:
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400336
337 mptscsih_remove(pdev);
338 return error;
339}
340
341static struct pci_driver mptfc_driver = {
342 .name = "mptfc",
343 .id_table = mptfc_pci_table,
344 .probe = mptfc_probe,
345 .remove = __devexit_p(mptscsih_remove),
Greg Kroah-Hartmand18c3db2005-06-23 17:35:56 -0700346 .shutdown = mptscsih_shutdown,
Moore, Eric Dean 2496af32005-04-22 18:02:41 -0400347#ifdef CONFIG_PM
348 .suspend = mptscsih_suspend,
349 .resume = mptscsih_resume,
350#endif
351};
352
353/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
354/**
355 * mptfc_init - Register MPT adapter(s) as SCSI host(s) with
356 * linux scsi mid-layer.
357 *
358 * Returns 0 for success, non-zero for failure.
359 */
360static int __init
361mptfc_init(void)
362{
363
364 show_mptmod_ver(my_NAME, my_VERSION);
365
366 mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);
367 mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
368 mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
369
370 if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) {
371 devtprintk((KERN_INFO MYNAM
372 ": Registered for IOC event notifications\n"));
373 }
374
375 if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) {
376 dprintk((KERN_INFO MYNAM
377 ": Registered for IOC reset notifications\n"));
378 }
379
380 return pci_register_driver(&mptfc_driver);
381}
382
383/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
384/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
385/**
386 * mptfc_exit - Unregisters MPT adapter(s)
387 *
388 */
389static void __exit
390mptfc_exit(void)
391{
392 pci_unregister_driver(&mptfc_driver);
393
394 mpt_reset_deregister(mptfcDoneCtx);
395 dprintk((KERN_INFO MYNAM
396 ": Deregistered for IOC reset notifications\n"));
397
398 mpt_event_deregister(mptfcDoneCtx);
399 dprintk((KERN_INFO MYNAM
400 ": Deregistered for IOC event notifications\n"));
401
402 mpt_deregister(mptfcInternalCtx);
403 mpt_deregister(mptfcTaskCtx);
404 mpt_deregister(mptfcDoneCtx);
405}
406
407module_init(mptfc_init);
408module_exit(mptfc_exit);