[SCSI] fusion: kzalloc / kcalloc conversion
[deliverable/linux.git] / drivers / message / fusion / mptfc.c
CommitLineData
2496af39
MED
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
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
2496af39 86static struct scsi_host_template mptfc_driver_template = {
f78496da 87 .module = THIS_MODULE,
2496af39
MED
88 .proc_name = "mptfc",
89 .proc_info = mptscsih_proc_info,
90 .name = "MPT FC Host",
91 .info = mptscsih_info,
92 .queuecommand = mptscsih_qcmd,
c7c82987 93 .target_alloc = mptscsih_target_alloc,
2496af39
MED
94 .slave_alloc = mptscsih_slave_alloc,
95 .slave_configure = mptscsih_slave_configure,
c7c82987 96 .target_destroy = mptscsih_target_destroy,
2496af39 97 .slave_destroy = mptscsih_slave_destroy,
6e3815ba 98 .change_queue_depth = mptscsih_change_queue_depth,
2496af39
MED
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,
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,
2496af39
MED
110};
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 },
3fadc59d
MED
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 },
2496af39
MED
131 {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;
1ca00bb7 151 int ii;
2496af39
MED
152 int numSGE = 0;
153 int scale;
154 int ioc_cap;
2496af39
MED
155 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);
d335cc38
MED
162 ioc->DoneCtx = mptfcDoneCtx;
163 ioc->TaskCtx = mptfcTaskCtx;
164 ioc->InternalCtx = mptfcInternalCtx;
2496af39
MED
165
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);
7acec1e7
MED
172 error = -ENODEV;
173 goto out_mptfc_probe;
2496af39
MED
174 }
175
176 if (!ioc->active) {
177 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
178 ioc->name);
7acec1e7
MED
179 error = -ENODEV;
180 goto out_mptfc_probe;
2496af39
MED
181 }
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);
466544d8 196 return 0;
2496af39
MED
197 }
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);
7acec1e7
MED
205 error = -1;
206 goto out_mptfc_probe;
2496af39
MED
207 }
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
2496af39
MED
262 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 */
1ca00bb7
CH
270 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
271 if (!hd->ScsiLookup) {
2496af39 272 error = -ENOMEM;
7acec1e7 273 goto out_mptfc_probe;
2496af39
MED
274 }
275
1ca00bb7
CH
276 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
277 ioc->name, hd->ScsiLookup));
2496af39
MED
278
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 */
1ca00bb7
CH
284 hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
285 if (!hd->Targets) {
2496af39 286 error = -ENOMEM;
7acec1e7 287 goto out_mptfc_probe;
2496af39
MED
288 }
289
1ca00bb7 290 dprintk((KERN_INFO " vdev @ %p\n", hd->Targets));
2496af39
MED
291
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
2496af39
MED
314 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"));
7acec1e7 329 goto out_mptfc_probe;
2496af39
MED
330 }
331
332 scsi_scan_host(sh);
333 return 0;
334
7acec1e7 335out_mptfc_probe:
2496af39
MED
336
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),
d18c3db5 346 .shutdown = mptscsih_shutdown,
2496af39
MED
347#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);
This page took 0.10757 seconds and 5 git commands to generate.