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 .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, 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, 110 }; 111 112 /**************************************************************************** 113 * Supported hardware 114 */ 115 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 */ 132 }; 133 MODULE_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 */ 144 static int 145 mptfc_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); 163 ioc->DoneCtx = mptfcDoneCtx; 164 ioc->TaskCtx = mptfcTaskCtx; 165 ioc->InternalCtx = mptfcInternalCtx; 166 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); 173 error = -ENODEV; 174 goto out_mptfc_probe; 175 } 176 177 if (!ioc->active) { 178 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n", 179 ioc->name); 180 error = -ENODEV; 181 goto out_mptfc_probe; 182 } 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); 197 return 0; 198 } 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); 206 error = -1; 207 goto out_mptfc_probe; 208 } 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 263 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; 275 goto out_mptfc_probe; 276 } 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; 293 goto out_mptfc_probe; 294 } 295 296 memset(mem, 0, sz); 297 hd->Targets = (VirtTarget **) mem; 298 299 dprintk((KERN_INFO 300 " vdev @ %p, sz=%d\n", hd->Targets, sz)); 301 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 324 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")); 339 goto out_mptfc_probe; 340 } 341 342 scsi_scan_host(sh); 343 return 0; 344 345 out_mptfc_probe: 346 347 mptscsih_remove(pdev); 348 return error; 349 } 350 351 static struct pci_driver mptfc_driver = { 352 .name = "mptfc", 353 .id_table = mptfc_pci_table, 354 .probe = mptfc_probe, 355 .remove = __devexit_p(mptscsih_remove), 356 .shutdown = mptscsih_shutdown, 357 #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 */ 370 static int __init 371 mptfc_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 */ 399 static void __exit 400 mptfc_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 417 module_init(mptfc_init); 418 module_exit(mptfc_exit); 419