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