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