diff options
Diffstat (limited to 'drivers/scsi')
30 files changed, 452 insertions, 571 deletions
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index 867f6fd5c2c0..7045511f9ad2 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -84,6 +84,7 @@ #include <linux/pci.h> #include <linux/time.h> #include <linux/mutex.h> +#include <linux/smp_lock.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/uaccess.h> @@ -862,11 +863,13 @@ out: } /* End twa_chrdev_ioctl() */ /* This function handles open for the character device */ +/* NOTE that this function will race with remove. */ static int twa_chrdev_open(struct inode *inode, struct file *file) { unsigned int minor_number; int retval = TW_IOCTL_ERROR_OS_ENODEV; + cycle_kernel_lock(); minor_number = iminor(inode); if (minor_number >= twa_device_extension_count) goto out; diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index 8c22329aa85e..a0537f09aa21 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -198,6 +198,7 @@ #include <linux/module.h> #include <linux/reboot.h> +#include <linux/smp_lock.h> #include <linux/spinlock.h> #include <linux/interrupt.h> #include <linux/moduleparam.h> @@ -1027,10 +1028,12 @@ out: } /* End tw_chrdev_ioctl() */ /* This function handles open for the character device */ +/* NOTE that this function races with remove. */ static int tw_chrdev_open(struct inode *inode, struct file *file) { unsigned int minor_number; + cycle_kernel_lock(); dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_open()\n"); minor_number = iminor(inode); diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c index ced3eebe252c..84bb61628372 100644 --- a/drivers/scsi/a100u2w.c +++ b/drivers/scsi/a100u2w.c @@ -389,7 +389,7 @@ static u8 orc_load_firmware(struct orc_host * host) outb(PRGMRST | DOWNLOAD, host->base + ORC_RISCCTL); /* Enable SRAM programming */ data32_ptr = (u8 *) & data32; - data32 = 0; /* Initial FW address to 0 */ + data32 = cpu_to_le32(0); /* Initial FW address to 0 */ outw(0x0010, host->base + ORC_EBIOSADR0); *data32_ptr = inb(host->base + ORC_EBIOSDATA); /* Read from BIOS */ outw(0x0011, host->base + ORC_EBIOSADR0); @@ -397,18 +397,19 @@ static u8 orc_load_firmware(struct orc_host * host) outw(0x0012, host->base + ORC_EBIOSADR0); *(data32_ptr + 2) = inb(host->base + ORC_EBIOSDATA); /* Read from BIOS */ outw(*(data32_ptr + 2), host->base + ORC_EBIOSADR2); - outl(data32, host->base + ORC_FWBASEADR); /* Write FW address */ + outl(le32_to_cpu(data32), host->base + ORC_FWBASEADR); /* Write FW address */ /* Copy the code from the BIOS to the SRAM */ - bios_addr = (u16) data32; /* FW code locate at BIOS address + ? */ + udelay(500); /* Required on Sun Ultra 5 ... 350 -> failures */ + bios_addr = (u16) le32_to_cpu(data32); /* FW code locate at BIOS address + ? */ for (i = 0, data32_ptr = (u8 *) & data32; /* Download the code */ i < 0x1000; /* Firmware code size = 4K */ i++, bios_addr++) { outw(bios_addr, host->base + ORC_EBIOSADR0); *data32_ptr++ = inb(host->base + ORC_EBIOSDATA); /* Read from BIOS */ if ((i % 4) == 3) { - outl(data32, host->base + ORC_RISCRAM); /* Write every 4 bytes */ + outl(le32_to_cpu(data32), host->base + ORC_RISCRAM); /* Write every 4 bytes */ data32_ptr = (u8 *) & data32; } } @@ -423,7 +424,7 @@ static u8 orc_load_firmware(struct orc_host * host) outw(bios_addr, host->base + ORC_EBIOSADR0); *data32_ptr++ = inb(host->base + ORC_EBIOSDATA); /* Read from BIOS */ if ((i % 4) == 3) { - if (inl(host->base + ORC_RISCRAM) != data32) { + if (inl(host->base + ORC_RISCRAM) != le32_to_cpu(data32)) { outb(PRGMRST, host->base + ORC_RISCCTL); /* Reset program to 0 */ outb(data, host->base + ORC_GCFG); /*Disable EEPROM programming */ return 0; @@ -459,8 +460,8 @@ static void setup_SCBs(struct orc_host * host) for (i = 0; i < ORC_MAXQUEUE; i++) { escb_phys = (host->escb_phys + (sizeof(struct orc_extended_scb) * i)); - scb->sg_addr = (u32) escb_phys; - scb->sense_addr = (u32) escb_phys; + scb->sg_addr = cpu_to_le32((u32) escb_phys); + scb->sense_addr = cpu_to_le32((u32) escb_phys); scb->escb = escb; scb->scbidx = i; scb++; @@ -642,8 +643,8 @@ static int orc_device_reset(struct orc_host * host, struct scsi_cmnd *cmd, unsig scb->link = 0xFF; scb->reserved0 = 0; scb->reserved1 = 0; - scb->xferlen = 0; - scb->sg_len = 0; + scb->xferlen = cpu_to_le32(0); + scb->sg_len = cpu_to_le32(0); escb->srb = NULL; escb->srb = cmd; @@ -839,7 +840,7 @@ static irqreturn_t orc_interrupt(struct orc_host * host) * Build a host adapter control block from the SCSI mid layer command */ -static void inia100_build_scb(struct orc_host * host, struct orc_scb * scb, struct scsi_cmnd * cmd) +static int inia100_build_scb(struct orc_host * host, struct orc_scb * scb, struct scsi_cmnd * cmd) { /* Create corresponding SCB */ struct scatterlist *sg; struct orc_sgent *sgent; /* Pointer to SG list */ @@ -858,28 +859,30 @@ static void inia100_build_scb(struct orc_host * host, struct orc_scb * scb, stru scb->lun = cmd->device->lun; scb->reserved0 = 0; scb->reserved1 = 0; - scb->sg_len = 0; + scb->sg_len = cpu_to_le32(0); - scb->xferlen = (u32) scsi_bufflen(cmd); + scb->xferlen = cpu_to_le32((u32) scsi_bufflen(cmd)); sgent = (struct orc_sgent *) & escb->sglist[0]; count_sg = scsi_dma_map(cmd); - BUG_ON(count_sg < 0); + if (count_sg < 0) + return count_sg; + BUG_ON(count_sg > TOTAL_SG_ENTRY); /* Build the scatter gather lists */ if (count_sg) { - scb->sg_len = (u32) (count_sg * 8); + scb->sg_len = cpu_to_le32((u32) (count_sg * 8)); scsi_for_each_sg(cmd, sg, count_sg, i) { - sgent->base = (u32) sg_dma_address(sg); - sgent->length = (u32) sg_dma_len(sg); + sgent->base = cpu_to_le32((u32) sg_dma_address(sg)); + sgent->length = cpu_to_le32((u32) sg_dma_len(sg)); sgent++; } } else { - scb->sg_len = 0; - sgent->base = 0; - sgent->length = 0; + scb->sg_len = cpu_to_le32(0); + sgent->base = cpu_to_le32(0); + sgent->length = cpu_to_le32(0); } - scb->sg_addr = (u32) scb->sense_addr; + scb->sg_addr = (u32) scb->sense_addr; /* sense_addr is already little endian */ scb->hastat = 0; scb->tastat = 0; scb->link = 0xFF; @@ -896,6 +899,7 @@ static void inia100_build_scb(struct orc_host * host, struct orc_scb * scb, stru scb->tag_msg = 0; /* No tag support */ } memcpy(scb->cdb, cmd->cmnd, scb->cdb_len); + return 0; } /** @@ -919,7 +923,10 @@ static int inia100_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd if ((scb = orc_alloc_scb(host)) == NULL) return SCSI_MLQUEUE_HOST_BUSY; - inia100_build_scb(host, scb, cmd); + if (inia100_build_scb(host, scb, cmd)) { + orc_release_scb(host, scb); + return SCSI_MLQUEUE_HOST_BUSY; + } orc_exec_scb(host, scb); /* Start execute SCB */ return 0; } diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 5797b2c42f08..9aa301c1ed07 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -38,6 +38,7 @@ #include <linux/moduleparam.h> #include <linux/pci.h> #include <linux/slab.h> +#include <linux/smp_lock.h> #include <linux/spinlock.h> #include <linux/syscalls.h> #include <linux/delay.h> @@ -667,6 +668,7 @@ static int aac_cfg_open(struct inode *inode, struct file *file) unsigned minor_number = iminor(inode); int err = -ENODEV; + lock_kernel(); /* BKL pushdown: nothing else protects this list */ list_for_each_entry(aac, &aac_devices, entry) { if (aac->id == minor_number) { file->private_data = aac; @@ -674,6 +676,7 @@ static int aac_cfg_open(struct inode *inode, struct file *file) break; } } + unlock_kernel(); return err; } diff --git a/drivers/scsi/aic94xx/aic94xx_sds.c b/drivers/scsi/aic94xx/aic94xx_sds.c index 4446e3d584dc..8630a75b2872 100644 --- a/drivers/scsi/aic94xx/aic94xx_sds.c +++ b/drivers/scsi/aic94xx/aic94xx_sds.c @@ -1093,9 +1093,9 @@ out: * @bytes_to_verify: total bytes to verify */ int asd_verify_flash_seg(struct asd_ha_struct *asd_ha, - void *src, u32 dest_offset, u32 bytes_to_verify) + const void *src, u32 dest_offset, u32 bytes_to_verify) { - u8 *src_buf; + const u8 *src_buf; u8 flash_char; int err; u32 nv_offset, reg, i; @@ -1105,7 +1105,7 @@ int asd_verify_flash_seg(struct asd_ha_struct *asd_ha, err = FLASH_OK; nv_offset = dest_offset; - src_buf = (u8 *)src; + src_buf = (const u8 *)src; for (i = 0; i < bytes_to_verify; i++) { flash_char = asd_read_reg_byte(asd_ha, reg + nv_offset + i); if (flash_char != src_buf[i]) { @@ -1124,9 +1124,9 @@ int asd_verify_flash_seg(struct asd_ha_struct *asd_ha, * @bytes_to_write: total bytes to write */ int asd_write_flash_seg(struct asd_ha_struct *asd_ha, - void *src, u32 dest_offset, u32 bytes_to_write) + const void *src, u32 dest_offset, u32 bytes_to_write) { - u8 *src_buf; + const u8 *src_buf; u32 nv_offset, reg, i; int err; @@ -1153,7 +1153,7 @@ int asd_write_flash_seg(struct asd_ha_struct *asd_ha, return err; } - src_buf = (u8 *)src; + src_buf = (const u8 *)src; for (i = 0; i < bytes_to_write; i++) { /* Setup program command sequence */ switch (asd_ha->hw_prof.flash.method) { diff --git a/drivers/scsi/aic94xx/aic94xx_sds.h b/drivers/scsi/aic94xx/aic94xx_sds.h index bb9795a04dc3..a06dc0114b8c 100644 --- a/drivers/scsi/aic94xx/aic94xx_sds.h +++ b/drivers/scsi/aic94xx/aic94xx_sds.h @@ -110,9 +110,9 @@ struct bios_file_header { }; int asd_verify_flash_seg(struct asd_ha_struct *asd_ha, - void *src, u32 dest_offset, u32 bytes_to_verify); + const void *src, u32 dest_offset, u32 bytes_to_verify); int asd_write_flash_seg(struct asd_ha_struct *asd_ha, - void *src, u32 dest_offset, u32 bytes_to_write); + const void *src, u32 dest_offset, u32 bytes_to_write); int asd_chk_write_status(struct asd_ha_struct *asd_ha, u32 sector_addr, u8 erase_flag); int asd_check_flash_type(struct asd_ha_struct *asd_ha); diff --git a/drivers/scsi/aic94xx/aic94xx_seq.c b/drivers/scsi/aic94xx/aic94xx_seq.c index f4272ac4c685..8f98e33155e9 100644 --- a/drivers/scsi/aic94xx/aic94xx_seq.c +++ b/drivers/scsi/aic94xx/aic94xx_seq.c @@ -46,7 +46,7 @@ static const struct firmware *sequencer_fw; static u16 cseq_vecs[CSEQ_NUM_VECS], lseq_vecs[LSEQ_NUM_VECS], mode2_task, cseq_idle_loop, lseq_idle_loop; -static u8 *cseq_code, *lseq_code; +static const u8 *cseq_code, *lseq_code; static u32 cseq_code_size, lseq_code_size; static u16 first_scb_site_no = 0xFFFF; @@ -1235,7 +1235,8 @@ int asd_release_firmware(void) static int asd_request_firmware(struct asd_ha_struct *asd_ha) { int err, i; - struct sequencer_file_header header, *hdr_ptr; + struct sequencer_file_header header; + const struct sequencer_file_header *hdr_ptr; u32 csum = 0; u16 *ptr_cseq_vecs, *ptr_lseq_vecs; @@ -1249,7 +1250,7 @@ static int asd_request_firmware(struct asd_ha_struct *asd_ha) if (err) return err; - hdr_ptr = (struct sequencer_file_header *)sequencer_fw->data; + hdr_ptr = (const struct sequencer_file_header *)sequencer_fw->data; header.csum = le32_to_cpu(hdr_ptr->csum); header.major = le32_to_cpu(hdr_ptr->major); diff --git a/drivers/scsi/arm/Kconfig b/drivers/scsi/arm/Kconfig index 7236143941f3..a8587f1f5e7e 100644 --- a/drivers/scsi/arm/Kconfig +++ b/drivers/scsi/arm/Kconfig @@ -3,7 +3,7 @@ # config SCSI_ACORNSCSI_3 tristate "Acorn SCSI card (aka30) support" - depends on ARCH_ACORN && SCSI && BROKEN + depends on ARCH_ACORN && SCSI select SCSI_SPI_ATTRS help This enables support for the Acorn SCSI card (aka30). If you have an diff --git a/drivers/scsi/arm/acornscsi-io.S b/drivers/scsi/arm/acornscsi-io.S index 93467e6ac923..5cebe3105260 100644 --- a/drivers/scsi/arm/acornscsi-io.S +++ b/drivers/scsi/arm/acornscsi-io.S @@ -10,17 +10,10 @@ #include <asm/assembler.h> #include <asm/hardware.h> -#if (IO_BASE == (PCIO_BASE & 0xff000000)) -#define ADDR(off,reg) \ - tst off, $0x80000000 ;\ - mov reg, $IO_BASE ;\ - orreq reg, reg, $(PCIO_BASE & 0x00ff0000) -#else -#define ADDR(off,reg) \ - tst off, $0x80000000 ;\ - movne reg, $IO_BASE ;\ - moveq reg, $(PCIO_BASE & 0xff000000) ;\ - orreq reg, reg, $(PCIO_BASE & 0x00ff0000) +#if defined(__APCS_32__) +#define LOADREGS(t,r,l...) ldm##t r, l +#elif defined(__APCS_26__) +#define LOADREGS(t,r,l...) ldm##t r, l##^ #endif @ Purpose: transfer a block of data from the acorn scsi card to memory diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c index 8e53f02cc311..918ccf818757 100644 --- a/drivers/scsi/arm/acornscsi.c +++ b/drivers/scsi/arm/acornscsi.c @@ -123,12 +123,6 @@ #define DBG(cmd,xxx...) xxx #endif -#ifndef STRINGIFY -#define STRINGIFY(x) #x -#endif -#define STRx(x) STRINGIFY(x) -#define NO_WRITE_STR STRx(NO_WRITE) - #include <linux/module.h> #include <linux/kernel.h> #include <linux/string.h> @@ -141,9 +135,10 @@ #include <linux/interrupt.h> #include <linux/init.h> #include <linux/bitops.h> +#include <linux/stringify.h> +#include <linux/io.h> #include <asm/system.h> -#include <asm/io.h> #include <asm/ecard.h> #include "../scsi.h" @@ -203,44 +198,46 @@ static void acornscsi_abortcmd(AS_Host *host, unsigned char tag); * Miscellaneous */ -static inline void -sbic_arm_write(unsigned int io_port, int reg, int value) +/* Offsets from MEMC base */ +#define SBIC_REGIDX 0x2000 +#define SBIC_REGVAL 0x2004 +#define DMAC_OFFSET 0x3000 + +/* Offsets from FAST IOC base */ +#define INT_REG 0x2000 +#define PAGE_REG 0x3000 + +static inline void sbic_arm_write(AS_Host *host, unsigned int reg, unsigned int value) { - __raw_writeb(reg, io_port); - __raw_writeb(value, io_port + 4); + writeb(reg, host->base + SBIC_REGIDX); + writeb(value, host->base + SBIC_REGVAL); } -#define sbic_arm_writenext(io,val) \ - __raw_writeb((val), (io) + 4) - -static inline -int sbic_arm_read(unsigned int io_port, int reg) +static inline int sbic_arm_read(AS_Host *host, unsigned int reg) { if(reg == SBIC_ASR) - return __raw_readl(io_port) & 255; - __raw_writeb(reg, io_port); - return __raw_readl(io_port + 4) & 255; + return readl(host->base + SBIC_REGIDX) & 255; + writeb(reg, host->base + SBIC_REGIDX); + return readl(host->base + SBIC_REGVAL) & 255; } -#define sbic_arm_readnext(io) \ - __raw_readb((io) + 4) +#define sbic_arm_writenext(host, val) writeb((val), (host)->base + SBIC_REGVAL) +#define sbic_arm_readnext(host) readb((host)->base + SBIC_REGVAL) #ifdef USE_DMAC -#define dmac_read(io_port,reg) \ - inb((io_port) + (reg)) +#define dmac_read(host,reg) \ + readb((host)->base + DMAC_OFFSET + ((reg) << 2)) -#define dmac_write(io_port,reg,value) \ - ({ outb((value), (io_port) + (reg)); }) +#define dmac_write(host,reg,value) \ + ({ writeb((value), (host)->base + DMAC_OFFSET + ((reg) << 2)); }) -#define dmac_clearintr(io_port) \ - ({ outb(0, (io_port)); }) +#define dmac_clearintr(host) writeb(0, (host)->fast + INT_REG) -static inline -unsigned int dmac_address(unsigned int io_port) +static inline unsigned int dmac_address(AS_Host *host) { - return dmac_read(io_port, DMAC_TXADRHI) << 16 | - dmac_read(io_port, DMAC_TXADRMD) << 8 | - dmac_read(io_port, DMAC_TXADRLO); + return dmac_read(host, DMAC_TXADRHI) << 16 | + dmac_read(host, DMAC_TXADRMD) << 8 | + dmac_read(host, DMAC_TXADRLO); } static @@ -248,15 +245,15 @@ void acornscsi_dumpdma(AS_Host *host, char *where) { unsigned int mode, addr, len; - mode = dmac_read(host->dma.io_port, DMAC_MODECON); - addr = dmac_address(host->dma.io_port); - len = dmac_read(host->dma.io_port, DMAC_TXCNTHI) << 8 | - dmac_read(host->dma.io_port, DMAC_TXCNTLO); + mode = dmac_read(host, DMAC_MODECON); + addr = dmac_address(host); + len = dmac_read(host, DMAC_TXCNTHI) << 8 | + dmac_read(host, DMAC_TXCNTLO); printk("scsi%d: %s: DMAC %02x @%06x+%04x msk %02x, ", host->host->host_no, where, mode, addr, (len + 1) & 0xffff, - dmac_read(host->dma.io_port, DMAC_MASKREG)); + dmac_read(host, DMAC_MASKREG)); printk("DMA @%06x, ", host->dma.start_addr); printk("BH @%p +%04x, ", host->scsi.SCp.ptr, @@ -272,9 +269,9 @@ unsigned long acornscsi_sbic_xfcount(AS_Host *host) { unsigned long length; - length = sbic_arm_read(host->scsi.io_port, SBIC_TRANSCNTH) << 16; - length |= sbic_arm_readnext(host->scsi.io_port) << 8; - length |= sbic_arm_readnext(host->scsi.io_port); + length = sbic_arm_read(host, SBIC_TRANSCNTH) << 16; + length |= sbic_arm_readnext(host) << 8; + length |= sbic_arm_readnext(host); return length; } @@ -285,7 +282,7 @@ acornscsi_sbic_wait(AS_Host *host, int stat_mask, int stat, int timeout, char *m int asr; do { - asr = sbic_arm_read(host->scsi.io_port, SBIC_ASR); + asr = sbic_arm_read(host, SBIC_ASR); if ((asr & stat_mask) == stat) return 0; @@ -304,7 +301,7 @@ int acornscsi_sbic_issuecmd(AS_Host *host, int command) if (acornscsi_sbic_wait(host, ASR_CIP, 0, 1000, "issuing command")) return -1; - sbic_arm_write(host->scsi.io_port, SBIC_CMND, command); + sbic_arm_write(host, SBIC_CMND, command); return 0; } @@ -331,20 +328,20 @@ void acornscsi_resetcard(AS_Host *host) /* assert reset line */ host->card.page_reg = 0x80; - outb(host->card.page_reg, host->card.io_page); + writeb(host->card.page_reg, host->fast + PAGE_REG); /* wait 3 cs. SCSI standard says 25ms. */ acornscsi_csdelay(3); host->card.page_reg = 0; - outb(host->card.page_reg, host->card.io_page); + writeb(host->card.page_reg, host->fast + PAGE_REG); /* * Should get a reset from the card */ timeout = 1000; do { - if (inb(host->card.io_intr) & 8) + if (readb(host->fast + INT_REG) & 8) break; udelay(1); } while (--timeout); @@ -353,19 +350,19 @@ void acornscsi_resetcard(AS_Host *host) printk("scsi%d: timeout while resetting card\n", host->host->host_no); - sbic_arm_read(host->scsi.io_port, SBIC_ASR); - sbic_arm_read(host->scsi.io_port, SBIC_SSR); + sbic_arm_read(host, SBIC_ASR); + sbic_arm_read(host, SBIC_SSR); /* setup sbic - WD33C93A */ - sbic_arm_write(host->scsi.io_port, SBIC_OWNID, OWNID_EAF | host->host->this_id); - sbic_arm_write(host->scsi.io_port, SBIC_CMND, CMND_RESET); + sbic_arm_write(host, SBIC_OWNID, OWNID_EAF | host->host->this_id); + sbic_arm_write(host, SBIC_CMND, CMND_RESET); /* * Command should cause a reset interrupt */ timeout = 1000; do { - if (inb(host->card.io_intr) & 8) + if (readb(host->fast + INT_REG) & 8) break; udelay(1); } while (--timeout); @@ -374,26 +371,26 @@ void acornscsi_resetcard(AS_Host *host) printk("scsi%d: timeout while resetting card\n", host->host->host_no); - sbic_arm_read(host->scsi.io_port, SBIC_ASR); - if (sbic_arm_read(host->scsi.io_port, SBIC_SSR) != 0x01) + sbic_arm_read(host, SBIC_ASR); + if (sbic_arm_read(host, SBIC_SSR) != 0x01) printk(KERN_CRIT "scsi%d: WD33C93A didn't give enhanced reset interrupt\n", host->host->host_no); - sbic_arm_write(host->scsi.io_port, SBIC_CTRL, INIT_SBICDMA | CTRL_IDI); - sbic_arm_write(host->scsi.io_port, SBIC_TIMEOUT, TIMEOUT_TIME); - sbic_arm_write(host->scsi.io_port, SBIC_SYNCHTRANSFER, SYNCHTRANSFER_2DBA); - sbic_arm_write(host->scsi.io_port, SBIC_SOURCEID, SOURCEID_ER | SOURCEID_DSP); + sbic_arm_write(host, SBIC_CTRL, INIT_SBICDMA | CTRL_IDI); + sbic_arm_write(host, SBIC_TIMEOUT, TIMEOUT_TIME); + sbic_arm_write(host, SBIC_SYNCHTRANSFER, SYNCHTRANSFER_2DBA); + sbic_arm_write(host, SBIC_SOURCEID, SOURCEID_ER | SOURCEID_DSP); host->card.page_reg = 0x40; - outb(host->card.page_reg, host->card.io_page); + writeb(host->card.page_reg, host->fast + PAGE_REG); /* setup dmac - uPC71071 */ - dmac_write(host->dma.io_port, DMAC_INIT, 0); + dmac_write(host, DMAC_INIT, 0); #ifdef USE_DMAC - dmac_write(host->dma.io_port, DMAC_INIT, INIT_8BIT); - dmac_write(host->dma.io_port, DMAC_CHANNEL, CHANNEL_0); - dmac_write(host->dma.io_port, DMAC_DEVCON0, INIT_DEVCON0); - dmac_write(host->dma.io_port, DMAC_DEVCON1, INIT_DEVCON1); + dmac_write(host, DMAC_INIT, INIT_8BIT); + dmac_write(host, DMAC_CHANNEL, CHANNEL_0); + dmac_write(host, DMAC_DEVCON0, INIT_DEVCON0); + dmac_write(host, DMAC_DEVCON1, INIT_DEVCON1); #endif host->SCpnt = NULL; @@ -741,9 +738,9 @@ intr_ret_t acornscsi_kick(AS_Host *host) * If we have an interrupt pending, then we may have been reselected. * In this case, we don't want to write to the registers */ - if (!(sbic_arm_read(host->scsi.io_port, SBIC_ASR) & (ASR_INT|ASR_BSY|ASR_CIP))) { - sbic_arm_write(host->scsi.io_port, SBIC_DESTID, SCpnt->device->id); - sbic_arm_write(host->scsi.io_port, SBIC_CMND, CMND_SELWITHATN); + if (!(sbic_arm_read(host, SBIC_ASR) & (ASR_INT|ASR_BSY|ASR_CIP))) { + sbic_arm_write(host, SBIC_DESTID, SCpnt->device->id); + sbic_arm_write(host, SBIC_CMND, CMND_SELWITHATN); } /* @@ -807,7 +804,7 @@ static void acornscsi_done(AS_Host *host, struct scsi_cmnd **SCpntp, struct scsi_cmnd *SCpnt = *SCpntp; /* clean up */ - sbic_arm_write(host->scsi.io_port, SBIC_SOURCEID, SOURCEID_ER | SOURCEID_DSP); + sbic_arm_write(host, SBIC_SOURCEID, SOURCEID_ER | SOURCEID_DSP); host->stats.fins += 1; @@ -918,13 +915,13 @@ static void acornscsi_data_read(AS_Host *host, char *ptr, unsigned int start_addr, unsigned int length) { - extern void __acornscsi_in(int port, char *buf, int len); + extern void __acornscsi_in(void __iomem *, char *buf, int len); unsigned int page, offset, len = length; page = (start_addr >> 12); offset = start_addr & ((1 << 12) - 1); - outb((page & 0x3f) | host->card.page_reg, host->card.io_page); + writeb((page & 0x3f) | host->card.page_reg, host->fast + PAGE_REG); while (len > 0) { unsigned int this_len; @@ -934,7 +931,7 @@ void acornscsi_data_read(AS_Host *host, char *ptr, else this_len = len; - __acornscsi_in(host->card.io_ram + (offset << 1), ptr, this_len); + __acornscsi_in(host->base + (offset << 1), ptr, this_len); offset += this_len; ptr += this_len; @@ -943,10 +940,10 @@ void acornscsi_data_read(AS_Host *host, char *ptr, if (offset == (1 << 12)) { offset = 0; page ++; - outb((page & 0x3f) | host->card.page_reg, host->card.io_page); + writeb((page & 0x3f) | host->card.page_reg, host->fast + PAGE_REG); } } - outb(host->card.page_reg, host->card.io_page); + writeb(host->card.page_reg, host->fast + PAGE_REG); } /* @@ -963,13 +960,13 @@ static void acornscsi_data_write(AS_Host *host, char *ptr, unsigned int start_addr, unsigned int length) { - extern void __acornscsi_out(int port, char *buf, int len); + extern void __acornscsi_out(void __iomem *, char *buf, int len); unsigned int page, offset, len = length; page = (start_addr >> 12); offset = start_addr & ((1 << 12) - 1); - outb((page & 0x3f) | host->card.page_reg, host->card.io_page); + writeb((page & 0x3f) | host->card.page_reg, host->fast + PAGE_REG); while (len > 0) { unsigned int this_len; @@ -979,7 +976,7 @@ void acornscsi_data_write(AS_Host *host, char *ptr, else this_len = len; - __acornscsi_out(host->card.io_ram + (offset << 1), ptr, this_len); + __acornscsi_out(host->base + (offset << 1), ptr, this_len); offset += this_len; ptr += this_len; @@ -988,10 +985,10 @@ void acornscsi_data_write(AS_Host *host, char *ptr, if (offset == (1 << 12)) { offset = 0; page ++; - outb((page & 0x3f) | host->card.page_reg, host->card.io_page); + writeb((page & 0x3f) | host->card.page_reg, host->fast + PAGE_REG); } } - outb(host->card.page_reg, host->card.io_page); + writeb(host->card.page_reg, host->fast + PAGE_REG); } /* ========================================================================================= @@ -1008,8 +1005,8 @@ void acornscsi_data_write(AS_Host *host, char *ptr, static inline void acornscsi_dma_stop(AS_Host *host) { - dmac_write(host->dma.io_port, DMAC_MASKREG, MASK_ON); - dmac_clearintr(host->dma.io_intr_clear); + dmac_write(host, DMAC_MASKREG, MASK_ON); + dmac_clearintr(host); #if (DEBUG & DEBUG_DMA) DBG(host->SCpnt, acornscsi_dumpdma(host, "stop")); @@ -1031,7 +1028,7 @@ void acornscsi_dma_setup(AS_Host *host, dmadir_t direction) host->dma.direction = direction; - dmac_write(host->dma.io_port, DMAC_MASKREG, MASK_ON); + dmac_write(host, DMAC_MASKREG, MASK_ON); if (direction == DMA_OUT) { #if (DEBUG & DEBUG_NO_WRITE) @@ -1062,13 +1059,13 @@ void acornscsi_dma_setup(AS_Host *host, dmadir_t direction) length); length -= 1; - dmac_write(host->dma.io_port, DMAC_TXCNTLO, length); - dmac_write(host->dma.io_port, DMAC_TXCNTHI, length >> 8); - dmac_write(host->dma.io_port, DMAC_TXADRLO, address); - dmac_write(host->dma.io_port, DMAC_TXADRMD, address >> 8); - dmac_write(host->dma.io_port, DMAC_TXADRHI, 0); - dmac_write(host->dma.io_port, DMAC_MODECON, mode); - dmac_write(host->dma.io_port, DMAC_MASKREG, MASK_OFF); + dmac_write(host, DMAC_TXCNTLO, length); + dmac_write(host, DMAC_TXCNTHI, length >> 8); + dmac_write(host, DMAC_TXADRLO, address); + dmac_write(host, DMAC_TXADRMD, address >> 8); + dmac_write(host, DMAC_TXADRHI, 0); + dmac_write(host, DMAC_MODECON, mode); + dmac_write(host, DMAC_MASKREG, MASK_OFF); #if (DEBUG & DEBUG_DMA) DBG(host->SCpnt, acornscsi_dumpdma(host, "strt")); @@ -1088,8 +1085,8 @@ void acornscsi_dma_setup(AS_Host *host, dmadir_t direction) static void acornscsi_dma_cleanup(AS_Host *host) { - dmac_write(host->dma.io_port, DMAC_MASKREG, MASK_ON); - dmac_clearintr(host->dma.io_intr_clear); + dmac_write(host, DMAC_MASKREG, MASK_ON); + dmac_clearintr(host); /* * Check for a pending transfer @@ -1116,7 +1113,7 @@ void acornscsi_dma_cleanup(AS_Host *host) /* * Calculate number of bytes transferred from DMA. */ - transferred = dmac_address(host->dma.io_port) - host->dma.start_addr; + transferred = dmac_address(host) - host->dma.start_addr; host->dma.transferred += transferred; if (host->dma.direction == DMA_IN) @@ -1152,13 +1149,13 @@ void acornscsi_dma_intr(AS_Host *host) DBG(host->SCpnt, acornscsi_dumpdma(host, "inti")); #endif - dmac_write(host->dma.io_port, DMAC_MASKREG, MASK_ON); - dmac_clearintr(host->dma.io_intr_clear); + dmac_write(host, DMAC_MASKREG, MASK_ON); + dmac_clearintr(host); /* * Calculate amount transferred via DMA */ - transferred = dmac_address(host->dma.io_port) - host->dma.start_addr; + transferred = dmac_address(host) - host->dma.start_addr; host->dma.transferred += transferred; /* @@ -1190,12 +1187,12 @@ void acornscsi_dma_intr(AS_Host *host) length); length -= 1; - dmac_write(host->dma.io_port, DMAC_TXCNTLO, length); - dmac_write(host->dma.io_port, DMAC_TXCNTHI, length >> 8); - dmac_write(host->dma.io_port, DMAC_TXADRLO, address); - dmac_write(host->dma.io_port, DMAC_TXADRMD, address >> 8); - dmac_write(host->dma.io_port, DMAC_TXADRHI, 0); - dmac_write(host->dma.io_port, DMAC_MASKREG, MASK_OFF); + dmac_write(host, DMAC_TXCNTLO, length); + dmac_write(host, DMAC_TXCNTHI, length >> 8); + dmac_write(host, DMAC_TXADRLO, address); + dmac_write(host, DMAC_TXADRMD, address >> 8); + dmac_write(host, DMAC_TXADRHI, 0); + dmac_write(host, DMAC_MASKREG, MASK_OFF); #if (DEBUG & DEBUG_DMA) DBG(host->SCpnt, acornscsi_dumpdma(host, "into")); @@ -1209,15 +1206,15 @@ void acornscsi_dma_intr(AS_Host *host) * attention condition. We continue giving one byte until * the device recognises the attention. */ - if (dmac_read(host->dma.io_port, DMAC_STATUS) & STATUS_RQ0) { + if (dmac_read(host, DMAC_STATUS) & STATUS_RQ0) { acornscsi_abortcmd(host, host->SCpnt->tag); - dmac_write(host->dma.io_port, DMAC_TXCNTLO, 0); - dmac_write(host->dma.io_port, DMAC_TXCNTHI, 0); - dmac_write(host->dma.io_port, DMAC_TXADRLO, 0); - dmac_write(host->dma.io_port, DMAC_TXADRMD, 0); - dmac_write(host->dma.io_port, DMAC_TXADRHI, 0); - dmac_write(host->dma.io_port, DMAC_MASKREG, MASK_OFF); + dmac_write(host, DMAC_TXCNTLO, 0); + dmac_write(host, DMAC_TXCNTHI, 0); + dmac_write(host, DMAC_TXADRLO, 0); + dmac_write(host, DMAC_TXADRMD, 0); + dmac_write(host, DMAC_TXADRHI, 0); + dmac_write(host, DMAC_MASKREG, MASK_OFF); } #endif } @@ -1271,9 +1268,9 @@ void acornscsi_dma_adjust(AS_Host *host) host->dma.xfer_setup = 0; else { transferred += host->dma.start_addr; - dmac_write(host->dma.io_port, DMAC_TXADRLO, transferred); - dmac_write(host->dma.io_port, DMAC_TXADRMD, transferred >> 8); - dmac_write(host->dma.io_port, DMAC_TXADRHI, transferred >> 16); + dmac_write(host, DMAC_TXADRLO, transferred); + dmac_write(host, DMAC_TXADRMD, transferred >> 8); + dmac_write(host, DMAC_TXADRHI, transferred >> 16); #if (DEBUG & (DEBUG_DMA|DEBUG_WRITE)) DBG(host->SCpnt, acornscsi_dumpdma(host, "adjo")); #endif @@ -1292,12 +1289,12 @@ acornscsi_write_pio(AS_Host *host, char *bytes, int *ptr, int len, unsigned int int my_ptr = *ptr; while (my_ptr < len) { - asr = sbic_arm_read(host->scsi.io_port, SBIC_ASR); + asr = sbic_arm_read(host, SBIC_ASR); if (asr & ASR_DBR) { timeout = max_timeout; - sbic_arm_write(host->scsi.io_port, SBIC_DATA, bytes[my_ptr++]); + sbic_arm_write(host, SBIC_DATA, bytes[my_ptr++]); } else if (asr & ASR_INT) break; else if (--timeout == 0) @@ -1320,9 +1317,9 @@ acornscsi_sendcommand(AS_Host *host) { struct scsi_cmnd *SCpnt = host->SCpnt; - sbic_arm_write(host->scsi.io_port, SBIC_TRANSCNTH, 0); - sbic_arm_writenext(host->scsi.io_port, 0); - sbic_arm_writenext(host->scsi.io_port, SCpnt->cmd_len - host->scsi.SCp.sent_command); + sbic_arm_write(host, SBIC_TRANSCNTH, 0); + sbic_arm_writenext(host, 0); + sbic_arm_writenext(host, SCpnt->cmd_len - host->scsi.SCp.sent_command); acornscsi_sbic_issuecmd(host, CMND_XFERINFO); @@ -1351,7 +1348,7 @@ void acornscsi_sendmessage(AS_Host *host) acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 1"); - sbic_arm_write(host->scsi.io_port, SBIC_DATA, NOP); + sbic_arm_write(host, SBIC_DATA, NOP); host->scsi.last_message = NOP; #if (DEBUG & DEBUG_MESSAGES) @@ -1365,7 +1362,7 @@ void acornscsi_sendmessage(AS_Host *host) acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 2"); - sbic_arm_write(host->scsi.io_port, SBIC_DATA, msg->msg[0]); + sbic_arm_write(host, SBIC_DATA, msg->msg[0]); host->scsi.last_message = msg->msg[0]; #if (DEBUG & DEBUG_MESSAGES) @@ -1382,9 +1379,9 @@ void acornscsi_sendmessage(AS_Host *host) * initiator. This provides an interlock so that the * initiator can determine which message byte is rejected. */ - sbic_arm_write(host->scsi.io_port, SBIC_TRANSCNTH, 0); - sbic_arm_writenext(host->scsi.io_port, 0); - sbic_arm_writenext(host->scsi.io_port, message_length); + sbic_arm_write(host, SBIC_TRANSCNTH, 0); + sbic_arm_writenext(host, 0); + sbic_arm_writenext(host, message_length); acornscsi_sbic_issuecmd(host, CMND_XFERINFO); msgnr = 0; @@ -1421,7 +1418,7 @@ void acornscsi_readstatusbyte(AS_Host *host) { acornscsi_sbic_issuecmd(host, CMND_XFERINFO|CMND_SBT); acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "reading status byte"); - host->scsi.SCp.Status = sbic_arm_read(host->scsi.io_port, SBIC_DATA); + host->scsi.SCp.Status = sbic_arm_read(host, SBIC_DATA); } /* @@ -1438,12 +1435,12 @@ unsigned char acornscsi_readmessagebyte(AS_Host *host) acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "for message byte"); - message = sbic_arm_read(host->scsi.io_port, SBIC_DATA); + message = sbic_arm_read(host, SBIC_DATA); /* wait for MSGIN-XFER-PAUSED */ acornscsi_sbic_wait(host, ASR_INT, ASR_INT, 1000, "for interrupt after message byte"); - sbic_arm_read(host->scsi.io_port, SBIC_SSR); + sbic_arm_read(host, SBIC_SSR); return message; } @@ -1480,7 +1477,7 @@ void acornscsi_message(AS_Host *host) /* wait for next msg-in */ acornscsi_sbic_wait(host, ASR_INT, ASR_INT, 1000, "for interrupt after negate ack"); - sbic_arm_read(host->scsi.io_port, SBIC_SSR); + sbic_arm_read(host, SBIC_SSR); } } while (msgidx < msglen); @@ -1602,7 +1599,7 @@ void acornscsi_message(AS_Host *host) host->host->host_no, acornscsi_target(host)); host->device[host->SCpnt->device->id].sync_xfer = SYNCHTRANSFER_2DBA; host->device[host->SCpnt->device->id].sync_state = SYNC_ASYNCHRONOUS; - sbic_arm_write(host->scsi.io_port, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); + sbic_arm_write(host, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); break; default: @@ -1652,7 +1649,7 @@ void acornscsi_message(AS_Host *host) host->device[host->SCpnt->device->id].sync_xfer = calc_sync_xfer(period * 4, length); } - sbic_arm_write(host->scsi.io_port, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); + sbic_arm_write(host, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); break; #else /* We do not accept synchronous transfers. Respond with a @@ -1792,10 +1789,10 @@ int acornscsi_starttransfer(AS_Host *host) residual = scsi_bufflen(host->SCpnt) - host->scsi.SCp.scsi_xferred; - sbic_arm_write(host->scsi.io_port, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); - sbic_arm_writenext(host->scsi.io_port, residual >> 16); - sbic_arm_writenext(host->scsi.io_port, residual >> 8); - sbic_arm_writenext(host->scsi.io_port, residual); + sbic_arm_write(host, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); + sbic_arm_writenext(host, residual >> 16); + sbic_arm_writenext(host, residual >> 8); + sbic_arm_writenext(host, residual); acornscsi_sbic_issuecmd(host, CMND_XFERINFO); return 1; } @@ -1816,7 +1813,7 @@ int acornscsi_reconnect(AS_Host *host) { unsigned int target, lun, ok = 0; - target = sbic_arm_read(host->scsi.io_port, SBIC_SOURCEID); + target = sbic_arm_read(host, SBIC_SOURCEID); if (!(target & 8)) printk(KERN_ERR "scsi%d: invalid source id after reselection " @@ -1832,7 +1829,7 @@ int acornscsi_reconnect(AS_Host *host) host->SCpnt = NULL; } - lun = sbic_arm_read(host->scsi.io_port, SBIC_DATA) & 7; + lun = sbic_arm_read(host, SBIC_DATA) & 7; host->scsi.reconnected.target = target; host->scsi.reconnected.lun = lun; @@ -1952,7 +1949,7 @@ static void acornscsi_abortcmd(AS_Host *host, unsigned char tag) { host->scsi.phase = PHASE_ABORTED; - sbic_arm_write(host->scsi.io_port, SBIC_CMND, CMND_ASSERTATN); + sbic_arm_write(host, SBIC_CMND, CMND_ASSERTATN); msgqueue_flush(&host->scsi.msgs); #ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE @@ -1979,11 +1976,11 @@ intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq) { unsigned int asr, ssr; - asr = sbic_arm_read(host->scsi.io_port, SBIC_ASR); + asr = sbic_arm_read(host, SBIC_ASR); if (!(asr & ASR_INT)) return INTR_IDLE; - ssr = sbic_arm_read(host->scsi.io_port, SBIC_SSR); + ssr = sbic_arm_read(host, SBIC_SSR); #if (DEBUG & DEBUG_PHASES) print_sbic_status(asr, ssr, host->scsi.phase); @@ -1999,15 +1996,15 @@ intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq) printk(KERN_ERR "scsi%d: reset in standard mode but wanted advanced mode.\n", host->host->host_no); /* setup sbic - WD33C93A */ - sbic_arm_write(host->scsi.io_port, SBIC_OWNID, OWNID_EAF | host->host->this_id); - sbic_arm_write(host->scsi.io_port, SBIC_CMND, CMND_RESET); + sbic_arm_write(host, SBIC_OWNID, OWNID_EAF | host->host->this_id); + sbic_arm_write(host, SBIC_CMND, CMND_RESET); return INTR_IDLE; case 0x01: /* reset state - advanced */ - sbic_arm_write(host->scsi.io_port, SBIC_CTRL, INIT_SBICDMA | CTRL_IDI); - sbic_arm_write(host->scsi.io_port, SBIC_TIMEOUT, TIMEOUT_TIME); - sbic_arm_write(host->scsi.io_port, SBIC_SYNCHTRANSFER, SYNCHTRANSFER_2DBA); - sbic_arm_write(host->scsi.io_port, SBIC_SOURCEID, SOURCEID_ER | SOURCEID_DSP); + sbic_arm_write(host, SBIC_CTRL, INIT_SBICDMA | CTRL_IDI); + sbic_arm_write(host, SBIC_TIMEOUT, TIMEOUT_TIME); + sbic_arm_write(host, SBIC_SYNCHTRANSFER, SYNCHTRANSFER_2DBA); + sbic_arm_write(host, SBIC_SOURCEID, SOURCEID_ER | SOURCEID_DSP); msgqueue_flush(&host->scsi.msgs); return INTR_IDLE; @@ -2025,10 +2022,10 @@ intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq) msgqueue_flush(&host->scsi.msgs); host->dma.transferred = host->scsi.SCp.scsi_xferred; /* 33C93 gives next interrupt indicating bus phase */ - asr = sbic_arm_read(host->scsi.io_port, SBIC_ASR); + asr = sbic_arm_read(host, SBIC_ASR); if (!(asr & ASR_INT)) break; - ssr = sbic_arm_read(host->scsi.io_port, SBIC_SSR); + ssr = sbic_arm_read(host, SBIC_SSR); ADD_STATUS(8, ssr, host->scsi.phase, 1); ADD_STATUS(host->SCpnt->device->id, ssr, host->scsi.phase, 1); goto connected; @@ -2476,11 +2473,11 @@ acornscsi_intr(int irq, void *dev_id) do { ret = INTR_IDLE; - iostatus = inb(host->card.io_intr); + iostatus = readb(host->fast + INT_REG); if (iostatus & 2) { acornscsi_dma_intr(host); - iostatus = inb(host->card.io_intr); + iostatus = readb(host->fast + INT_REG); } if (iostatus & 8) @@ -2655,7 +2652,7 @@ static enum res_abort acornscsi_do_abort(AS_Host *host, struct scsi_cmnd *SCpnt) * busylun bit. */ case PHASE_CONNECTED: - sbic_arm_write(host->scsi.io_port, SBIC_CMND, CMND_DISCONNECT); + sbic_arm_write(host, SBIC_CMND, CMND_DISCONNECT); host->SCpnt = NULL; res = res_success_clear; break; @@ -2699,8 +2696,8 @@ int acornscsi_abort(struct scsi_cmnd *SCpnt) #if (DEBUG & DEBUG_ABORT) { int asr, ssr; - asr = sbic_arm_read(host->scsi.io_port, SBIC_ASR); - ssr = sbic_arm_read(host->scsi.io_port, SBIC_SSR); + asr = sbic_arm_read(host, SBIC_ASR); + ssr = sbic_arm_read(host, SBIC_SSR); printk(KERN_WARNING "acornscsi_abort: "); print_sbic_status(asr, ssr, host->scsi.phase); @@ -2731,9 +2728,7 @@ int acornscsi_abort(struct scsi_cmnd *SCpnt) //#if (DEBUG & DEBUG_ABORT) printk("success\n"); //#endif - SCpnt->result = DID_ABORT << 16; - SCpnt->scsi_done(SCpnt); - result = SCSI_ABORT_SUCCESS; + result = SUCCESS; break; /* @@ -2745,7 +2740,7 @@ int acornscsi_abort(struct scsi_cmnd *SCpnt) //#if (DEBUG & DEBUG_ABORT) printk("snooze\n"); //#endif - result = SCSI_ABORT_SNOOZE; + result = FAILED; break; /* @@ -2755,11 +2750,7 @@ int acornscsi_abort(struct scsi_cmnd *SCpnt) default: case res_not_running: acornscsi_dumplog(host, SCpnt->device->id); -#if (DEBUG & DEBUG_ABORT) - result = SCSI_ABORT_SNOOZE; -#else - result = SCSI_ABORT_NOT_RUNNING; -#endif + result = FAILED; //#if (DEBUG & DEBUG_ABORT) printk("not running\n"); //#endif @@ -2770,13 +2761,12 @@ int acornscsi_abort(struct scsi_cmnd *SCpnt) } /* - * Prototype: int acornscsi_reset(struct scsi_cmnd *SCpnt, unsigned int reset_flags) + * Prototype: int acornscsi_reset(struct scsi_cmnd *SCpnt) * Purpose : reset a command on this host/reset this host * Params : SCpnt - command causing reset - * result - what type of reset to perform * Returns : one of SCSI_RESET_ macros */ -int acornscsi_reset(struct scsi_cmnd *SCpnt, unsigned int reset_flags) +int acornscsi_bus_reset(struct scsi_cmnd *SCpnt) { AS_Host *host = (AS_Host *)SCpnt->device->host->hostdata; struct scsi_cmnd *SCptr; @@ -2787,8 +2777,8 @@ int acornscsi_reset(struct scsi_cmnd *SCpnt, unsigned int reset_flags) { int asr, ssr; - asr = sbic_arm_read(host->scsi.io_port, SBIC_ASR); - ssr = sbic_arm_read(host->scsi.io_port, SBIC_SSR); + asr = sbic_arm_read(host, SBIC_ASR); + ssr = sbic_arm_read(host, SBIC_SSR); printk(KERN_WARNING "acornscsi_reset: "); print_sbic_status(asr, ssr, host->scsi.phase); @@ -2798,28 +2788,16 @@ int acornscsi_reset(struct scsi_cmnd *SCpnt, unsigned int reset_flags) acornscsi_dma_stop(host); - SCptr = host->SCpnt; - /* * do hard reset. This resets all devices on this host, and so we * must set the reset status on all commands. */ acornscsi_resetcard(host); - /* - * report reset on commands current connected/disconnected - */ - acornscsi_reportstatus(&host->SCpnt, &SCptr, DID_RESET); - while ((SCptr = queue_remove(&host->queues.disconnected)) != NULL) - acornscsi_reportstatus(&SCptr, &SCpnt, DID_RESET); - - if (SCpnt) { - SCpnt->result = DID_RESET << 16; - SCpnt->scsi_done(SCpnt); - } + ; - return SCSI_RESET_BUS_RESET | SCSI_RESET_HOST_RESET | SCSI_RESET_SUCCESS; + return SUCCESS; } /*============================================================================================== @@ -2850,7 +2828,7 @@ char *acornscsi_info(struct Scsi_Host *host) " LINK" #endif #if (DEBUG & DEBUG_NO_WRITE) - " NOWRITE ("NO_WRITE_STR")" + " NOWRITE (" __stringify(NO_WRITE) ")" #endif , host->hostt->name, host->io_port, host->irq, VER_MAJOR, VER_MINOR, VER_PATCH); @@ -2881,15 +2859,15 @@ int acornscsi_proc_info(struct Scsi_Host *instance, char *buffer, char **start, " LINK" #endif #if (DEBUG & DEBUG_NO_WRITE) - " NOWRITE ("NO_WRITE_STR")" + " NOWRITE (" __stringify(NO_WRITE) ")" #endif "\n\n", VER_MAJOR, VER_MINOR, VER_PATCH); - p += sprintf(p, "SBIC: WD33C93A Address: %08X IRQ : %d\n", - host->scsi.io_port, host->scsi.irq); + p += sprintf(p, "SBIC: WD33C93A Address: %p IRQ : %d\n", + host->base + SBIC_REGIDX, host->scsi.irq); #ifdef USE_DMAC - p += sprintf(p, "DMAC: uPC71071 Address: %08X IRQ : %d\n\n", - host->dma.io_port, host->scsi.irq); + p += sprintf(p, "DMAC: uPC71071 Address: %p IRQ : %d\n\n", + host->base + DMAC_OFFSET, host->scsi.irq); #endif p += sprintf(p, "Statistics:\n" @@ -2976,9 +2954,8 @@ static struct scsi_host_template acornscsi_template = { .name = "AcornSCSI", .info = acornscsi_info, .queuecommand = acornscsi_queuecmd, -#warning fixme - .abort = acornscsi_abort, - .reset = acornscsi_reset, + .eh_abort_handler = acornscsi_abort, + .eh_bus_reset_handler = acornscsi_bus_reset, .can_queue = 16, .this_id = 7, .sg_tablesize = SG_ALL, @@ -2992,48 +2969,37 @@ acornscsi_probe(struct expansion_card *ec, const struct ecard_id *id) { struct Scsi_Host *host; AS_Host *ashost; - int ret = -ENOMEM; + int ret; - host = scsi_host_alloc(&acornscsi_template, sizeof(AS_Host)); - if (!host) + ret = ecard_request_resources(ec); + if (ret) goto out; + host = scsi_host_alloc(&acornscsi_template, sizeof(AS_Host)); + if (!host) { + ret = -ENOMEM; + goto out_release; + } + ashost = (AS_Host *)host->hostdata; - host->io_port = ecard_address(ec, ECARD_MEMC, 0); - host->irq = ec->irq; + ashost->base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0); + ashost->fast = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0); + if (!ashost->base || !ashost->fast) + goto out_put; - ashost->host = host; - ashost->scsi.io_port = ioaddr(host->io_port + 0x800); - ashost->scsi.irq = host->irq; - ashost->card.io_intr = POD_SPACE(host->io_port) + 0x800; - ashost->card.io_page = POD_SPACE(host->io_port) + 0xc00; - ashost->card.io_ram = ioaddr(host->io_port); - ashost->dma.io_port = host->io_port + 0xc00; - ashost->dma.io_intr_clear = POD_SPACE(host->io_port) + 0x800; + host->irq = ec->irq; + ashost->host = host; + ashost->scsi.irq = host->irq; - ec->irqaddr = (char *)ioaddr(ashost->card.io_intr); + ec->irqaddr = ashost->fast + INT_REG; ec->irqmask = 0x0a; - ret = -EBUSY; - if (!request_region(host->io_port + 0x800, 2, "acornscsi(sbic)")) - goto err_1; - if (!request_region(ashost->card.io_intr, 1, "acornscsi(intr)")) - goto err_2; - if (!request_region(ashost->card.io_page, 1, "acornscsi(page)")) - goto err_3; -#ifdef USE_DMAC - if (!request_region(ashost->dma.io_port, 256, "acornscsi(dmac)")) - goto err_4; -#endif - if (!request_region(host->io_port, 2048, "acornscsi(ram)")) - goto err_5; - ret = request_irq(host->irq, acornscsi_intr, IRQF_DISABLED, "acornscsi", ashost); if (ret) { printk(KERN_CRIT "scsi%d: IRQ%d not free: %d\n", host->host_no, ashost->scsi.irq, ret); - goto err_6; + goto out_put; } memset(&ashost->stats, 0, sizeof (ashost->stats)); @@ -3045,27 +3011,22 @@ acornscsi_probe(struct expansion_card *ec, const struct ecard_id *id) ret = scsi_add_host(host, &ec->dev); if (ret) - goto err_7; + goto out_irq; scsi_scan_host(host); goto out; - err_7: + out_irq: free_irq(host->irq, ashost); - err_6: - release_region(host->io_port, 2048); - err_5: -#ifdef USE_DMAC - release_region(ashost->dma.io_port, 256); -#endif - err_4: - release_region(ashost->card.io_page, 1); - err_3: - release_region(ashost->card.io_intr, 1); - err_2: - release_region(host->io_port + 0x800, 2); - err_1: + msgqueue_free(&ashost->scsi.msgs); + queue_free(&ashost->queues.disconnected); + queue_free(&ashost->queues.issue); + out_put: + ecardm_iounmap(ec, ashost->fast); + ecardm_iounmap(ec, ashost->base); scsi_host_put(host); + out_release: + ecard_release_resources(ec); out: return ret; } @@ -3081,20 +3042,17 @@ static void __devexit acornscsi_remove(struct expansion_card *ec) /* * Put card into RESET state */ - outb(0x80, ashost->card.io_page); + writeb(0x80, ashost->fast + PAGE_REG); free_irq(host->irq, ashost); - release_region(host->io_port + 0x800, 2); - release_region(ashost->card.io_intr, 1); - release_region(ashost->card.io_page, 1); - release_region(ashost->dma.io_port, 256); - release_region(host->io_port, 2048); - msgqueue_free(&ashost->scsi.msgs); queue_free(&ashost->queues.disconnected); queue_free(&ashost->queues.issue); + ecardm_iounmap(ec, ashost->fast); + ecardm_iounmap(ec, ashost->base); scsi_host_put(host); + ecard_release_resources(ec); } static const struct ecard_id acornscsi_cids[] = { diff --git a/drivers/scsi/arm/acornscsi.h b/drivers/scsi/arm/acornscsi.h index d11424b89f42..8d2172a0b351 100644 --- a/drivers/scsi/arm/acornscsi.h +++ b/drivers/scsi/arm/acornscsi.h @@ -179,7 +179,6 @@ /* miscellaneous internal variables */ -#define POD_SPACE(x) ((x) + 0xd0000) #define MASK_ON (MASKREG_M3|MASKREG_M2|MASKREG_M1|MASKREG_M0) #define MASK_OFF (MASKREG_M3|MASKREG_M2|MASKREG_M1) @@ -279,10 +278,11 @@ typedef struct acornscsi_hostdata { struct Scsi_Host *host; /* host */ struct scsi_cmnd *SCpnt; /* currently processing command */ struct scsi_cmnd *origSCpnt; /* original connecting command */ + void __iomem *base; /* memc base address */ + void __iomem *fast; /* fast ioc base address */ /* driver information */ struct { - unsigned int io_port; /* base address of WD33C93 */ unsigned int irq; /* interrupt */ phase_t phase; /* current phase */ @@ -329,8 +329,6 @@ typedef struct acornscsi_hostdata { /* DMA info */ struct { - unsigned int io_port; /* base address of DMA controller */ - unsigned int io_intr_clear; /* address of DMA interrupt clear */ unsigned int free_addr; /* next free address */ unsigned int start_addr; /* start address of current transfer */ dmadir_t direction; /* dma direction */ @@ -345,9 +343,6 @@ typedef struct acornscsi_hostdata { /* card info */ struct { - unsigned int io_intr; /* base address of interrupt id reg */ - unsigned int io_page; /* base address of page reg */ - unsigned int io_ram; /* base address of RAM access */ unsigned char page_reg; /* current setting of page reg */ } card; diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index c4b938bc30d3..aa2011b64683 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c @@ -22,6 +22,7 @@ #include <linux/chio.h> /* here are all the ioctls */ #include <linux/mutex.h> #include <linux/idr.h> +#include <linux/smp_lock.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> @@ -571,16 +572,19 @@ ch_open(struct inode *inode, struct file *file) scsi_changer *ch; int minor = iminor(inode); + lock_kernel(); spin_lock(&ch_index_lock); ch = idr_find(&ch_index_idr, minor); if (NULL == ch || scsi_device_get(ch->device)) { spin_unlock(&ch_index_lock); + unlock_kernel(); return -ENXIO; } spin_unlock(&ch_index_lock); file->private_data = ch; + unlock_kernel(); return 0; } diff --git a/drivers/scsi/dpt/dptsig.h b/drivers/scsi/dpt/dptsig.h index 72c8992fdf21..a6644b332b53 100644 --- a/drivers/scsi/dpt/dptsig.h +++ b/drivers/scsi/dpt/dptsig.h @@ -85,7 +85,7 @@ typedef unsigned int sigINT; /* ------------------------------------------------------------------ */ /* What type of processor the file is meant to run on. */ /* This will let us know whether to read sigWORDs as high/low or low/high. */ -#define PROC_INTEL 0x00 /* Intel 80x86 */ +#define PROC_INTEL 0x00 /* Intel 80x86/ia64 */ #define PROC_MOTOROLA 0x01 /* Motorola 68K */ #define PROC_MIPS4000 0x02 /* MIPS RISC 4000 */ #define PROC_ALPHA 0x03 /* DEC Alpha */ @@ -104,6 +104,7 @@ typedef unsigned int sigINT; #define PROC_486 0x08 /* Intel 80486 */ #define PROC_PENTIUM 0x10 /* Intel 586 aka P5 aka Pentium */ #define PROC_SEXIUM 0x20 /* Intel 686 aka P6 aka Pentium Pro or MMX */ +#define PROC_IA64 0x40 /* Intel IA64 processor */ /* PROC_i960: */ #define PROC_960RX 0x01 /* Intel 80960RC/RD */ diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 8508816f303d..2bc30e32b67a 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -49,6 +49,7 @@ MODULE_DESCRIPTION("Adaptec I2O RAID Driver"); #include <linux/kernel.h> /* for printk */ #include <linux/sched.h> #include <linux/reboot.h> +#include <linux/smp_lock.h> #include <linux/spinlock.h> #include <linux/dma-mapping.h> @@ -1727,10 +1728,12 @@ static int adpt_open(struct inode *inode, struct file *file) int minor; adpt_hba* pHba; + lock_kernel(); //TODO check for root access // minor = iminor(inode); if (minor >= hba_count) { + unlock_kernel(); return -ENXIO; } mutex_lock(&adpt_configuration_lock); @@ -1741,6 +1744,7 @@ static int adpt_open(struct inode *inode, struct file *file) } if (pHba == NULL) { mutex_unlock(&adpt_configuration_lock); + unlock_kernel(); return -ENXIO; } @@ -1751,6 +1755,7 @@ static int adpt_open(struct inode *inode, struct file *file) pHba->in_use = 1; mutex_unlock(&adpt_configuration_lock); + unlock_kernel(); return 0; } diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c index 3d5ad243e77f..62a4618530d0 100644 --- a/drivers/scsi/esp_scsi.c +++ b/drivers/scsi/esp_scsi.c @@ -2361,6 +2361,24 @@ void scsi_esp_unregister(struct esp *esp) } EXPORT_SYMBOL(scsi_esp_unregister); +static int esp_target_alloc(struct scsi_target *starget) +{ + struct esp *esp = shost_priv(dev_to_shost(&starget->dev)); + struct esp_target_data *tp = &esp->target[starget->id]; + + tp->starget = starget; + + return 0; +} + +static void esp_target_destroy(struct scsi_target *starget) +{ + struct esp *esp = shost_priv(dev_to_shost(&starget->dev)); + struct esp_target_data *tp = &esp->target[starget->id]; + + tp->starget = NULL; +} + static int esp_slave_alloc(struct scsi_device *dev) { struct esp *esp = shost_priv(dev->host); @@ -2372,8 +2390,6 @@ static int esp_slave_alloc(struct scsi_device *dev) return -ENOMEM; dev->hostdata = lp; - tp->starget = dev->sdev_target; - spi_min_period(tp->starget) = esp->min_period; spi_max_offset(tp->starget) = 15; @@ -2610,6 +2626,8 @@ struct scsi_host_template scsi_esp_template = { .name = "esp", .info = esp_info, .queuecommand = esp_queuecommand, + .target_alloc = esp_target_alloc, + .target_destroy = esp_target_destroy, .slave_alloc = esp_slave_alloc, .slave_configure = esp_slave_configure, .slave_destroy = esp_slave_destroy, diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 46771d4c81bd..822d5214692b 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -120,6 +120,7 @@ #include <linux/timer.h> #include <linux/dma-mapping.h> #include <linux/list.h> +#include <linux/smp_lock.h> #ifdef GDTH_RTC #include <linux/mc146818rtc.h> @@ -4019,10 +4020,12 @@ static int gdth_open(struct inode *inode, struct file *filep) { gdth_ha_str *ha; + lock_kernel(); list_for_each_entry(ha, &gdth_instances, list) { if (!ha->sdev) ha->sdev = scsi_get_host_dev(ha->shost); } + unlock_kernel(); TRACE(("gdth_open()\n")); return 0; diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 497ca68d1ffc..35cd892dce04 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -456,6 +456,10 @@ static int __scsi_host_match(struct device *dev, void *data) * * Return value: * A pointer to located Scsi_Host or NULL. + * + * The caller must do a scsi_host_put() to drop the reference + * that scsi_host_get() took. The put_device() below dropped + * the reference from class_find_device(). **/ struct Scsi_Host *scsi_host_lookup(unsigned short hostnum) { @@ -463,9 +467,10 @@ struct Scsi_Host *scsi_host_lookup(unsigned short hostnum) struct Scsi_Host *shost = ERR_PTR(-ENXIO); cdev = class_find_device(&shost_class, &hostnum, __scsi_host_match); - if (cdev) + if (cdev) { shost = scsi_host_get(class_to_shost(cdev)); - + put_device(cdev); + } return shost; } EXPORT_SYMBOL(scsi_host_lookup); diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 44d8d5163a1a..683bce375c74 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -60,6 +60,13 @@ #define IDESCSI_DEBUG_LOG 0 +#if IDESCSI_DEBUG_LOG +#define debug_log(fmt, args...) \ + printk(KERN_INFO "ide-scsi: " fmt, ## args) +#else +#define debug_log(fmt, args...) do {} while (0) +#endif + /* * SCSI command transformation layer */ @@ -129,14 +136,15 @@ static inline idescsi_scsi_t *drive_to_idescsi(ide_drive_t *ide_drive) #define IDESCSI_PC_RQ 90 /* - * PIO data transfer routines using the scatter gather table. + * PIO data transfer routine using the scatter gather table. */ -static void idescsi_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, - unsigned int bcount) +static void ide_scsi_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, + unsigned int bcount, int write) { ide_hwif_t *hwif = drive->hwif; - int count; + xfer_func_t *xf = write ? hwif->output_data : hwif->input_data; char *buf; + int count; while (bcount) { count = min(pc->sg->length - pc->b_count, bcount); @@ -145,13 +153,13 @@ static void idescsi_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, local_irq_save(flags); buf = kmap_atomic(sg_page(pc->sg), KM_IRQ0) + - pc->sg->offset; - hwif->input_data(drive, NULL, buf + pc->b_count, count); + pc->sg->offset; + xf(drive, NULL, buf + pc->b_count, count); kunmap_atomic(buf - pc->sg->offset, KM_IRQ0); local_irq_restore(flags); } else { buf = sg_virt(pc->sg); - hwif->input_data(drive, NULL, buf + pc->b_count, count); + xf(drive, NULL, buf + pc->b_count, count); } bcount -= count; pc->b_count += count; if (pc->b_count == pc->sg->length) { @@ -163,51 +171,34 @@ static void idescsi_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, } if (bcount) { - printk (KERN_ERR "ide-scsi: scatter gather table too small, discarding data\n"); - ide_pad_transfer(drive, 0, bcount); + printk(KERN_ERR "%s: scatter gather table too small, %s\n", + drive->name, write ? "padding with zeros" + : "discarding data"); + ide_pad_transfer(drive, write, bcount); } } -static void idescsi_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, - unsigned int bcount) +static void ide_scsi_hex_dump(u8 *data, int len) { - ide_hwif_t *hwif = drive->hwif; - int count; - char *buf; + print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1, data, len, 0); +} - while (bcount) { - count = min(pc->sg->length - pc->b_count, bcount); - if (PageHighMem(sg_page(pc->sg))) { - unsigned long flags; +static int idescsi_end_request(ide_drive_t *, int, int); - local_irq_save(flags); - buf = kmap_atomic(sg_page(pc->sg), KM_IRQ0) + - pc->sg->offset; - hwif->output_data(drive, NULL, buf + pc->b_count, count); - kunmap_atomic(buf - pc->sg->offset, KM_IRQ0); - local_irq_restore(flags); - } else { - buf = sg_virt(pc->sg); - hwif->output_data(drive, NULL, buf + pc->b_count, count); - } - bcount -= count; pc->b_count += count; - if (pc->b_count == pc->sg->length) { - if (!--pc->sg_cnt) - break; - pc->sg = sg_next(pc->sg); - pc->b_count = 0; - } - } +static void ide_scsi_callback(ide_drive_t *drive) +{ + idescsi_scsi_t *scsi = drive_to_idescsi(drive); + struct ide_atapi_pc *pc = scsi->pc; - if (bcount) { - printk (KERN_ERR "ide-scsi: scatter gather table too small, padding with zeros\n"); - ide_pad_transfer(drive, 1, bcount); - } -} + if (pc->flags & PC_FLAG_TIMEDOUT) + debug_log("%s: got timed out packet %lu at %lu\n", __func__, + pc->scsi_cmd->serial_number, jiffies); + /* end this request now - scsi should retry it*/ + else if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) + printk(KERN_INFO "Packet command completed, %d bytes" + " transferred\n", pc->xferred); -static void ide_scsi_hex_dump(u8 *data, int len) -{ - print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1, data, len, 0); + idescsi_end_request(drive, 1, 0); } static int idescsi_check_condition(ide_drive_t *drive, @@ -228,14 +219,16 @@ static int idescsi_check_condition(ide_drive_t *drive, kfree(pc); return -ENOMEM; } - ide_init_drive_cmd(rq); + blk_rq_init(NULL, rq); rq->special = (char *) pc; pc->rq = rq; pc->buf = buf; pc->c[0] = REQUEST_SENSE; pc->c[4] = pc->req_xfer = pc->buf_size = SCSI_SENSE_BUFFERSIZE; rq->cmd_type = REQ_TYPE_SENSE; + rq->cmd_flags |= REQ_PREEMPT; pc->timeout = jiffies + WAIT_READY; + pc->callback = ide_scsi_callback; /* NOTE! Save the failed packet command in "rq->buffer" */ rq->buffer = (void *) failed_cmd->special; pc->scsi_cmd = ((struct ide_atapi_pc *) failed_cmd->special)->scsi_cmd; @@ -244,11 +237,10 @@ static int idescsi_check_condition(ide_drive_t *drive, ide_scsi_hex_dump(pc->c, 6); } rq->rq_disk = scsi->disk; - return ide_do_drive_cmd(drive, rq, ide_preempt); + ide_do_drive_cmd(drive, rq); + return 0; } -static int idescsi_end_request(ide_drive_t *, int, int); - static ide_startstop_t idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) { @@ -256,7 +248,7 @@ idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT)) /* force an abort */ - hwif->OUTBSYNC(drive, WIN_IDLEIMMEDIATE, + hwif->OUTBSYNC(hwif, WIN_IDLEIMMEDIATE, hwif->io_ports.command_addr); rq->errors++; @@ -269,10 +261,9 @@ idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) static ide_startstop_t idescsi_atapi_abort(ide_drive_t *drive, struct request *rq) { -#if IDESCSI_DEBUG_LOG - printk(KERN_WARNING "idescsi_atapi_abort called for %lu\n", + debug_log("%s called for %lu\n", __func__, ((struct ide_atapi_pc *) rq->special)->scsi_cmd->serial_number); -#endif + rq->errors |= ERROR_MAX; idescsi_end_request(drive, 0, 0); @@ -351,9 +342,9 @@ static int idescsi_expiry(ide_drive_t *drive) idescsi_scsi_t *scsi = drive_to_idescsi(drive); struct ide_atapi_pc *pc = scsi->pc; -#if IDESCSI_DEBUG_LOG - printk(KERN_WARNING "idescsi_expiry called for %lu at %lu\n", pc->scsi_cmd->serial_number, jiffies); -#endif + debug_log("%s called for %lu at %lu\n", __func__, + pc->scsi_cmd->serial_number, jiffies); + pc->flags |= PC_FLAG_TIMEDOUT; return 0; /* we do not want the ide subsystem to retry */ @@ -365,141 +356,19 @@ static int idescsi_expiry(ide_drive_t *drive) static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive) { idescsi_scsi_t *scsi = drive_to_idescsi(drive); - ide_hwif_t *hwif = drive->hwif; struct ide_atapi_pc *pc = scsi->pc; - struct request *rq = pc->rq; - unsigned int temp; - u16 bcount; - u8 stat, ireason; - -#if IDESCSI_DEBUG_LOG - printk (KERN_INFO "ide-scsi: Reached idescsi_pc_intr interrupt handler\n"); -#endif /* IDESCSI_DEBUG_LOG */ - - if (pc->flags & PC_FLAG_TIMEDOUT) { -#if IDESCSI_DEBUG_LOG - printk(KERN_WARNING "idescsi_pc_intr: got timed out packet %lu at %lu\n", - pc->scsi_cmd->serial_number, jiffies); -#endif - /* end this request now - scsi should retry it*/ - idescsi_end_request (drive, 1, 0); - return ide_stopped; - } - if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { - pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; -#if IDESCSI_DEBUG_LOG - printk ("ide-scsi: %s: DMA complete\n", drive->name); -#endif /* IDESCSI_DEBUG_LOG */ - pc->xferred = pc->req_xfer; - (void)hwif->dma_ops->dma_end(drive); - } - - /* Clear the interrupt */ - stat = ide_read_status(drive); - - if ((stat & DRQ_STAT) == 0) { - /* No more interrupts */ - if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) - printk(KERN_INFO "Packet command completed, %d bytes" - " transferred\n", pc->xferred); - local_irq_enable_in_hardirq(); - if (stat & ERR_STAT) - rq->errors++; - idescsi_end_request (drive, 1, 0); - return ide_stopped; - } - bcount = (hwif->INB(hwif->io_ports.lbah_addr) << 8) | - hwif->INB(hwif->io_ports.lbam_addr); - ireason = hwif->INB(hwif->io_ports.nsect_addr); - - if (ireason & CD) { - printk(KERN_ERR "ide-scsi: CoD != 0 in idescsi_pc_intr\n"); - return ide_do_reset (drive); - } - if (ireason & IO) { - temp = pc->xferred + bcount; - if (temp > pc->req_xfer) { - if (temp > pc->buf_size) { - printk(KERN_ERR "ide-scsi: The scsi wants to " - "send us more data than expected " - "- discarding data\n"); - temp = pc->buf_size - pc->xferred; - if (temp) { - pc->flags &= ~PC_FLAG_WRITING; - if (pc->sg) - idescsi_input_buffers(drive, pc, - temp); - else - hwif->input_data(drive, NULL, - pc->cur_pos, temp); - printk(KERN_ERR "ide-scsi: transferred" - " %d of %d bytes\n", - temp, bcount); - } - pc->xferred += temp; - pc->cur_pos += temp; - ide_pad_transfer(drive, 0, bcount - temp); - ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry); - return ide_started; - } -#if IDESCSI_DEBUG_LOG - printk (KERN_NOTICE "ide-scsi: The scsi wants to send us more data than expected - allowing transfer\n"); -#endif /* IDESCSI_DEBUG_LOG */ - } - } - if (ireason & IO) { - pc->flags &= ~PC_FLAG_WRITING; - if (pc->sg) - idescsi_input_buffers(drive, pc, bcount); - else - hwif->input_data(drive, NULL, pc->cur_pos, bcount); - } else { - pc->flags |= PC_FLAG_WRITING; - if (pc->sg) - idescsi_output_buffers(drive, pc, bcount); - else - hwif->output_data(drive, NULL, pc->cur_pos, bcount); - } - /* Update the current position */ - pc->xferred += bcount; - pc->cur_pos += bcount; - /* And set the interrupt handler again */ - ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry); - return ide_started; + return ide_pc_intr(drive, pc, idescsi_pc_intr, get_timeout(pc), + idescsi_expiry, NULL, NULL, NULL, + ide_scsi_io_buffers); } static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; idescsi_scsi_t *scsi = drive_to_idescsi(drive); - struct ide_atapi_pc *pc = scsi->pc; - ide_startstop_t startstop; - u8 ireason; - if (ide_wait_stat(&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) { - printk(KERN_ERR "ide-scsi: Strange, packet command " - "initiated yet DRQ isn't asserted\n"); - return startstop; - } - ireason = hwif->INB(hwif->io_ports.nsect_addr); - if ((ireason & CD) == 0 || (ireason & IO)) { - printk(KERN_ERR "ide-scsi: (IO,CoD) != (0,1) while " - "issuing a packet command\n"); - return ide_do_reset (drive); - } - BUG_ON(HWGROUP(drive)->handler != NULL); - /* Set the interrupt routine */ - ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry); - - /* Send the actual packet */ - hwif->output_data(drive, NULL, scsi->pc->c, 12); - - if (pc->flags & PC_FLAG_DMA_OK) { - pc->flags |= PC_FLAG_DMA_IN_PROGRESS; - hwif->dma_ops->dma_start(drive); - } - return ide_started; + return ide_transfer_pc(drive, scsi->pc, idescsi_pc_intr, + get_timeout(scsi->pc), idescsi_expiry); } static inline int idescsi_set_direction(struct ide_atapi_pc *pc) @@ -545,38 +414,12 @@ static ide_startstop_t idescsi_issue_pc(ide_drive_t *drive, struct ide_atapi_pc *pc) { idescsi_scsi_t *scsi = drive_to_idescsi(drive); - ide_hwif_t *hwif = drive->hwif; - u16 bcount; - u8 dma = 0; /* Set the current packet command */ scsi->pc = pc; - /* We haven't transferred any data yet */ - pc->xferred = 0; - pc->cur_pos = pc->buf; - /* Request to transfer the entire buffer at once */ - bcount = min(pc->req_xfer, 63 * 1024); - - if (drive->using_dma && !idescsi_map_sg(drive, pc)) { - hwif->sg_mapped = 1; - dma = !hwif->dma_ops->dma_setup(drive); - hwif->sg_mapped = 0; - } - - ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK, bcount, dma); - if (dma) - pc->flags |= PC_FLAG_DMA_OK; - - if (test_bit(IDESCSI_DRQ_INTERRUPT, &scsi->flags)) { - ide_execute_command(drive, WIN_PACKETCMD, &idescsi_transfer_pc, - get_timeout(pc), idescsi_expiry); - return ide_started; - } else { - /* Issue the packet command */ - ide_execute_pkt_cmd(drive); - return idescsi_transfer_pc(drive); - } + return ide_issue_pc(drive, pc, idescsi_transfer_pc, + get_timeout(pc), idescsi_expiry); } /* @@ -584,14 +427,22 @@ static ide_startstop_t idescsi_issue_pc(ide_drive_t *drive, */ static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *rq, sector_t block) { -#if IDESCSI_DEBUG_LOG - printk (KERN_INFO "dev: %s, cmd: %x, errors: %d\n", rq->rq_disk->disk_name,rq->cmd[0],rq->errors); - printk (KERN_INFO "sector: %ld, nr_sectors: %ld, current_nr_sectors: %d\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors); -#endif /* IDESCSI_DEBUG_LOG */ + debug_log("dev: %s, cmd: %x, errors: %d\n", rq->rq_disk->disk_name, + rq->cmd[0], rq->errors); + debug_log("sector: %ld, nr_sectors: %ld, current_nr_sectors: %d\n", + rq->sector, rq->nr_sectors, rq->current_nr_sectors); if (blk_sense_request(rq) || blk_special_request(rq)) { - return idescsi_issue_pc(drive, - (struct ide_atapi_pc *) rq->special); + struct ide_atapi_pc *pc = (struct ide_atapi_pc *)rq->special; + idescsi_scsi_t *scsi = drive_to_idescsi(drive); + + if (test_bit(IDESCSI_DRQ_INTERRUPT, &scsi->flags)) + pc->flags |= PC_FLAG_DRQ_INTERRUPT; + + if (drive->using_dma && !idescsi_map_sg(drive, pc)) + pc->flags |= PC_FLAG_DMA_OK; + + return idescsi_issue_pc(drive, pc); } blk_dump_rq_flags(rq, "ide-scsi: unsup command"); idescsi_end_request (drive, 0, 0); @@ -646,6 +497,8 @@ static void ide_scsi_remove(ide_drive_t *drive) put_disk(g); ide_scsi_put(scsi); + + drive->scsi = 0; } static int ide_scsi_probe(ide_drive_t *); @@ -765,6 +618,8 @@ static int idescsi_queue (struct scsi_cmnd *cmd, memset (pc->c, 0, 12); pc->flags = 0; + if (cmd->sc_data_direction == DMA_TO_DEVICE) + pc->flags |= PC_FLAG_WRITING; pc->rq = rq; memcpy (pc->c, cmd->cmnd, cmd->cmd_len); pc->buf = NULL; @@ -775,6 +630,7 @@ static int idescsi_queue (struct scsi_cmnd *cmd, pc->scsi_cmd = cmd; pc->done = done; pc->timeout = jiffies + cmd->timeout_per_command; + pc->callback = ide_scsi_callback; if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) { printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number); @@ -785,12 +641,11 @@ static int idescsi_queue (struct scsi_cmnd *cmd, } } - ide_init_drive_cmd (rq); + blk_rq_init(NULL, rq); rq->special = (char *) pc; rq->cmd_type = REQ_TYPE_SPECIAL; spin_unlock_irq(host->host_lock); - rq->rq_disk = scsi->disk; - (void) ide_do_drive_cmd (drive, rq, ide_end); + blk_execute_rq_nowait(drive->queue, scsi->disk, rq, 0, NULL); spin_lock_irq(host->host_lock); return 0; abort: @@ -985,6 +840,8 @@ static int ide_scsi_probe(ide_drive_t *drive) !(host = scsi_host_alloc(&idescsi_template,sizeof(idescsi_scsi_t)))) return -ENODEV; + drive->scsi = 1; + g = alloc_disk(1 << PARTN_BITS); if (!g) goto out_host_put; @@ -993,10 +850,10 @@ static int ide_scsi_probe(ide_drive_t *drive) host->max_id = 1; -#if IDESCSI_DEBUG_LOG if (drive->id->last_lun) - printk(KERN_NOTICE "%s: id->last_lun=%u\n", drive->name, drive->id->last_lun); -#endif + debug_log("%s: id->last_lun=%u\n", drive->name, + drive->id->last_lun); + if ((drive->id->last_lun & 0x7) != 7) host->max_lun = (drive->id->last_lun & 0x7) + 1; else @@ -1025,6 +882,7 @@ static int ide_scsi_probe(ide_drive_t *drive) put_disk(g); out_host_put: + drive->scsi = 0; scsi_host_put(host); return err; } diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 999e91ea7451..e7a3a6554425 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -71,6 +71,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/libata.h> +#include <linux/hdreg.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/processor.h> @@ -4913,8 +4914,11 @@ static int ipr_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) struct ipr_resource_entry *res; res = (struct ipr_resource_entry *)sdev->hostdata; - if (res && ipr_is_gata(res)) + if (res && ipr_is_gata(res)) { + if (cmd == HDIO_GET_IDENTITY) + return -ENOTTY; return ata_scsi_ioctl(sdev, cmd, arg); + } return -EINVAL; } diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 18551aaf5e09..28c9da7d4a5c 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -46,6 +46,7 @@ #include <linux/pci.h> #include <linux/init.h> #include <linux/dma-mapping.h> +#include <linux/smp_lock.h> #include <scsi/scsicam.h> #include "scsi.h" @@ -3272,12 +3273,12 @@ mega_init_scb(adapter_t *adapter) * @filep - unused * * Routines for the character/ioctl interface to the driver. Find out if this - * is a valid open. If yes, increment the module use count so that it cannot - * be unloaded. + * is a valid open. */ static int megadev_open (struct inode *inode, struct file *filep) { + cycle_kernel_lock(); /* * Only allow superuser to access private ioctl interface */ diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c index 0ad215e27b83..ac3b280c2a72 100644 --- a/drivers/scsi/megaraid/megaraid_mm.c +++ b/drivers/scsi/megaraid/megaraid_mm.c @@ -15,6 +15,7 @@ * Common management module */ #include <linux/sched.h> +#include <linux/smp_lock.h> #include "megaraid_mm.h" @@ -96,6 +97,7 @@ mraid_mm_open(struct inode *inode, struct file *filep) */ if (!capable(CAP_SYS_ADMIN)) return (-EACCES); + cycle_kernel_lock(); return 0; } diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 7d84c8bbcf3f..fc7ac158476c 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -33,6 +33,7 @@ #include <linux/spinlock.h> #include <linux/interrupt.h> #include <linux/delay.h> +#include <linux/smp_lock.h> #include <linux/uio.h> #include <asm/uaccess.h> #include <linux/fs.h> @@ -2863,6 +2864,7 @@ static void megasas_shutdown(struct pci_dev *pdev) */ static int megasas_mgmt_open(struct inode *inode, struct file *filep) { + cycle_kernel_lock(); /* * Allow only those users with admin rights */ diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 243d8becd30f..1c79f9794f4e 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -50,6 +50,7 @@ static const char * osst_version = "0.99.4"; #include <linux/moduleparam.h> #include <linux/delay.h> #include <linux/jiffies.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h> #include <asm/dma.h> #include <asm/system.h> @@ -4359,7 +4360,7 @@ os_bypass: /* Open the device */ -static int os_scsi_tape_open(struct inode * inode, struct file * filp) +static int __os_scsi_tape_open(struct inode * inode, struct file * filp) { unsigned short flags; int i, b_size, new_session = 0, retval = 0; @@ -4725,6 +4726,18 @@ err_out: return retval; } +/* BKL pushdown: spaghetti avoidance wrapper */ +static int os_scsi_tape_open(struct inode * inode, struct file * filp) +{ + int ret; + + lock_kernel(); + ret = __os_scsi_tape_open(inode, filp); + unlock_kernel(); + return ret; +} + + /* Flush the tape buffer before close */ static int os_scsi_tape_flush(struct file * filp, fl_owner_t id) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 0451903452e6..88d1b5f44e59 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -207,6 +207,15 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, */ blk_execute_rq(req->q, NULL, req, 1); + /* + * Some devices (USB mass-storage in particular) may transfer + * garbage data together with a residue indicating that the data + * is invalid. Prevent the garbage from being misinterpreted + * and prevent security leaks by zeroing out the excess data. + */ + if (unlikely(req->data_len > 0 && req->data_len <= bufflen)) + memset(buffer + (bufflen - req->data_len), 0, req->data_len); + ret = req->errors; out: blk_put_request(req); diff --git a/drivers/scsi/scsi_tgt_if.c b/drivers/scsi/scsi_tgt_if.c index d2557dbc2dc1..0e9533f7aabc 100644 --- a/drivers/scsi/scsi_tgt_if.c +++ b/drivers/scsi/scsi_tgt_if.c @@ -21,6 +21,7 @@ */ #include <linux/miscdevice.h> #include <linux/file.h> +#include <linux/smp_lock.h> #include <net/tcp.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> @@ -321,6 +322,7 @@ static int tgt_open(struct inode *inode, struct file *file) { tx_ring.tr_idx = rx_ring.tr_idx = 0; + cycle_kernel_lock(); return 0; } diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 71069d952dc7..0c63947d8a9d 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1119,6 +1119,8 @@ sd_spinup_disk(struct scsi_disk *sdkp) cmd[1] = 1; /* Return immediately */ memset((void *) &cmd[2], 0, 8); cmd[4] = 1; /* Start spin cycle */ + if (sdkp->device->start_stop_pwr_cond) + cmd[4] |= 1 << 4; scsi_execute_req(sdkp->device, cmd, DMA_NONE, NULL, 0, &sshdr, SD_TIMEOUT, SD_MAX_RETRIES); @@ -1785,6 +1787,9 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start) if (start) cmd[4] |= 1; /* START */ + if (sdp->start_stop_pwr_cond) + cmd[4] |= start ? 1 << 4 : 3 << 4; /* Active or Standby */ + if (!scsi_device_online(sdp)) return -ENODEV; diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c index 45df83b9d847..0fe031f003e7 100644 --- a/drivers/scsi/ses.c +++ b/drivers/scsi/ses.c @@ -61,7 +61,7 @@ static int ses_probe(struct device *dev) return err; } -#define SES_TIMEOUT 30 +#define SES_TIMEOUT (30 * HZ) #define SES_RETRIES 3 static int ses_recv_diag(struct scsi_device *sdev, int page_code, diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 2010fa039cfe..d3b8ebb83776 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -49,6 +49,7 @@ static int sg_version_num = 30534; /* 2 digits for each component */ #include <linux/delay.h> #include <linux/scatterlist.h> #include <linux/blktrace_api.h> +#include <linux/smp_lock.h> #include "scsi.h" #include <scsi/scsi_dbg.h> @@ -182,8 +183,9 @@ static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, int tablesize); static ssize_t sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp); -static ssize_t sg_new_write(Sg_fd * sfp, const char __user *buf, size_t count, - int blocking, int read_only, Sg_request ** o_srp); +static ssize_t sg_new_write(Sg_fd *sfp, struct file *file, + const char __user *buf, size_t count, int blocking, + int read_only, Sg_request **o_srp); static int sg_common_write(Sg_fd * sfp, Sg_request * srp, unsigned char *cmnd, int timeout, int blocking); static int sg_u_iovec(sg_io_hdr_t * hp, int sg_num, int ind, @@ -204,7 +206,6 @@ static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id); static Sg_request *sg_add_request(Sg_fd * sfp); static int sg_remove_request(Sg_fd * sfp, Sg_request * srp); static int sg_res_in_use(Sg_fd * sfp); -static int sg_allow_access(unsigned char opcode, char dev_type); static int sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len); static Sg_device *sg_get_dev(int dev); #ifdef CONFIG_SCSI_PROC_FS @@ -227,19 +228,26 @@ sg_open(struct inode *inode, struct file *filp) int res; int retval; + lock_kernel(); nonseekable_open(inode, filp); SCSI_LOG_TIMEOUT(3, printk("sg_open: dev=%d, flags=0x%x\n", dev, flags)); sdp = sg_get_dev(dev); - if ((!sdp) || (!sdp->device)) + if ((!sdp) || (!sdp->device)) { + unlock_kernel(); return -ENXIO; - if (sdp->detached) + } + if (sdp->detached) { + unlock_kernel(); return -ENODEV; + } /* This driver's module count bumped by fops_get in <linux/fs.h> */ /* Prevent the device driver from vanishing while we sleep */ retval = scsi_device_get(sdp->device); - if (retval) + if (retval) { + unlock_kernel(); return retval; + } if (!((flags & O_NONBLOCK) || scsi_block_when_processing_errors(sdp->device))) { @@ -295,10 +303,12 @@ sg_open(struct inode *inode, struct file *filp) retval = -ENOMEM; goto error_out; } + unlock_kernel(); return 0; error_out: scsi_device_put(sdp->device); + unlock_kernel(); return retval; } @@ -544,7 +554,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) return -EFAULT; blocking = !(filp->f_flags & O_NONBLOCK); if (old_hdr.reply_len < 0) - return sg_new_write(sfp, buf, count, blocking, 0, NULL); + return sg_new_write(sfp, filp, buf, count, blocking, 0, NULL); if (count < (SZ_SG_HEADER + 6)) return -EIO; /* The minimum scsi command length is 6 bytes. */ @@ -621,8 +631,9 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) } static ssize_t -sg_new_write(Sg_fd * sfp, const char __user *buf, size_t count, - int blocking, int read_only, Sg_request ** o_srp) +sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf, + size_t count, int blocking, int read_only, + Sg_request **o_srp) { int k; Sg_request *srp; @@ -678,8 +689,7 @@ sg_new_write(Sg_fd * sfp, const char __user *buf, size_t count, sg_remove_request(sfp, srp); return -EFAULT; } - if (read_only && - (!sg_allow_access(cmnd[0], sfp->parentdp->device->type))) { + if (read_only && !blk_verify_command(file, cmnd)) { sg_remove_request(sfp, srp); return -EPERM; } @@ -799,7 +809,7 @@ sg_ioctl(struct inode *inode, struct file *filp, if (!access_ok(VERIFY_WRITE, p, SZ_SG_IO_HDR)) return -EFAULT; result = - sg_new_write(sfp, p, SZ_SG_IO_HDR, + sg_new_write(sfp, filp, p, SZ_SG_IO_HDR, blocking, read_only, &srp); if (result < 0) return result; @@ -1051,7 +1061,7 @@ sg_ioctl(struct inode *inode, struct file *filp, if (copy_from_user(&opcode, siocp->data, 1)) return -EFAULT; - if (!sg_allow_access(opcode, sdp->device->type)) + if (!blk_verify_command(filp, &opcode)) return -EPERM; } return sg_scsi_ioctl(filp, sdp->device->request_queue, NULL, p); @@ -2505,30 +2515,6 @@ sg_page_free(struct page *page, int size) __free_pages(page, order); } -#ifndef MAINTENANCE_IN_CMD -#define MAINTENANCE_IN_CMD 0xa3 -#endif - -static unsigned char allow_ops[] = { TEST_UNIT_READY, REQUEST_SENSE, - INQUIRY, READ_CAPACITY, READ_BUFFER, READ_6, READ_10, READ_12, - READ_16, MODE_SENSE, MODE_SENSE_10, LOG_SENSE, REPORT_LUNS, - SERVICE_ACTION_IN, RECEIVE_DIAGNOSTIC, READ_LONG, MAINTENANCE_IN_CMD -}; - -static int -sg_allow_access(unsigned char opcode, char dev_type) -{ - int k; - - if (TYPE_SCANNER == dev_type) /* TYPE_ROM maybe burner */ - return 1; - for (k = 0; k < sizeof (allow_ops); ++k) { - if (opcode == allow_ops[k]) - return 1; - } - return 0; -} - #ifdef CONFIG_SCSI_PROC_FS static int sg_idr_max_id(int id, void *p, void *data) diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 7ee86d4a7618..27f5bfd1def3 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -178,6 +178,9 @@ int sr_test_unit_ready(struct scsi_device *sdev, struct scsi_sense_hdr *sshdr) the_result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, sshdr, SR_TIMEOUT, retries--); + if (scsi_sense_valid(sshdr) && + sshdr->sense_key == UNIT_ATTENTION) + sdev->changed = 1; } while (retries > 0 && (!scsi_status_is_good(the_result) || @@ -670,24 +673,20 @@ fail: static void get_sectorsize(struct scsi_cd *cd) { unsigned char cmd[10]; - unsigned char *buffer; + unsigned char buffer[8]; int the_result, retries = 3; int sector_size; struct request_queue *queue; - buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); - if (!buffer) - goto Enomem; - do { cmd[0] = READ_CAPACITY; memset((void *) &cmd[1], 0, 9); - memset(buffer, 0, 8); + memset(buffer, 0, sizeof(buffer)); /* Do the command and wait.. */ the_result = scsi_execute_req(cd->device, cmd, DMA_FROM_DEVICE, - buffer, 8, NULL, SR_TIMEOUT, - MAX_RETRIES); + buffer, sizeof(buffer), NULL, + SR_TIMEOUT, MAX_RETRIES); retries--; @@ -742,14 +741,8 @@ static void get_sectorsize(struct scsi_cd *cd) queue = cd->device->request_queue; blk_queue_hardsect_size(queue, sector_size); -out: - kfree(buffer); - return; -Enomem: - cd->capacity = 0x1fffff; - cd->device->sector_size = 2048; /* A guess, just in case */ - goto out; + return; } static void get_capabilities(struct scsi_cd *cd) diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 6e5a5bb31311..4684cc716aa4 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -38,6 +38,7 @@ static const char *verstr = "20080224"; #include <linux/cdev.h> #include <linux/delay.h> #include <linux/mutex.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h> #include <asm/dma.h> @@ -1113,7 +1114,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp) } -/* Open the device. Needs to be called with BKL only because of incrementing the SCSI host +/* Open the device. Needs to take the BKL only because of incrementing the SCSI host module count. */ static int st_open(struct inode *inode, struct file *filp) { @@ -1123,6 +1124,7 @@ static int st_open(struct inode *inode, struct file *filp) int dev = TAPE_NR(inode); char *name; + lock_kernel(); /* * We really want to do nonseekable_open(inode, filp); here, but some * versions of tar incorrectly call lseek on tapes and bail out if that @@ -1130,8 +1132,10 @@ static int st_open(struct inode *inode, struct file *filp) */ filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE); - if (!(STp = scsi_tape_get(dev))) + if (!(STp = scsi_tape_get(dev))) { + unlock_kernel(); return -ENXIO; + } write_lock(&st_dev_arr_lock); filp->private_data = STp; @@ -1140,6 +1144,7 @@ static int st_open(struct inode *inode, struct file *filp) if (STp->in_use) { write_unlock(&st_dev_arr_lock); scsi_tape_put(STp); + unlock_kernel(); DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); ) return (-EBUSY); } @@ -1188,12 +1193,14 @@ static int st_open(struct inode *inode, struct file *filp) retval = (-EIO); goto err_out; } + unlock_kernel(); return 0; err_out: normalize_buffer(STp->buffer); STp->in_use = 0; scsi_tape_put(STp); + unlock_kernel(); return retval; } |