diff -Nur linux-2.4.21.org/drivers/scsi/megaraid.c linux-2.4.21/drivers/scsi/megaraid.c --- linux-2.4.21.org/drivers/scsi/megaraid.c 2003-06-13 14:51:36.000000000 +0000 +++ linux-2.4.21/drivers/scsi/megaraid.c 2003-07-07 17:44:56.000000000 +0000 @@ -9,7 +9,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * Version : v1.18f (Dec 10, 2002) + * Version : v1.18j (July 7, 2003) * * Description: Linux device driver for LSI Logic MegaRAID controller * @@ -512,6 +512,47 @@ * * remove GFP_DMA flag for ioctl. This was causing overrun of DMA buffers. * + * Version 1.18g + * Fri Jan 31 18:29:25 EST 2003 - Atul Mukker + * + * Write the interrupt valid signature 0x10001234 as soon as reading it to + * flush memory caches. + * + * While sending back the inquiry information, check if the original request + * had an associated scatter-gather list and tranfer data from bounce buffer + * accordingly. + * + * Version 1.18h + * Thu Feb 6 17:18:48 EST 2003 - Atul Mukker + * + * Reduce the number of sectors per command to 128 from original value of + * 1024. Big IO sizes along with certain other operation going on in parallel, + * e.g., check consistency and rebuild put a heavy constraint on fW resources + * resulting in aborted commands. + * + * Version 1.18i + * Fri Jun 20 07:39:05 EDT 2003 - Atul Mukker + * + * Request and reserve memory/IO regions. Otherwise a panic occurs if 2.00.x + * driver is loaded on top of 1.18x driver + * + * Prevent memory leak in cases when data transfer from/to application fails + * and ioctl is failing. + * + * Set the PCI dma_mask to default value of 0xFFFFFFFF when we get a handle to + * it. The previous value of 64-bit might be sticky and would cause the memory + * for mailbox and scatter lists to be allocated beyond 4GB. This was observed + * on an Itenium + * + * Version 1.18j + * Mon Jul 7 14:39:55 EDT 2003 - Atul Mukker + * + * Disable /proc/megaraid/stat file to prevent buffer overflow error during + * read of this file. + * + * Add support for ioctls on AMD-64 bit platforms + * - Sreenivas Bagalkote + * * BUGS: * Some older 2.1 kernels (eg. 2.1.90) have a bug in pci.c that * fails to detect the controller as a pci device on the system. @@ -575,12 +616,27 @@ #include #include +#ifdef __x86_64__ +#include +#endif + #include "sd.h" #include "scsi.h" #include "hosts.h" #include "megaraid.h" +#ifdef __x86_64__ +/* + * The IOCTL cmd received from 32 bit compiled applications + */ + +extern int register_ioctl32_conversion( unsigned int cmd, + int(*handler)(unsigned int, unsigned int, unsigned long, + struct file* )); +extern int unregister_ioctl32_conversion( unsigned int cmd ); +#endif + /* *================================================================ * #Defines @@ -1141,8 +1197,14 @@ switch (SCpnt->cmnd[0]) { case INQUIRY: case READ_CAPACITY: - memcpy (SCpnt->request_buffer, - pScb->bounce_buffer, SCpnt->request_bufflen); + if ( SCpnt->use_sg ) { + sgList = (struct scatterlist *)SCpnt->request_buffer; + memcpy(sgList[0].address, pScb->bounce_buffer, + SCpnt->request_bufflen); + } else { + memcpy (SCpnt->request_buffer, pScb->bounce_buffer, + SCpnt->request_bufflen); + } break; } #endif @@ -2202,30 +2264,22 @@ megaCfg = (mega_host_config *) devp; mbox = (mega_mailbox *) tmpBox; - if (megaCfg->host->irq == irq) { - if (megaCfg->flag & IN_ISR) { - TRACE (("ISR called reentrantly!!\n")); - printk ("ISR called reentrantly!!\n"); - } - megaCfg->flag |= IN_ISR; - - if (mega_busyWaitMbox (megaCfg)) { - printk (KERN_WARNING "Error: mailbox busy in isr!\n"); - } + IO_LOCK; /* Check if a valid interrupt is pending */ if (megaCfg->flag & BOARD_QUARTZ) { dword = RDOUTDOOR (megaCfg); if (dword != 0x10001234) { /* Spurious interrupt */ - megaCfg->flag &= ~IN_ISR; + IO_UNLOCK; return; } + WROUTDOOR (megaCfg, 0x10001234); } else { byte = READ_PORT (megaCfg->host->io_port, INTR_PORT); if ((byte & VALID_INTR_BYTE) == 0) { /* Spurious interrupt */ - megaCfg->flag &= ~IN_ISR; + IO_UNLOCK; return; } WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte); @@ -2234,58 +2288,26 @@ for (idx = 0; idx < MAX_FIRMWARE_STATUS; idx++) completed[idx] = 0; - IO_LOCK; megaCfg->nInterrupts++; - qCnt = 0xff; while ((qCnt = megaCfg->mbox->numstatus) == 0xFF) ; + megaCfg->mbox->numstatus = 0xFF; - qStatus = 0xff; - while ((qStatus = megaCfg->mbox->status) == 0xFF) ; + qStatus = megaCfg->mbox->status; /* Get list of completed requests */ for (idx = 0; idx < qCnt; idx++) { - while ((sIdx = megaCfg->mbox->completed[idx]) == 0xFF) { - printk ("p"); - } - completed[idx] = sIdx; - sIdx = 0xFF; + completed[idx] = megaCfg->mbox->completed[idx]; } if (megaCfg->flag & BOARD_QUARTZ) { - WROUTDOOR (megaCfg, dword); /* Acknowledge interrupt */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - /* In this case mbox contains physical address */ -#if 0 - WRINDOOR (megaCfg, megaCfg->adjdmahandle64 | 0x2); -#else WRINDOOR (megaCfg, 0x2); -#endif - -#else - -#if 0 - WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2); -#else - WRINDOOR (megaCfg, 0x2); -#endif - -#endif - -#if 0 while (RDINDOOR (megaCfg) & 0x02) ; -#endif } else { CLEAR_INTR (megaCfg->host->io_port); } -#if DEBUG - if (qCnt >= MAX_FIRMWARE_STATUS) { - printk ("megaraid_isr: cmplt=%d ", qCnt); - } -#endif - for (idx = 0; idx < qCnt; idx++) { sIdx = completed[idx]; if ((sIdx > 0) && (sIdx <= MAX_COMMANDS)) { @@ -2355,26 +2377,24 @@ mega_runpendq (megaCfg); IO_UNLOCK; - } - } /*==================================================*/ /* Wait until the controller's mailbox is available */ /*==================================================*/ -static int mega_busyWaitMbox (mega_host_config * megaCfg) +static inline int mega_busyWaitMbox (mega_host_config * megaCfg) { mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox; long counter; - for (counter = 0; counter < 10000; counter++) { + for (counter = 0; counter < 10; counter++) { if (!mbox->busy) { return 0; } - udelay (100); + udelay (1); } - return -1; /* give up after 1 second */ + return -1; /* give up after 10 usecs */ } /*===================================================== @@ -2420,25 +2440,8 @@ phys_mbox = virt_to_bus (megaCfg->mbox); #endif -#if DEBUG - ShowMbox (pScb); -#endif - /* Wait until mailbox is free */ if (mega_busyWaitMbox (megaCfg)) { - printk ("Blocked mailbox......!!\n"); - udelay (1000); - -#if DEBUG - showMbox (pLastScb); -#endif - - /* Abort command */ - if (pScb == NULL) { - TRACE (("NULL pScb in megaIssue\n")); - printk ("NULL pScb in megaIssue\n"); - } - mega_cmd_done (megaCfg, pScb, 0x08); return -1; } @@ -2486,13 +2489,10 @@ WRINDOOR (megaCfg, phys_mbox | 0x1); while (mbox->numstatus == 0xFF) ; - while (mbox->status == 0xFF) ; while (mbox->mraid_poll != 0x77) ; mbox->mraid_poll = 0; mbox->mraid_ack = 0x77; - - /* while ((cmdDone = RDOUTDOOR (megaCfg)) != 0x10001234); - WROUTDOOR (megaCfg, cmdDone); */ + mbox->numstatus = 0xFF; if (pScb) { mega_cmd_done (megaCfg, pScb, mbox->status); @@ -2523,12 +2523,6 @@ enable_irq (megaCfg->host->irq); retval = mbox->status; } -#if DEBUG - while (mega_busyWaitMbox (megaCfg)) { - printk(KERN_ERR "Blocked mailbox on exit......!\n"); - udelay (1000); - } -#endif return retval; } @@ -2964,15 +2958,15 @@ int i, j; -#if BITS_PER_LONG==64 - u64 megaBase; -#else - u32 megaBase; -#endif + unsigned long megaBase; + unsigned long tbase; u16 pciIdx = 0; u16 numFound = 0; u16 subsysid, subsysvid; + u8 did_mem_map_f = 0; + u8 did_io_map_f = 0; + u8 did_scsi_register_f = 0; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) /* 0x20100 */ while (!pcibios_find_device @@ -2991,6 +2985,17 @@ pciBus = pdev->bus->number; pciDevFun = pdev->devfn; #endif + + /* + * Set the dma_mask to default value. It might be sticky from previous + * insmod-rmmod sequence + */ + pdev->dma_mask = 0xFFFFFFFF; + + did_mem_map_f = 0; + did_io_map_f = 0; + did_scsi_register_f = 0; + if ((flag & BOARD_QUARTZ) && (skip_id == -1)) { if( (pciVendor == PCI_VENDOR_ID_PERC4_DI_YSTONE && pciDev == PCI_DEVICE_ID_PERC4_DI_YSTONE) || @@ -3041,6 +3046,7 @@ if( (subsysvid != AMI_SUBSYS_ID) && (subsysvid != DELL_SUBSYS_ID) && (subsysvid != LSI_SUBSYS_ID) && + (subsysvid != INTEL_SUBSYS_ID) && (subsysvid != HP_SUBSYS_ID) ) continue; } @@ -3065,22 +3071,55 @@ megaIrq = pdev->irq; #endif + tbase = megaBase; + pciIdx++; if (flag & BOARD_QUARTZ) { + megaBase &= PCI_BASE_ADDRESS_MEM_MASK; + + if( ! request_mem_region(megaBase, 128, + "MegaRAID: LSI Logic Corporation" ) ) { + + printk(KERN_WARNING "megaraid: mem region busy!\n"); + + continue; + } + megaBase = (long) ioremap (megaBase, 128); - if (!megaBase) + + if (!megaBase) { + + printk(KERN_WARNING "megaraid: could not map hba memory!\n"); + + release_mem_region(tbase, 128); + continue; + } + did_mem_map_f = 1; + } else { megaBase &= PCI_BASE_ADDRESS_IO_MASK; megaBase += 0x10; + + if( ! request_region(megaBase, 16, + "MegaRAID: LSI Logic Corporation") ) { + + printk(KERN_WARNING "megaraid: region busy.\n"); + + continue; + } + did_io_map_f = 1; + } /* Initialize SCSI Host structure */ host = scsi_register (pHostTmpl, sizeof (mega_host_config)); if (!host) - goto err_unmap; + goto fail_attach; + + did_scsi_register_f = 1; /* * Comment the following initialization if you know 'max_sectors' is @@ -3088,7 +3127,7 @@ * This field was introduced in Linus's kernel 2.4.7pre3 and it * greatly increases the IO performance - AM */ - host->max_sectors = 1024; + host->max_sectors = 128; scsi_set_pci_device(host, pdev); megaCfg = (mega_host_config *) host->hostdata; @@ -3130,11 +3169,8 @@ megaCfg->host->unique_id = (pciBus << 8) | pciDevFun; megaCtlrs[numCtlrs] = megaCfg; - if (!(flag & BOARD_QUARTZ)) { - - /* Request our IO Range */ - if( !request_region(megaBase, 16, "megaraid") ) - goto err_unregister; + if (flag & BOARD_QUARTZ) { + megaCfg->host->base = tbase; } /* Request our IRQ */ @@ -3143,7 +3179,7 @@ printk (KERN_WARNING "megaraid: Couldn't register IRQ %d!\n", megaIrq); - goto err_release; + goto fail_attach; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) @@ -3265,8 +3301,7 @@ sizeof (mega_mailbox64), (void *) megaCfg->mailbox64ptr, megaCfg->dma_handle64); - scsi_unregister (host); - continue; + goto fail_attach; } /* @@ -3301,14 +3336,17 @@ #endif #endif continue; - err_release: - if (flag & BOARD_QUARTZ) - release_region (megaBase, 16); - err_unregister: - scsi_unregister (host); - err_unmap: - if (flag & BOARD_QUARTZ) - iounmap ((void *) megaBase); +fail_attach: + if( did_mem_map_f ) { + iounmap((void *)megaBase); + release_mem_region(tbase, 128); + } + if( did_io_map_f ) { + release_region(megaBase, 16); + } + if( did_scsi_register_f ) { + scsi_unregister (host); + } } return numFound; } @@ -3408,6 +3446,12 @@ } init_MUTEX (&mimd_entry_mtx); +#ifdef __x86_64__ + /* + * Register the 32-bit ioctl conversion + */ + register_ioctl32_conversion( MEGAIOCCMD, sys_ioctl ); +#endif } return count; @@ -3439,6 +3483,7 @@ /* Free our resources */ if (megaCfg->flag & BOARD_QUARTZ) { iounmap ((void *) megaCfg->base); + release_mem_region(megaCfg->host->base, 128); } else { release_region (megaCfg->host->io_port, 16); } @@ -3485,6 +3530,9 @@ unregister_chrdev (major, "megadev"); unregister_reboot_notifier (&mega_notifier); +#ifdef __x86_64__ + unregister_ioctl32_conversion( MEGAIOCCMD ); +#endif return 0; } @@ -4244,6 +4292,11 @@ proc_printf (megaCfg, "Interrupts Collected = %lu\n", megaCfg->nInterrupts); + proc_printf (megaCfg, "INTERFACE DISABLED\n"); + COPY_BACK; + return count; + +#if 0 // can cause buffer overrun with 40 logical drives and IO information for (i = 0; i < megaCfg->numldrv; i++) { proc_printf (megaCfg, "Logical Drive %d:\n", i); @@ -4259,6 +4312,7 @@ COPY_BACK; return count; +#endif } static int proc_read_status (char *page, char **start, off_t offset, @@ -4896,16 +4950,16 @@ if( kvaddr == NULL ) { printk(KERN_WARNING "megaraid:allocation failed\n"); ret = -ENOMEM; - goto out; + goto out_ioctl_cmd_new; } ioc.ui.fcs.buffer = kvaddr; if (inlen) { /* copyin the user data */ - if (copy_from_user(kvaddr, (char *)uaddr, length )) { - ret = -EFAULT; - goto out; + if( copy_from_user(kvaddr, (char *)uaddr, length ) ) { + ret = -EFAULT; + goto out_ioctl_cmd_new; } } } @@ -4923,7 +4977,7 @@ if( !scsicmd->result && outlen ) { if (copy_to_user(uaddr, kvaddr, length)) { ret = -EFAULT; - goto out; + goto out_ioctl_cmd_new; } } @@ -4944,7 +4999,8 @@ put_user (scsicmd->result, &uioc->mbox[17]); } -out: +out_ioctl_cmd_new: + if (kvaddr) { dma_free_consistent(pdevp, length, kvaddr, dma_addr); } @@ -5045,12 +5101,8 @@ if( kvaddr == NULL ) { printk (KERN_WARNING "megaraid:allocation failed\n"); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /*0x20400 */ - kfree(scsicmd); -#else - scsi_init_free((char *)scsicmd, sizeof(Scsi_Cmnd)); -#endif - return -ENOMEM; + ret = -ENOMEM; + goto out_ioctl_cmd; } ioc.data = kvaddr; @@ -5058,9 +5110,15 @@ if (inlen) { if (ioc.mbox[0] == MEGA_MBOXCMD_PASSTHRU) { /* copyin the user data */ - copy_from_user (kvaddr, uaddr, ioc.pthru.dataxferlen); + if( copy_from_user (kvaddr, uaddr, ioc.pthru.dataxferlen)){ + ret = -EFAULT; + goto out_ioctl_cmd; + } } else { - copy_from_user (kvaddr, uaddr, inlen); + if( copy_from_user (kvaddr, uaddr, inlen) ) { + ret = -EFAULT; + goto out_ioctl_cmd; + } } } } @@ -5078,11 +5136,15 @@ if (!scsicmd->result && outlen) { if (ioc.mbox[0] == MEGA_MBOXCMD_PASSTHRU) { - if (copy_to_user (uaddr, kvaddr, ioc.pthru.dataxferlen)) + if (copy_to_user (uaddr, kvaddr, ioc.pthru.dataxferlen)) { ret = -EFAULT; + goto out_ioctl_cmd; + } } else { - if (copy_to_user (uaddr, kvaddr, outlen)) + if (copy_to_user (uaddr, kvaddr, outlen)) { ret = -EFAULT; + goto out_ioctl_cmd; + } } } @@ -5107,6 +5169,8 @@ put_user (scsicmd->result, &uioc->mbox[17]); /* status */ } +out_ioctl_cmd: + if (kvaddr) { dma_free_consistent(pdevp, PAGE_SIZE, kvaddr, dma_addr ); } diff -Nur linux-2.4.21.org/drivers/scsi/megaraid.h linux-2.4.21/drivers/scsi/megaraid.h --- linux-2.4.21.org/drivers/scsi/megaraid.h 2003-06-13 14:51:36.000000000 +0000 +++ linux-2.4.21/drivers/scsi/megaraid.h 2003-07-07 17:43:59.000000000 +0000 @@ -30,7 +30,8 @@ #define M_RD_IOCTL_CMD_NEW 0x81 #define M_RD_DRIVER_IOCTL_INTERFACE 0x82 -#define MEGARAID_VERSION "v1.18f (Release Date: Tue Dec 10 09:54:39 EST 2002)\n" +#define MEGARAID_VERSION "v1.18j (Release Date: Mon Jul 7 14:39:55 EDT 2003)\n" + #define MEGARAID_IOCTL_VERSION 114 @@ -190,6 +191,7 @@ #define AMI_SUBSYS_ID 0x101E #define DELL_SUBSYS_ID 0x1028 #define HP_SUBSYS_ID 0x103C +#define INTEL_SUBSYS_ID 0x8086 #define AMI_SIGNATURE 0x3344 #define AMI_SIGNATURE_471 0xCCCC @@ -899,7 +901,9 @@ * Defines for Driver IOCTL interface, Op-code:M_RD_DRIVER_IOCTL_INTERFACE */ #define MEGAIOC_MAGIC 'm' -#define MEGAIOCCMD _IOWR(MEGAIOC_MAGIC, 0) /* Mega IOCTL command */ + +/* Mega IOCTL command */ +#define MEGAIOCCMD _IOWR(MEGAIOC_MAGIC, 0, struct uioctl_t) #define MEGAIOC_QNADAP 'm' /* Query # of adapters */ #define MEGAIOC_QDRVRVER 'e' /* Query driver version */