1 /* 2 * linux/drivers/message/fusion/mptspi.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 47 #include "linux_compat.h" /* linux-2.6 tweaks */ 48 #include <linux/module.h> 49 #include <linux/kernel.h> 50 #include <linux/init.h> 51 #include <linux/errno.h> 52 #include <linux/kdev_t.h> 53 #include <linux/blkdev.h> 54 #include <linux/delay.h> /* for mdelay */ 55 #include <linux/interrupt.h> /* needed for in_interrupt() proto */ 56 #include <linux/reboot.h> /* notifier code */ 57 #include <linux/sched.h> 58 #include <linux/workqueue.h> 59 60 #include <scsi/scsi.h> 61 #include <scsi/scsi_cmnd.h> 62 #include <scsi/scsi_device.h> 63 #include <scsi/scsi_host.h> 64 #include <scsi/scsi_tcq.h> 65 66 #include "mptbase.h" 67 #include "mptscsih.h" 68 69 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 70 #define my_NAME "Fusion MPT SPI Host driver" 71 #define my_VERSION MPT_LINUX_VERSION_COMMON 72 #define MYNAM "mptspi" 73 74 MODULE_AUTHOR(MODULEAUTHOR); 75 MODULE_DESCRIPTION(my_NAME); 76 MODULE_LICENSE("GPL"); 77 78 /* Command line args */ 79 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION 80 static int mpt_dv = MPTSCSIH_DOMAIN_VALIDATION; 81 module_param(mpt_dv, int, 0); 82 MODULE_PARM_DESC(mpt_dv, " DV Algorithm: enhanced=1, basic=0 (default=MPTSCSIH_DOMAIN_VALIDATION=1)"); 83 84 static int mpt_width = MPTSCSIH_MAX_WIDTH; 85 module_param(mpt_width, int, 0); 86 MODULE_PARM_DESC(mpt_width, " Max Bus Width: wide=1, narrow=0 (default=MPTSCSIH_MAX_WIDTH=1)"); 87 88 static ushort mpt_factor = MPTSCSIH_MIN_SYNC; 89 module_param(mpt_factor, ushort, 0); 90 MODULE_PARM_DESC(mpt_factor, " Min Sync Factor (default=MPTSCSIH_MIN_SYNC=0x08)"); 91 #endif 92 93 static int mpt_saf_te = MPTSCSIH_SAF_TE; 94 module_param(mpt_saf_te, int, 0); 95 MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)"); 96 97 static int mpt_pq_filter = 0; 98 module_param(mpt_pq_filter, int, 0); 99 MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)"); 100 101 static int mptspiDoneCtx = -1; 102 static int mptspiTaskCtx = -1; 103 static int mptspiInternalCtx = -1; /* Used only for internal commands */ 104 105 static struct scsi_host_template mptspi_driver_template = { 106 .module = THIS_MODULE, 107 .proc_name = "mptspi", 108 .proc_info = mptscsih_proc_info, 109 .name = "MPT SPI Host", 110 .info = mptscsih_info, 111 .queuecommand = mptscsih_qcmd, 112 .target_alloc = mptscsih_target_alloc, 113 .slave_alloc = mptscsih_slave_alloc, 114 .slave_configure = mptscsih_slave_configure, 115 .target_destroy = mptscsih_target_destroy, 116 .slave_destroy = mptscsih_slave_destroy, 117 .change_queue_depth = mptscsih_change_queue_depth, 118 .eh_abort_handler = mptscsih_abort, 119 .eh_device_reset_handler = mptscsih_dev_reset, 120 .eh_bus_reset_handler = mptscsih_bus_reset, 121 .eh_host_reset_handler = mptscsih_host_reset, 122 .bios_param = mptscsih_bios_param, 123 .can_queue = MPT_SCSI_CAN_QUEUE, 124 .this_id = -1, 125 .sg_tablesize = MPT_SCSI_SG_DEPTH, 126 .max_sectors = 8192, 127 .cmd_per_lun = 7, 128 .use_clustering = ENABLE_CLUSTERING, 129 }; 130 131 132 /**************************************************************************** 133 * Supported hardware 134 */ 135 136 static struct pci_device_id mptspi_pci_table[] = { 137 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1030, 138 PCI_ANY_ID, PCI_ANY_ID }, 139 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_1030_53C1035, 140 PCI_ANY_ID, PCI_ANY_ID }, 141 {0} /* Terminating entry */ 142 }; 143 MODULE_DEVICE_TABLE(pci, mptspi_pci_table); 144 145 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 146 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 147 /* 148 * mptspi_probe - Installs scsi devices per bus. 149 * @pdev: Pointer to pci_dev structure 150 * 151 * Returns 0 for success, non-zero for failure. 152 * 153 */ 154 static int 155 mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) 156 { 157 struct Scsi_Host *sh; 158 MPT_SCSI_HOST *hd; 159 MPT_ADAPTER *ioc; 160 unsigned long flags; 161 int sz, ii; 162 int numSGE = 0; 163 int scale; 164 int ioc_cap; 165 u8 *mem; 166 int error=0; 167 int r; 168 169 if ((r = mpt_attach(pdev,id)) != 0) 170 return r; 171 172 ioc = pci_get_drvdata(pdev); 173 ioc->DoneCtx = mptspiDoneCtx; 174 ioc->TaskCtx = mptspiTaskCtx; 175 ioc->InternalCtx = mptspiInternalCtx; 176 177 /* Added sanity check on readiness of the MPT adapter. 178 */ 179 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) { 180 printk(MYIOC_s_WARN_FMT 181 "Skipping because it's not operational!\n", 182 ioc->name); 183 error = -ENODEV; 184 goto out_mptspi_probe; 185 } 186 187 if (!ioc->active) { 188 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n", 189 ioc->name); 190 error = -ENODEV; 191 goto out_mptspi_probe; 192 } 193 194 /* Sanity check - ensure at least 1 port is INITIATOR capable 195 */ 196 ioc_cap = 0; 197 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { 198 if (ioc->pfacts[ii].ProtocolFlags & 199 MPI_PORTFACTS_PROTOCOL_INITIATOR) 200 ioc_cap ++; 201 } 202 203 if (!ioc_cap) { 204 printk(MYIOC_s_WARN_FMT 205 "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n", 206 ioc->name, ioc); 207 return 0; 208 } 209 210 sh = scsi_host_alloc(&mptspi_driver_template, sizeof(MPT_SCSI_HOST)); 211 212 if (!sh) { 213 printk(MYIOC_s_WARN_FMT 214 "Unable to register controller with SCSI subsystem\n", 215 ioc->name); 216 error = -1; 217 goto out_mptspi_probe; 218 } 219 220 spin_lock_irqsave(&ioc->FreeQlock, flags); 221 222 /* Attach the SCSI Host to the IOC structure 223 */ 224 ioc->sh = sh; 225 226 sh->io_port = 0; 227 sh->n_io_port = 0; 228 sh->irq = 0; 229 230 /* set 16 byte cdb's */ 231 sh->max_cmd_len = 16; 232 233 /* Yikes! This is important! 234 * Otherwise, by default, linux 235 * only scans target IDs 0-7! 236 * pfactsN->MaxDevices unreliable 237 * (not supported in early 238 * versions of the FW). 239 * max_id = 1 + actual max id, 240 * max_lun = 1 + actual last lun, 241 * see hosts.h :o( 242 */ 243 sh->max_id = MPT_MAX_SCSI_DEVICES; 244 245 sh->max_lun = MPT_LAST_LUN + 1; 246 sh->max_channel = 0; 247 sh->this_id = ioc->pfacts[0].PortSCSIID; 248 249 /* Required entry. 250 */ 251 sh->unique_id = ioc->id; 252 253 /* Verify that we won't exceed the maximum 254 * number of chain buffers 255 * We can optimize: ZZ = req_sz/sizeof(SGE) 256 * For 32bit SGE's: 257 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ 258 * + (req_sz - 64)/sizeof(SGE) 259 * A slightly different algorithm is required for 260 * 64bit SGEs. 261 */ 262 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); 263 if (sizeof(dma_addr_t) == sizeof(u64)) { 264 numSGE = (scale - 1) * 265 (ioc->facts.MaxChainDepth-1) + scale + 266 (ioc->req_sz - 60) / (sizeof(dma_addr_t) + 267 sizeof(u32)); 268 } else { 269 numSGE = 1 + (scale - 1) * 270 (ioc->facts.MaxChainDepth-1) + scale + 271 (ioc->req_sz - 64) / (sizeof(dma_addr_t) + 272 sizeof(u32)); 273 } 274 275 if (numSGE < sh->sg_tablesize) { 276 /* Reset this value */ 277 dprintk((MYIOC_s_INFO_FMT 278 "Resetting sg_tablesize to %d from %d\n", 279 ioc->name, numSGE, sh->sg_tablesize)); 280 sh->sg_tablesize = numSGE; 281 } 282 283 spin_unlock_irqrestore(&ioc->FreeQlock, flags); 284 285 hd = (MPT_SCSI_HOST *) sh->hostdata; 286 hd->ioc = ioc; 287 288 /* SCSI needs scsi_cmnd lookup table! 289 * (with size equal to req_depth*PtrSz!) 290 */ 291 sz = ioc->req_depth * sizeof(void *); 292 mem = kmalloc(sz, GFP_ATOMIC); 293 if (mem == NULL) { 294 error = -ENOMEM; 295 goto out_mptspi_probe; 296 } 297 298 memset(mem, 0, sz); 299 hd->ScsiLookup = (struct scsi_cmnd **) mem; 300 301 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", 302 ioc->name, hd->ScsiLookup, sz)); 303 304 /* Allocate memory for the device structures. 305 * A non-Null pointer at an offset 306 * indicates a device exists. 307 * max_id = 1 + maximum id (hosts.h) 308 */ 309 sz = sh->max_id * sizeof(void *); 310 mem = kmalloc(sz, GFP_ATOMIC); 311 if (mem == NULL) { 312 error = -ENOMEM; 313 goto out_mptspi_probe; 314 } 315 316 memset(mem, 0, sz); 317 hd->Targets = (VirtTarget **) mem; 318 319 dprintk((KERN_INFO 320 " vdev @ %p, sz=%d\n", hd->Targets, sz)); 321 322 /* Clear the TM flags 323 */ 324 hd->tmPending = 0; 325 hd->tmState = TM_STATE_NONE; 326 hd->resetPending = 0; 327 hd->abortSCpnt = NULL; 328 329 /* Clear the pointer used to store 330 * single-threaded commands, i.e., those 331 * issued during a bus scan, dv and 332 * configuration pages. 333 */ 334 hd->cmdPtr = NULL; 335 336 /* Initialize this SCSI Hosts' timers 337 * To use, set the timer expires field 338 * and add_timer 339 */ 340 init_timer(&hd->timer); 341 hd->timer.data = (unsigned long) hd; 342 hd->timer.function = mptscsih_timer_expired; 343 344 ioc->spi_data.Saf_Te = mpt_saf_te; 345 hd->mpt_pq_filter = mpt_pq_filter; 346 347 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION 348 if (ioc->spi_data.maxBusWidth > mpt_width) 349 ioc->spi_data.maxBusWidth = mpt_width; 350 if (ioc->spi_data.minSyncFactor < mpt_factor) 351 ioc->spi_data.minSyncFactor = mpt_factor; 352 if (ioc->spi_data.minSyncFactor == MPT_ASYNC) { 353 ioc->spi_data.maxSyncOffset = 0; 354 } 355 ioc->spi_data.mpt_dv = mpt_dv; 356 hd->negoNvram = 0; 357 358 ddvprintk((MYIOC_s_INFO_FMT 359 "dv %x width %x factor %x saf_te %x mpt_pq_filter %x\n", 360 ioc->name, 361 mpt_dv, 362 mpt_width, 363 mpt_factor, 364 mpt_saf_te, 365 mpt_pq_filter)); 366 #else 367 hd->negoNvram = MPT_SCSICFG_USE_NVRAM; 368 ddvprintk((MYIOC_s_INFO_FMT 369 "saf_te %x mpt_pq_filter %x\n", 370 ioc->name, 371 mpt_saf_te, 372 mpt_pq_filter)); 373 #endif 374 375 ioc->spi_data.forceDv = 0; 376 ioc->spi_data.noQas = 0; 377 378 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) 379 ioc->spi_data.dvStatus[ii] = 380 MPT_SCSICFG_NEGOTIATE; 381 382 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) 383 ioc->spi_data.dvStatus[ii] |= 384 MPT_SCSICFG_DV_NOT_DONE; 385 386 init_waitqueue_head(&hd->scandv_waitq); 387 hd->scandv_wait_done = 0; 388 hd->last_queue_full = 0; 389 390 error = scsi_add_host (sh, &ioc->pcidev->dev); 391 if(error) { 392 dprintk((KERN_ERR MYNAM 393 "scsi_add_host failed\n")); 394 goto out_mptspi_probe; 395 } 396 397 scsi_scan_host(sh); 398 return 0; 399 400 out_mptspi_probe: 401 402 mptscsih_remove(pdev); 403 return error; 404 } 405 406 static struct pci_driver mptspi_driver = { 407 .name = "mptspi", 408 .id_table = mptspi_pci_table, 409 .probe = mptspi_probe, 410 .remove = __devexit_p(mptscsih_remove), 411 .shutdown = mptscsih_shutdown, 412 #ifdef CONFIG_PM 413 .suspend = mptscsih_suspend, 414 .resume = mptscsih_resume, 415 #endif 416 }; 417 418 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 419 /** 420 * mptspi_init - Register MPT adapter(s) as SCSI host(s) with 421 * linux scsi mid-layer. 422 * 423 * Returns 0 for success, non-zero for failure. 424 */ 425 static int __init 426 mptspi_init(void) 427 { 428 429 show_mptmod_ver(my_NAME, my_VERSION); 430 431 mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER); 432 mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER); 433 mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER); 434 435 if (mpt_event_register(mptspiDoneCtx, mptscsih_event_process) == 0) { 436 devtprintk((KERN_INFO MYNAM 437 ": Registered for IOC event notifications\n")); 438 } 439 440 if (mpt_reset_register(mptspiDoneCtx, mptscsih_ioc_reset) == 0) { 441 dprintk((KERN_INFO MYNAM 442 ": Registered for IOC reset notifications\n")); 443 } 444 445 return pci_register_driver(&mptspi_driver); 446 } 447 448 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 449 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 450 /** 451 * mptspi_exit - Unregisters MPT adapter(s) 452 * 453 */ 454 static void __exit 455 mptspi_exit(void) 456 { 457 pci_unregister_driver(&mptspi_driver); 458 459 mpt_reset_deregister(mptspiDoneCtx); 460 dprintk((KERN_INFO MYNAM 461 ": Deregistered for IOC reset notifications\n")); 462 463 mpt_event_deregister(mptspiDoneCtx); 464 dprintk((KERN_INFO MYNAM 465 ": Deregistered for IOC event notifications\n")); 466 467 mpt_deregister(mptspiInternalCtx); 468 mpt_deregister(mptspiTaskCtx); 469 mpt_deregister(mptspiDoneCtx); 470 } 471 472 module_init(mptspi_init); 473 module_exit(mptspi_exit); 474