diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2010-07-15 11:24:43 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2010-07-15 11:24:43 +1000 |
commit | 0d98dfccdf4087d30fe2a4d76777ff626c088bc3 (patch) | |
tree | c8a05cb62b57f2369d6b94dbc97c579303545a28 /drivers | |
parent | df48ccf50c7a827933836491dd063eeb6277d270 (diff) | |
parent | cbc588d74f238166ec3544374b31f2e23040654f (diff) |
Merge remote branch 'block/for-next'
Conflicts:
drivers/block/virtio_blk.c
Diffstat (limited to 'drivers')
83 files changed, 1581 insertions, 827 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index a54273d2c3c6..0a8cd3484791 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1111,10 +1111,10 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev) */ static int atapi_drain_needed(struct request *rq) { - if (likely(!blk_pc_request(rq))) + if (likely(rq->cmd_type != REQ_TYPE_BLOCK_PC)) return 0; - if (!blk_rq_bytes(rq) || (rq->cmd_flags & REQ_RW)) + if (!blk_rq_bytes(rq) || (rq->cmd_flags & REQ_WRITE)) return 0; return atapi_cmd_type(rq->cmd[0]) == ATAPI_MISC; diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index c5f22bb0a48e..4e2c367fec11 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -79,23 +79,28 @@ static int DAC960_open(struct block_device *bdev, fmode_t mode) struct gendisk *disk = bdev->bd_disk; DAC960_Controller_T *p = disk->queue->queuedata; int drive_nr = (long)disk->private_data; + int ret = -ENXIO; + lock_kernel(); if (p->FirmwareType == DAC960_V1_Controller) { if (p->V1.LogicalDriveInformation[drive_nr]. LogicalDriveState == DAC960_V1_LogicalDrive_Offline) - return -ENXIO; + goto out; } else { DAC960_V2_LogicalDeviceInfo_T *i = p->V2.LogicalDeviceInformation[drive_nr]; if (!i || i->LogicalDeviceState == DAC960_V2_LogicalDevice_Offline) - return -ENXIO; + goto out; } check_disk_change(bdev); if (!get_capacity(p->disks[drive_nr])) - return -ENXIO; - return 0; + goto out; + ret = 0; +out: + unlock_kernel(); + return ret; } static int DAC960_getgeo(struct block_device *bdev, struct hd_geometry *geo) diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 832798aa14f6..76f114f0bba3 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -60,6 +60,7 @@ #include <linux/hdreg.h> #include <linux/delay.h> #include <linux/init.h> +#include <linux/smp_lock.h> #include <linux/amifdreg.h> #include <linux/amifd.h> #include <linux/buffer_head.h> @@ -1423,7 +1424,7 @@ static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo) return 0; } -static int fd_ioctl(struct block_device *bdev, fmode_t mode, +static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long param) { struct amiga_floppy_struct *p = bdev->bd_disk->private_data; @@ -1500,6 +1501,18 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode, return 0; } +static int fd_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long param) +{ + int ret; + + lock_kernel(); + ret = fd_locked_ioctl(bdev, mode, cmd, param); + unlock_kernel(); + + return ret; +} + static void fd_probe(int dev) { unsigned long code; @@ -1542,10 +1555,13 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) int old_dev; unsigned long flags; + lock_kernel(); old_dev = fd_device[drive]; - if (fd_ref[drive] && old_dev != system) + if (fd_ref[drive] && old_dev != system) { + unlock_kernel(); return -EBUSY; + } if (mode & (FMODE_READ|FMODE_WRITE)) { check_disk_change(bdev); @@ -1558,8 +1574,10 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) fd_deselect (drive); rel_fdc(); - if (wrprot) + if (wrprot) { + unlock_kernel(); return -EROFS; + } } } @@ -1576,6 +1594,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) printk(KERN_INFO "fd%d: accessing %s-disk with %s-layout\n",drive, unit[drive].type->name, data_types[system].name); + unlock_kernel(); return 0; } @@ -1584,6 +1603,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode) struct amiga_floppy_struct *p = disk->private_data; int drive = p - unit; + lock_kernel(); if (unit[drive].dirty == 1) { del_timer (flush_track_timer + drive); non_int_flush_track (drive); @@ -1597,6 +1617,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode) /* the mod_use counter is handled this way */ floppy_off (drive | 0x40000000); #endif + unlock_kernel(); return 0; } @@ -1638,7 +1659,7 @@ static const struct block_device_operations floppy_fops = { .owner = THIS_MODULE, .open = floppy_open, .release = floppy_release, - .locked_ioctl = fd_ioctl, + .ioctl = fd_ioctl, .getgeo = fd_getgeo, .media_changed = amiga_floppy_change, }; diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 035cefe4045a..a946929735a5 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -12,6 +12,7 @@ #include <linux/slab.h> #include <linux/genhd.h> #include <linux/netdevice.h> +#include <linux/smp_lock.h> #include "aoe.h" static struct kmem_cache *buf_pool_cache; @@ -124,13 +125,16 @@ aoeblk_open(struct block_device *bdev, fmode_t mode) struct aoedev *d = bdev->bd_disk->private_data; ulong flags; + lock_kernel(); spin_lock_irqsave(&d->lock, flags); if (d->flags & DEVFL_UP) { d->nopen++; spin_unlock_irqrestore(&d->lock, flags); + unlock_kernel(); return 0; } spin_unlock_irqrestore(&d->lock, flags); + unlock_kernel(); return -ENODEV; } @@ -173,7 +177,7 @@ aoeblk_make_request(struct request_queue *q, struct bio *bio) BUG(); bio_endio(bio, -ENXIO); return 0; - } else if (bio_rw_flagged(bio, BIO_RW_BARRIER)) { + } else if (bio->bi_rw & REQ_HARDBARRIER) { bio_endio(bio, -EOPNOTSUPP); return 0; } else if (bio->bi_io_vec == NULL) { diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index e35cf59cbfde..aceb96476524 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c @@ -67,6 +67,7 @@ #include <linux/delay.h> #include <linux/init.h> #include <linux/blkdev.h> +#include <linux/smp_lock.h> #include <asm/atafd.h> #include <asm/atafdreg.h> @@ -359,7 +360,7 @@ static void finish_fdc( void ); static void finish_fdc_done( int dummy ); static void setup_req_params( int drive ); static void redo_fd_request( void); -static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int +static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long param); static void fd_probe( int drive ); static int fd_test_drive_present( int drive ); @@ -1480,7 +1481,7 @@ void do_fd_request(struct request_queue * q) atari_enable_irq( IRQ_MFP_FDC ); } -static int fd_ioctl(struct block_device *bdev, fmode_t mode, +static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long param) { struct gendisk *disk = bdev->bd_disk; @@ -1665,6 +1666,17 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode, } } +static int fd_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) +{ + int ret; + + lock_kernel(); + ret = fd_locked_ioctl(bdev, mode, cmd, arg); + unlock_kernel(); + + return ret; +} /* Initialize the 'unit' variable for drive 'drive' */ @@ -1838,24 +1850,36 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) return 0; } +static int floppy_unlocked_open(struct block_device *bdev, fmode_t mode) +{ + int ret; + + lock_kernel(); + ret = floppy_open(bdev, mode); + unlock_kernel(); + + return ret; +} static int floppy_release(struct gendisk *disk, fmode_t mode) { struct atari_floppy_struct *p = disk->private_data; + lock_kernel(); if (p->ref < 0) p->ref = 0; else if (!p->ref--) { printk(KERN_ERR "floppy_release with fd_ref == 0"); p->ref = 0; } + unlock_kernel(); return 0; } static const struct block_device_operations floppy_fops = { .owner = THIS_MODULE, - .open = floppy_open, + .open = floppy_unlocked_open, .release = floppy_release, - .locked_ioctl = fd_ioctl, + .ioctl = fd_ioctl, .media_changed = check_floppy_change, .revalidate_disk= floppy_revalidate, }; diff --git a/drivers/block/brd.c b/drivers/block/brd.c index f1bf79d9bc0a..1c7f63792ff8 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -15,6 +15,7 @@ #include <linux/blkdev.h> #include <linux/bio.h> #include <linux/highmem.h> +#include <linux/smp_lock.h> #include <linux/radix-tree.h> #include <linux/buffer_head.h> /* invalidate_bh_lrus() */ #include <linux/slab.h> @@ -340,7 +341,7 @@ static int brd_make_request(struct request_queue *q, struct bio *bio) get_capacity(bdev->bd_disk)) goto out; - if (unlikely(bio_rw_flagged(bio, BIO_RW_DISCARD))) { + if (unlikely(bio->bi_rw & REQ_DISCARD)) { err = 0; discard_from_brd(brd, sector, bio->bi_size); goto out; @@ -401,6 +402,7 @@ static int brd_ioctl(struct block_device *bdev, fmode_t mode, * ram device BLKFLSBUF has special semantics, we want to actually * release and destroy the ramdisk data. */ + lock_kernel(); mutex_lock(&bdev->bd_mutex); error = -EBUSY; if (bdev->bd_openers <= 1) { @@ -417,13 +419,14 @@ static int brd_ioctl(struct block_device *bdev, fmode_t mode, error = 0; } mutex_unlock(&bdev->bd_mutex); + unlock_kernel(); return error; } static const struct block_device_operations brd_fops = { .owner = THIS_MODULE, - .locked_ioctl = brd_ioctl, + .ioctl = brd_ioctl, #ifdef CONFIG_BLK_DEV_XIP .direct_access = brd_direct_access, #endif @@ -479,7 +482,7 @@ static struct brd_device *brd_alloc(int i) if (!brd->brd_queue) goto out_free_dev; blk_queue_make_request(brd->brd_queue, brd_make_request); - blk_queue_ordered(brd->brd_queue, QUEUE_ORDERED_TAG, NULL); + blk_queue_ordered(brd->brd_queue, QUEUE_ORDERED_TAG); blk_queue_max_hw_sectors(brd->brd_queue, 1024); blk_queue_bounce_limit(brd->brd_queue, BLK_BOUNCE_ANY); diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 51ceaee98f9f..665a470310a9 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -56,16 +56,14 @@ #include <linux/kthread.h> #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) -#define DRIVER_NAME "HP CISS Driver (v 3.6.20)" -#define DRIVER_VERSION CCISS_DRIVER_VERSION(3, 6, 20) +#define DRIVER_NAME "HP CISS Driver (v 3.6.26)" +#define DRIVER_VERSION CCISS_DRIVER_VERSION(3, 6, 26) /* Embedded module documentation macros - see modules.h */ MODULE_AUTHOR("Hewlett-Packard Company"); MODULE_DESCRIPTION("Driver for HP Smart Array Controllers"); -MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400" - " SA6i P600 P800 P400 P400i E200 E200i E500 P700m" - " Smart Array G2 Series SAS/SATA Controllers"); -MODULE_VERSION("3.6.20"); +MODULE_SUPPORTED_DEVICE("HP Smart Array Controllers"); +MODULE_VERSION("3.6.26"); MODULE_LICENSE("GPL"); static int cciss_allow_hpsa; @@ -107,6 +105,11 @@ static const struct pci_device_id cciss_pci_device_id[] = { {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3249}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324A}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324B}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3250}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3251}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3252}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3253}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3254}, {0,} }; @@ -146,6 +149,11 @@ static struct board_type products[] = { {0x3249103C, "Smart Array P812", &SA5_access}, {0x324A103C, "Smart Array P712m", &SA5_access}, {0x324B103C, "Smart Array P711m", &SA5_access}, + {0x3250103C, "Smart Array", &SA5_access}, + {0x3251103C, "Smart Array", &SA5_access}, + {0x3252103C, "Smart Array", &SA5_access}, + {0x3253103C, "Smart Array", &SA5_access}, + {0x3254103C, "Smart Array", &SA5_access}, }; /* How long to wait (in milliseconds) for board to go into simple mode */ @@ -167,9 +175,13 @@ static DEFINE_MUTEX(scan_mutex); static LIST_HEAD(scan_q); static void do_cciss_request(struct request_queue *q); -static irqreturn_t do_cciss_intr(int irq, void *dev_id); +static irqreturn_t do_cciss_intx(int irq, void *dev_id); +static irqreturn_t do_cciss_msix_intr(int irq, void *dev_id); static int cciss_open(struct block_device *bdev, fmode_t mode); +static int cciss_unlocked_open(struct block_device *bdev, fmode_t mode); static int cciss_release(struct gendisk *disk, fmode_t mode); +static int do_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg); static int cciss_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg); static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo); @@ -197,7 +209,6 @@ static int sendcmd_withirq_core(ctlr_info_t *h, CommandList_struct *c, int attempt_retry); static int process_sendcmd_error(ctlr_info_t *h, CommandList_struct *c); -static void fail_all_cmds(unsigned long ctlr); static int add_to_scan_list(struct ctlr_info *h); static int scan_thread(void *data); static int check_for_unit_attention(ctlr_info_t *h, CommandList_struct *c); @@ -205,6 +216,12 @@ static void cciss_hba_release(struct device *dev); static void cciss_device_release(struct device *dev); static void cciss_free_gendisk(ctlr_info_t *h, int drv_index); static void cciss_free_drive_info(ctlr_info_t *h, int drv_index); +static inline u32 next_command(ctlr_info_t *h); + +/* performant mode helper functions */ +static void calc_bucket_map(int *bucket, int num_buckets, int nsgs, + int *bucket_map); +static void cciss_put_controller_into_performant_mode(ctlr_info_t *h); #ifdef CONFIG_PROC_FS static void cciss_procinit(int i); @@ -221,9 +238,9 @@ static int cciss_compat_ioctl(struct block_device *, fmode_t, static const struct block_device_operations cciss_fops = { .owner = THIS_MODULE, - .open = cciss_open, + .open = cciss_unlocked_open, .release = cciss_release, - .locked_ioctl = cciss_ioctl, + .ioctl = do_ioctl, .getgeo = cciss_getgeo, #ifdef CONFIG_COMPAT .compat_ioctl = cciss_compat_ioctl, @@ -231,6 +248,16 @@ static const struct block_device_operations cciss_fops = { .revalidate_disk = cciss_revalidate, }; +/* set_performant_mode: Modify the tag for cciss performant + * set bit 0 for pull model, bits 3-1 for block fetch + * register number + */ +static void set_performant_mode(ctlr_info_t *h, CommandList_struct *c) +{ + if (likely(h->transMethod == CFGTBL_Trans_Performant)) + c->busaddr |= 1 | (h->blockFetchTable[c->Header.SGList] << 1); +} + /* * Enqueuing and dequeuing functions for cmdlists. */ @@ -257,6 +284,18 @@ static inline void removeQ(CommandList_struct *c) hlist_del_init(&c->list); } +static void enqueue_cmd_and_start_io(ctlr_info_t *h, + CommandList_struct *c) +{ + unsigned long flags; + set_performant_mode(h, c); + spin_lock_irqsave(&h->lock, flags); + addQ(&h->reqQ, c); + h->Qdepth++; + start_io(h); + spin_unlock_irqrestore(&h->lock, flags); +} + static void cciss_free_sg_chain_blocks(SGDescriptor_struct **cmd_sg_list, int nr_cmds) { @@ -366,7 +405,7 @@ static void cciss_seq_show_header(struct seq_file *seq) h->product_name, (unsigned long)h->board_id, h->firm_ver[0], h->firm_ver[1], h->firm_ver[2], - h->firm_ver[3], (unsigned int)h->intr[SIMPLE_MODE_INT], + h->firm_ver[3], (unsigned int)h->intr[PERF_MODE_INT], h->num_luns, h->Qdepth, h->commands_outstanding, h->maxQsinceinit, h->max_outstanding, h->maxSG); @@ -1004,13 +1043,28 @@ static int cciss_open(struct block_device *bdev, fmode_t mode) return 0; } +static int cciss_unlocked_open(struct block_device *bdev, fmode_t mode) +{ + int ret; + + lock_kernel(); + ret = cciss_open(bdev, mode); + unlock_kernel(); + + return ret; +} + /* * Close. Sync first. */ static int cciss_release(struct gendisk *disk, fmode_t mode) { - ctlr_info_t *host = get_host(disk); - drive_info_struct *drv = get_drv(disk); + ctlr_info_t *host; + drive_info_struct *drv; + + lock_kernel(); + host = get_host(disk); + drv = get_drv(disk); #ifdef CCISS_DEBUG printk(KERN_DEBUG "cciss_release %s\n", disk->disk_name); @@ -1018,11 +1072,10 @@ static int cciss_release(struct gendisk *disk, fmode_t mode) drv->usage_count--; host->usage_count--; + unlock_kernel(); return 0; } -#ifdef CONFIG_COMPAT - static int do_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long arg) { @@ -1033,6 +1086,8 @@ static int do_ioctl(struct block_device *bdev, fmode_t mode, return ret; } +#ifdef CONFIG_COMPAT + static int cciss_ioctl32_passthru(struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long arg); static int cciss_ioctl32_big_passthru(struct block_device *bdev, fmode_t mode, @@ -1377,7 +1432,6 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, CommandList_struct *c; char *buff = NULL; u64bit temp64; - unsigned long flags; DECLARE_COMPLETION_ONSTACK(wait); if (!arg) @@ -1449,13 +1503,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, } c->waiting = &wait; - /* Put the request on the tail of the request queue */ - spin_lock_irqsave(CCISS_LOCK(ctlr), flags); - addQ(&host->reqQ, c); - host->Qdepth++; - start_io(host); - spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); - + enqueue_cmd_and_start_io(host, c); wait_for_completion(&wait); /* unlock the buffers from DMA */ @@ -1495,7 +1543,6 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, unsigned char **buff = NULL; int *buff_size = NULL; u64bit temp64; - unsigned long flags; BYTE sg_used = 0; int status = 0; int i; @@ -1602,12 +1649,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, } } c->waiting = &wait; - /* Put the request on the tail of the request queue */ - spin_lock_irqsave(CCISS_LOCK(ctlr), flags); - addQ(&host->reqQ, c); - host->Qdepth++; - start_io(host); - spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); + enqueue_cmd_and_start_io(host, c); wait_for_completion(&wait); /* unlock the buffers from DMA */ for (i = 0; i < sg_used; i++) { @@ -1729,8 +1771,8 @@ static void cciss_softirq_done(struct request *rq) CommandList_struct *cmd = rq->completion_data; ctlr_info_t *h = hba[cmd->ctlr]; SGDescriptor_struct *curr_sg = cmd->SG; - unsigned long flags; u64bit temp64; + unsigned long flags; int i, ddir; int sg_index = 0; @@ -1760,7 +1802,7 @@ static void cciss_softirq_done(struct request *rq) #endif /* CCISS_DEBUG */ /* set the residual count for pc requests */ - if (blk_pc_request(rq)) + if (rq->cmd_type == REQ_TYPE_BLOCK_PC) rq->resid_len = cmd->err_info->ResidualCnt; blk_end_request_all(rq, (rq->errors == 0) ? 0 : -EIO); @@ -2679,17 +2721,11 @@ static int sendcmd_withirq_core(ctlr_info_t *h, CommandList_struct *c, { DECLARE_COMPLETION_ONSTACK(wait); u64bit buff_dma_handle; - unsigned long flags; int return_status = IO_OK; resend_cmd2: c->waiting = &wait; - /* Put the request on the tail of the queue and send it */ - spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); - addQ(&h->reqQ, c); - h->Qdepth++; - start_io(h); - spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); + enqueue_cmd_and_start_io(h, c); wait_for_completion(&wait); @@ -2966,7 +3002,7 @@ static inline int evaluate_target_status(ctlr_info_t *h, driver_byte = DRIVER_OK; msg_byte = cmd->err_info->CommandStatus; /* correct? seems too device specific */ - if (blk_pc_request(cmd->rq)) + if (cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC) host_byte = DID_PASSTHROUGH; else host_byte = DID_OK; @@ -2975,7 +3011,7 @@ static inline int evaluate_target_status(ctlr_info_t *h, host_byte, driver_byte); if (cmd->err_info->ScsiStatus != SAM_STAT_CHECK_CONDITION) { - if (!blk_pc_request(cmd->rq)) + if (cmd->rq->cmd_type != REQ_TYPE_BLOCK_PC) printk(KERN_WARNING "cciss: cmd %p " "has SCSI Status 0x%x\n", cmd, cmd->err_info->ScsiStatus); @@ -2985,15 +3021,17 @@ static inline int evaluate_target_status(ctlr_info_t *h, /* check the sense key */ sense_key = 0xf & cmd->err_info->SenseInfo[2]; /* no status or recovered error */ - if (((sense_key == 0x0) || (sense_key == 0x1)) && !blk_pc_request(cmd->rq)) + if (((sense_key == 0x0) || (sense_key == 0x1)) && + (cmd->rq->cmd_type != REQ_TYPE_BLOCK_PC)) error_value = 0; if (check_for_unit_attention(h, cmd)) { - *retry_cmd = !blk_pc_request(cmd->rq); + *retry_cmd = !(cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC); return 0; } - if (!blk_pc_request(cmd->rq)) { /* Not SG_IO or similar? */ + /* Not SG_IO or similar? */ + if (cmd->rq->cmd_type != REQ_TYPE_BLOCK_PC) { if (error_value != 0) printk(KERN_WARNING "cciss: cmd %p has CHECK CONDITION" " sense key = 0x%x\n", cmd, sense_key); @@ -3035,7 +3073,7 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd, rq->errors = evaluate_target_status(h, cmd, &retry_cmd); break; case CMD_DATA_UNDERRUN: - if (blk_fs_request(cmd->rq)) { + if (cmd->rq->cmd_type == REQ_TYPE_FS) { printk(KERN_WARNING "cciss: cmd %p has" " completed with data underrun " "reported\n", cmd); @@ -3043,7 +3081,7 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd, } break; case CMD_DATA_OVERRUN: - if (blk_fs_request(cmd->rq)) + if (cmd->rq->cmd_type == REQ_TYPE_FS) printk(KERN_WARNING "cciss: cmd %p has" " completed with data overrun " "reported\n", cmd); @@ -3053,42 +3091,48 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd, "reported invalid\n", cmd); rq->errors = make_status_bytes(SAM_STAT_GOOD, cmd->err_info->CommandStatus, DRIVER_OK, - blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR); + (cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC) ? + DID_PASSTHROUGH : DID_ERROR); break; case CMD_PROTOCOL_ERR: printk(KERN_WARNING "cciss: cmd %p has " "protocol error \n", cmd); rq->errors = make_status_bytes(SAM_STAT_GOOD, cmd->err_info->CommandStatus, DRIVER_OK, - blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR); + (cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC) ? + DID_PASSTHROUGH : DID_ERROR); break; case CMD_HARDWARE_ERR: printk(KERN_WARNING "cciss: cmd %p had " " hardware error\n", cmd); rq->errors = make_status_bytes(SAM_STAT_GOOD, cmd->err_info->CommandStatus, DRIVER_OK, - blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR); + (cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC) ? + DID_PASSTHROUGH : DID_ERROR); break; case CMD_CONNECTION_LOST: printk(KERN_WARNING "cciss: cmd %p had " "connection lost\n", cmd); rq->errors = make_status_bytes(SAM_STAT_GOOD, cmd->err_info->CommandStatus, DRIVER_OK, - blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR); + (cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC) ? + DID_PASSTHROUGH : DID_ERROR); break; case CMD_ABORTED: printk(KERN_WARNING "cciss: cmd %p was " "aborted\n", cmd); rq->errors = make_status_bytes(SAM_STAT_GOOD, cmd->err_info->CommandStatus, DRIVER_OK, - blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ABORT); + (cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC) ? + DID_PASSTHROUGH : DID_ABORT); break; case CMD_ABORT_FAILED: printk(KERN_WARNING "cciss: cmd %p reports " "abort failed\n", cmd); rq->errors = make_status_bytes(SAM_STAT_GOOD, cmd->err_info->CommandStatus, DRIVER_OK, - blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR); + (cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC) ? + DID_PASSTHROUGH : DID_ERROR); break; case CMD_UNSOLICITED_ABORT: printk(KERN_WARNING "cciss%d: unsolicited " @@ -3104,13 +3148,15 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd, "many times\n", h->ctlr, cmd); rq->errors = make_status_bytes(SAM_STAT_GOOD, cmd->err_info->CommandStatus, DRIVER_OK, - blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ABORT); + (cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC) ? + DID_PASSTHROUGH : DID_ABORT); break; case CMD_TIMEOUT: printk(KERN_WARNING "cciss: cmd %p timedout\n", cmd); rq->errors = make_status_bytes(SAM_STAT_GOOD, cmd->err_info->CommandStatus, DRIVER_OK, - blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR); + (cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC) ? + DID_PASSTHROUGH : DID_ERROR); break; default: printk(KERN_WARNING "cciss: cmd %p returned " @@ -3118,7 +3164,8 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd, cmd->err_info->CommandStatus); rq->errors = make_status_bytes(SAM_STAT_GOOD, cmd->err_info->CommandStatus, DRIVER_OK, - blk_pc_request(cmd->rq) ? DID_PASSTHROUGH : DID_ERROR); + (cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC) ? + DID_PASSTHROUGH : DID_ERROR); } after_error_processing: @@ -3132,6 +3179,34 @@ after_error_processing: blk_complete_request(cmd->rq); } +static inline u32 cciss_tag_contains_index(u32 tag) +{ +#define DIRECT_LOOKUP_BIT 0x10 + return tag & DIRECT_LOOKUP_BIT; +} + +static inline u32 cciss_tag_to_index(u32 tag) +{ +#define DIRECT_LOOKUP_SHIFT 5 + return tag >> DIRECT_LOOKUP_SHIFT; +} + +static inline u32 cciss_tag_discard_error_bits(u32 tag) +{ +#define CCISS_ERROR_BITS 0x03 + return tag & ~CCISS_ERROR_BITS; +} + +static inline void cciss_mark_tag_indexed(u32 *tag) +{ + *tag |= DIRECT_LOOKUP_BIT; +} + +static inline void cciss_set_tag_index(u32 *tag, u32 index) +{ + *tag |= (index << DIRECT_LOOKUP_SHIFT); +} + /* * Get a request and submit it to the controller. */ @@ -3180,8 +3255,8 @@ static void do_cciss_request(struct request_queue *q) /* got command from pool, so use the command block index instead */ /* for direct lookups. */ /* The first 2 bits are reserved for controller error reporting. */ - c->Header.Tag.lower = (c->cmdindex << 3); - c->Header.Tag.lower |= 0x04; /* flag for direct lookup. */ + cciss_set_tag_index(&c->Header.Tag.lower, c->cmdindex); + cciss_mark_tag_indexed(&c->Header.Tag.lower); memcpy(&c->Header.LUN, drv->LunID, sizeof(drv->LunID)); c->Request.CDBLen = 10; /* 12 byte commands not in FW yet; */ c->Request.Type.Type = TYPE_CMD; /* It is a command. */ @@ -3242,11 +3317,14 @@ static void do_cciss_request(struct request_queue *q) blk_rq_sectors(creq), seg, chained); #endif /* CCISS_DEBUG */ - c->Header.SGList = c->Header.SGTotal = seg + chained; - if (seg > h->max_cmd_sgentries) + c->Header.SGTotal = seg + chained; + if (seg <= h->max_cmd_sgentries) + c->Header.SGList = c->Header.SGTotal; + else c->Header.SGList = h->max_cmd_sgentries; + set_performant_mode(h, c); - if (likely(blk_fs_request(creq))) { + if (likely(creq->cmd_type == REQ_TYPE_FS)) { if(h->cciss_read == CCISS_READ_10) { c->Request.CDB[1] = 0; c->Request.CDB[2] = (start_blk >> 24) & 0xff; /* MSB */ @@ -3276,7 +3354,7 @@ static void do_cciss_request(struct request_queue *q) c->Request.CDB[13]= blk_rq_sectors(creq) & 0xff; c->Request.CDB[14] = c->Request.CDB[15] = 0; } - } else if (blk_pc_request(creq)) { + } else if (creq->cmd_type == REQ_TYPE_BLOCK_PC) { c->Request.CDBLen = creq->cmd_len; memcpy(c->Request.CDB, creq->cmd, BLK_MAX_CDB); } else { @@ -3313,16 +3391,97 @@ static inline int interrupt_pending(ctlr_info_t *h) static inline long interrupt_not_for_us(ctlr_info_t *h) { - return (((h->access.intr_pending(h) == 0) || - (h->interrupts_enabled == 0))); + return !(h->msi_vector || h->msix_vector) && + ((h->access.intr_pending(h) == 0) || + (h->interrupts_enabled == 0)); } -static irqreturn_t do_cciss_intr(int irq, void *dev_id) +static inline int bad_tag(ctlr_info_t *h, u32 tag_index, + u32 raw_tag) { - ctlr_info_t *h = dev_id; + if (unlikely(tag_index >= h->nr_cmds)) { + dev_warn(&h->pdev->dev, "bad tag 0x%08x ignored.\n", raw_tag); + return 1; + } + return 0; +} + +static inline void finish_cmd(ctlr_info_t *h, CommandList_struct *c, + u32 raw_tag) +{ + removeQ(c); + if (likely(c->cmd_type == CMD_RWREQ)) + complete_command(h, c, 0); + else if (c->cmd_type == CMD_IOCTL_PEND) + complete(c->waiting); +#ifdef CONFIG_CISS_SCSI_TAPE + else if (c->cmd_type == CMD_SCSI) + complete_scsi_command(c, 0, raw_tag); +#endif +} + +static inline u32 next_command(ctlr_info_t *h) +{ + u32 a; + + if (unlikely(h->transMethod != CFGTBL_Trans_Performant)) + return h->access.command_completed(h); + + if ((*(h->reply_pool_head) & 1) == (h->reply_pool_wraparound)) { + a = *(h->reply_pool_head); /* Next cmd in ring buffer */ + (h->reply_pool_head)++; + h->commands_outstanding--; + } else { + a = FIFO_EMPTY; + } + /* Check for wraparound */ + if (h->reply_pool_head == (h->reply_pool + h->max_commands)) { + h->reply_pool_head = h->reply_pool; + h->reply_pool_wraparound ^= 1; + } + return a; +} + +/* process completion of an indexed ("direct lookup") command */ +static inline u32 process_indexed_cmd(ctlr_info_t *h, u32 raw_tag) +{ + u32 tag_index; CommandList_struct *c; + + tag_index = cciss_tag_to_index(raw_tag); + if (bad_tag(h, tag_index, raw_tag)) + return next_command(h); + c = h->cmd_pool + tag_index; + finish_cmd(h, c, raw_tag); + return next_command(h); +} + +/* process completion of a non-indexed command */ +static inline u32 process_nonindexed_cmd(ctlr_info_t *h, u32 raw_tag) +{ + u32 tag; + CommandList_struct *c = NULL; + struct hlist_node *tmp; + __u32 busaddr_masked, tag_masked; + + tag = cciss_tag_discard_error_bits(raw_tag); + hlist_for_each_entry(c, tmp, &h->cmpQ, list) { + busaddr_masked = cciss_tag_discard_error_bits(c->busaddr); + tag_masked = cciss_tag_discard_error_bits(tag); + if (busaddr_masked == tag_masked) { + finish_cmd(h, c, raw_tag); + return next_command(h); + } + } + bad_tag(h, h->nr_cmds + 1, raw_tag); + return next_command(h); +} + +static irqreturn_t do_cciss_intx(int irq, void *dev_id) +{ + ctlr_info_t *h = dev_id; unsigned long flags; - __u32 a, a1, a2; + u32 raw_tag; if (interrupt_not_for_us(h)) return IRQ_NONE; @@ -3332,50 +3491,41 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id) */ spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); while (interrupt_pending(h)) { - while ((a = get_next_completion(h)) != FIFO_EMPTY) { - a1 = a; - if ((a & 0x04)) { - a2 = (a >> 3); - if (a2 >= h->nr_cmds) { - printk(KERN_WARNING - "cciss: controller cciss%d failed, stopping.\n", - h->ctlr); - spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); - fail_all_cmds(h->ctlr); - return IRQ_HANDLED; - } + raw_tag = get_next_completion(h); + while (raw_tag != FIFO_EMPTY) { + if (cciss_tag_contains_index(raw_tag)) + raw_tag = process_indexed_cmd(h, raw_tag); + else + raw_tag = process_nonindexed_cmd(h, raw_tag); + } + } - c = h->cmd_pool + a2; - a = c->busaddr; + spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); + return IRQ_HANDLED; +} - } else { - struct hlist_node *tmp; +/* Add a second interrupt handler for MSI/MSI-X mode. In this mode we never + * check the interrupt pending register because it is not set. + */ +static irqreturn_t do_cciss_msix_intr(int irq, void *dev_id) +{ + ctlr_info_t *h = dev_id; + unsigned long flags; + u32 raw_tag; - a &= ~3; - c = NULL; - hlist_for_each_entry(c, tmp, &h->cmpQ, list) { - if (c->busaddr == a) - break; - } - } - /* - * If we've found the command, take it off the - * completion Q and free it - */ - if (c && c->busaddr == a) { - removeQ(c); - if (c->cmd_type == CMD_RWREQ) { - complete_command(h, c, 0); - } else if (c->cmd_type == CMD_IOCTL_PEND) { - complete(c->waiting); - } -# ifdef CONFIG_CISS_SCSI_TAPE - else if (c->cmd_type == CMD_SCSI) - complete_scsi_command(c, 0, a1); -# endif - continue; - } - } + if (interrupt_not_for_us(h)) + return IRQ_NONE; + /* + * If there are completed commands in the completion queue, + * we had better do something about it. + */ + spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); + raw_tag = get_next_completion(h); + while (raw_tag != FIFO_EMPTY) { + if (cciss_tag_contains_index(raw_tag)) + raw_tag = process_indexed_cmd(h, raw_tag); + else + raw_tag = process_nonindexed_cmd(h, raw_tag); } spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); @@ -3630,6 +3780,155 @@ static int find_PCI_BAR_index(struct pci_dev *pdev, unsigned long pci_bar_addr) return -1; } +/* Fill in bucket_map[], given nsgs (the max number of + * scatter gather elements supported) and bucket[], + * which is an array of 8 integers. The bucket[] array + * contains 8 different DMA transfer sizes (in 16 + * byte increments) which the controller uses to fetch + * commands. This function fills in bucket_map[], which + * maps a given number of scatter gather elements to one of + * the 8 DMA transfer sizes. The point of it is to allow the + * controller to only do as much DMA as needed to fetch the + * command, with the DMA transfer size encoded in the lower + * bits of the command address. + */ +static void calc_bucket_map(int bucket[], int num_buckets, + int nsgs, int *bucket_map) +{ + int i, j, b, size; + + /* even a command with 0 SGs requires 4 blocks */ +#define MINIMUM_TRANSFER_BLOCKS 4 +#define NUM_BUCKETS 8 + /* Note, bucket_map must have nsgs+1 entries. */ + for (i = 0; i <= nsgs; i++) { + /* Compute size of a command with i SG entries */ + size = i + MINIMUM_TRANSFER_BLOCKS; + b = num_buckets; /* Assume the biggest bucket */ + /* Find the bucket that is just big enough */ + for (j = 0; j < 8; j++) { + if (bucket[j] >= size) { + b = j; + break; + } + } + /* for a command with i SG entries, use bucket b. */ + bucket_map[i] = b; + } +} + +static void +cciss_put_controller_into_performant_mode(ctlr_info_t *h) +{ + int l = 0; + __u32 trans_support; + __u32 trans_offset; + /* + * 5 = 1 s/g entry or 4k + * 6 = 2 s/g entry or 8k + * 8 = 4 s/g entry or 16k + * 10 = 6 s/g entry or 24k + */ + int bft[8] = { 5, 6, 8, 10, 12, 20, 28, MAXSGENTRIES + 4}; + unsigned long register_value; + + BUILD_BUG_ON(28 > MAXSGENTRIES + 4); + + /* Attempt to put controller into performant mode if supported */ + /* Does board support performant mode? */ + trans_support = readl(&(h->cfgtable->TransportSupport)); + if (!(trans_support & PERFORMANT_MODE)) + return; + + printk(KERN_WARNING "cciss%d: Placing controller into " + "performant mode\n", h->ctlr); + /* Performant mode demands commands on a 32 byte boundary + * pci_alloc_consistent aligns on page boundarys already. + * Just need to check if divisible by 32 + */ + if ((sizeof(CommandList_struct) % 32) != 0) { + printk(KERN_WARNING "%s %d %s\n", + "cciss info: command size[", + (int)sizeof(CommandList_struct), + "] not divisible by 32, no performant mode..\n"); + return; + } + + /* Performant mode ring buffer and supporting data structures */ + h->reply_pool = (__u64 *)pci_alloc_consistent( + h->pdev, h->max_commands * sizeof(__u64), + &(h->reply_pool_dhandle)); + + /* Need a block fetch table for performant mode */ + h->blockFetchTable = kmalloc(((h->maxsgentries+1) * + sizeof(__u32)), GFP_KERNEL); + + if ((h->reply_pool == NULL) || (h->blockFetchTable == NULL)) + goto clean_up; + + h->reply_pool_wraparound = 1; /* spec: init to 1 */ + + /* Controller spec: zero out this buffer. */ + memset(h->reply_pool, 0, h->max_commands * sizeof(__u64)); + h->reply_pool_head = h->reply_pool; + + trans_offset = readl(&(h->cfgtable->TransMethodOffset)); + calc_bucket_map(bft, ARRAY_SIZE(bft), h->maxsgentries, + h->blockFetchTable); + writel(bft[0], &h->transtable->BlockFetch0); + writel(bft[1], &h->transtable->BlockFetch1); + writel(bft[2], &h->transtable->BlockFetch2); + writel(bft[3], &h->transtable->BlockFetch3); + writel(bft[4], &h->transtable->BlockFetch4); + writel(bft[5], &h->transtable->BlockFetch5); + writel(bft[6], &h->transtable->BlockFetch6); + writel(bft[7], &h->transtable->BlockFetch7); + + /* size of controller ring buffer */ + writel(h->max_commands, &h->transtable->RepQSize); + writel(1, &h->transtable->RepQCount); + writel(0, &h->transtable->RepQCtrAddrLow32); + writel(0, &h->transtable->RepQCtrAddrHigh32); + writel(h->reply_pool_dhandle, &h->transtable->RepQAddr0Low32); + writel(0, &h->transtable->RepQAddr0High32); + writel(CFGTBL_Trans_Performant, + &(h->cfgtable->HostWrite.TransportRequest)); + + h->transMethod = CFGTBL_Trans_Performant; + writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); + /* under certain very rare conditions, this can take awhile. + * (e.g.: hot replace a failed 144GB drive in a RAID 5 set right + * as we enter this code.) */ + for (l = 0; l < MAX_CONFIG_WAIT; l++) { + register_value = readl(h->vaddr + SA5_DOORBELL); + if (!(register_value & CFGTBL_ChangeReq)) + break; + /* delay and try again */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(10); + } + register_value = readl(&(h->cfgtable->TransportActive)); + if (!(register_value & CFGTBL_Trans_Performant)) { + printk(KERN_WARNING "cciss: unable to get board into" + " performant mode\n"); + return; + } + + /* Change the access methods to the performant access methods */ + h->access = SA5_performant_access; + + return; +clean_up: + kfree(h->blockFetchTable); + if (h->reply_pool) + pci_free_consistent(h->pdev, + h->max_commands * sizeof(__u64), + h->reply_pool, + h->reply_pool_dhandle); + return; + +} /* cciss_put_controller_into_performant_mode */ + /* If MSI/MSI-X is supported by the kernel we will try to enable it on * controllers that are capable. If not, we use IO-APIC mode. */ @@ -3679,7 +3978,7 @@ static void __devinit cciss_interrupt_mode(ctlr_info_t *c, default_int_mode: #endif /* CONFIG_PCI_MSI */ /* if we get here we're going to use the default interrupt mode */ - c->intr[SIMPLE_MODE_INT] = pdev->irq; + c->intr[PERF_MODE_INT] = pdev->irq; return; } @@ -3691,6 +3990,7 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) __u32 cfg_base_addr; __u64 cfg_base_addr_index; int i, prod_index, err; + __u32 trans_offset; subsystem_vendor_id = pdev->subsystem_vendor; subsystem_device_id = pdev->subsystem_device; @@ -3804,11 +4104,16 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) c->cfgtable = remap_pci_mem(pci_resource_start(pdev, cfg_base_addr_index) + cfg_offset, sizeof(CfgTable_struct)); + /* Find performant mode table. */ + trans_offset = readl(&(c->cfgtable->TransMethodOffset)); + c->transtable = remap_pci_mem(pci_resource_start(pdev, + cfg_base_addr_index) + cfg_offset+trans_offset, + sizeof(*c->transtable)); c->board_id = board_id; -#ifdef CCISS_DEBUG - print_cfg_table(c->cfgtable); -#endif /* CCISS_DEBUG */ + #ifdef CCISS_DEBUG + print_cfg_table(c->cfgtable); + #endif /* CCISS_DEBUG */ /* Some controllers support Zero Memory Raid (ZMR). * When configured in ZMR mode the number of supported @@ -3818,7 +4123,7 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) * are supported on the controller then subtract 4 to * leave a little room for ioctl calls. */ - c->max_commands = readl(&(c->cfgtable->CmdsOutMax)); + c->max_commands = readl(&(c->cfgtable->MaxPerformantModeCommands)); c->maxsgentries = readl(&(c->cfgtable->MaxSGElements)); /* @@ -3863,7 +4168,7 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) * kernels revealed a bug in the refetch if dom0 resides on a P600. */ if(board_id == 0x3225103C) { - __u32 dma_prefetch; + __u32 dma_prefetch; __u32 dma_refetch; dma_prefetch = readl(c->vaddr + I2O_DMA1_CFG); dma_prefetch |= 0x8000; @@ -3874,38 +4179,9 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) } #ifdef CCISS_DEBUG - printk("Trying to put board into Simple mode\n"); -#endif /* CCISS_DEBUG */ - c->max_commands = readl(&(c->cfgtable->CmdsOutMax)); - /* Update the field, and then ring the doorbell */ - writel(CFGTBL_Trans_Simple, &(c->cfgtable->HostWrite.TransportRequest)); - writel(CFGTBL_ChangeReq, c->vaddr + SA5_DOORBELL); - - /* under certain very rare conditions, this can take awhile. - * (e.g.: hot replace a failed 144GB drive in a RAID 5 set right - * as we enter this code.) */ - for (i = 0; i < MAX_CONFIG_WAIT; i++) { - if (!(readl(c->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq)) - break; - /* delay and try again */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(msecs_to_jiffies(1)); - } - -#ifdef CCISS_DEBUG - printk(KERN_DEBUG "I counter got to %d %x\n", i, - readl(c->vaddr + SA5_DOORBELL)); -#endif /* CCISS_DEBUG */ -#ifdef CCISS_DEBUG - print_cfg_table(c->cfgtable); + printk(KERN_WARNING "Trying to put board into Performant mode\n"); #endif /* CCISS_DEBUG */ - - if (!(readl(&(c->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) { - printk(KERN_WARNING "cciss: unable to get board into" - " simple mode\n"); - err = -ENODEV; - goto err_out_free_res; - } + cciss_put_controller_into_performant_mode(c); return 0; err_out_free_res: @@ -4190,7 +4466,6 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, i = alloc_cciss_hba(); if (i < 0) return -1; - hba[i]->busy_initializing = 1; INIT_HLIST_HEAD(&hba[i]->cmpQ); INIT_HLIST_HEAD(&hba[i]->reqQ); @@ -4238,16 +4513,26 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, /* make sure the board interrupts are off */ hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF); - if (request_irq(hba[i]->intr[SIMPLE_MODE_INT], do_cciss_intr, - IRQF_DISABLED | IRQF_SHARED, hba[i]->devname, hba[i])) { - printk(KERN_ERR "cciss: Unable to get irq %d for %s\n", - hba[i]->intr[SIMPLE_MODE_INT], hba[i]->devname); - goto clean2; + if (hba[i]->msi_vector || hba[i]->msix_vector) { + if (request_irq(hba[i]->intr[PERF_MODE_INT], + do_cciss_msix_intr, + IRQF_DISABLED, hba[i]->devname, hba[i])) { + printk(KERN_ERR "cciss: Unable to get irq %d for %s\n", + hba[i]->intr[PERF_MODE_INT], hba[i]->devname); + goto clean2; + } + } else { + if (request_irq(hba[i]->intr[PERF_MODE_INT], do_cciss_intx, + IRQF_DISABLED, hba[i]->devname, hba[i])) { + printk(KERN_ERR "cciss: Unable to get irq %d for %s\n", + hba[i]->intr[PERF_MODE_INT], hba[i]->devname); + goto clean2; + } } printk(KERN_INFO "%s: <0x%x> at PCI %s IRQ %d%s using DAC\n", hba[i]->devname, pdev->device, pci_name(pdev), - hba[i]->intr[SIMPLE_MODE_INT], dac ? "" : " not"); + hba[i]->intr[PERF_MODE_INT], dac ? "" : " not"); hba[i]->cmd_pool_bits = kmalloc(DIV_ROUND_UP(hba[i]->nr_cmds, BITS_PER_LONG) @@ -4353,7 +4638,7 @@ clean4: hba[i]->nr_cmds * sizeof(ErrorInfo_struct), hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle); - free_irq(hba[i]->intr[SIMPLE_MODE_INT], hba[i]); + free_irq(hba[i]->intr[PERF_MODE_INT], hba[i]); clean2: unregister_blkdev(hba[i]->major, hba[i]->devname); clean1: @@ -4395,7 +4680,7 @@ static void cciss_shutdown(struct pci_dev *pdev) printk(KERN_WARNING "cciss%d: Error flushing cache\n", h->ctlr); h->access.set_intr_mask(h, CCISS_INTR_OFF); - free_irq(h->intr[2], h); + free_irq(h->intr[PERF_MODE_INT], h); } static void __devexit cciss_remove_one(struct pci_dev *pdev) @@ -4495,7 +4780,6 @@ static int __init cciss_init(void) * array of them, the size must be a multiple of 8 bytes. */ BUILD_BUG_ON(sizeof(CommandList_struct) % COMMANDLIST_ALIGNMENT); - printk(KERN_INFO DRIVER_NAME "\n"); err = bus_register(&cciss_bus_type); @@ -4542,46 +4826,5 @@ static void __exit cciss_cleanup(void) bus_unregister(&cciss_bus_type); } -static void fail_all_cmds(unsigned long ctlr) -{ - /* If we get here, the board is apparently dead. */ - ctlr_info_t *h = hba[ctlr]; - CommandList_struct *c; - unsigned long flags; - - printk(KERN_WARNING "cciss%d: controller not responding.\n", h->ctlr); - h->alive = 0; /* the controller apparently died... */ - - spin_lock_irqsave(CCISS_LOCK(ctlr), flags); - - pci_disable_device(h->pdev); /* Make sure it is really dead. */ - - /* move everything off the request queue onto the completed queue */ - while (!hlist_empty(&h->reqQ)) { - c = hlist_entry(h->reqQ.first, CommandList_struct, list); - removeQ(c); - h->Qdepth--; - addQ(&h->cmpQ, c); - } - - /* Now, fail everything on the completed queue with a HW error */ - while (!hlist_empty(&h->cmpQ)) { - c = hlist_entry(h->cmpQ.first, CommandList_struct, list); - removeQ(c); - if (c->cmd_type != CMD_MSG_STALE) - c->err_info->CommandStatus = CMD_HARDWARE_ERR; - if (c->cmd_type == CMD_RWREQ) { - complete_command(h, c, 0); - } else if (c->cmd_type == CMD_IOCTL_PEND) - complete(c->waiting); -#ifdef CONFIG_CISS_SCSI_TAPE - else if (c->cmd_type == CMD_SCSI) - complete_scsi_command(c, 0, 0); -#endif - } - spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); - return; -} - module_init(cciss_init); module_exit(cciss_cleanup); diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index c5d411174db0..8a9f5b58daa8 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h @@ -25,7 +25,7 @@ struct access_method { void (*submit_command)(ctlr_info_t *h, CommandList_struct *c); void (*set_intr_mask)(ctlr_info_t *h, unsigned long val); unsigned long (*fifo_full)(ctlr_info_t *h); - unsigned long (*intr_pending)(ctlr_info_t *h); + bool (*intr_pending)(ctlr_info_t *h); unsigned long (*command_completed)(ctlr_info_t *h); }; typedef struct _drive_info_struct @@ -85,8 +85,8 @@ struct ctlr_info int max_cmd_sgentries; SGDescriptor_struct **cmd_sg_list; -# define DOORBELL_INT 0 -# define PERF_MODE_INT 1 +# define PERF_MODE_INT 0 +# define DOORBELL_INT 1 # define SIMPLE_MODE_INT 2 # define MEMQ_MODE_INT 3 unsigned int intr[4]; @@ -137,10 +137,27 @@ struct ctlr_info struct list_head scan_list; struct completion scan_wait; struct device dev; + /* + * Performant mode tables. + */ + u32 trans_support; + u32 trans_offset; + struct TransTable_struct *transtable; + unsigned long transMethod; + + /* + * Performant mode completion buffer + */ + u64 *reply_pool; + dma_addr_t reply_pool_dhandle; + u64 *reply_pool_head; + size_t reply_pool_size; + unsigned char reply_pool_wraparound; + u32 *blockFetchTable; }; -/* Defining the diffent access_menthods */ -/* +/* Defining the diffent access_methods + * * Memory mapped FIFO interface (SMART 53xx cards) */ #define SA5_DOORBELL 0x20 @@ -159,6 +176,15 @@ struct ctlr_info #define SA5B_INTR_PENDING 0x04 #define FIFO_EMPTY 0xffffffff #define CCISS_FIRMWARE_READY 0xffff0000 /* value in scratchpad register */ +/* Perf. mode flags */ +#define SA5_PERF_INTR_PENDING 0x04 +#define SA5_PERF_INTR_OFF 0x05 +#define SA5_OUTDB_STATUS_PERF_BIT 0x01 +#define SA5_OUTDB_CLEAR_PERF_BIT 0x01 +#define SA5_OUTDB_CLEAR 0xA0 +#define SA5_OUTDB_CLEAR_PERF_BIT 0x01 +#define SA5_OUTDB_STATUS 0x9C + #define CISS_ERROR_BIT 0x02 @@ -170,8 +196,9 @@ struct ctlr_info static void SA5_submit_command( ctlr_info_t *h, CommandList_struct *c) { #ifdef CCISS_DEBUG - printk("Sending %x - down to controller\n", c->busaddr ); -#endif /* CCISS_DEBUG */ + printk(KERN_WARNING "cciss%d: Sending %08x - down to controller\n", + h->ctlr, c->busaddr); +#endif /* CCISS_DEBUG */ writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET); h->commands_outstanding++; if ( h->commands_outstanding > h->max_outstanding) @@ -214,6 +241,20 @@ static void SA5B_intr_mask(ctlr_info_t *h, unsigned long val) h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); } } + +/* Performant mode intr_mask */ +static void SA5_performant_intr_mask(ctlr_info_t *h, unsigned long val) +{ + if (val) { /* turn on interrupts */ + h->interrupts_enabled = 1; + writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); + } else { + h->interrupts_enabled = 0; + writel(SA5_PERF_INTR_OFF, + h->vaddr + SA5_REPLY_INTR_MASK_OFFSET); + } +} + /* * Returns true if fifo is full. * @@ -250,10 +291,44 @@ static unsigned long SA5_completed(ctlr_info_t *h) return ( register_value); } + +/* Performant mode command completed */ +static unsigned long SA5_performant_completed(ctlr_info_t *h) +{ + unsigned long register_value = FIFO_EMPTY; + + /* flush the controller write of the reply queue by reading + * outbound doorbell status register. + */ + register_value = readl(h->vaddr + SA5_OUTDB_STATUS); + /* msi auto clears the interrupt pending bit. */ + if (!(h->msi_vector || h->msix_vector)) { + writel(SA5_OUTDB_CLEAR_PERF_BIT, h->vaddr + SA5_OUTDB_CLEAR); + /* Do a read in order to flush the write to the controller + * (as per spec.) + */ + register_value = readl(h->vaddr + SA5_OUTDB_STATUS); + } + + if ((*(h->reply_pool_head) & 1) == (h->reply_pool_wraparound)) { + register_value = *(h->reply_pool_head); + (h->reply_pool_head)++; + h->commands_outstanding--; + } else { + register_value = FIFO_EMPTY; + } + /* Check for wraparound */ + if (h->reply_pool_head == (h->reply_pool + h->max_commands)) { + h->reply_pool_head = h->reply_pool; + h->reply_pool_wraparound ^= 1; + } + + return register_value; +} /* * Returns true if an interrupt is pending.. */ -static unsigned long SA5_intr_pending(ctlr_info_t *h) +static bool SA5_intr_pending(ctlr_info_t *h) { unsigned long register_value = readl(h->vaddr + SA5_INTR_STATUS); @@ -268,7 +343,7 @@ static unsigned long SA5_intr_pending(ctlr_info_t *h) /* * Returns true if an interrupt is pending.. */ -static unsigned long SA5B_intr_pending(ctlr_info_t *h) +static bool SA5B_intr_pending(ctlr_info_t *h) { unsigned long register_value = readl(h->vaddr + SA5_INTR_STATUS); @@ -280,6 +355,20 @@ static unsigned long SA5B_intr_pending(ctlr_info_t *h) return 0 ; } +static bool SA5_performant_intr_pending(ctlr_info_t *h) +{ + unsigned long register_value = readl(h->vaddr + SA5_INTR_STATUS); + + if (!register_value) + return false; + + if (h->msi_vector || h->msix_vector) + return true; + + /* Read outbound doorbell to flush */ + register_value = readl(h->vaddr + SA5_OUTDB_STATUS); + return register_value & SA5_OUTDB_STATUS_PERF_BIT; +} static struct access_method SA5_access = { SA5_submit_command, @@ -297,6 +386,14 @@ static struct access_method SA5B_access = { SA5_completed, }; +static struct access_method SA5_performant_access = { + SA5_submit_command, + SA5_performant_intr_mask, + SA5_fifo_full, + SA5_performant_intr_pending, + SA5_performant_completed, +}; + struct board_type { __u32 board_id; char *product_name; diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h index e624ff959cb6..936b9666da6a 100644 --- a/drivers/block/cciss_cmd.h +++ b/drivers/block/cciss_cmd.h @@ -54,6 +54,7 @@ #define CFGTBL_AccCmds 0x00000001l #define CFGTBL_Trans_Simple 0x00000002l +#define CFGTBL_Trans_Performant 0x00000004l #define CFGTBL_BusType_Ultra2 0x00000001l #define CFGTBL_BusType_Ultra3 0x00000002l @@ -173,12 +174,15 @@ typedef struct _SGDescriptor_struct { * PAD_64 can be adjusted independently as needed for 32-bit * and 64-bits systems. */ -#define COMMANDLIST_ALIGNMENT (8) +#define COMMANDLIST_ALIGNMENT (32) #define IS_64_BIT ((sizeof(long) - 4)/4) #define IS_32_BIT (!IS_64_BIT) #define PAD_32 (0) #define PAD_64 (4) #define PADSIZE (IS_32_BIT * PAD_32 + IS_64_BIT * PAD_64) +#define DIRECT_LOOKUP_BIT 0x10 +#define DIRECT_LOOKUP_SHIFT 5 + typedef struct _CommandList_struct { CommandListHeader_struct Header; RequestBlock_struct Request; @@ -195,7 +199,7 @@ typedef struct _CommandList_struct { struct completion *waiting; int retry_count; void * scsi_cmd; - char pad[PADSIZE]; + char pad[PADSIZE]; } CommandList_struct; /* Configuration Table Structure */ @@ -209,12 +213,15 @@ typedef struct _HostWrite_struct { typedef struct _CfgTable_struct { BYTE Signature[4]; DWORD SpecValence; +#define SIMPLE_MODE 0x02 +#define PERFORMANT_MODE 0x04 +#define MEMQ_MODE 0x08 DWORD TransportSupport; DWORD TransportActive; HostWrite_struct HostWrite; DWORD CmdsOutMax; DWORD BusTypes; - DWORD Reserved; + DWORD TransMethodOffset; BYTE ServerName[16]; DWORD HeartBeat; DWORD SCSI_Prefetch; @@ -222,6 +229,25 @@ typedef struct _CfgTable_struct { DWORD MaxLogicalUnits; DWORD MaxPhysicalDrives; DWORD MaxPhysicalDrivesPerLogicalUnit; + DWORD MaxPerformantModeCommands; } CfgTable_struct; + +struct TransTable_struct { + u32 BlockFetch0; + u32 BlockFetch1; + u32 BlockFetch2; + u32 BlockFetch3; + u32 BlockFetch4; + u32 BlockFetch5; + u32 BlockFetch6; + u32 BlockFetch7; + u32 RepQSize; + u32 RepQCount; + u32 RepQCtrAddrLow32; + u32 RepQCtrAddrHigh32; + u32 RepQAddr0Low32; + u32 RepQAddr0High32; +}; + #pragma pack() #endif /* CCISS_CMD_H */ diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 72dae92f3cab..8e0a709286df 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -93,8 +93,8 @@ static struct scsi_host_template cciss_driver_template = { #pragma pack(1) -#define SCSI_PAD_32 0 -#define SCSI_PAD_64 0 +#define SCSI_PAD_32 8 +#define SCSI_PAD_64 8 struct cciss_scsi_cmd_stack_elem_t { CommandList_struct cmd; diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index abb4ec6690fc..28937b661564 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -35,6 +35,7 @@ #include <linux/seq_file.h> #include <linux/init.h> #include <linux/hdreg.h> +#include <linux/smp_lock.h> #include <linux/spinlock.h> #include <linux/blkdev.h> #include <linux/genhd.h> @@ -157,7 +158,7 @@ static int sendcmd( unsigned int blkcnt, unsigned int log_unit ); -static int ida_open(struct block_device *bdev, fmode_t mode); +static int ida_unlocked_open(struct block_device *bdev, fmode_t mode); static int ida_release(struct gendisk *disk, fmode_t mode); static int ida_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg); static int ida_getgeo(struct block_device *bdev, struct hd_geometry *geo); @@ -195,9 +196,9 @@ static inline ctlr_info_t *get_host(struct gendisk *disk) static const struct block_device_operations ida_fops = { .owner = THIS_MODULE, - .open = ida_open, + .open = ida_unlocked_open, .release = ida_release, - .locked_ioctl = ida_ioctl, + .ioctl = ida_ioctl, .getgeo = ida_getgeo, .revalidate_disk= ida_revalidate, }; @@ -840,13 +841,29 @@ static int ida_open(struct block_device *bdev, fmode_t mode) return 0; } +static int ida_unlocked_open(struct block_device *bdev, fmode_t mode) +{ + int ret; + + lock_kernel(); + ret = ida_open(bdev, mode); + unlock_kernel(); + + return ret; +} + /* * Close. Sync first. */ static int ida_release(struct gendisk *disk, fmode_t mode) { - ctlr_info_t *host = get_host(disk); + ctlr_info_t *host; + + lock_kernel(); + host = get_host(disk); host->usage_count--; + unlock_kernel(); + return 0; } @@ -1128,7 +1145,7 @@ static int ida_getgeo(struct block_device *bdev, struct hd_geometry *geo) * ida_ioctl does some miscellaneous stuff like reporting drive geometry, * setting readahead and submitting commands from userspace to the controller. */ -static int ida_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) +static int ida_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { drv_info_t *drv = get_drv(bdev->bd_disk); ctlr_info_t *host = get_host(bdev->bd_disk); @@ -1192,6 +1209,19 @@ out_passthru: } } + +static int ida_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long param) +{ + int ret; + + lock_kernel(); + ret = ida_locked_ioctl(bdev, mode, cmd, param); + unlock_kernel(); + + return ret; +} + /* * ida_ctlr_ioctl is for passing commands to the controller from userspace. * The command block (io) has already been copied to kernel space for us, diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index df018990c422..9400845d602e 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -79,8 +79,8 @@ static int _drbd_md_sync_page_io(struct drbd_conf *mdev, md_io.error = 0; if ((rw & WRITE) && !test_bit(MD_NO_BARRIER, &mdev->flags)) - rw |= (1 << BIO_RW_BARRIER); - rw |= ((1<<BIO_RW_UNPLUG) | (1<<BIO_RW_SYNCIO)); + rw |= REQ_HARDBARRIER; + rw |= REQ_UNPLUG | REQ_SYNC; retry: bio = bio_alloc(GFP_NOIO, 1); @@ -103,11 +103,11 @@ static int _drbd_md_sync_page_io(struct drbd_conf *mdev, /* check for unsupported barrier op. * would rather check on EOPNOTSUPP, but that is not reliable. * don't try again for ANY return value != 0 */ - if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER) && !ok)) { + if (unlikely((bio->bi_rw & REQ_HARDBARRIER) && !ok)) { /* Try again with no barrier */ dev_warn(DEV, "Barriers not supported on meta data device - disabling\n"); set_bit(MD_NO_BARRIER, &mdev->flags); - rw &= ~(1 << BIO_RW_BARRIER); + rw &= ~REQ_HARDBARRIER; bio_put(bio); goto retry; } diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 7258c95e895e..d2b6764a7b1f 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -2425,15 +2425,15 @@ int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req) /* NOTE: no need to check if barriers supported here as we would * not pass the test in make_request_common in that case */ - if (bio_rw_flagged(req->master_bio, BIO_RW_BARRIER)) { + if (req->master_bio->bi_rw & REQ_HARDBARRIER) { dev_err(DEV, "ASSERT FAILED would have set DP_HARDBARRIER\n"); /* dp_flags |= DP_HARDBARRIER; */ } - if (bio_rw_flagged(req->master_bio, BIO_RW_SYNCIO)) + if (req->master_bio->bi_rw & REQ_SYNC) dp_flags |= DP_RW_SYNC; /* for now handle SYNCIO and UNPLUG * as if they still were one and the same flag */ - if (bio_rw_flagged(req->master_bio, BIO_RW_UNPLUG)) + if (req->master_bio->bi_rw & REQ_UNPLUG) dp_flags |= DP_RW_SYNC; if (mdev->state.conn >= C_SYNC_SOURCE && mdev->state.conn <= C_PAUSED_SYNC_T) @@ -2604,6 +2604,7 @@ static int drbd_open(struct block_device *bdev, fmode_t mode) unsigned long flags; int rv = 0; + lock_kernel(); spin_lock_irqsave(&mdev->req_lock, flags); /* to have a stable mdev->state.role * and no race with updating open_cnt */ @@ -2618,6 +2619,7 @@ static int drbd_open(struct block_device *bdev, fmode_t mode) if (!rv) mdev->open_cnt++; spin_unlock_irqrestore(&mdev->req_lock, flags); + unlock_kernel(); return rv; } @@ -2625,7 +2627,9 @@ static int drbd_open(struct block_device *bdev, fmode_t mode) static int drbd_release(struct gendisk *gd, fmode_t mode) { struct drbd_conf *mdev = gd->private_data; + lock_kernel(); mdev->open_cnt--; + unlock_kernel(); return 0; } diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index dff48701b84d..cba1deb7b271 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -1180,7 +1180,7 @@ next_bio: bio->bi_sector = sector; bio->bi_bdev = mdev->ldev->backing_bdev; /* we special case some flags in the multi-bio case, see below - * (BIO_RW_UNPLUG, BIO_RW_BARRIER) */ + * (REQ_UNPLUG, REQ_HARDBARRIER) */ bio->bi_rw = rw; bio->bi_private = e; bio->bi_end_io = drbd_endio_sec; @@ -1209,16 +1209,16 @@ next_bio: bios = bios->bi_next; bio->bi_next = NULL; - /* strip off BIO_RW_UNPLUG unless it is the last bio */ + /* strip off REQ_UNPLUG unless it is the last bio */ if (bios) - bio->bi_rw &= ~(1<<BIO_RW_UNPLUG); + bio->bi_rw &= ~REQ_UNPLUG; drbd_generic_make_request(mdev, fault_type, bio); - /* strip off BIO_RW_BARRIER, + /* strip off REQ_HARDBARRIER, * unless it is the first or last bio */ if (bios && bios->bi_next) - bios->bi_rw &= ~(1<<BIO_RW_BARRIER); + bios->bi_rw &= ~REQ_HARDBARRIER; } while (bios); maybe_kick_lo(mdev); return 0; @@ -1233,7 +1233,7 @@ fail: } /** - * w_e_reissue() - Worker callback; Resubmit a bio, without BIO_RW_BARRIER set + * w_e_reissue() - Worker callback; Resubmit a bio, without REQ_HARDBARRIER set * @mdev: DRBD device. * @w: work object. * @cancel: The connection will be closed anyways (unused in this callback) @@ -1245,7 +1245,7 @@ int w_e_reissue(struct drbd_conf *mdev, struct drbd_work *w, int cancel) __relea (and DE_BARRIER_IN_NEXT_EPOCH_ISSUED in the previous Epoch) so that we can finish that epoch in drbd_may_finish_epoch(). That is necessary if we already have a long chain of Epochs, before - we realize that BIO_RW_BARRIER is actually not supported */ + we realize that REQ_HARDBARRIER is actually not supported */ /* As long as the -ENOTSUPP on the barrier is reported immediately that will never trigger. If it is reported late, we will just @@ -1824,14 +1824,14 @@ static int receive_Data(struct drbd_conf *mdev, struct p_header *h) epoch = list_entry(e->epoch->list.prev, struct drbd_epoch, list); if (epoch == e->epoch) { set_bit(DE_CONTAINS_A_BARRIER, &e->epoch->flags); - rw |= (1<<BIO_RW_BARRIER); + rw |= REQ_HARDBARRIER; e->flags |= EE_IS_BARRIER; } else { if (atomic_read(&epoch->epoch_size) > 1 || !test_bit(DE_CONTAINS_A_BARRIER, &epoch->flags)) { set_bit(DE_BARRIER_IN_NEXT_EPOCH_ISSUED, &epoch->flags); set_bit(DE_CONTAINS_A_BARRIER, &e->epoch->flags); - rw |= (1<<BIO_RW_BARRIER); + rw |= REQ_HARDBARRIER; e->flags |= EE_IS_BARRIER; } } @@ -1841,10 +1841,10 @@ static int receive_Data(struct drbd_conf *mdev, struct p_header *h) dp_flags = be32_to_cpu(p->dp_flags); if (dp_flags & DP_HARDBARRIER) { dev_err(DEV, "ASSERT FAILED would have submitted barrier request\n"); - /* rw |= (1<<BIO_RW_BARRIER); */ + /* rw |= REQ_HARDBARRIER; */ } if (dp_flags & DP_RW_SYNC) - rw |= (1<<BIO_RW_SYNCIO) | (1<<BIO_RW_UNPLUG); + rw |= REQ_SYNC | REQ_UNPLUG; if (dp_flags & DP_MAY_SET_IN_SYNC) e->flags |= EE_MAY_SET_IN_SYNC; diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 654f1ef5cbb0..f761d98a4e90 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -997,7 +997,7 @@ int drbd_make_request_26(struct request_queue *q, struct bio *bio) * because of those XXX, this is not yet enabled, * i.e. in drbd_init_set_defaults we set the NO_BARRIER_SUPP bit. */ - if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER) && test_bit(NO_BARRIER_SUPP, &mdev->flags))) { + if (unlikely(bio->bi_rw & REQ_HARDBARRIER) && test_bit(NO_BARRIER_SUPP, &mdev->flags)) { /* dev_warn(DEV, "Rejecting barrier request as underlying device does not support\n"); */ bio_endio(bio, -EOPNOTSUPP); return 0; diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 90c4038702da..3126d5122b2b 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -178,6 +178,7 @@ static int print_unex = 1; #include <linux/slab.h> #include <linux/mm.h> #include <linux/bio.h> +#include <linux/smp_lock.h> #include <linux/string.h> #include <linux/jiffies.h> #include <linux/fcntl.h> @@ -514,8 +515,6 @@ static unsigned long fdc_busy; static DECLARE_WAIT_QUEUE_HEAD(fdc_wait); static DECLARE_WAIT_QUEUE_HEAD(command_done); -#define NO_SIGNAL (!interruptible || !signal_pending(current)) - /* Errors during formatting are counted here. */ static int format_errors; @@ -578,7 +577,7 @@ static void reset_fdc(void); #define NEED_1_RECAL -2 #define NEED_2_RECAL -3 -static int usage_count; +static atomic_t usage_count = ATOMIC_INIT(0); /* buffer related variables */ static int buffer_track = -1; @@ -858,36 +857,15 @@ static void set_fdc(int drive) } /* locks the driver */ -static int _lock_fdc(int drive, bool interruptible, int line) +static int lock_fdc(int drive, bool interruptible) { - if (!usage_count) { - pr_err("Trying to lock fdc while usage count=0 at line %d\n", - line); + if (WARN(atomic_read(&usage_count) == 0, + "Trying to lock fdc while usage count=0\n")) return -1; - } - - if (test_and_set_bit(0, &fdc_busy)) { - DECLARE_WAITQUEUE(wait, current); - add_wait_queue(&fdc_wait, &wait); - - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - - if (!test_and_set_bit(0, &fdc_busy)) - break; - schedule(); - - if (!NO_SIGNAL) { - remove_wait_queue(&fdc_wait, &wait); - return -EINTR; - } - } + if (wait_event_interruptible(fdc_wait, !test_and_set_bit(0, &fdc_busy))) + return -EINTR; - set_current_state(TASK_RUNNING); - remove_wait_queue(&fdc_wait, &wait); - flush_scheduled_work(); - } command_status = FD_COMMAND_NONE; __reschedule_timeout(drive, "lock fdc"); @@ -895,11 +873,8 @@ static int _lock_fdc(int drive, bool interruptible, int line) return 0; } -#define lock_fdc(drive, interruptible) \ - _lock_fdc(drive, interruptible, __LINE__) - /* unlocks the driver */ -static inline void unlock_fdc(void) +static void unlock_fdc(void) { unsigned long flags; @@ -1224,7 +1199,7 @@ static int need_more_output(void) /* Set perpendicular mode as required, based on data rate, if supported. * 82077 Now tested. 1Mbps data rate only possible with 82077-1. */ -static inline void perpendicular_mode(void) +static void perpendicular_mode(void) { unsigned char perp_mode; @@ -2015,25 +1990,10 @@ static int wait_til_done(void (*handler)(void), bool interruptible) schedule_bh(handler); - if (command_status < 2 && NO_SIGNAL) { - DECLARE_WAITQUEUE(wait, current); - - add_wait_queue(&command_done, &wait); - for (;;) { - set_current_state(interruptible ? - TASK_INTERRUPTIBLE : - TASK_UNINTERRUPTIBLE); - - if (command_status >= 2 || !NO_SIGNAL) - break; - - is_alive(__func__, ""); - schedule(); - } - - set_current_state(TASK_RUNNING); - remove_wait_queue(&command_done, &wait); - } + if (interruptible) + wait_event_interruptible(command_done, command_status >= 2); + else + wait_event(command_done, command_status >= 2); if (command_status < 2) { cancel_activity(); @@ -2583,10 +2543,8 @@ static int make_raw_rw_request(void) int tracksize; int ssize; - if (max_buffer_sectors == 0) { - pr_info("VFS: Block I/O scheduled on unopened device\n"); + if (WARN(max_buffer_sectors == 0, "VFS: Block I/O scheduled on unopened device\n")) return 0; - } set_fdc((long)current_req->rq_disk->private_data); @@ -2936,19 +2894,16 @@ static void process_fd_request(void) static void do_fd_request(struct request_queue *q) { - if (max_buffer_sectors == 0) { - pr_info("VFS: %s called on non-open device\n", __func__); + if (WARN(max_buffer_sectors == 0, + "VFS: %s called on non-open device\n", __func__)) return; - } - if (usage_count == 0) { - pr_info("warning: usage count=0, current_req=%p exiting\n", - current_req); - pr_info("sect=%ld type=%x flags=%x\n", - (long)blk_rq_pos(current_req), current_req->cmd_type, - current_req->cmd_flags); + if (WARN(atomic_read(&usage_count) == 0, + "warning: usage count=0, current_req=%p sect=%ld type=%x flags=%x\n", + current_req, (long)blk_rq_pos(current_req), current_req->cmd_type, + current_req->cmd_flags)) return; - } + if (test_bit(0, &fdc_busy)) { /* fdc busy, this new request will be treated when the current one is done */ @@ -3033,7 +2988,7 @@ static inline int fd_copyin(void __user *param, void *address, return copy_from_user(address, param, size) ? -EFAULT : 0; } -static inline const char *drive_name(int type, int drive) +static const char *drive_name(int type, int drive) { struct floppy_struct *floppy; @@ -3103,7 +3058,7 @@ static struct cont_t raw_cmd_cont = { .done = raw_cmd_done }; -static inline int raw_cmd_copyout(int cmd, void __user *param, +static int raw_cmd_copyout(int cmd, void __user *param, struct floppy_raw_cmd *ptr) { int ret; @@ -3148,7 +3103,7 @@ static void raw_cmd_free(struct floppy_raw_cmd **ptr) } } -static inline int raw_cmd_copyin(int cmd, void __user *param, +static int raw_cmd_copyin(int cmd, void __user *param, struct floppy_raw_cmd **rcmd) { struct floppy_raw_cmd *ptr; @@ -3266,7 +3221,7 @@ static int invalidate_drive(struct block_device *bdev) return 0; } -static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, +static int set_geometry(unsigned int cmd, struct floppy_struct *g, int drive, int type, struct block_device *bdev) { int cnt; @@ -3337,7 +3292,7 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, } /* handle obsolete ioctl's */ -static int ioctl_table[] = { +static unsigned int ioctl_table[] = { FDCLRPRM, FDSETPRM, FDDEFPRM, @@ -3365,7 +3320,7 @@ static int ioctl_table[] = { FDTWADDLE }; -static inline int normalize_ioctl(int *cmd, int *size) +static int normalize_ioctl(unsigned int *cmd, int *size) { int i; @@ -3417,7 +3372,7 @@ static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo) return 0; } -static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, +static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long param) { int drive = (long)bdev->bd_disk->private_data; @@ -3593,6 +3548,18 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, return 0; } +static int fd_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long param) +{ + int ret; + + lock_kernel(); + ret = fd_locked_ioctl(bdev, mode, cmd, param); + unlock_kernel(); + + return ret; +} + static void __init config_types(void) { bool has_drive = false; @@ -3649,6 +3616,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode) { int drive = (long)disk->private_data; + lock_kernel(); mutex_lock(&open_lock); if (UDRS->fd_ref < 0) UDRS->fd_ref = 0; @@ -3659,6 +3627,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode) if (!UDRS->fd_ref) opened_bdev[drive] = NULL; mutex_unlock(&open_lock); + unlock_kernel(); return 0; } @@ -3676,6 +3645,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) int res = -EBUSY; char *tmp; + lock_kernel(); mutex_lock(&open_lock); old_dev = UDRS->fd_device; if (opened_bdev[drive] && opened_bdev[drive] != bdev) @@ -3752,6 +3722,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) goto out; } mutex_unlock(&open_lock); + unlock_kernel(); return 0; out: if (UDRS->fd_ref < 0) @@ -3762,6 +3733,7 @@ out: opened_bdev[drive] = NULL; out2: mutex_unlock(&open_lock); + unlock_kernel(); return res; } @@ -3829,6 +3801,7 @@ static int __floppy_read_block_0(struct block_device *bdev) bio.bi_size = size; bio.bi_bdev = bdev; bio.bi_sector = 0; + bio.bi_flags = BIO_QUIET; init_completion(&complete); bio.bi_private = &complete; bio.bi_end_io = floppy_rb0_complete; @@ -3857,10 +3830,10 @@ static int floppy_revalidate(struct gendisk *disk) if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || test_bit(FD_VERIFY_BIT, &UDRS->flags) || test_bit(drive, &fake_change) || NO_GEOM) { - if (usage_count == 0) { - pr_info("VFS: revalidate called on non-open device.\n"); + if (WARN(atomic_read(&usage_count) == 0, + "VFS: revalidate called on non-open device.\n")) return -EFAULT; - } + lock_fdc(drive, false); cf = (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) || test_bit(FD_VERIFY_BIT, &UDRS->flags)); @@ -3893,7 +3866,7 @@ static const struct block_device_operations floppy_fops = { .owner = THIS_MODULE, .open = floppy_open, .release = floppy_release, - .locked_ioctl = fd_ioctl, + .ioctl = fd_ioctl, .getgeo = fd_getgeo, .media_changed = check_floppy_change, .revalidate_disk = floppy_revalidate, @@ -4126,7 +4099,7 @@ static ssize_t floppy_cmos_show(struct device *dev, return sprintf(buf, "%X\n", UDP->cmos); } -DEVICE_ATTR(cmos, S_IRUGO, floppy_cmos_show, NULL); +static DEVICE_ATTR(cmos, S_IRUGO, floppy_cmos_show, NULL); static void floppy_device_release(struct device *dev) { @@ -4175,6 +4148,9 @@ static int __init floppy_init(void) int i, unit, drive; int err, dr; + set_debugt(); + interruptjiffies = resultjiffies = jiffies; + #if defined(CONFIG_PPC) if (check_legacy_ioport(FDC1)) return -ENODEV; @@ -4353,7 +4329,7 @@ out_unreg_platform_dev: platform_device_unregister(&floppy_device[drive]); out_flush_work: flush_scheduled_work(); - if (usage_count) + if (atomic_read(&usage_count)) floppy_release_irq_and_dma(); out_unreg_region: blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); @@ -4370,8 +4346,6 @@ out_put_disk: return err; } -static DEFINE_SPINLOCK(floppy_usage_lock); - static const struct io_region { int offset; int size; @@ -4417,14 +4391,8 @@ static void floppy_release_regions(int fdc) static int floppy_grab_irq_and_dma(void) { - unsigned long flags; - - spin_lock_irqsave(&floppy_usage_lock, flags); - if (usage_count++) { - spin_unlock_irqrestore(&floppy_usage_lock, flags); + if (atomic_inc_return(&usage_count) > 1) return 0; - } - spin_unlock_irqrestore(&floppy_usage_lock, flags); /* * We might have scheduled a free_irq(), wait it to @@ -4435,9 +4403,7 @@ static int floppy_grab_irq_and_dma(void) if (fd_request_irq()) { DPRINT("Unable to grab IRQ%d for the floppy driver\n", FLOPPY_IRQ); - spin_lock_irqsave(&floppy_usage_lock, flags); - usage_count--; - spin_unlock_irqrestore(&floppy_usage_lock, flags); + atomic_dec(&usage_count); return -1; } if (fd_request_dma()) { @@ -4447,9 +4413,7 @@ static int floppy_grab_irq_and_dma(void) use_virtual_dma = can_use_virtual_dma = 1; if (!(can_use_virtual_dma & 1)) { fd_free_irq(); - spin_lock_irqsave(&floppy_usage_lock, flags); - usage_count--; - spin_unlock_irqrestore(&floppy_usage_lock, flags); + atomic_dec(&usage_count); return -1; } } @@ -4484,9 +4448,7 @@ cleanup: fd_free_dma(); while (--fdc >= 0) floppy_release_regions(fdc); - spin_lock_irqsave(&floppy_usage_lock, flags); - usage_count--; - spin_unlock_irqrestore(&floppy_usage_lock, flags); + atomic_dec(&usage_count); return -1; } @@ -4498,14 +4460,10 @@ static void floppy_release_irq_and_dma(void) #endif long tmpsize; unsigned long tmpaddr; - unsigned long flags; - spin_lock_irqsave(&floppy_usage_lock, flags); - if (--usage_count) { - spin_unlock_irqrestore(&floppy_usage_lock, flags); + if (!atomic_dec_and_test(&usage_count)) return; - } - spin_unlock_irqrestore(&floppy_usage_lock, flags); + if (irqdma_allocated) { fd_disable_dma(); fd_free_dma(); @@ -4598,7 +4556,7 @@ static void __exit floppy_module_exit(void) del_timer_sync(&fd_timer); blk_cleanup_queue(floppy_queue); - if (usage_count) + if (atomic_read(&usage_count)) floppy_release_irq_and_dma(); /* eject disk, if any */ diff --git a/drivers/block/hd.c b/drivers/block/hd.c index 81c78b3ce2df..30ec6b37424e 100644 --- a/drivers/block/hd.c +++ b/drivers/block/hd.c @@ -627,7 +627,7 @@ repeat: req_data_dir(req) == READ ? "read" : "writ", cyl, head, sec, nsect, req->buffer); #endif - if (blk_fs_request(req)) { + if (req->cmd_type == REQ_TYPE_FS) { switch (rq_data_dir(req)) { case READ: hd_out(disk, nsect, sec, head, cyl, ATA_CMD_PIO_READ, diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 6120922f459f..f3c636d23718 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -67,6 +67,7 @@ #include <linux/compat.h> #include <linux/suspend.h> #include <linux/freezer.h> +#include <linux/smp_lock.h> #include <linux/writeback.h> #include <linux/buffer_head.h> /* for invalidate_bdev() */ #include <linux/completion.h> @@ -476,7 +477,7 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio) pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset; if (bio_rw(bio) == WRITE) { - bool barrier = bio_rw_flagged(bio, BIO_RW_BARRIER); + bool barrier = (bio->bi_rw & REQ_HARDBARRIER); struct file *file = lo->lo_backing_file; if (barrier) { @@ -831,7 +832,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, lo->lo_queue->unplug_fn = loop_unplug; if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync) - blk_queue_ordered(lo->lo_queue, QUEUE_ORDERED_DRAIN, NULL); + blk_queue_ordered(lo->lo_queue, QUEUE_ORDERED_DRAIN); set_capacity(lo->lo_disk, size); bd_set_size(bdev, size << 9); @@ -1408,9 +1409,11 @@ static int lo_open(struct block_device *bdev, fmode_t mode) { struct loop_device *lo = bdev->bd_disk->private_data; + lock_kernel(); mutex_lock(&lo->lo_ctl_mutex); lo->lo_refcnt++; mutex_unlock(&lo->lo_ctl_mutex); + unlock_kernel(); return 0; } @@ -1420,6 +1423,7 @@ static int lo_release(struct gendisk *disk, fmode_t mode) struct loop_device *lo = disk->private_data; int err; + lock_kernel(); mutex_lock(&lo->lo_ctl_mutex); if (--lo->lo_refcnt) @@ -1444,6 +1448,7 @@ static int lo_release(struct gendisk *disk, fmode_t mode) out: mutex_unlock(&lo->lo_ctl_mutex); out_unlocked: + lock_kernel(); return 0; } diff --git a/drivers/block/mg_disk.c b/drivers/block/mg_disk.c index 28db925dbdad..b82c5ce5e9df 100644 --- a/drivers/block/mg_disk.c +++ b/drivers/block/mg_disk.c @@ -670,7 +670,7 @@ static void mg_request_poll(struct request_queue *q) break; } - if (unlikely(!blk_fs_request(host->req))) { + if (unlikely(host->req->cmd_type != REQ_TYPE_FS)) { mg_end_request_cur(host, -EIO); continue; } @@ -756,7 +756,7 @@ static void mg_request(struct request_queue *q) continue; } - if (unlikely(!blk_fs_request(req))) { + if (unlikely(req->cmd_type != REQ_TYPE_FS)) { mg_end_request_cur(host, -EIO); continue; } diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 218d091f3c52..6751789fb379 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -24,6 +24,7 @@ #include <linux/errno.h> #include <linux/file.h> #include <linux/ioctl.h> +#include <linux/smp_lock.h> #include <linux/compiler.h> #include <linux/err.h> #include <linux/kernel.h> @@ -448,7 +449,7 @@ static void nbd_clear_que(struct nbd_device *lo) static void nbd_handle_req(struct nbd_device *lo, struct request *req) { - if (!blk_fs_request(req)) + if (req->cmd_type != REQ_TYPE_FS) goto error_out; nbd_cmd(req) = NBD_CMD_READ; @@ -716,9 +717,11 @@ static int nbd_ioctl(struct block_device *bdev, fmode_t mode, dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu\n", lo->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg); + lock_kernel(); mutex_lock(&lo->tx_lock); error = __nbd_ioctl(bdev, lo, cmd, arg); mutex_unlock(&lo->tx_lock); + unlock_kernel(); return error; } @@ -726,7 +729,7 @@ static int nbd_ioctl(struct block_device *bdev, fmode_t mode, static const struct block_device_operations nbd_fops = { .owner = THIS_MODULE, - .locked_ioctl = nbd_ioctl, + .ioctl = nbd_ioctl, }; /* diff --git a/drivers/block/osdblk.c b/drivers/block/osdblk.c index 6cd8b705b11b..2284b4f05c62 100644 --- a/drivers/block/osdblk.c +++ b/drivers/block/osdblk.c @@ -310,7 +310,8 @@ static void osdblk_rq_fn(struct request_queue *q) break; /* filter out block requests we don't understand */ - if (!blk_fs_request(rq) && !blk_barrier_rq(rq)) { + if (rq->cmd_type != REQ_TYPE_FS && + !(rq->cmd_flags & REQ_HARDBARRIER)) { blk_end_request_all(rq, 0); continue; } @@ -322,7 +323,7 @@ static void osdblk_rq_fn(struct request_queue *q) * driver-specific, etc. */ - do_flush = (rq->special == (void *) 0xdeadbeefUL); + do_flush = rq->cmd_flags & REQ_FLUSH; do_write = (rq_data_dir(rq) == WRITE); if (!do_flush) { /* osd_flush does not use a bio */ @@ -379,14 +380,6 @@ static void osdblk_rq_fn(struct request_queue *q) } } -static void osdblk_prepare_flush(struct request_queue *q, struct request *rq) -{ - /* add driver-specific marker, to indicate that this request - * is a flush command - */ - rq->special = (void *) 0xdeadbeefUL; -} - static void osdblk_free_disk(struct osdblk_device *osdev) { struct gendisk *disk = osdev->disk; @@ -446,7 +439,7 @@ static int osdblk_init_disk(struct osdblk_device *osdev) blk_queue_stack_limits(q, osd_request_queue(osdev->osd)); blk_queue_prep_rq(q, blk_queue_start_tag); - blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH, osdblk_prepare_flush); + blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH); disk->queue = q; diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c index 71acf4e53356..76f8565e1e8d 100644 --- a/drivers/block/paride/pcd.c +++ b/drivers/block/paride/pcd.c @@ -138,6 +138,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY}; #include <linux/cdrom.h> #include <linux/spinlock.h> #include <linux/blkdev.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h> static DEFINE_SPINLOCK(pcd_lock); @@ -224,13 +225,21 @@ static char *pcd_buf; /* buffer for request in progress */ static int pcd_block_open(struct block_device *bdev, fmode_t mode) { struct pcd_unit *cd = bdev->bd_disk->private_data; - return cdrom_open(&cd->info, bdev, mode); + int ret; + + lock_kernel(); + ret = cdrom_open(&cd->info, bdev, mode); + unlock_kernel(); + + return ret; } static int pcd_block_release(struct gendisk *disk, fmode_t mode) { struct pcd_unit *cd = disk->private_data; + lock_kernel(); cdrom_release(&cd->info, mode); + unlock_kernel(); return 0; } @@ -238,7 +247,13 @@ static int pcd_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long arg) { struct pcd_unit *cd = bdev->bd_disk->private_data; - return cdrom_ioctl(&cd->info, bdev, mode, cmd, arg); + int ret; + + lock_kernel(); + ret = cdrom_ioctl(&cd->info, bdev, mode, cmd, arg); + unlock_kernel(); + + return ret; } static int pcd_block_media_changed(struct gendisk *disk) @@ -251,7 +266,7 @@ static const struct block_device_operations pcd_bdops = { .owner = THIS_MODULE, .open = pcd_block_open, .release = pcd_block_release, - .locked_ioctl = pcd_block_ioctl, + .ioctl = pcd_block_ioctl, .media_changed = pcd_block_media_changed, }; diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index c1e5cd029b23..985f0d4f1d1e 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c @@ -153,6 +153,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_GEO, D_SBY, D_DLY, D_SLV}; #include <linux/blkdev.h> #include <linux/blkpg.h> #include <linux/kernel.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h> #include <linux/workqueue.h> @@ -439,7 +440,7 @@ static char *pd_buf; /* buffer for request in progress */ static enum action do_pd_io_start(void) { - if (blk_special_request(pd_req)) { + if (pd_req->cmd_type == REQ_TYPE_SPECIAL) { phase = pd_special; return pd_special(); } @@ -735,12 +736,14 @@ static int pd_open(struct block_device *bdev, fmode_t mode) { struct pd_unit *disk = bdev->bd_disk->private_data; + lock_kernel(); disk->access++; if (disk->removable) { pd_special_command(disk, pd_media_check); pd_special_command(disk, pd_door_lock); } + unlock_kernel(); return 0; } @@ -768,8 +771,10 @@ static int pd_ioctl(struct block_device *bdev, fmode_t mode, switch (cmd) { case CDROMEJECT: + lock_kernel(); if (disk->access == 1) pd_special_command(disk, pd_eject); + unlock_kernel(); return 0; default: return -EINVAL; @@ -780,8 +785,10 @@ static int pd_release(struct gendisk *p, fmode_t mode) { struct pd_unit *disk = p->private_data; + lock_kernel(); if (!--disk->access && disk->removable) pd_special_command(disk, pd_door_unlock); + unlock_kernel(); return 0; } @@ -812,7 +819,7 @@ static const struct block_device_operations pd_fops = { .owner = THIS_MODULE, .open = pd_open, .release = pd_release, - .locked_ioctl = pd_ioctl, + .ioctl = pd_ioctl, .getgeo = pd_getgeo, .media_changed = pd_check_media, .revalidate_disk= pd_revalidate diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c index c059aab3006b..4457b494882a 100644 --- a/drivers/block/paride/pf.c +++ b/drivers/block/paride/pf.c @@ -152,6 +152,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_LUN, D_DLY}; #include <linux/spinlock.h> #include <linux/blkdev.h> #include <linux/blkpg.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h> static DEFINE_SPINLOCK(pf_spin_lock); @@ -266,7 +267,7 @@ static const struct block_device_operations pf_fops = { .owner = THIS_MODULE, .open = pf_open, .release = pf_release, - .locked_ioctl = pf_ioctl, + .ioctl = pf_ioctl, .getgeo = pf_getgeo, .media_changed = pf_check_media, }; @@ -299,20 +300,26 @@ static void __init pf_init_units(void) static int pf_open(struct block_device *bdev, fmode_t mode) { struct pf_unit *pf = bdev->bd_disk->private_data; + int ret; + lock_kernel(); pf_identify(pf); + ret = -ENODEV; if (pf->media_status == PF_NM) - return -ENODEV; + goto out; + ret = -EROFS; if ((pf->media_status == PF_RO) && (mode & FMODE_WRITE)) - return -EROFS; + goto out; + ret = 0; pf->access++; if (pf->removable) pf_lock(pf, 1); - - return 0; +out: + unlock_kernel(); + return ret; } static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo) @@ -342,7 +349,10 @@ static int pf_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, u if (pf->access != 1) return -EBUSY; + lock_kernel(); pf_eject(pf); + unlock_kernel(); + return 0; } @@ -350,14 +360,18 @@ static int pf_release(struct gendisk *disk, fmode_t mode) { struct pf_unit *pf = disk->private_data; - if (pf->access <= 0) + lock_kernel(); + if (pf->access <= 0) { + unlock_kernel(); return -EINVAL; + } pf->access--; if (!pf->access && pf->removable) pf_lock(pf, 0); + unlock_kernel(); return 0; } diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 8a549db2aa78..b1cbeb59bb76 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -57,6 +57,7 @@ #include <linux/seq_file.h> #include <linux/miscdevice.h> #include <linux/freezer.h> +#include <linux/smp_lock.h> #include <linux/mutex.h> #include <linux/slab.h> #include <scsi/scsi_cmnd.h> @@ -1221,7 +1222,7 @@ static int pkt_start_recovery(struct packet_data *pkt) pkt->bio->bi_flags = 1 << BIO_UPTODATE; pkt->bio->bi_idx = 0; - BUG_ON(pkt->bio->bi_rw != (1 << BIO_RW)); + BUG_ON(pkt->bio->bi_rw != REQ_WRITE); BUG_ON(pkt->bio->bi_vcnt != pkt->frames); BUG_ON(pkt->bio->bi_size != pkt->frames * CD_FRAMESIZE); BUG_ON(pkt->bio->bi_end_io != pkt_end_io_packet_write); @@ -2382,6 +2383,7 @@ static int pkt_open(struct block_device *bdev, fmode_t mode) VPRINTK(DRIVER_NAME": entering open\n"); + lock_kernel(); mutex_lock(&ctl_mutex); pd = pkt_find_dev_from_minor(MINOR(bdev->bd_dev)); if (!pd) { @@ -2409,6 +2411,7 @@ static int pkt_open(struct block_device *bdev, fmode_t mode) } mutex_unlock(&ctl_mutex); + unlock_kernel(); return 0; out_dec: @@ -2416,6 +2419,7 @@ out_dec: out: VPRINTK(DRIVER_NAME": failed open (%d)\n", ret); mutex_unlock(&ctl_mutex); + unlock_kernel(); return ret; } @@ -2424,6 +2428,7 @@ static int pkt_close(struct gendisk *disk, fmode_t mode) struct pktcdvd_device *pd = disk->private_data; int ret = 0; + lock_kernel(); mutex_lock(&ctl_mutex); pd->refcnt--; BUG_ON(pd->refcnt < 0); @@ -2432,6 +2437,7 @@ static int pkt_close(struct gendisk *disk, fmode_t mode) pkt_release_dev(pd, flush); } mutex_unlock(&ctl_mutex); + unlock_kernel(); return ret; } @@ -2762,10 +2768,12 @@ out_mem: static int pkt_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { struct pktcdvd_device *pd = bdev->bd_disk->private_data; + int ret; VPRINTK("pkt_ioctl: cmd %x, dev %d:%d\n", cmd, MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev)); + lock_kernel(); switch (cmd) { case CDROMEJECT: /* @@ -2783,14 +2791,16 @@ static int pkt_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, case CDROM_LAST_WRITTEN: case CDROM_SEND_PACKET: case SCSI_IOCTL_SEND_COMMAND: - return __blkdev_driver_ioctl(pd->bdev, mode, cmd, arg); + ret = __blkdev_driver_ioctl(pd->bdev, mode, cmd, arg); + break; default: VPRINTK(DRIVER_NAME": Unknown ioctl for %s (%x)\n", pd->name, cmd); - return -ENOTTY; + ret = -ENOTTY; } + unlock_kernel(); - return 0; + return ret; } static int pkt_media_changed(struct gendisk *disk) @@ -2812,7 +2822,7 @@ static const struct block_device_operations pktcdvd_ops = { .owner = THIS_MODULE, .open = pkt_open, .release = pkt_close, - .locked_ioctl = pkt_ioctl, + .ioctl = pkt_ioctl, .media_changed = pkt_media_changed, }; diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index 3b419e3fffa1..e9da874d0419 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c @@ -196,13 +196,12 @@ static void ps3disk_do_request(struct ps3_storage_device *dev, dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__); while ((req = blk_fetch_request(q))) { - if (blk_fs_request(req)) { - if (ps3disk_submit_request_sg(dev, req)) - break; - } else if (req->cmd_type == REQ_TYPE_LINUX_BLOCK && - req->cmd[0] == REQ_LB_OP_FLUSH) { + if (req->cmd_flags & REQ_FLUSH) { if (ps3disk_submit_flush_request(dev, req)) break; + } else if (req->cmd_type == REQ_TYPE_FS) { + if (ps3disk_submit_request_sg(dev, req)) + break; } else { blk_dump_rq_flags(req, DEVICE_NAME " bad request"); __blk_end_request_all(req, -EIO); @@ -257,8 +256,7 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data) return IRQ_HANDLED; } - if (req->cmd_type == REQ_TYPE_LINUX_BLOCK && - req->cmd[0] == REQ_LB_OP_FLUSH) { + if (req->cmd_flags & REQ_FLUSH) { read = 0; op = "flush"; } else { @@ -398,16 +396,6 @@ static int ps3disk_identify(struct ps3_storage_device *dev) return 0; } -static void ps3disk_prepare_flush(struct request_queue *q, struct request *req) -{ - struct ps3_storage_device *dev = q->queuedata; - - dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__); - - req->cmd_type = REQ_TYPE_LINUX_BLOCK; - req->cmd[0] = REQ_LB_OP_FLUSH; -} - static unsigned long ps3disk_mask; static DEFINE_MUTEX(ps3disk_mask_mutex); @@ -480,8 +468,7 @@ static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev) blk_queue_dma_alignment(queue, dev->blk_size-1); blk_queue_logical_block_size(queue, dev->blk_size); - blk_queue_ordered(queue, QUEUE_ORDERED_DRAIN_FLUSH, - ps3disk_prepare_flush); + blk_queue_ordered(queue, QUEUE_ORDERED_DRAIN_FLUSH); blk_queue_max_segments(queue, -1); blk_queue_max_segment_size(queue, dev->bounce_size); diff --git a/drivers/block/swim.c b/drivers/block/swim.c index e463657569ff..2e46815876df 100644 --- a/drivers/block/swim.c +++ b/drivers/block/swim.c @@ -20,6 +20,7 @@ #include <linux/fd.h> #include <linux/slab.h> #include <linux/blkdev.h> +#include <linux/smp_lock.h> #include <linux/hdreg.h> #include <linux/kernel.h> #include <linux/delay.h> @@ -661,11 +662,23 @@ out: return err; } +static int floppy_unlocked_open(struct block_device *bdev, fmode_t mode) +{ + int ret; + + lock_kernel(); + ret = floppy_open(bdev, mode); + unlock_kernel(); + + return ret; +} + static int floppy_release(struct gendisk *disk, fmode_t mode) { struct floppy_state *fs = disk->private_data; struct swim __iomem *base = fs->swd->base; + lock_kernel(); if (fs->ref_count < 0) fs->ref_count = 0; else if (fs->ref_count > 0) @@ -673,6 +686,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode) if (fs->ref_count == 0) swim_motor(base, OFF); + unlock_kernel(); return 0; } @@ -690,7 +704,9 @@ static int floppy_ioctl(struct block_device *bdev, fmode_t mode, case FDEJECT: if (fs->ref_count != 1) return -EBUSY; + lock_kernel(); err = floppy_eject(fs); + unlock_kernel(); return err; case FDGETPRM: @@ -751,9 +767,9 @@ static int floppy_revalidate(struct gendisk *disk) static const struct block_device_operations floppy_fops = { .owner = THIS_MODULE, - .open = floppy_open, + .open = floppy_unlocked_open, .release = floppy_release, - .locked_ioctl = floppy_ioctl, + .ioctl = floppy_ioctl, .getgeo = floppy_getgeo, .media_changed = floppy_check_change, .revalidate_disk = floppy_revalidate, diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index ed6fb91123ab..cc6a3864822c 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c @@ -25,6 +25,7 @@ #include <linux/ioctl.h> #include <linux/blkdev.h> #include <linux/interrupt.h> +#include <linux/smp_lock.h> #include <linux/module.h> #include <linux/spinlock.h> #include <asm/io.h> @@ -839,7 +840,7 @@ static int fd_eject(struct floppy_state *fs) static struct floppy_struct floppy_type = { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL }; /* 7 1.44MB 3.5" */ -static int floppy_ioctl(struct block_device *bdev, fmode_t mode, +static int floppy_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long param) { struct floppy_state *fs = bdev->bd_disk->private_data; @@ -867,6 +868,18 @@ static int floppy_ioctl(struct block_device *bdev, fmode_t mode, return -ENOTTY; } +static int floppy_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long param) +{ + int ret; + + lock_kernel(); + ret = floppy_locked_ioctl(bdev, mode, cmd, param); + unlock_kernel(); + + return ret; +} + static int floppy_open(struct block_device *bdev, fmode_t mode) { struct floppy_state *fs = bdev->bd_disk->private_data; @@ -936,15 +949,28 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) return 0; } +static int floppy_unlocked_open(struct block_device *bdev, fmode_t mode) +{ + int ret; + + lock_kernel(); + ret = floppy_open(bdev, mode); + unlock_kernel(); + + return ret; +} + static int floppy_release(struct gendisk *disk, fmode_t mode) { struct floppy_state *fs = disk->private_data; struct swim3 __iomem *sw = fs->swim3; + lock_kernel(); if (fs->ref_count > 0 && --fs->ref_count == 0) { swim3_action(fs, MOTOR_OFF); out_8(&sw->control_bic, 0xff); swim3_select(fs, RELAX); } + unlock_kernel(); return 0; } @@ -995,9 +1021,9 @@ static int floppy_revalidate(struct gendisk *disk) } static const struct block_device_operations floppy_fops = { - .open = floppy_open, + .open = floppy_unlocked_open, .release = floppy_release, - .locked_ioctl = floppy_ioctl, + .ioctl = floppy_ioctl, .media_changed = floppy_check_change, .revalidate_disk= floppy_revalidate, }; diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 0536b5b29adc..c48e14878582 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -28,6 +28,7 @@ #include <linux/timer.h> #include <linux/scatterlist.h> #include <linux/slab.h> +#include <linux/smp_lock.h> #include <scsi/scsi.h> #define DRV_NAME "ub" @@ -648,7 +649,7 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq) return 0; } - if (lun->changed && !blk_pc_request(rq)) { + if (lun->changed && rq->cmd_type != REQ_TYPE_BLOCK_PC) { blk_start_request(rq); ub_end_rq(rq, SAM_STAT_CHECK_CONDITION); return 0; @@ -684,7 +685,7 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq) } urq->nsg = n_elem; - if (blk_pc_request(rq)) { + if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { ub_cmd_build_packet(sc, lun, cmd, urq); } else { ub_cmd_build_block(sc, lun, cmd, urq); @@ -781,7 +782,7 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) rq = urq->rq; if (cmd->error == 0) { - if (blk_pc_request(rq)) { + if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { if (cmd->act_len >= rq->resid_len) rq->resid_len = 0; else @@ -795,7 +796,7 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) } } } else { - if (blk_pc_request(rq)) { + if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { /* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */ memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE); rq->sense_len = UB_SENSE_SIZE; @@ -1710,6 +1711,18 @@ err_open: return rc; } +static int ub_bd_unlocked_open(struct block_device *bdev, fmode_t mode) +{ + int ret; + + lock_kernel(); + ret = ub_bd_open(bdev, mode); + unlock_kernel(); + + return ret; +} + + /* */ static int ub_bd_release(struct gendisk *disk, fmode_t mode) @@ -1717,7 +1730,10 @@ static int ub_bd_release(struct gendisk *disk, fmode_t mode) struct ub_lun *lun = disk->private_data; struct ub_dev *sc = lun->udev; + lock_kernel(); ub_put(sc); + unlock_kernel(); + return 0; } @@ -1729,8 +1745,13 @@ static int ub_bd_ioctl(struct block_device *bdev, fmode_t mode, { struct gendisk *disk = bdev->bd_disk; void __user *usermem = (void __user *) arg; + int ret; + + lock_kernel(); + ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, usermem); + unlock_kernel(); - return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, usermem); + return ret; } /* @@ -1792,9 +1813,9 @@ static int ub_bd_media_changed(struct gendisk *disk) static const struct block_device_operations ub_bd_fops = { .owner = THIS_MODULE, - .open = ub_bd_open, + .open = ub_bd_unlocked_open, .release = ub_bd_release, - .locked_ioctl = ub_bd_ioctl, + .ioctl = ub_bd_ioctl, .media_changed = ub_bd_media_changed, .revalidate_disk = ub_bd_revalidate, }; diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 2f9470ff8f7c..8be57151f5d6 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -478,7 +478,7 @@ static void process_page(unsigned long data) le32_to_cpu(desc->local_addr)>>9, le32_to_cpu(desc->transfer_size)); dump_dmastat(card, control); - } else if (test_bit(BIO_RW, &bio->bi_rw) && + } else if ((bio->bi_rw & REQ_WRITE) && le32_to_cpu(desc->local_addr) >> 9 == card->init_size) { card->init_size += le32_to_cpu(desc->transfer_size) >> 9; diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index 788d93882ab9..f651e51a3319 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c @@ -41,6 +41,7 @@ #include <linux/errno.h> #include <linux/init.h> #include <linux/string.h> +#include <linux/smp_lock.h> #include <linux/dma-mapping.h> #include <linux/completion.h> #include <linux/device.h> @@ -175,6 +176,18 @@ static int viodasd_open(struct block_device *bdev, fmode_t mode) return 0; } +static int viodasd_unlocked_open(struct block_device *bdev, fmode_t mode) +{ + int ret; + + lock_kernel(); + ret = viodasd_open(bdev, mode); + unlock_kernel(); + + return ret; +} + + /* * External release entry point. */ @@ -183,6 +196,7 @@ static int viodasd_release(struct gendisk *disk, fmode_t mode) struct viodasd_device *d = disk->private_data; HvLpEvent_Rc hvrc; + lock_kernel(); /* Send the event to OS/400. We DON'T expect a response */ hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, HvLpEvent_Type_VirtualIo, @@ -195,6 +209,9 @@ static int viodasd_release(struct gendisk *disk, fmode_t mode) 0, 0, 0); if (hvrc != 0) pr_warning("HV close call failed %d\n", (int)hvrc); + + unlock_kernel(); + return 0; } @@ -219,7 +236,7 @@ static int viodasd_getgeo(struct block_device *bdev, struct hd_geometry *geo) */ static const struct block_device_operations viodasd_fops = { .owner = THIS_MODULE, - .open = viodasd_open, + .open = viodasd_unlocked_open, .release = viodasd_release, .getgeo = viodasd_getgeo, }; @@ -361,7 +378,7 @@ static void do_viodasd_request(struct request_queue *q) if (req == NULL) return; /* check that request contains a valid command */ - if (!blk_fs_request(req)) { + if (req->cmd_type != REQ_TYPE_FS) { viodasd_end_request(req, -EIO, blk_rq_sectors(req)); continue; } diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 23b7c48df843..2aafafca2b13 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -2,6 +2,7 @@ #include <linux/spinlock.h> #include <linux/slab.h> #include <linux/blkdev.h> +#include <linux/smp_lock.h> #include <linux/hdreg.h> #include <linux/virtio.h> #include <linux/virtio_blk.h> @@ -65,13 +66,18 @@ static void blk_done(struct virtqueue *vq) break; } - if (blk_pc_request(vbr->req)) { + switch (vbr->req->cmd_type) { + case REQ_TYPE_BLOCK_PC: vbr->req->resid_len = vbr->in_hdr.residual; vbr->req->sense_len = vbr->in_hdr.sense_len; vbr->req->errors = vbr->in_hdr.errors; - } - if (blk_special_request(vbr->req)) + break; + case REQ_TYPE_SPECIAL: vbr->req->errors = (error != 0); + break; + default: + break; + } __blk_end_request_all(vbr->req, error); list_del(&vbr->list); @@ -94,36 +100,35 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, return false; vbr->req = req; - switch (req->cmd_type) { - case REQ_TYPE_FS: - vbr->out_hdr.type = 0; - vbr->out_hdr.sector = blk_rq_pos(vbr->req); - vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); - break; - case REQ_TYPE_BLOCK_PC: - vbr->out_hdr.type = VIRTIO_BLK_T_SCSI_CMD; - vbr->out_hdr.sector = 0; - vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); - break; - case REQ_TYPE_SPECIAL: - vbr->out_hdr.type = VIRTIO_BLK_T_GET_ID; + + if (req->cmd_flags & REQ_FLUSH) { + vbr->out_hdr.type = VIRTIO_BLK_T_FLUSH; vbr->out_hdr.sector = 0; vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); - break; - case REQ_TYPE_LINUX_BLOCK: - if (req->cmd[0] == REQ_LB_OP_FLUSH) { - vbr->out_hdr.type = VIRTIO_BLK_T_FLUSH; + } else { + switch (req->cmd_type) { + case REQ_TYPE_FS: + vbr->out_hdr.type = 0; + vbr->out_hdr.sector = blk_rq_pos(vbr->req); + vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); + break; + case REQ_TYPE_BLOCK_PC: + vbr->out_hdr.type = VIRTIO_BLK_T_SCSI_CMD; vbr->out_hdr.sector = 0; vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); break; + case REQ_TYPE_SPECIAL: + vbr->out_hdr.type = VIRTIO_BLK_T_GET_ID; + vbr->out_hdr.sector = 0; + vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); + break; + default: + /* We don't put anything else in the queue. */ + BUG(); } - /*FALLTHRU*/ - default: - /* We don't put anything else in the queue. */ - BUG(); } - if (blk_barrier_rq(vbr->req)) + if (vbr->req->cmd_flags & REQ_HARDBARRIER) vbr->out_hdr.type |= VIRTIO_BLK_T_BARRIER; sg_set_buf(&vblk->sg[out++], &vbr->out_hdr, sizeof(vbr->out_hdr)); @@ -134,12 +139,12 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, * block, and before the normal inhdr we put the sense data and the * inhdr with additional status information before the normal inhdr. */ - if (blk_pc_request(vbr->req)) + if (vbr->req->cmd_type == REQ_TYPE_BLOCK_PC) sg_set_buf(&vblk->sg[out++], vbr->req->cmd, vbr->req->cmd_len); num = blk_rq_map_sg(q, vbr->req, vblk->sg + out); - if (blk_pc_request(vbr->req)) { + if (vbr->req->cmd_type == REQ_TYPE_BLOCK_PC) { sg_set_buf(&vblk->sg[num + out + in++], vbr->req->sense, 96); sg_set_buf(&vblk->sg[num + out + in++], &vbr->in_hdr, sizeof(vbr->in_hdr)); @@ -190,12 +195,6 @@ static void do_virtblk_request(struct request_queue *q) virtqueue_kick(vblk->vq); } -static void virtblk_prepare_flush(struct request_queue *q, struct request *req) -{ - req->cmd_type = REQ_TYPE_LINUX_BLOCK; - req->cmd[0] = REQ_LB_OP_FLUSH; -} - /* return id (s/n) string for *disk to *id_str */ static int virtblk_get_id(struct gendisk *disk, char *id_str) @@ -219,7 +218,7 @@ static int virtblk_get_id(struct gendisk *disk, char *id_str) return blk_execute_rq(vblk->disk->queue, vblk->disk, req, false); } -static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, +static int virtblk_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long data) { struct gendisk *disk = bdev->bd_disk; @@ -235,6 +234,18 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, (void __user *)data); } +static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long param) +{ + int ret; + + lock_kernel(); + ret = virtblk_locked_ioctl(bdev, mode, cmd, param); + unlock_kernel(); + + return ret; +} + /* We provide getgeo only to please some old bootloader/partitioning tools */ static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo) { @@ -261,7 +272,7 @@ static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo) } static const struct block_device_operations virtblk_fops = { - .locked_ioctl = virtblk_ioctl, + .ioctl = virtblk_ioctl, .owner = THIS_MODULE, .getgeo = virtblk_getgeo, }; @@ -383,8 +394,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) * flushing a volatile write cache on the host. Use that * to implement write barrier support. */ - blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH, - virtblk_prepare_flush); + blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH); } else if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER)) { /* * If the BARRIER feature is supported the host expects us @@ -393,7 +403,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) * never re-orders outstanding I/O. This feature is not * useful for real life scenarious and deprecated. */ - blk_queue_ordered(q, QUEUE_ORDERED_TAG, NULL); + blk_queue_ordered(q, QUEUE_ORDERED_TAG); } else { /* * If the FLUSH feature is not supported we must assume that @@ -401,7 +411,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) * caching. We still need to drain the queue to provider * proper barrier semantics. */ - blk_queue_ordered(q, QUEUE_ORDERED_DRAIN, NULL); + blk_queue_ordered(q, QUEUE_ORDERED_DRAIN); } /* If disk is read-only in the host, the guest should obey */ diff --git a/drivers/block/xd.c b/drivers/block/xd.c index 18a80ff57ce8..d5a3cd750561 100644 --- a/drivers/block/xd.c +++ b/drivers/block/xd.c @@ -46,6 +46,7 @@ #include <linux/init.h> #include <linux/wait.h> #include <linux/blkdev.h> +#include <linux/smp_lock.h> #include <linux/blkpg.h> #include <linux/delay.h> #include <linux/io.h> @@ -133,7 +134,7 @@ static int xd_getgeo(struct block_device *bdev, struct hd_geometry *geo); static const struct block_device_operations xd_fops = { .owner = THIS_MODULE, - .locked_ioctl = xd_ioctl, + .ioctl = xd_ioctl, .getgeo = xd_getgeo, }; static DECLARE_WAIT_QUEUE_HEAD(xd_wait_int); @@ -322,7 +323,7 @@ static void do_xd_request (struct request_queue * q) int res = -EIO; int retry; - if (!blk_fs_request(req)) + if (req->cmd_type != REQ_TYPE_FS) goto done; if (block + count > get_capacity(req->rq_disk)) goto done; @@ -347,7 +348,7 @@ static int xd_getgeo(struct block_device *bdev, struct hd_geometry *geo) } /* xd_ioctl: handle device ioctl's */ -static int xd_ioctl(struct block_device *bdev, fmode_t mode, u_int cmd, u_long arg) +static int xd_locked_ioctl(struct block_device *bdev, fmode_t mode, u_int cmd, u_long arg) { switch (cmd) { case HDIO_SET_DMA: @@ -375,6 +376,18 @@ static int xd_ioctl(struct block_device *bdev, fmode_t mode, u_int cmd, u_long a } } +static int xd_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long param) +{ + int ret; + + lock_kernel(); + ret = xd_locked_ioctl(bdev, mode, cmd, param); + unlock_kernel(); + + return ret; +} + /* xd_readwrite: handle a read/write request */ static int xd_readwrite (u_char operation,XD_INFO *p,char *buffer,u_int block,u_int count) { diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 82ed403147c0..91374282755d 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -41,6 +41,7 @@ #include <linux/cdrom.h> #include <linux/module.h> #include <linux/slab.h> +#include <linux/smp_lock.h> #include <linux/scatterlist.h> #include <xen/xen.h> @@ -238,7 +239,7 @@ static int blkif_queue_request(struct request *req) ring_req->operation = rq_data_dir(req) ? BLKIF_OP_WRITE : BLKIF_OP_READ; - if (blk_barrier_rq(req)) + if (req->cmd_flags & REQ_HARDBARRIER) ring_req->operation = BLKIF_OP_WRITE_BARRIER; ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg); @@ -309,7 +310,7 @@ static void do_blkif_request(struct request_queue *rq) blk_start_request(req); - if (!blk_fs_request(req)) { + if (req->cmd_type != REQ_TYPE_FS) { __blk_end_request_all(req, -EIO); continue; } @@ -373,8 +374,7 @@ static int xlvbd_barrier(struct blkfront_info *info) int err; err = blk_queue_ordered(info->rq, - info->feature_barrier ? QUEUE_ORDERED_DRAIN : QUEUE_ORDERED_NONE, - NULL); + info->feature_barrier ? QUEUE_ORDERED_DRAIN : QUEUE_ORDERED_NONE); if (err) return err; @@ -1019,13 +1019,18 @@ static int blkfront_is_ready(struct xenbus_device *dev) static int blkif_open(struct block_device *bdev, fmode_t mode) { struct blkfront_info *info = bdev->bd_disk->private_data; + + lock_kernel(); info->users++; + unlock_kernel(); + return 0; } static int blkif_release(struct gendisk *disk, fmode_t mode) { struct blkfront_info *info = disk->private_data; + lock_kernel(); info->users--; if (info->users == 0) { /* Check whether we have been instructed to close. We will @@ -1037,6 +1042,7 @@ static int blkif_release(struct gendisk *disk, fmode_t mode) if (state == XenbusStateClosing && info->is_ready) blkfront_closing(dev); } + unlock_kernel(); return 0; } @@ -1046,7 +1052,7 @@ static const struct block_device_operations xlvbd_block_fops = .open = blkif_open, .release = blkif_release, .getgeo = blkif_getgeo, - .locked_ioctl = blkif_ioctl, + .ioctl = blkif_ioctl, }; diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index a7b83c0a7eb5..b71888b909a0 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -89,6 +89,7 @@ #include <linux/delay.h> #include <linux/slab.h> #include <linux/blkdev.h> +#include <linux/smp_lock.h> #include <linux/ata.h> #include <linux/hdreg.h> #include <linux/platform_device.h> @@ -465,7 +466,7 @@ struct request *ace_get_next_request(struct request_queue * q) struct request *req; while ((req = blk_peek_request(q)) != NULL) { - if (blk_fs_request(req)) + if (req->cmd_type == REQ_TYPE_FS) break; blk_start_request(req); __blk_end_request_all(req, -EIO); @@ -901,11 +902,14 @@ static int ace_open(struct block_device *bdev, fmode_t mode) dev_dbg(ace->dev, "ace_open() users=%i\n", ace->users + 1); + lock_kernel(); spin_lock_irqsave(&ace->lock, flags); ace->users++; spin_unlock_irqrestore(&ace->lock, flags); check_disk_change(bdev); + unlock_kernel(); + return 0; } @@ -917,6 +921,7 @@ static int ace_release(struct gendisk *disk, fmode_t mode) dev_dbg(ace->dev, "ace_release() users=%i\n", ace->users - 1); + lock_kernel(); spin_lock_irqsave(&ace->lock, flags); ace->users--; if (ace->users == 0) { @@ -924,6 +929,7 @@ static int ace_release(struct gendisk *disk, fmode_t mode) ace_out(ace, ACE_CTRL, val & ~ACE_CTRL_LOCKREQ); } spin_unlock_irqrestore(&ace->lock, flags); + unlock_kernel(); return 0; } diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c index 9114654b54d9..d75b2bb601ad 100644 --- a/drivers/block/z2ram.c +++ b/drivers/block/z2ram.c @@ -33,6 +33,7 @@ #include <linux/module.h> #include <linux/blkdev.h> #include <linux/bitops.h> +#include <linux/smp_lock.h> #include <linux/slab.h> #include <asm/setup.h> @@ -153,6 +154,7 @@ static int z2_open(struct block_device *bdev, fmode_t mode) device = MINOR(bdev->bd_dev); + lock_kernel(); if ( current_device != -1 && current_device != device ) { rc = -EBUSY; @@ -294,20 +296,25 @@ static int z2_open(struct block_device *bdev, fmode_t mode) set_capacity(z2ram_gendisk, z2ram_size >> 9); } + unlock_kernel(); return 0; err_out_kfree: kfree(z2ram_map); err_out: + unlock_kernel(); return rc; } static int z2_release(struct gendisk *disk, fmode_t mode) { - if ( current_device == -1 ) - return 0; - + lock_kernel(); + if ( current_device == -1 ) { + unlock_kernel(); + return 0; + } + unlock_kernel(); /* * FIXME: unmap memory */ diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index e3749d0ba68b..af13c62dc473 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -242,6 +242,8 @@ -------------------------------------------------------------------------*/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #define REVISION "Revision: 3.20" #define VERSION "Id: cdrom.c 3.20 2003/12/17" @@ -314,11 +316,17 @@ static const char *mrw_format_status[] = { static const char *mrw_address_space[] = { "DMA", "GAA" }; #if (ERRLOGMASK!=CD_NOTHING) -#define cdinfo(type, fmt, args...) \ - if ((ERRLOGMASK & type) || debug==1 ) \ - printk(KERN_INFO "cdrom: " fmt, ## args) +#define cdinfo(type, fmt, args...) \ +do { \ + if ((ERRLOGMASK & type) || debug == 1) \ + pr_info(fmt, ##args); \ +} while (0) #else -#define cdinfo(type, fmt, args...) +#define cdinfo(type, fmt, args...) \ +do { \ + if (0 && (ERRLOGMASK & type) || debug == 1) \ + pr_info(fmt, ##args); \ +} while (0) #endif /* These are used to simplify getting data in from and back to user land */ @@ -395,7 +403,7 @@ int register_cdrom(struct cdrom_device_info *cdi) if (cdo->open == NULL || cdo->release == NULL) return -EINVAL; if (!banner_printed) { - printk(KERN_INFO "Uniform CD-ROM driver " REVISION "\n"); + pr_info("Uniform CD-ROM driver " REVISION "\n"); banner_printed = 1; cdrom_sysctl_register(); } @@ -546,7 +554,7 @@ static int cdrom_mrw_bgformat(struct cdrom_device_info *cdi, int cont) unsigned char buffer[12]; int ret; - printk(KERN_INFO "cdrom: %sstarting format\n", cont ? "Re" : ""); + pr_info("%sstarting format\n", cont ? "Re" : ""); /* * FmtData bit set (bit 4), format type is 1 @@ -576,7 +584,7 @@ static int cdrom_mrw_bgformat(struct cdrom_device_info *cdi, int cont) ret = cdi->ops->generic_packet(cdi, &cgc); if (ret) - printk(KERN_INFO "cdrom: bgformat failed\n"); + pr_info("bgformat failed\n"); return ret; } @@ -622,8 +630,7 @@ static int cdrom_mrw_exit(struct cdrom_device_info *cdi) ret = 0; if (di.mrw_status == CDM_MRW_BGFORMAT_ACTIVE) { - printk(KERN_INFO "cdrom: issuing MRW back ground " - "format suspend\n"); + pr_info("issuing MRW background format suspend\n"); ret = cdrom_mrw_bgformat_susp(cdi, 0); } @@ -658,7 +665,8 @@ static int cdrom_mrw_set_lba_space(struct cdrom_device_info *cdi, int space) if ((ret = cdrom_mode_select(cdi, &cgc))) return ret; - printk(KERN_INFO "cdrom: %s: mrw address space %s selected\n", cdi->name, mrw_address_space[space]); + pr_info("%s: mrw address space %s selected\n", + cdi->name, mrw_address_space[space]); return 0; } @@ -762,7 +770,7 @@ static int cdrom_mrw_open_write(struct cdrom_device_info *cdi) * always reset to DMA lba space on open */ if (cdrom_mrw_set_lba_space(cdi, MRW_LBA_DMA)) { - printk(KERN_ERR "cdrom: failed setting lba address space\n"); + pr_err("failed setting lba address space\n"); return 1; } @@ -781,8 +789,7 @@ static int cdrom_mrw_open_write(struct cdrom_device_info *cdi) * 3 - MRW formatting complete */ ret = 0; - printk(KERN_INFO "cdrom open: mrw_status '%s'\n", - mrw_format_status[di.mrw_status]); + pr_info("open: mrw_status '%s'\n", mrw_format_status[di.mrw_status]); if (!di.mrw_status) ret = 1; else if (di.mrw_status == CDM_MRW_BGFORMAT_INACTIVE && @@ -932,8 +939,7 @@ static void cdrom_dvd_rw_close_write(struct cdrom_device_info *cdi) return; } - printk(KERN_INFO "cdrom: %s: dirty DVD+RW media, \"finalizing\"\n", - cdi->name); + pr_info("%s: dirty DVD+RW media, \"finalizing\"\n", cdi->name); init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE); cgc.cmd[0] = GPCMD_FLUSH_CACHE; @@ -2176,7 +2182,7 @@ retry: * frame dma, so drop to single frame dma if we need to */ if (cdi->cdda_method == CDDA_BPC_FULL && nframes > 1) { - printk("cdrom: dropping to single frame dma\n"); + pr_info("dropping to single frame dma\n"); cdi->cdda_method = CDDA_BPC_SINGLE; goto retry; } @@ -2189,7 +2195,7 @@ retry: if (cdi->last_sense != 0x04 && cdi->last_sense != 0x0b) return ret; - printk("cdrom: dropping to old style cdda (sense=%x)\n", cdi->last_sense); + pr_info("dropping to old style cdda (sense=%x)\n", cdi->last_sense); cdi->cdda_method = CDDA_OLD; return cdrom_read_cdda_old(cdi, ubuf, lba, nframes); } @@ -3401,7 +3407,7 @@ static int cdrom_print_info(const char *header, int val, char *info, "\t%d", CDROM_CAN(val) != 0); break; default: - printk(KERN_INFO "cdrom: invalid option%d\n", option); + pr_info("invalid option%d\n", option); return 1; } if (!ret) @@ -3491,7 +3497,7 @@ doit: mutex_unlock(&cdrom_mutex); return proc_dostring(ctl, write, buffer, lenp, ppos); done: - printk(KERN_INFO "cdrom: info buffer too small\n"); + pr_info("info buffer too small\n"); goto doit; } @@ -3665,7 +3671,7 @@ static int __init cdrom_init(void) static void __exit cdrom_exit(void) { - printk(KERN_INFO "Uniform CD-ROM driver unloaded\n"); + pr_info("Uniform CD-ROM driver unloaded\n"); cdrom_sysctl_unregister(); } diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c index 03c71f7698cb..261107d1457c 100644 --- a/drivers/cdrom/gdrom.c +++ b/drivers/cdrom/gdrom.c @@ -19,6 +19,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> @@ -32,6 +34,7 @@ #include <linux/blkdev.h> #include <linux/interrupt.h> #include <linux/device.h> +#include <linux/smp_lock.h> #include <linux/wait.h> #include <linux/workqueue.h> #include <linux/platform_device.h> @@ -339,8 +342,7 @@ static int gdrom_get_last_session(struct cdrom_device_info *cd_info, tocuse = 0; err = gdrom_readtoc_cmd(gd.toc, 0); if (err) { - printk(KERN_INFO "GDROM: Could not get CD " - "table of contents\n"); + pr_info("Could not get CD table of contents\n"); return -ENXIO; } } @@ -357,8 +359,7 @@ static int gdrom_get_last_session(struct cdrom_device_info *cd_info, } while (track >= fentry); if ((track > 100) || (track < get_entry_track(gd.toc->first))) { - printk(KERN_INFO "GDROM: No data on the last " - "session of the CD\n"); + pr_info("No data on the last session of the CD\n"); gdrom_getsense(NULL); return -ENXIO; } @@ -451,14 +452,14 @@ static int gdrom_getsense(short *bufstring) goto cleanup_sense; insw(GDROM_DATA_REG, &sense, sense_command->buflen/2); if (sense[1] & 40) { - printk(KERN_INFO "GDROM: Drive not ready - command aborted\n"); + pr_info("Drive not ready - command aborted\n"); goto cleanup_sense; } sense_key = sense[1] & 0x0F; if (sense_key < ARRAY_SIZE(sense_texts)) - printk(KERN_INFO "GDROM: %s\n", sense_texts[sense_key].text); + pr_info("%s\n", sense_texts[sense_key].text); else - printk(KERN_ERR "GDROM: Unknown sense key: %d\n", sense_key); + pr_err("Unknown sense key: %d\n", sense_key); if (bufstring) /* return addional sense data */ memcpy(bufstring, &sense[4], 2); if (sense_key < 2) @@ -492,12 +493,18 @@ static struct cdrom_device_ops gdrom_ops = { static int gdrom_bdops_open(struct block_device *bdev, fmode_t mode) { - return cdrom_open(gd.cd_info, bdev, mode); + int ret; + lock_kernel(); + ret = cdrom_open(gd.cd_info, bdev, mode); + unlock_kernel(); + return ret; } static int gdrom_bdops_release(struct gendisk *disk, fmode_t mode) { + lock_kernel(); cdrom_release(gd.cd_info, mode); + unlock_kernel(); return 0; } @@ -509,7 +516,13 @@ static int gdrom_bdops_mediachanged(struct gendisk *disk) static int gdrom_bdops_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long arg) { - return cdrom_ioctl(gd.cd_info, bdev, mode, cmd, arg); + int ret; + + lock_kernel(); + ret = cdrom_ioctl(gd.cd_info, bdev, mode, cmd, arg); + unlock_kernel(); + + return ret; } static const struct block_device_operations gdrom_bdops = { @@ -517,7 +530,7 @@ static const struct block_device_operations gdrom_bdops = { .open = gdrom_bdops_open, .release = gdrom_bdops_release, .media_changed = gdrom_bdops_mediachanged, - .locked_ioctl = gdrom_bdops_ioctl, + .ioctl = gdrom_bdops_ioctl, }; static irqreturn_t gdrom_command_interrupt(int irq, void *dev_id) @@ -643,14 +656,13 @@ static void gdrom_request(struct request_queue *rq) struct request *req; while ((req = blk_fetch_request(rq)) != NULL) { - if (!blk_fs_request(req)) { - printk(KERN_DEBUG "GDROM: Non-fs request ignored\n"); + if (req->cmd_type != REQ_TYPE_FS) { + printk(KERN_DEBUG "gdrom: Non-fs request ignored\n"); __blk_end_request_all(req, -EIO); continue; } if (rq_data_dir(req) != READ) { - printk(KERN_NOTICE "GDROM: Read only device -"); - printk(" write request ignored\n"); + pr_notice("Read only device - write request ignored\n"); __blk_end_request_all(req, -EIO); continue; } @@ -685,7 +697,7 @@ static int __devinit gdrom_outputversion(void) firmw_ver = kstrndup(id->firmver, 16, GFP_KERNEL); if (!firmw_ver) goto free_manuf_name; - printk(KERN_INFO "GDROM: %s from %s with firmware %s\n", + pr_info("%s from %s with firmware %s\n", model_name, manuf_name, firmw_ver); err = 0; kfree(firmw_ver); @@ -757,7 +769,7 @@ static int __devinit probe_gdrom(struct platform_device *devptr) int err; /* Start the device */ if (gdrom_execute_diagnostic() != 1) { - printk(KERN_WARNING "GDROM: ATA Probe for GDROM failed.\n"); + pr_warning("ATA Probe for GDROM failed\n"); return -ENODEV; } /* Print out firmware ID */ @@ -767,7 +779,7 @@ static int __devinit probe_gdrom(struct platform_device *devptr) gdrom_major = register_blkdev(0, GDROM_DEV_NAME); if (gdrom_major <= 0) return gdrom_major; - printk(KERN_INFO "GDROM: Registered with major number %d\n", + pr_info("Registered with major number %d\n", gdrom_major); /* Specify basic properties of drive */ gd.cd_info = kzalloc(sizeof(struct cdrom_device_info), GFP_KERNEL); @@ -818,7 +830,7 @@ probe_fail_no_disk: unregister_blkdev(gdrom_major, GDROM_DEV_NAME); gdrom_major = 0; probe_fail_no_mem: - printk(KERN_WARNING "GDROM: Probe failed - error is 0x%X\n", err); + pr_warning("Probe failed - error is 0x%X\n", err); return err; } diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index 451cd7071b1d..56bf9f44700c 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -31,6 +31,8 @@ * the OS/400 partition. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/major.h> #include <linux/blkdev.h> #include <linux/cdrom.h> @@ -40,6 +42,7 @@ #include <linux/module.h> #include <linux/completion.h> #include <linux/proc_fs.h> +#include <linux/smp_lock.h> #include <linux/seq_file.h> #include <linux/scatterlist.h> @@ -53,9 +56,6 @@ #define VIOCD_VERS "1.06" -#define VIOCD_KERN_WARNING KERN_WARNING "viocd: " -#define VIOCD_KERN_INFO KERN_INFO "viocd: " - /* * Should probably make this a module parameter....sigh */ @@ -154,13 +154,21 @@ static const struct file_operations proc_viocd_operations = { static int viocd_blk_open(struct block_device *bdev, fmode_t mode) { struct disk_info *di = bdev->bd_disk->private_data; - return cdrom_open(&di->viocd_info, bdev, mode); + int ret; + + lock_kernel(); + ret = cdrom_open(&di->viocd_info, bdev, mode); + unlock_kernel(); + + return ret; } static int viocd_blk_release(struct gendisk *disk, fmode_t mode) { struct disk_info *di = disk->private_data; + lock_kernel(); cdrom_release(&di->viocd_info, mode); + unlock_kernel(); return 0; } @@ -168,7 +176,13 @@ static int viocd_blk_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long arg) { struct disk_info *di = bdev->bd_disk->private_data; - return cdrom_ioctl(&di->viocd_info, bdev, mode, cmd, arg); + int ret; + + lock_kernel(); + ret = cdrom_ioctl(&di->viocd_info, bdev, mode, cmd, arg); + unlock_kernel(); + + return ret; } static int viocd_blk_media_changed(struct gendisk *disk) @@ -181,7 +195,7 @@ static const struct block_device_operations viocd_fops = { .owner = THIS_MODULE, .open = viocd_blk_open, .release = viocd_blk_release, - .locked_ioctl = viocd_blk_ioctl, + .ioctl = viocd_blk_ioctl, .media_changed = viocd_blk_media_changed, }; @@ -202,9 +216,8 @@ static int viocd_open(struct cdrom_device_info *cdi, int purpose) (u64)&we, VIOVERSION << 16, ((u64)device_no << 48), 0, 0, 0); if (hvrc != 0) { - printk(VIOCD_KERN_WARNING - "bad rc on HvCallEvent_signalLpEventFast %d\n", - (int)hvrc); + pr_warning("bad rc on HvCallEvent_signalLpEventFast %d\n", + (int)hvrc); return -EIO; } @@ -213,8 +226,8 @@ static int viocd_open(struct cdrom_device_info *cdi, int purpose) if (we.rc) { const struct vio_error_entry *err = vio_lookup_rc(viocd_err_table, we.sub_result); - printk(VIOCD_KERN_WARNING "bad rc %d:0x%04X on open: %s\n", - we.rc, we.sub_result, err->msg); + pr_warning("bad rc %d:0x%04X on open: %s\n", + we.rc, we.sub_result, err->msg); return -err->errno; } @@ -234,9 +247,8 @@ static void viocd_release(struct cdrom_device_info *cdi) viopath_targetinst(viopath_hostLp), 0, VIOVERSION << 16, ((u64)device_no << 48), 0, 0, 0); if (hvrc != 0) - printk(VIOCD_KERN_WARNING - "bad rc on HvCallEvent_signalLpEventFast %d\n", - (int)hvrc); + pr_warning("bad rc on HvCallEvent_signalLpEventFast %d\n", + (int)hvrc); } /* Send a read or write request to OS/400 */ @@ -262,13 +274,12 @@ static int send_request(struct request *req) sg_init_table(&sg, 1); if (blk_rq_map_sg(req->q, req, &sg) == 0) { - printk(VIOCD_KERN_WARNING - "error setting up scatter/gather list\n"); + pr_warning("error setting up scatter/gather list\n"); return -1; } if (dma_map_sg(diskinfo->dev, &sg, 1, direction) == 0) { - printk(VIOCD_KERN_WARNING "error allocating sg tce\n"); + pr_warning("error allocating sg tce\n"); return -1; } dmaaddr = sg_dma_address(&sg); @@ -284,7 +295,7 @@ static int send_request(struct request *req) ((u64)DEVICE_NR(diskinfo) << 48) | dmaaddr, (u64)blk_rq_pos(req) * 512, len, 0); if (hvrc != HvLpEvent_Rc_Good) { - printk(VIOCD_KERN_WARNING "hv error on op %d\n", (int)hvrc); + pr_warning("hv error on op %d\n", (int)hvrc); return -1; } @@ -298,11 +309,10 @@ static void do_viocd_request(struct request_queue *q) struct request *req; while ((rwreq == 0) && ((req = blk_fetch_request(q)) != NULL)) { - if (!blk_fs_request(req)) + if (req->cmd_type != REQ_TYPE_FS) __blk_end_request_all(req, -EIO); else if (send_request(req) < 0) { - printk(VIOCD_KERN_WARNING - "unable to send message to OS/400!"); + pr_warning("unable to send message to OS/400!\n"); __blk_end_request_all(req, -EIO); } else rwreq++; @@ -327,8 +337,8 @@ static int viocd_media_changed(struct cdrom_device_info *cdi, int disc_nr) (u64)&we, VIOVERSION << 16, ((u64)device_no << 48), 0, 0, 0); if (hvrc != 0) { - printk(VIOCD_KERN_WARNING "bad rc on HvCallEvent_signalLpEventFast %d\n", - (int)hvrc); + pr_warning("bad rc on HvCallEvent_signalLpEventFast %d\n", + (int)hvrc); return -EIO; } @@ -338,9 +348,8 @@ static int viocd_media_changed(struct cdrom_device_info *cdi, int disc_nr) if (we.rc) { const struct vio_error_entry *err = vio_lookup_rc(viocd_err_table, we.sub_result); - printk(VIOCD_KERN_WARNING - "bad rc %d:0x%04X on check_change: %s; Assuming no change\n", - we.rc, we.sub_result, err->msg); + pr_warning("bad rc %d:0x%04X on check_change: %s; Assuming no change\n", + we.rc, we.sub_result, err->msg); return 0; } @@ -367,8 +376,8 @@ static int viocd_lock_door(struct cdrom_device_info *cdi, int locking) (u64)&we, VIOVERSION << 16, (device_no << 48) | (flags << 32), 0, 0, 0); if (hvrc != 0) { - printk(VIOCD_KERN_WARNING "bad rc on HvCallEvent_signalLpEventFast %d\n", - (int)hvrc); + pr_warning("bad rc on HvCallEvent_signalLpEventFast %d\n", + (int)hvrc); return -EIO; } @@ -455,8 +464,7 @@ static void vio_handle_cd_event(struct HvLpEvent *event) return; /* First, we should NEVER get an int here...only acks */ if (hvlpevent_is_int(event)) { - printk(VIOCD_KERN_WARNING - "Yikes! got an int in viocd event handler!\n"); + pr_warning("Yikes! got an int in viocd event handler!\n"); if (hvlpevent_need_ack(event)) { event->xRc = HvLpEvent_Rc_InvalidSubtype; HvCallEvent_ackLpEvent(event); @@ -510,10 +518,9 @@ return_complete: const struct vio_error_entry *err = vio_lookup_rc(viocd_err_table, bevent->sub_result); - printk(VIOCD_KERN_WARNING "request %p failed " - "with rc %d:0x%04X: %s\n", - req, event->xRc, - bevent->sub_result, err->msg); + pr_warning("request %p failed with rc %d:0x%04X: %s\n", + req, event->xRc, + bevent->sub_result, err->msg); __blk_end_request_all(req, -EIO); } else __blk_end_request_all(req, 0); @@ -524,9 +531,8 @@ return_complete: break; default: - printk(VIOCD_KERN_WARNING - "message with invalid subtype %0x04X!\n", - event->xSubtype & VIOMINOR_SUBTYPE_MASK); + pr_warning("message with invalid subtype %0x04X!\n", + event->xSubtype & VIOMINOR_SUBTYPE_MASK); if (hvlpevent_need_ack(event)) { event->xRc = HvLpEvent_Rc_InvalidSubtype; HvCallEvent_ackLpEvent(event); @@ -593,23 +599,19 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id) sprintf(c->name, VIOCD_DEVICE "%c", 'a' + deviceno); if (register_cdrom(c) != 0) { - printk(VIOCD_KERN_WARNING "Cannot register viocd CD-ROM %s!\n", - c->name); + pr_warning("Cannot register viocd CD-ROM %s!\n", c->name); goto out; } - printk(VIOCD_KERN_INFO "cd %s is iSeries resource %10.10s " - "type %4.4s, model %3.3s\n", - c->name, d->rsrcname, d->type, d->model); + pr_info("cd %s is iSeries resource %10.10s type %4.4s, model %3.3s\n", + c->name, d->rsrcname, d->type, d->model); q = blk_init_queue(do_viocd_request, &viocd_reqlock); if (q == NULL) { - printk(VIOCD_KERN_WARNING "Cannot allocate queue for %s!\n", - c->name); + pr_warning("Cannot allocate queue for %s!\n", c->name); goto out_unregister_cdrom; } gendisk = alloc_disk(1); if (gendisk == NULL) { - printk(VIOCD_KERN_WARNING "Cannot create gendisk for %s!\n", - c->name); + pr_warning("Cannot create gendisk for %s!\n", c->name); goto out_cleanup_queue; } gendisk->major = VIOCD_MAJOR; @@ -682,21 +684,19 @@ static int __init viocd_init(void) return -ENODEV; } - printk(VIOCD_KERN_INFO "vers " VIOCD_VERS ", hosting partition %d\n", - viopath_hostLp); + pr_info("vers " VIOCD_VERS ", hosting partition %d\n", viopath_hostLp); if (register_blkdev(VIOCD_MAJOR, VIOCD_DEVICE) != 0) { - printk(VIOCD_KERN_WARNING "Unable to get major %d for %s\n", - VIOCD_MAJOR, VIOCD_DEVICE); + pr_warning("Unable to get major %d for %s\n", + VIOCD_MAJOR, VIOCD_DEVICE); return -EIO; } ret = viopath_open(viopath_hostLp, viomajorsubtype_cdio, MAX_CD_REQ + 2); if (ret) { - printk(VIOCD_KERN_WARNING - "error opening path to host partition %d\n", - viopath_hostLp); + pr_warning("error opening path to host partition %d\n", + viopath_hostLp); goto out_unregister; } diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index f9daffd7d0e3..e88a2cf17711 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -190,7 +190,7 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq) BUG_ON(sense_len > sizeof(*sense)); - if (blk_sense_request(rq) || drive->sense_rq_armed) + if (rq->cmd_type == REQ_TYPE_SENSE || drive->sense_rq_armed) return; memset(sense, 0, sizeof(*sense)); @@ -307,13 +307,16 @@ EXPORT_SYMBOL_GPL(ide_cd_expiry); int ide_cd_get_xferlen(struct request *rq) { - if (blk_fs_request(rq)) + switch (rq->cmd_type) { + case REQ_TYPE_FS: return 32768; - else if (blk_sense_request(rq) || blk_pc_request(rq) || - rq->cmd_type == REQ_TYPE_ATA_PC) + case REQ_TYPE_SENSE: + case REQ_TYPE_BLOCK_PC: + case REQ_TYPE_ATA_PC: return blk_rq_bytes(rq); - else + default: return 0; + } } EXPORT_SYMBOL_GPL(ide_cd_get_xferlen); @@ -474,12 +477,12 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) if (uptodate == 0) drive->failed_pc = NULL; - if (blk_special_request(rq)) { + if (rq->cmd_type == REQ_TYPE_SPECIAL) { rq->errors = 0; error = 0; } else { - if (blk_fs_request(rq) == 0 && uptodate <= 0) { + if (rq->cmd_type != REQ_TYPE_FS && uptodate <= 0) { if (rq->errors == 0) rq->errors = -EIO; } diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 64207df8da82..5108e9739c96 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -31,6 +31,7 @@ #include <linux/delay.h> #include <linux/timer.h> #include <linux/seq_file.h> +#include <linux/smp_lock.h> #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/errno.h> @@ -176,7 +177,7 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive, if (!sense->valid) break; if (failed_command == NULL || - !blk_fs_request(failed_command)) + failed_command->cmd_type != REQ_TYPE_FS) break; sector = (sense->information[0] << 24) | (sense->information[1] << 16) | @@ -292,7 +293,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) "stat 0x%x", rq->cmd[0], rq->cmd_type, err, stat); - if (blk_sense_request(rq)) { + if (rq->cmd_type == REQ_TYPE_SENSE) { /* * We got an error trying to get sense info from the drive * (probably while trying to recover from a former error). @@ -303,7 +304,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) } /* if we have an error, pass CHECK_CONDITION as the SCSI status byte */ - if (blk_pc_request(rq) && !rq->errors) + if (rq->cmd_type == REQ_TYPE_BLOCK_PC && !rq->errors) rq->errors = SAM_STAT_CHECK_CONDITION; if (blk_noretry_request(rq)) @@ -311,13 +312,14 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) switch (sense_key) { case NOT_READY: - if (blk_fs_request(rq) && rq_data_dir(rq) == WRITE) { + if (rq->cmd_type == REQ_TYPE_FS && rq_data_dir(rq) == WRITE) { if (ide_cd_breathe(drive, rq)) return 1; } else { cdrom_saw_media_change(drive); - if (blk_fs_request(rq) && !blk_rq_quiet(rq)) + if (rq->cmd_type == REQ_TYPE_FS && + !(rq->cmd_flags & REQ_QUIET)) printk(KERN_ERR PFX "%s: tray open\n", drive->name); } @@ -326,7 +328,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) case UNIT_ATTENTION: cdrom_saw_media_change(drive); - if (blk_fs_request(rq) == 0) + if (rq->cmd_type != REQ_TYPE_FS) return 0; /* @@ -352,7 +354,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) * No point in retrying after an illegal request or data * protect error. */ - if (!blk_rq_quiet(rq)) + if (!(rq->cmd_flags & REQ_QUIET)) ide_dump_status(drive, "command error", stat); do_end_request = 1; break; @@ -361,20 +363,20 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) * No point in re-trying a zillion times on a bad sector. * If we got here the error is not correctable. */ - if (!blk_rq_quiet(rq)) + if (!(rq->cmd_flags & REQ_QUIET)) ide_dump_status(drive, "media error " "(bad sector)", stat); do_end_request = 1; break; case BLANK_CHECK: /* disk appears blank? */ - if (!blk_rq_quiet(rq)) + if (!(rq->cmd_flags & REQ_QUIET)) ide_dump_status(drive, "media error (blank)", stat); do_end_request = 1; break; default: - if (blk_fs_request(rq) == 0) + if (rq->cmd_type != REQ_TYPE_FS) break; if (err & ~ATA_ABORTED) { /* go to the default handler for other errors */ @@ -385,7 +387,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) do_end_request = 1; } - if (blk_fs_request(rq) == 0) { + if (rq->cmd_type != REQ_TYPE_FS) { rq->cmd_flags |= REQ_FAILED; do_end_request = 1; } @@ -525,7 +527,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) ide_expiry_t *expiry = NULL; int dma_error = 0, dma, thislen, uptodate = 0; int write = (rq_data_dir(rq) == WRITE) ? 1 : 0, rc = 0; - int sense = blk_sense_request(rq); + int sense = (rq->cmd_type == REQ_TYPE_SENSE); unsigned int timeout; u16 len; u8 ireason, stat; @@ -568,7 +570,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) ide_read_bcount_and_ireason(drive, &len, &ireason); - thislen = blk_fs_request(rq) ? len : cmd->nleft; + thislen = (rq->cmd_type == REQ_TYPE_FS) ? len : cmd->nleft; if (thislen > len) thislen = len; @@ -577,7 +579,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) /* If DRQ is clear, the command has completed. */ if ((stat & ATA_DRQ) == 0) { - if (blk_fs_request(rq)) { + if (rq->cmd_type == REQ_TYPE_FS) { /* * If we're not done reading/writing, complain. * Otherwise, complete the command normally. @@ -591,7 +593,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) rq->cmd_flags |= REQ_FAILED; uptodate = 0; } - } else if (!blk_pc_request(rq)) { + } else if (rq->cmd_type != REQ_TYPE_BLOCK_PC) { ide_cd_request_sense_fixup(drive, cmd); uptodate = cmd->nleft ? 0 : 1; @@ -640,7 +642,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) /* pad, if necessary */ if (len > 0) { - if (blk_fs_request(rq) == 0 || write == 0) + if (rq->cmd_type != REQ_TYPE_FS || write == 0) ide_pad_transfer(drive, write, len); else { printk(KERN_ERR PFX "%s: confused, missing data\n", @@ -649,11 +651,11 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) } } - if (blk_pc_request(rq)) { + if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { timeout = rq->timeout; } else { timeout = ATAPI_WAIT_PC; - if (!blk_fs_request(rq)) + if (rq->cmd_type != REQ_TYPE_FS) expiry = ide_cd_expiry; } @@ -662,7 +664,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) return ide_started; out_end: - if (blk_pc_request(rq) && rc == 0) { + if (rq->cmd_type == REQ_TYPE_BLOCK_PC && rc == 0) { rq->resid_len = 0; blk_end_request_all(rq, 0); hwif->rq = NULL; @@ -670,7 +672,7 @@ out_end: if (sense && uptodate) ide_cd_complete_failed_rq(drive, rq); - if (blk_fs_request(rq)) { + if (rq->cmd_type == REQ_TYPE_FS) { if (cmd->nleft == 0) uptodate = 1; } else { @@ -682,7 +684,7 @@ out_end: ide_cd_error_cmd(drive, cmd); /* make sure it's fully ended */ - if (blk_fs_request(rq) == 0) { + if (rq->cmd_type != REQ_TYPE_FS) { rq->resid_len -= cmd->nbytes - cmd->nleft; if (uptodate == 0 && (cmd->tf_flags & IDE_TFLAG_WRITE)) rq->resid_len += cmd->last_xfer_len; @@ -742,7 +744,7 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) ide_debug_log(IDE_DBG_PC, "rq->cmd[0]: 0x%x, rq->cmd_type: 0x%x", rq->cmd[0], rq->cmd_type); - if (blk_pc_request(rq)) + if (rq->cmd_type == REQ_TYPE_BLOCK_PC) rq->cmd_flags |= REQ_QUIET; else rq->cmd_flags &= ~REQ_FAILED; @@ -783,21 +785,26 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, if (drive->debug_mask & IDE_DBG_RQ) blk_dump_rq_flags(rq, "ide_cd_do_request"); - if (blk_fs_request(rq)) { + switch (rq->cmd_type) { + case REQ_TYPE_FS: if (cdrom_start_rw(drive, rq) == ide_stopped) goto out_end; - } else if (blk_sense_request(rq) || blk_pc_request(rq) || - rq->cmd_type == REQ_TYPE_ATA_PC) { + break; + case REQ_TYPE_SENSE: + case REQ_TYPE_BLOCK_PC: + case REQ_TYPE_ATA_PC: if (!rq->timeout) rq->timeout = ATAPI_WAIT_PC; cdrom_do_block_pc(drive, rq); - } else if (blk_special_request(rq)) { + break; + case REQ_TYPE_SPECIAL: /* right now this can only be a reset... */ uptodate = 1; goto out_end; - } else + default: BUG(); + } /* prepare sense request for this command */ ide_prep_sense(drive, rq); @@ -809,7 +816,7 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, cmd.rq = rq; - if (blk_fs_request(rq) || blk_rq_bytes(rq)) { + if (rq->cmd_type == REQ_TYPE_FS || blk_rq_bytes(rq)) { ide_init_sg_cmd(&cmd, blk_rq_bytes(rq)); ide_map_sg(drive, &cmd); } @@ -1365,9 +1372,9 @@ static int ide_cdrom_prep_pc(struct request *rq) static int ide_cdrom_prep_fn(struct request_queue *q, struct request *rq) { - if (blk_fs_request(rq)) + if (rq->cmd_type == REQ_TYPE_FS) return ide_cdrom_prep_fs(q, rq); - else if (blk_pc_request(rq)) + else if (rq->cmd_type == REQ_TYPE_BLOCK_PC) return ide_cdrom_prep_pc(rq); return 0; @@ -1584,17 +1591,19 @@ static struct ide_driver ide_cdrom_driver = { static int idecd_open(struct block_device *bdev, fmode_t mode) { - struct cdrom_info *info = ide_cd_get(bdev->bd_disk); - int rc = -ENOMEM; + struct cdrom_info *info; + int rc = -ENXIO; + lock_kernel(); + info = ide_cd_get(bdev->bd_disk); if (!info) - return -ENXIO; + goto out; rc = cdrom_open(&info->devinfo, bdev, mode); - if (rc < 0) ide_cd_put(info); - +out: + unlock_kernel(); return rc; } @@ -1602,9 +1611,11 @@ static int idecd_release(struct gendisk *disk, fmode_t mode) { struct cdrom_info *info = ide_drv_g(disk, cdrom_info); + lock_kernel(); cdrom_release(&info->devinfo, mode); ide_cd_put(info); + unlock_kernel(); return 0; } @@ -1648,7 +1659,7 @@ static int idecd_get_spindown(struct cdrom_device_info *cdi, unsigned long arg) return 0; } -static int idecd_ioctl(struct block_device *bdev, fmode_t mode, +static int idecd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { struct cdrom_info *info = ide_drv_g(bdev->bd_disk, cdrom_info); @@ -1670,6 +1681,19 @@ static int idecd_ioctl(struct block_device *bdev, fmode_t mode, return err; } +static int idecd_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) +{ + int ret; + + lock_kernel(); + ret = idecd_locked_ioctl(bdev, mode, cmd, arg); + unlock_kernel(); + + return ret; +} + + static int idecd_media_changed(struct gendisk *disk) { struct cdrom_info *info = ide_drv_g(disk, cdrom_info); @@ -1690,7 +1714,7 @@ static const struct block_device_operations idecd_ops = { .owner = THIS_MODULE, .open = idecd_open, .release = idecd_release, - .locked_ioctl = idecd_ioctl, + .ioctl = idecd_ioctl, .media_changed = idecd_media_changed, .revalidate_disk = idecd_revalidate_disk }; diff --git a/drivers/ide/ide-cd_ioctl.c b/drivers/ide/ide-cd_ioctl.c index 02712bf045c1..766b3deeb23c 100644 --- a/drivers/ide/ide-cd_ioctl.c +++ b/drivers/ide/ide-cd_ioctl.c @@ -454,7 +454,7 @@ int ide_cdrom_packet(struct cdrom_device_info *cdi, touch it at all. */ if (cgc->data_direction == CGC_DATA_WRITE) - flags |= REQ_RW; + flags |= REQ_WRITE; if (cgc->sense) memset(cgc->sense, 0, sizeof(struct request_sense)); diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 33d65039cce9..7433e07de30e 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -184,7 +184,7 @@ static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq, ide_hwif_t *hwif = drive->hwif; BUG_ON(drive->dev_flags & IDE_DFLAG_BLOCKED); - BUG_ON(!blk_fs_request(rq)); + BUG_ON(rq->cmd_type != REQ_TYPE_FS); ledtrig_ide_activity(); @@ -427,10 +427,15 @@ static void ide_disk_unlock_native_capacity(ide_drive_t *drive) drive->dev_flags |= IDE_DFLAG_NOHPA; /* disable HPA on resume */ } -static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) +static int idedisk_prep_fn(struct request_queue *q, struct request *rq) { ide_drive_t *drive = q->queuedata; - struct ide_cmd *cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC); + struct ide_cmd *cmd; + + if (!(rq->cmd_flags & REQ_FLUSH)) + return BLKPREP_OK; + + cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC); /* FIXME: map struct ide_taskfile on rq->cmd[] */ BUG_ON(cmd == NULL); @@ -448,6 +453,8 @@ static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) rq->cmd_type = REQ_TYPE_ATA_TASKFILE; rq->special = cmd; cmd->rq = rq; + + return BLKPREP_OK; } ide_devset_get(multcount, mult_count); @@ -513,7 +520,6 @@ static void update_ordered(ide_drive_t *drive) { u16 *id = drive->id; unsigned ordered = QUEUE_ORDERED_NONE; - prepare_flush_fn *prep_fn = NULL; if (drive->dev_flags & IDE_DFLAG_WCACHE) { unsigned long long capacity; @@ -538,12 +544,12 @@ static void update_ordered(ide_drive_t *drive) if (barrier) { ordered = QUEUE_ORDERED_DRAIN_FLUSH; - prep_fn = idedisk_prepare_flush; + blk_queue_prep_rq(drive->queue, idedisk_prep_fn); } } else ordered = QUEUE_ORDERED_DRAIN; - blk_queue_ordered(drive->queue, ordered, prep_fn); + blk_queue_ordered(drive->queue, ordered); } ide_devset_get_flag(wcache, IDE_DFLAG_WCACHE); diff --git a/drivers/ide/ide-disk_ioctl.c b/drivers/ide/ide-disk_ioctl.c index 7b783dd7c0be..ec94c66918f6 100644 --- a/drivers/ide/ide-disk_ioctl.c +++ b/drivers/ide/ide-disk_ioctl.c @@ -1,6 +1,7 @@ #include <linux/kernel.h> #include <linux/ide.h> #include <linux/hdreg.h> +#include <linux/smp_lock.h> #include "ide-disk.h" @@ -18,9 +19,13 @@ int ide_disk_ioctl(ide_drive_t *drive, struct block_device *bdev, fmode_t mode, { int err; + lock_kernel(); err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings); if (err != -EOPNOTSUPP) - return err; + goto out; - return generic_ide_ioctl(drive, bdev, cmd, arg); + err = generic_ide_ioctl(drive, bdev, cmd, arg); +out: + unlock_kernel(); + return err; } diff --git a/drivers/ide/ide-eh.c b/drivers/ide/ide-eh.c index e9abf2c3c335..c0aa93fb7a60 100644 --- a/drivers/ide/ide-eh.c +++ b/drivers/ide/ide-eh.c @@ -122,7 +122,7 @@ ide_startstop_t ide_error(ide_drive_t *drive, const char *msg, u8 stat) return ide_stopped; /* retry only "normal" I/O: */ - if (!blk_fs_request(rq)) { + if (rq->cmd_type != REQ_TYPE_FS) { if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { struct ide_cmd *cmd = rq->special; @@ -146,7 +146,8 @@ static inline void ide_complete_drive_reset(ide_drive_t *drive, int err) { struct request *rq = drive->hwif->rq; - if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET) { + if (rq && rq->cmd_type == REQ_TYPE_SPECIAL && + rq->cmd[0] == REQ_DRIVE_RESET) { if (err <= 0 && rq->errors == 0) rq->errors = -EIO; ide_complete_rq(drive, err ? err : 0, blk_rq_bytes(rq)); diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 4713bdca20b6..5406b6ea3ad1 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -73,7 +73,7 @@ static int ide_floppy_callback(ide_drive_t *drive, int dsc) drive->failed_pc = NULL; if (pc->c[0] == GPCMD_READ_10 || pc->c[0] == GPCMD_WRITE_10 || - (rq && blk_pc_request(rq))) + (rq && rq->cmd_type == REQ_TYPE_BLOCK_PC)) uptodate = 1; /* FIXME */ else if (pc->c[0] == GPCMD_REQUEST_SENSE) { @@ -98,7 +98,7 @@ static int ide_floppy_callback(ide_drive_t *drive, int dsc) "Aborting request!\n"); } - if (blk_special_request(rq)) + if (rq->cmd_type == REQ_TYPE_SPECIAL) rq->errors = uptodate ? 0 : IDE_DRV_ERROR_GENERAL; return uptodate; @@ -207,7 +207,7 @@ static void idefloppy_create_rw_cmd(ide_drive_t *drive, memcpy(rq->cmd, pc->c, 12); pc->rq = rq; - if (rq->cmd_flags & REQ_RW) + if (rq->cmd_flags & REQ_WRITE) pc->flags |= PC_FLAG_WRITING; pc->flags |= PC_FLAG_DMA_OK; @@ -247,14 +247,16 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, } else printk(KERN_ERR PFX "%s: I/O error\n", drive->name); - if (blk_special_request(rq)) { + if (rq->cmd_type == REQ_TYPE_SPECIAL) { rq->errors = 0; ide_complete_rq(drive, 0, blk_rq_bytes(rq)); return ide_stopped; } else goto out_end; } - if (blk_fs_request(rq)) { + + switch (rq->cmd_type) { + case REQ_TYPE_FS: if (((long)blk_rq_pos(rq) % floppy->bs_factor) || (blk_rq_sectors(rq) % floppy->bs_factor)) { printk(KERN_ERR PFX "%s: unsupported r/w rq size\n", @@ -263,13 +265,18 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, } pc = &floppy->queued_pc; idefloppy_create_rw_cmd(drive, pc, rq, (unsigned long)block); - } else if (blk_special_request(rq) || blk_sense_request(rq)) { + break; + case REQ_TYPE_SPECIAL: + case REQ_TYPE_SENSE: pc = (struct ide_atapi_pc *)rq->special; - } else if (blk_pc_request(rq)) { + break; + case REQ_TYPE_BLOCK_PC: pc = &floppy->queued_pc; idefloppy_blockpc_cmd(floppy, pc, rq); - } else + break; + default: BUG(); + } ide_prep_sense(drive, rq); @@ -280,7 +287,7 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, cmd.rq = rq; - if (blk_fs_request(rq) || blk_rq_bytes(rq)) { + if (rq->cmd_type == REQ_TYPE_FS || blk_rq_bytes(rq)) { ide_init_sg_cmd(&cmd, blk_rq_bytes(rq)); ide_map_sg(drive, &cmd); } @@ -290,7 +297,7 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, return ide_floppy_issue_pc(drive, &cmd, pc); out_end: drive->failed_pc = NULL; - if (blk_fs_request(rq) == 0 && rq->errors == 0) + if (rq->cmd_type != REQ_TYPE_FS && rq->errors == 0) rq->errors = -EIO; ide_complete_rq(drive, -EIO, blk_rq_bytes(rq)); return ide_stopped; diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c index 9c2288234dea..fd3d05ab3417 100644 --- a/drivers/ide/ide-floppy_ioctl.c +++ b/drivers/ide/ide-floppy_ioctl.c @@ -5,6 +5,7 @@ #include <linux/kernel.h> #include <linux/ide.h> #include <linux/cdrom.h> +#include <linux/smp_lock.h> #include <asm/unaligned.h> @@ -275,12 +276,15 @@ int ide_floppy_ioctl(ide_drive_t *drive, struct block_device *bdev, void __user *argp = (void __user *)arg; int err; - if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR) - return ide_floppy_lockdoor(drive, &pc, arg, cmd); + lock_kernel(); + if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR) { + err = ide_floppy_lockdoor(drive, &pc, arg, cmd); + goto out; + } err = ide_floppy_format_ioctl(drive, &pc, mode, cmd, argp); if (err != -ENOTTY) - return err; + goto out; /* * skip SCSI_IOCTL_SEND_COMMAND (deprecated) @@ -293,5 +297,7 @@ int ide_floppy_ioctl(ide_drive_t *drive, struct block_device *bdev, if (err == -ENOTTY) err = generic_ide_ioctl(drive, bdev, cmd, arg); +out: + unlock_kernel(); return err; } diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c index c102d23d9b38..137337a795a9 100644 --- a/drivers/ide/ide-gd.c +++ b/drivers/ide/ide-gd.c @@ -1,3 +1,4 @@ +#include <linux/smp_lock.h> #include <linux/module.h> #include <linux/types.h> #include <linux/string.h> @@ -237,6 +238,18 @@ out_put_idkp: return ret; } +static int ide_gd_unlocked_open(struct block_device *bdev, fmode_t mode) +{ + int ret; + + lock_kernel(); + ret = ide_gd_open(bdev, mode); + unlock_kernel(); + + return ret; +} + + static int ide_gd_release(struct gendisk *disk, fmode_t mode) { struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj); @@ -244,6 +257,7 @@ static int ide_gd_release(struct gendisk *disk, fmode_t mode) ide_debug_log(IDE_DBG_FUNC, "enter"); + lock_kernel(); if (idkp->openers == 1) drive->disk_ops->flush(drive); @@ -255,6 +269,7 @@ static int ide_gd_release(struct gendisk *disk, fmode_t mode) idkp->openers--; ide_disk_put(idkp); + unlock_kernel(); return 0; } @@ -321,9 +336,9 @@ static int ide_gd_ioctl(struct block_device *bdev, fmode_t mode, static const struct block_device_operations ide_gd_ops = { .owner = THIS_MODULE, - .open = ide_gd_open, + .open = ide_gd_unlocked_open, .release = ide_gd_release, - .locked_ioctl = ide_gd_ioctl, + .ioctl = ide_gd_ioctl, .getgeo = ide_gd_getgeo, .media_changed = ide_gd_media_changed, .unlock_native_capacity = ide_gd_unlock_native_capacity, diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 172ac9218154..a381be814070 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -135,7 +135,7 @@ EXPORT_SYMBOL(ide_complete_rq); void ide_kill_rq(ide_drive_t *drive, struct request *rq) { - u8 drv_req = blk_special_request(rq) && rq->rq_disk; + u8 drv_req = (rq->cmd_type == REQ_TYPE_SPECIAL) && rq->rq_disk; u8 media = drive->media; drive->failed_pc = NULL; @@ -145,7 +145,7 @@ void ide_kill_rq(ide_drive_t *drive, struct request *rq) } else { if (media == ide_tape) rq->errors = IDE_DRV_ERROR_GENERAL; - else if (blk_fs_request(rq) == 0 && rq->errors == 0) + else if (rq->cmd_type != REQ_TYPE_FS && rq->errors == 0) rq->errors = -EIO; } @@ -307,7 +307,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) { ide_startstop_t startstop; - BUG_ON(!blk_rq_started(rq)); + BUG_ON(!(rq->cmd_flags & REQ_STARTED)); #ifdef DEBUG printk("%s: start_request: current=0x%08lx\n", @@ -353,7 +353,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) pm->pm_step == IDE_PM_COMPLETED) ide_complete_pm_rq(drive, rq); return startstop; - } else if (!rq->rq_disk && blk_special_request(rq)) + } else if (!rq->rq_disk && rq->cmd_type == REQ_TYPE_SPECIAL) /* * TODO: Once all ULDs have been modified to * check for specific op codes rather than diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c index 1c08311b0a0e..92406097efeb 100644 --- a/drivers/ide/ide-pm.c +++ b/drivers/ide/ide-pm.c @@ -191,10 +191,10 @@ void ide_complete_pm_rq(ide_drive_t *drive, struct request *rq) #ifdef DEBUG_PM printk("%s: completing PM request, %s\n", drive->name, - blk_pm_suspend_request(rq) ? "suspend" : "resume"); + (rq->cmd_type == REQ_TYPE_PM_SUSPEND) ? "suspend" : "resume"); #endif spin_lock_irqsave(q->queue_lock, flags); - if (blk_pm_suspend_request(rq)) + if (rq->cmd_type == REQ_TYPE_PM_SUSPEND) blk_stop_queue(q); else drive->dev_flags &= ~IDE_DFLAG_BLOCKED; @@ -210,11 +210,11 @@ void ide_check_pm_state(ide_drive_t *drive, struct request *rq) { struct request_pm_state *pm = rq->special; - if (blk_pm_suspend_request(rq) && + if (rq->cmd_type == REQ_TYPE_PM_SUSPEND && pm->pm_step == IDE_PM_START_SUSPEND) /* Mark drive blocked when starting the suspend sequence. */ drive->dev_flags |= IDE_DFLAG_BLOCKED; - else if (blk_pm_resume_request(rq) && + else if (rq->cmd_type == REQ_TYPE_PM_RESUME && pm->pm_step == IDE_PM_START_RESUME) { /* * The first thing we do on wakeup is to wait for BSY bit to diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index b07232880ec9..6d622cb5ac81 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -32,6 +32,7 @@ #include <linux/errno.h> #include <linux/genhd.h> #include <linux/seq_file.h> +#include <linux/smp_lock.h> #include <linux/slab.h> #include <linux/pci.h> #include <linux/ide.h> @@ -577,7 +578,8 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, rq->cmd[0], (unsigned long long)blk_rq_pos(rq), blk_rq_sectors(rq)); - BUG_ON(!(blk_special_request(rq) || blk_sense_request(rq))); + BUG_ON(!(rq->cmd_type == REQ_TYPE_SPECIAL || + rq->cmd_type == REQ_TYPE_SENSE)); /* Retry a failed packet command */ if (drive->failed_pc && drive->pc->c[0] == REQUEST_SENSE) { @@ -1905,7 +1907,11 @@ static const struct file_operations idetape_fops = { static int idetape_open(struct block_device *bdev, fmode_t mode) { - struct ide_tape_obj *tape = ide_tape_get(bdev->bd_disk, false, 0); + struct ide_tape_obj *tape; + + lock_kernel(); + tape = ide_tape_get(bdev->bd_disk, false, 0); + unlock_kernel(); if (!tape) return -ENXIO; @@ -1917,7 +1923,10 @@ static int idetape_release(struct gendisk *disk, fmode_t mode) { struct ide_tape_obj *tape = ide_drv_g(disk, ide_tape_obj); + lock_kernel(); ide_tape_put(tape); + unlock_kernel(); + return 0; } @@ -1926,9 +1935,14 @@ static int idetape_ioctl(struct block_device *bdev, fmode_t mode, { struct ide_tape_obj *tape = ide_drv_g(bdev->bd_disk, ide_tape_obj); ide_drive_t *drive = tape->drive; - int err = generic_ide_ioctl(drive, bdev, cmd, arg); + int err; + + lock_kernel(); + err = generic_ide_ioctl(drive, bdev, cmd, arg); if (err == -EINVAL) err = idetape_blkdev_ioctl(drive, cmd, arg); + unlock_kernel(); + return err; } @@ -1936,7 +1950,7 @@ static const struct block_device_operations idetape_block_ops = { .owner = THIS_MODULE, .open = idetape_open, .release = idetape_release, - .locked_ioctl = idetape_ioctl, + .ioctl = idetape_ioctl, }; static int ide_tape_probe(ide_drive_t *drive) diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index 10f457ca6af2..0590c75b0ab6 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -356,7 +356,7 @@ static void dispatch_io(int rw, unsigned int num_regions, BUG_ON(num_regions > DM_IO_MAX_REGIONS); if (sync) - rw |= (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG); + rw |= REQ_SYNC | REQ_UNPLUG; /* * For multiple regions we need to be careful to rewind @@ -364,7 +364,7 @@ static void dispatch_io(int rw, unsigned int num_regions, */ for (i = 0; i < num_regions; i++) { *dp = old_pages; - if (where[i].count || (rw & (1 << BIO_RW_BARRIER))) + if (where[i].count || (rw & REQ_HARDBARRIER)) do_region(rw, i, where + i, dp, io); } @@ -412,8 +412,8 @@ retry: } set_current_state(TASK_RUNNING); - if (io->eopnotsupp_bits && (rw & (1 << BIO_RW_BARRIER))) { - rw &= ~(1 << BIO_RW_BARRIER); + if (io->eopnotsupp_bits && (rw & REQ_HARDBARRIER)) { + rw &= ~REQ_HARDBARRIER; goto retry; } @@ -479,8 +479,8 @@ static int dp_init(struct dm_io_request *io_req, struct dpages *dp) * New collapsed (a)synchronous interface. * * If the IO is asynchronous (i.e. it has notify.fn), you must either unplug - * the queue with blk_unplug() some time later or set the BIO_RW_SYNC bit in - * io_req->bi_rw. If you fail to do one of these, the IO will be submitted to + * the queue with blk_unplug() some time later or set REQ_SYNC in +io_req->bi_rw. If you fail to do one of these, the IO will be submitted to * the disk after q->unplug_delay, which defaults to 3ms in blk-settings.c. */ int dm_io(struct dm_io_request *io_req, unsigned num_regions, diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c index addf83475040..d8587bac5682 100644 --- a/drivers/md/dm-kcopyd.c +++ b/drivers/md/dm-kcopyd.c @@ -345,7 +345,7 @@ static int run_io_job(struct kcopyd_job *job) { int r; struct dm_io_request io_req = { - .bi_rw = job->rw | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG), + .bi_rw = job->rw | REQ_SYNC | REQ_UNPLUG, .mem.type = DM_IO_PAGE_LIST, .mem.ptr.pl = job->pages, .mem.offset = job->offset, diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index ddda531723dc..74136262d654 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -1211,7 +1211,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, if (error == -EOPNOTSUPP) goto out; - if ((error == -EWOULDBLOCK) && bio_rw_flagged(bio, BIO_RW_AHEAD)) + if ((error == -EWOULDBLOCK) && (bio->bi_rw & REQ_RAHEAD)) goto out; if (unlikely(error)) { diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index e610725db766..d6e28d732b4d 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c @@ -284,7 +284,7 @@ static int stripe_end_io(struct dm_target *ti, struct bio *bio, if (!error) return 0; /* I/O complete */ - if ((error == -EWOULDBLOCK) && bio_rw_flagged(bio, BIO_RW_AHEAD)) + if ((error == -EWOULDBLOCK) && (bio->bi_rw & REQ_RAHEAD)) return error; if (error == -EOPNOTSUPP) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index d21e1284604f..a3f21dc02bd8 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -15,6 +15,7 @@ #include <linux/blkpg.h> #include <linux/bio.h> #include <linux/buffer_head.h> +#include <linux/smp_lock.h> #include <linux/mempool.h> #include <linux/slab.h> #include <linux/idr.h> @@ -338,6 +339,7 @@ static int dm_blk_open(struct block_device *bdev, fmode_t mode) { struct mapped_device *md; + lock_kernel(); spin_lock(&_minor_lock); md = bdev->bd_disk->private_data; @@ -355,6 +357,7 @@ static int dm_blk_open(struct block_device *bdev, fmode_t mode) out: spin_unlock(&_minor_lock); + unlock_kernel(); return md ? 0 : -ENXIO; } @@ -362,8 +365,12 @@ out: static int dm_blk_close(struct gendisk *disk, fmode_t mode) { struct mapped_device *md = disk->private_data; + + lock_kernel(); atomic_dec(&md->open_count); dm_put(md); + unlock_kernel(); + return 0; } @@ -614,7 +621,7 @@ static void dec_pending(struct dm_io *io, int error) */ spin_lock_irqsave(&md->deferred_lock, flags); if (__noflush_suspending(md)) { - if (!bio_rw_flagged(io->bio, BIO_RW_BARRIER)) + if (!(io->bio->bi_rw & REQ_HARDBARRIER)) bio_list_add_head(&md->deferred, io->bio); } else @@ -626,7 +633,7 @@ static void dec_pending(struct dm_io *io, int error) io_error = io->error; bio = io->bio; - if (bio_rw_flagged(bio, BIO_RW_BARRIER)) { + if (bio->bi_rw & REQ_HARDBARRIER) { /* * There can be just one barrier request so we use * a per-device variable for error reporting. @@ -792,12 +799,12 @@ static void dm_end_request(struct request *clone, int error) { int rw = rq_data_dir(clone); int run_queue = 1; - bool is_barrier = blk_barrier_rq(clone); + bool is_barrier = clone->cmd_flags & REQ_HARDBARRIER; struct dm_rq_target_io *tio = clone->end_io_data; struct mapped_device *md = tio->md; struct request *rq = tio->orig; - if (blk_pc_request(rq) && !is_barrier) { + if (rq->cmd_type == REQ_TYPE_BLOCK_PC && !is_barrier) { rq->errors = clone->errors; rq->resid_len = clone->resid_len; @@ -844,7 +851,7 @@ void dm_requeue_unmapped_request(struct request *clone) struct request_queue *q = rq->q; unsigned long flags; - if (unlikely(blk_barrier_rq(clone))) { + if (unlikely(clone->cmd_flags & REQ_HARDBARRIER)) { /* * Barrier clones share an original request. * Leave it to dm_end_request(), which handles this special @@ -943,7 +950,7 @@ static void dm_complete_request(struct request *clone, int error) struct dm_rq_target_io *tio = clone->end_io_data; struct request *rq = tio->orig; - if (unlikely(blk_barrier_rq(clone))) { + if (unlikely(clone->cmd_flags & REQ_HARDBARRIER)) { /* * Barrier clones share an original request. So can't use * softirq_done with the original. @@ -972,7 +979,7 @@ void dm_kill_unmapped_request(struct request *clone, int error) struct dm_rq_target_io *tio = clone->end_io_data; struct request *rq = tio->orig; - if (unlikely(blk_barrier_rq(clone))) { + if (unlikely(clone->cmd_flags & REQ_HARDBARRIER)) { /* * Barrier clones share an original request. * Leave it to dm_end_request(), which handles this special @@ -1106,7 +1113,7 @@ static struct bio *split_bvec(struct bio *bio, sector_t sector, clone->bi_sector = sector; clone->bi_bdev = bio->bi_bdev; - clone->bi_rw = bio->bi_rw & ~(1 << BIO_RW_BARRIER); + clone->bi_rw = bio->bi_rw & ~REQ_HARDBARRIER; clone->bi_vcnt = 1; clone->bi_size = to_bytes(len); clone->bi_io_vec->bv_offset = offset; @@ -1133,7 +1140,7 @@ static struct bio *clone_bio(struct bio *bio, sector_t sector, clone = bio_alloc_bioset(GFP_NOIO, bio->bi_max_vecs, bs); __bio_clone(clone, bio); - clone->bi_rw &= ~(1 << BIO_RW_BARRIER); + clone->bi_rw &= ~REQ_HARDBARRIER; clone->bi_destructor = dm_bio_destructor; clone->bi_sector = sector; clone->bi_idx = idx; @@ -1301,7 +1308,7 @@ static void __split_and_process_bio(struct mapped_device *md, struct bio *bio) ci.map = dm_get_live_table(md); if (unlikely(!ci.map)) { - if (!bio_rw_flagged(bio, BIO_RW_BARRIER)) + if (!(bio->bi_rw & REQ_HARDBARRIER)) bio_io_error(bio); else if (!md->barrier_error) @@ -1414,7 +1421,7 @@ static int _dm_request(struct request_queue *q, struct bio *bio) * we have to queue this io for later. */ if (unlikely(test_bit(DMF_QUEUE_IO_TO_THREAD, &md->flags)) || - unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) { + unlikely(bio->bi_rw & REQ_HARDBARRIER)) { up_read(&md->io_lock); if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) && @@ -1455,20 +1462,9 @@ static int dm_request(struct request_queue *q, struct bio *bio) return _dm_request(q, bio); } -/* - * Mark this request as flush request, so that dm_request_fn() can - * recognize. - */ -static void dm_rq_prepare_flush(struct request_queue *q, struct request *rq) -{ - rq->cmd_type = REQ_TYPE_LINUX_BLOCK; - rq->cmd[0] = REQ_LB_OP_FLUSH; -} - static bool dm_rq_is_flush_request(struct request *rq) { - if (rq->cmd_type == REQ_TYPE_LINUX_BLOCK && - rq->cmd[0] == REQ_LB_OP_FLUSH) + if (rq->cmd_flags & REQ_FLUSH) return true; else return false; @@ -1912,8 +1908,7 @@ static struct mapped_device *alloc_dev(int minor) blk_queue_softirq_done(md->queue, dm_softirq_done); blk_queue_prep_rq(md->queue, dm_prep_fn); blk_queue_lld_busy(md->queue, dm_lld_busy); - blk_queue_ordered(md->queue, QUEUE_ORDERED_DRAIN_FLUSH, - dm_rq_prepare_flush); + blk_queue_ordered(md->queue, QUEUE_ORDERED_DRAIN_FLUSH); md->disk = alloc_disk(1); if (!md->disk) @@ -2296,7 +2291,7 @@ static void dm_wq_work(struct work_struct *work) if (dm_request_based(md)) generic_make_request(c); else { - if (bio_rw_flagged(c, BIO_RW_BARRIER)) + if (c->bi_rw & REQ_HARDBARRIER) process_barrier(md, c); else __split_and_process_bio(md, c); diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 7e0e057db9a7..ba19060bcf3f 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -294,7 +294,7 @@ static int linear_make_request (mddev_t *mddev, struct bio *bio) dev_info_t *tmp_dev; sector_t start_sector; - if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) { + if (unlikely(bio->bi_rw & REQ_HARDBARRIER)) { md_barrier_request(mddev, bio); return 0; } diff --git a/drivers/md/md.c b/drivers/md/md.c index cb20d0b0555a..700c96edf9b2 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -36,6 +36,7 @@ #include <linux/blkdev.h> #include <linux/sysctl.h> #include <linux/seq_file.h> +#include <linux/smp_lock.h> #include <linux/buffer_head.h> /* for invalidate_bdev */ #include <linux/poll.h> #include <linux/ctype.h> @@ -353,7 +354,7 @@ static void md_submit_barrier(struct work_struct *ws) /* an empty barrier - all done */ bio_endio(bio, 0); else { - bio->bi_rw &= ~(1<<BIO_RW_BARRIER); + bio->bi_rw &= ~REQ_HARDBARRIER; if (mddev->pers->make_request(mddev, bio)) generic_make_request(bio); mddev->barrier = POST_REQUEST_BARRIER; @@ -675,11 +676,11 @@ void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev, * if zero is reached. * If an error occurred, call md_error * - * As we might need to resubmit the request if BIO_RW_BARRIER + * As we might need to resubmit the request if REQ_HARDBARRIER * causes ENOTSUPP, we allocate a spare bio... */ struct bio *bio = bio_alloc(GFP_NOIO, 1); - int rw = (1<<BIO_RW) | (1<<BIO_RW_SYNCIO) | (1<<BIO_RW_UNPLUG); + int rw = REQ_WRITE | REQ_SYNC | REQ_UNPLUG; bio->bi_bdev = rdev->bdev; bio->bi_sector = sector; @@ -691,7 +692,7 @@ void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev, atomic_inc(&mddev->pending_writes); if (!test_bit(BarriersNotsupp, &rdev->flags)) { struct bio *rbio; - rw |= (1<<BIO_RW_BARRIER); + rw |= REQ_HARDBARRIER; rbio = bio_clone(bio, GFP_NOIO); rbio->bi_private = bio; rbio->bi_end_io = super_written_barrier; @@ -736,7 +737,7 @@ int sync_page_io(struct block_device *bdev, sector_t sector, int size, struct completion event; int ret; - rw |= (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG); + rw |= REQ_SYNC | REQ_UNPLUG; bio->bi_bdev = bdev; bio->bi_sector = sector; @@ -5902,6 +5903,7 @@ static int md_open(struct block_device *bdev, fmode_t mode) mddev_t *mddev = mddev_find(bdev->bd_dev); int err; + lock_kernel(); if (mddev->gendisk != bdev->bd_disk) { /* we are racing with mddev_put which is discarding this * bd_disk. @@ -5910,6 +5912,7 @@ static int md_open(struct block_device *bdev, fmode_t mode) /* Wait until bdev->bd_disk is definitely gone */ flush_scheduled_work(); /* Then retry the open from the top */ + unlock_kernel(); return -ERESTARTSYS; } BUG_ON(mddev != bdev->bd_disk->private_data); @@ -5923,6 +5926,7 @@ static int md_open(struct block_device *bdev, fmode_t mode) check_disk_size_change(mddev->gendisk, bdev); out: + unlock_kernel(); return err; } @@ -5931,8 +5935,10 @@ static int md_release(struct gendisk *disk, fmode_t mode) mddev_t *mddev = disk->private_data; BUG_ON(!mddev); + lock_kernel(); atomic_dec(&mddev->openers); mddev_put(mddev); + unlock_kernel(); return 0; } diff --git a/drivers/md/md.h b/drivers/md/md.h index 10597bfec000..fc56e0f21c80 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -67,7 +67,7 @@ struct mdk_rdev_s #define Faulty 1 /* device is known to have a fault */ #define In_sync 2 /* device is in_sync with rest of array */ #define WriteMostly 4 /* Avoid reading if at all possible */ -#define BarriersNotsupp 5 /* BIO_RW_BARRIER is not supported */ +#define BarriersNotsupp 5 /* REQ_HARDBARRIER is not supported */ #define AllReserved 6 /* If whole device is reserved for * one array */ #define AutoDetected 7 /* added by auto-detect */ @@ -254,7 +254,7 @@ struct mddev_s * fails. Only supported */ struct bio *biolist; /* bios that need to be retried - * because BIO_RW_BARRIER is not supported + * because REQ_HARDBARRIER is not supported */ atomic_t recovery_active; /* blocks scheduled, but not written */ diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 410fb60699ac..0307d217e7a4 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -91,7 +91,7 @@ static void multipath_end_request(struct bio *bio, int error) if (uptodate) multipath_end_bh_io(mp_bh, 0); - else if (!bio_rw_flagged(bio, BIO_RW_AHEAD)) { + else if (!(bio->bi_rw & REQ_RAHEAD)) { /* * oops, IO error: */ @@ -142,7 +142,7 @@ static int multipath_make_request(mddev_t *mddev, struct bio * bio) struct multipath_bh * mp_bh; struct multipath_info *multipath; - if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) { + if (unlikely(bio->bi_rw & REQ_HARDBARRIER)) { md_barrier_request(mddev, bio); return 0; } @@ -163,7 +163,7 @@ static int multipath_make_request(mddev_t *mddev, struct bio * bio) mp_bh->bio = *bio; mp_bh->bio.bi_sector += multipath->rdev->data_offset; mp_bh->bio.bi_bdev = multipath->rdev->bdev; - mp_bh->bio.bi_rw |= (1 << BIO_RW_FAILFAST_TRANSPORT); + mp_bh->bio.bi_rw |= REQ_FAILFAST_TRANSPORT; mp_bh->bio.bi_end_io = multipath_end_request; mp_bh->bio.bi_private = mp_bh; generic_make_request(&mp_bh->bio); @@ -398,7 +398,7 @@ static void multipathd (mddev_t *mddev) *bio = *(mp_bh->master_bio); bio->bi_sector += conf->multipaths[mp_bh->path].rdev->data_offset; bio->bi_bdev = conf->multipaths[mp_bh->path].rdev->bdev; - bio->bi_rw |= (1 << BIO_RW_FAILFAST_TRANSPORT); + bio->bi_rw |= REQ_FAILFAST_TRANSPORT; bio->bi_end_io = multipath_end_request; bio->bi_private = mp_bh; generic_make_request(bio); diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 563abed5a2cb..6f7af46d623c 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -483,7 +483,7 @@ static int raid0_make_request(mddev_t *mddev, struct bio *bio) struct strip_zone *zone; mdk_rdev_t *tmp_dev; - if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) { + if (unlikely(bio->bi_rw & REQ_HARDBARRIER)) { md_barrier_request(mddev, bio); return 0; } diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index a948da8012de..73cc74ffc26b 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -787,7 +787,7 @@ static int make_request(mddev_t *mddev, struct bio * bio) struct bio_list bl; struct page **behind_pages = NULL; const int rw = bio_data_dir(bio); - const bool do_sync = bio_rw_flagged(bio, BIO_RW_SYNCIO); + const bool do_sync = (bio->bi_rw & REQ_SYNC); bool do_barriers; mdk_rdev_t *blocked_rdev; @@ -822,7 +822,7 @@ static int make_request(mddev_t *mddev, struct bio * bio) finish_wait(&conf->wait_barrier, &w); } if (unlikely(!mddev->barriers_work && - bio_rw_flagged(bio, BIO_RW_BARRIER))) { + (bio->bi_rw & REQ_HARDBARRIER))) { if (rw == WRITE) md_write_end(mddev); bio_endio(bio, -EOPNOTSUPP); @@ -877,7 +877,7 @@ static int make_request(mddev_t *mddev, struct bio * bio) read_bio->bi_sector = r1_bio->sector + mirror->rdev->data_offset; read_bio->bi_bdev = mirror->rdev->bdev; read_bio->bi_end_io = raid1_end_read_request; - read_bio->bi_rw = READ | (do_sync << BIO_RW_SYNCIO); + read_bio->bi_rw = READ | do_sync; read_bio->bi_private = r1_bio; generic_make_request(read_bio); @@ -959,7 +959,7 @@ static int make_request(mddev_t *mddev, struct bio * bio) atomic_set(&r1_bio->remaining, 0); atomic_set(&r1_bio->behind_remaining, 0); - do_barriers = bio_rw_flagged(bio, BIO_RW_BARRIER); + do_barriers = bio->bi_rw & REQ_HARDBARRIER; if (do_barriers) set_bit(R1BIO_Barrier, &r1_bio->state); @@ -975,8 +975,7 @@ static int make_request(mddev_t *mddev, struct bio * bio) mbio->bi_sector = r1_bio->sector + conf->mirrors[i].rdev->data_offset; mbio->bi_bdev = conf->mirrors[i].rdev->bdev; mbio->bi_end_io = raid1_end_write_request; - mbio->bi_rw = WRITE | (do_barriers << BIO_RW_BARRIER) | - (do_sync << BIO_RW_SYNCIO); + mbio->bi_rw = WRITE | do_barriers | do_sync; mbio->bi_private = r1_bio; if (behind_pages) { @@ -1633,7 +1632,7 @@ static void raid1d(mddev_t *mddev) sync_request_write(mddev, r1_bio); unplug = 1; } else if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) { - /* some requests in the r1bio were BIO_RW_BARRIER + /* some requests in the r1bio were REQ_HARDBARRIER * requests which failed with -EOPNOTSUPP. Hohumm.. * Better resubmit without the barrier. * We know which devices to resubmit for, because @@ -1641,7 +1640,7 @@ static void raid1d(mddev_t *mddev) * We already have a nr_pending reference on these rdevs. */ int i; - const bool do_sync = bio_rw_flagged(r1_bio->master_bio, BIO_RW_SYNCIO); + const bool do_sync = (r1_bio->master_bio->bi_rw & REQ_SYNC); clear_bit(R1BIO_BarrierRetry, &r1_bio->state); clear_bit(R1BIO_Barrier, &r1_bio->state); for (i=0; i < conf->raid_disks; i++) @@ -1662,8 +1661,7 @@ static void raid1d(mddev_t *mddev) conf->mirrors[i].rdev->data_offset; bio->bi_bdev = conf->mirrors[i].rdev->bdev; bio->bi_end_io = raid1_end_write_request; - bio->bi_rw = WRITE | - (do_sync << BIO_RW_SYNCIO); + bio->bi_rw = WRITE | do_sync; bio->bi_private = r1_bio; r1_bio->bios[i] = bio; generic_make_request(bio); @@ -1698,7 +1696,7 @@ static void raid1d(mddev_t *mddev) (unsigned long long)r1_bio->sector); raid_end_bio_io(r1_bio); } else { - const bool do_sync = bio_rw_flagged(r1_bio->master_bio, BIO_RW_SYNCIO); + const bool do_sync = r1_bio->master_bio->bi_rw & REQ_SYNC; r1_bio->bios[r1_bio->read_disk] = mddev->ro ? IO_BLOCKED : NULL; r1_bio->read_disk = disk; @@ -1715,7 +1713,7 @@ static void raid1d(mddev_t *mddev) bio->bi_sector = r1_bio->sector + rdev->data_offset; bio->bi_bdev = rdev->bdev; bio->bi_end_io = raid1_end_read_request; - bio->bi_rw = READ | (do_sync << BIO_RW_SYNCIO); + bio->bi_rw = READ | do_sync; bio->bi_private = r1_bio; unplug = 1; generic_make_request(bio); diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 42e64e4e5e25..62ecb6650fd0 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -799,12 +799,12 @@ static int make_request(mddev_t *mddev, struct bio * bio) int i; int chunk_sects = conf->chunk_mask + 1; const int rw = bio_data_dir(bio); - const bool do_sync = bio_rw_flagged(bio, BIO_RW_SYNCIO); + const bool do_sync = (bio->bi_rw & REQ_SYNC); struct bio_list bl; unsigned long flags; mdk_rdev_t *blocked_rdev; - if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) { + if (unlikely(bio->bi_rw & REQ_HARDBARRIER)) { md_barrier_request(mddev, bio); return 0; } @@ -879,7 +879,7 @@ static int make_request(mddev_t *mddev, struct bio * bio) mirror->rdev->data_offset; read_bio->bi_bdev = mirror->rdev->bdev; read_bio->bi_end_io = raid10_end_read_request; - read_bio->bi_rw = READ | (do_sync << BIO_RW_SYNCIO); + read_bio->bi_rw = READ | do_sync; read_bio->bi_private = r10_bio; generic_make_request(read_bio); @@ -947,7 +947,7 @@ static int make_request(mddev_t *mddev, struct bio * bio) conf->mirrors[d].rdev->data_offset; mbio->bi_bdev = conf->mirrors[d].rdev->bdev; mbio->bi_end_io = raid10_end_write_request; - mbio->bi_rw = WRITE | (do_sync << BIO_RW_SYNCIO); + mbio->bi_rw = WRITE | do_sync; mbio->bi_private = r10_bio; atomic_inc(&r10_bio->remaining); @@ -1716,7 +1716,7 @@ static void raid10d(mddev_t *mddev) raid_end_bio_io(r10_bio); bio_put(bio); } else { - const bool do_sync = bio_rw_flagged(r10_bio->master_bio, BIO_RW_SYNCIO); + const bool do_sync = (r10_bio->master_bio->bi_rw & REQ_SYNC); bio_put(bio); rdev = conf->mirrors[mirror].rdev; if (printk_ratelimit()) @@ -1730,7 +1730,7 @@ static void raid10d(mddev_t *mddev) bio->bi_sector = r10_bio->devs[r10_bio->read_slot].addr + rdev->data_offset; bio->bi_bdev = rdev->bdev; - bio->bi_rw = READ | (do_sync << BIO_RW_SYNCIO); + bio->bi_rw = READ | do_sync; bio->bi_private = r10_bio; bio->bi_end_io = raid10_end_read_request; unplug = 1; diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 96c690279fc6..20ac2f14376a 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -3958,7 +3958,7 @@ static int make_request(mddev_t *mddev, struct bio * bi) const int rw = bio_data_dir(bi); int remaining; - if (unlikely(bio_rw_flagged(bi, BIO_RW_BARRIER))) { + if (unlikely(bi->bi_rw & REQ_HARDBARRIER)) { /* Drain all pending writes. We only really need * to ensure they have been submitted, but this is * easier. diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index 8327e248520a..eef78a068fd1 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c @@ -18,6 +18,7 @@ #include <linux/kthread.h> #include <linux/delay.h> #include <linux/slab.h> +#include <linux/smp_lock.h> #include <linux/memstick.h> #define DRIVER_NAME "mspro_block" @@ -179,6 +180,7 @@ static int mspro_block_bd_open(struct block_device *bdev, fmode_t mode) struct mspro_block_data *msb = disk->private_data; int rc = -ENXIO; + lock_kernel(); mutex_lock(&mspro_block_disk_lock); if (msb && msb->card) { @@ -190,6 +192,7 @@ static int mspro_block_bd_open(struct block_device *bdev, fmode_t mode) } mutex_unlock(&mspro_block_disk_lock); + unlock_kernel(); return rc; } @@ -221,7 +224,11 @@ static int mspro_block_disk_release(struct gendisk *disk) static int mspro_block_bd_release(struct gendisk *disk, fmode_t mode) { - return mspro_block_disk_release(disk); + int ret; + lock_kernel(); + ret = mspro_block_disk_release(disk); + unlock_kernel(); + return ret; } static int mspro_block_bd_getgeo(struct block_device *bdev, @@ -805,7 +812,8 @@ static void mspro_block_start(struct memstick_dev *card) static int mspro_block_prepare_req(struct request_queue *q, struct request *req) { - if (!blk_fs_request(req) && !blk_pc_request(req)) { + if (req->cmd_type != REQ_TYPE_FS && + req->cmd_type != REQ_TYPE_BLOCK_PC) { blk_dump_rq_flags(req, "MSPro unsupported request"); return BLKPREP_KILL; } diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index fc593fbab696..e6733bc99724 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -53,6 +53,7 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/i2o.h> +#include <linux/smp_lock.h> #include <linux/mempool.h> @@ -577,6 +578,7 @@ static int i2o_block_open(struct block_device *bdev, fmode_t mode) if (!dev->i2o_dev) return -ENODEV; + lock_kernel(); if (dev->power > 0x1f) i2o_block_device_power(dev, 0x02); @@ -585,6 +587,7 @@ static int i2o_block_open(struct block_device *bdev, fmode_t mode) i2o_block_device_lock(dev->i2o_dev, -1); osm_debug("Ready.\n"); + unlock_kernel(); return 0; }; @@ -615,6 +618,7 @@ static int i2o_block_release(struct gendisk *disk, fmode_t mode) if (!dev->i2o_dev) return 0; + lock_kernel(); i2o_block_device_flush(dev->i2o_dev); i2o_block_device_unlock(dev->i2o_dev, -1); @@ -625,6 +629,7 @@ static int i2o_block_release(struct gendisk *disk, fmode_t mode) operation = 0x24; i2o_block_device_power(dev, operation); + unlock_kernel(); return 0; } @@ -652,30 +657,40 @@ static int i2o_block_ioctl(struct block_device *bdev, fmode_t mode, { struct gendisk *disk = bdev->bd_disk; struct i2o_block_device *dev = disk->private_data; + int ret = -ENOTTY; /* Anyone capable of this syscall can do *real bad* things */ if (!capable(CAP_SYS_ADMIN)) return -EPERM; + lock_kernel(); switch (cmd) { case BLKI2OGRSTRAT: - return put_user(dev->rcache, (int __user *)arg); + ret = put_user(dev->rcache, (int __user *)arg); + break; case BLKI2OGWSTRAT: - return put_user(dev->wcache, (int __user *)arg); + ret = put_user(dev->wcache, (int __user *)arg); + break; case BLKI2OSRSTRAT: + ret = -EINVAL; if (arg < 0 || arg > CACHE_SMARTFETCH) - return -EINVAL; + break; dev->rcache = arg; + ret = 0; break; case BLKI2OSWSTRAT: + ret = -EINVAL; if (arg != 0 && (arg < CACHE_WRITETHROUGH || arg > CACHE_SMARTBACK)) - return -EINVAL; + break; dev->wcache = arg; + ret = 0; break; } - return -ENOTTY; + unlock_kernel(); + + return ret; }; /** @@ -883,7 +898,7 @@ static void i2o_block_request_fn(struct request_queue *q) if (!req) break; - if (blk_fs_request(req)) { + if (req->cmd_type == REQ_TYPE_FS) { struct i2o_block_delayed_request *dreq; struct i2o_block_request *ireq = req->special; unsigned int queue_depth; @@ -930,7 +945,8 @@ static const struct block_device_operations i2o_block_fops = { .owner = THIS_MODULE, .open = i2o_block_open, .release = i2o_block_release, - .locked_ioctl = i2o_block_ioctl, + .ioctl = i2o_block_ioctl, + .compat_ioctl = i2o_block_ioctl, .getgeo = i2o_block_getgeo, .media_changed = i2o_block_media_changed }; diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index cb9fbc83b090..8433cde29c8b 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -29,6 +29,7 @@ #include <linux/kdev_t.h> #include <linux/blkdev.h> #include <linux/mutex.h> +#include <linux/smp_lock.h> #include <linux/scatterlist.h> #include <linux/string_helpers.h> @@ -107,6 +108,7 @@ static int mmc_blk_open(struct block_device *bdev, fmode_t mode) struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk); int ret = -ENXIO; + lock_kernel(); if (md) { if (md->usage == 2) check_disk_change(bdev); @@ -117,6 +119,7 @@ static int mmc_blk_open(struct block_device *bdev, fmode_t mode) ret = -EROFS; } } + unlock_kernel(); return ret; } @@ -125,7 +128,9 @@ static int mmc_blk_release(struct gendisk *disk, fmode_t mode) { struct mmc_blk_data *md = disk->private_data; + lock_kernel(); mmc_blk_put(md); + unlock_kernel(); return 0; } diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index d6ded247d941..c77eb49eda0e 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -32,7 +32,7 @@ static int mmc_prep_request(struct request_queue *q, struct request *req) /* * We only like normal block requests. */ - if (!blk_fs_request(req)) { + if (req->cmd_type != REQ_TYPE_FS) { blk_dump_rq_flags(req, "MMC bad request"); return BLKPREP_KILL; } @@ -128,7 +128,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock mq->req = NULL; blk_queue_prep_rq(mq->queue, mmc_prep_request); - blk_queue_ordered(mq->queue, QUEUE_ORDERED_DRAIN, NULL); + blk_queue_ordered(mq->queue, QUEUE_ORDERED_DRAIN); queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue); #ifdef CONFIG_MMC_BLOCK_BOUNCE diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 03e19c1965cc..5ca80aee2ed0 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -15,6 +15,7 @@ #include <linux/blkdev.h> #include <linux/blkpg.h> #include <linux/spinlock.h> +#include <linux/smp_lock.h> #include <linux/hdreg.h> #include <linux/init.h> #include <linux/mutex.h> @@ -73,14 +74,14 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr, buf = req->buffer; - if (!blk_fs_request(req)) + if (req->cmd_type != REQ_TYPE_FS) return -EIO; if (blk_rq_pos(req) + blk_rq_cur_sectors(req) > get_capacity(req->rq_disk)) return -EIO; - if (blk_discard_rq(req)) + if (req->cmd_flags & REQ_DISCARD) return tr->discard(dev, block, nsect); switch(rq_data_dir(req)) { @@ -164,8 +165,9 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode) int ret; if (!dev) - return -ERESTARTSYS; + return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/ + lock_kernel(); mutex_lock(&dev->lock); if (!dev->mtd) { @@ -182,6 +184,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode) unlock: mutex_unlock(&dev->lock); blktrans_dev_put(dev); + unlock_kernel(); return ret; } @@ -193,6 +196,7 @@ static int blktrans_release(struct gendisk *disk, fmode_t mode) if (!dev) return ret; + lock_kernel(); mutex_lock(&dev->lock); /* Release one reference, we sure its not the last one here*/ @@ -205,6 +209,7 @@ static int blktrans_release(struct gendisk *disk, fmode_t mode) unlock: mutex_unlock(&dev->lock); blktrans_dev_put(dev); + unlock_kernel(); return ret; } @@ -237,6 +242,7 @@ static int blktrans_ioctl(struct block_device *bdev, fmode_t mode, if (!dev) return ret; + lock_kernel(); mutex_lock(&dev->lock); if (!dev->mtd) @@ -250,6 +256,7 @@ static int blktrans_ioctl(struct block_device *bdev, fmode_t mode, } unlock: mutex_unlock(&dev->lock); + unlock_kernel(); blktrans_dev_put(dev); return ret; } @@ -258,7 +265,7 @@ static const struct block_device_operations mtd_blktrans_ops = { .owner = THIS_MODULE, .open = blktrans_open, .release = blktrans_release, - .locked_ioctl = blktrans_ioctl, + .ioctl = blktrans_ioctl, .getgeo = blktrans_getgeo, }; diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 33975e922d65..1a84fae155e1 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -21,6 +21,7 @@ #include <linux/hdreg.h> #include <linux/async.h> #include <linux/mutex.h> +#include <linux/smp_lock.h> #include <asm/ccwdev.h> #include <asm/ebcdic.h> @@ -2196,7 +2197,7 @@ static void dasd_setup_queue(struct dasd_block *block) */ blk_queue_max_segment_size(block->request_queue, PAGE_SIZE); blk_queue_segment_boundary(block->request_queue, PAGE_SIZE - 1); - blk_queue_ordered(block->request_queue, QUEUE_ORDERED_DRAIN, NULL); + blk_queue_ordered(block->request_queue, QUEUE_ORDERED_DRAIN); } /* @@ -2235,6 +2236,7 @@ static int dasd_open(struct block_device *bdev, fmode_t mode) if (!block) return -ENODEV; + lock_kernel(); base = block->base; atomic_inc(&block->open_count); if (test_bit(DASD_FLAG_OFFLINE, &base->flags)) { @@ -2269,12 +2271,14 @@ static int dasd_open(struct block_device *bdev, fmode_t mode) goto out; } + unlock_kernel(); return 0; out: module_put(base->discipline->owner); unlock: atomic_dec(&block->open_count); + unlock_kernel(); return rc; } @@ -2282,8 +2286,10 @@ static int dasd_release(struct gendisk *disk, fmode_t mode) { struct dasd_block *block = disk->private_data; + lock_kernel(); atomic_dec(&block->open_count); module_put(block->base->discipline->owner); + unlock_kernel(); return 0; } diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 9b43ae94beba..2bd72aa34c59 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -14,6 +14,7 @@ #include <linux/init.h> #include <linux/slab.h> #include <linux/blkdev.h> +#include <linux/smp_lock.h> #include <linux/completion.h> #include <linux/interrupt.h> #include <linux/platform_device.h> @@ -775,6 +776,7 @@ dcssblk_open(struct block_device *bdev, fmode_t mode) struct dcssblk_dev_info *dev_info; int rc; + lock_kernel(); dev_info = bdev->bd_disk->private_data; if (NULL == dev_info) { rc = -ENODEV; @@ -784,6 +786,7 @@ dcssblk_open(struct block_device *bdev, fmode_t mode) bdev->bd_block_size = 4096; rc = 0; out: + unlock_kernel(); return rc; } @@ -794,6 +797,7 @@ dcssblk_release(struct gendisk *disk, fmode_t mode) struct segment_info *entry; int rc; + lock_kernel(); if (!dev_info) { rc = -ENODEV; goto out; @@ -811,6 +815,7 @@ dcssblk_release(struct gendisk *disk, fmode_t mode) up_write(&dcssblk_devices_sem); rc = 0; out: + unlock_kernel(); return rc; } diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index 097da8ce6be6..b7de02525ec9 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c @@ -16,6 +16,7 @@ #include <linux/fs.h> #include <linux/module.h> #include <linux/blkdev.h> +#include <linux/smp_lock.h> #include <linux/interrupt.h> #include <linux/buffer_head.h> #include <linux/kernel.h> @@ -361,6 +362,7 @@ tapeblock_open(struct block_device *bdev, fmode_t mode) struct tape_device * device; int rc; + lock_kernel(); device = tape_get_device(disk->private_data); if (device->required_tapemarks) { @@ -384,12 +386,14 @@ tapeblock_open(struct block_device *bdev, fmode_t mode) * is called. */ tape_state_set(device, TS_BLKUSE); + unlock_kernel(); return 0; release: tape_release(device); put_device: tape_put_device(device); + unlock_kernel(); return rc; } @@ -403,10 +407,12 @@ static int tapeblock_release(struct gendisk *disk, fmode_t mode) { struct tape_device *device = disk->private_data; - + + lock_kernel(); tape_state_set(device, TS_IN_USE); tape_release(device); tape_put_device(device); + unlock_kernel(); return 0; } diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c index 2a8cf137f609..4f785f254c1f 100644 --- a/drivers/scsi/aha1542.c +++ b/drivers/scsi/aha1542.c @@ -52,22 +52,6 @@ #define SCSI_BUF_PA(address) isa_virt_to_bus(address) #define SCSI_SG_PA(sgent) (isa_page_to_bus(sg_page((sgent))) + (sgent)->offset) -static void BAD_SG_DMA(Scsi_Cmnd * SCpnt, - struct scatterlist *sgp, - int nseg, - int badseg) -{ - printk(KERN_CRIT "sgpnt[%d:%d] page %p/0x%llx length %u\n", - badseg, nseg, sg_virt(sgp), - (unsigned long long)SCSI_SG_PA(sgp), - sgp->length); - - /* - * Not safe to continue. - */ - panic("Buffer at physical address > 16Mb used for aha1542"); -} - #include<linux/stat.h> #ifdef DEBUG @@ -691,8 +675,6 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) } scsi_for_each_sg(SCpnt, sg, sg_count, i) { any2scsi(cptr[i].dataptr, SCSI_SG_PA(sg)); - if (SCSI_SG_PA(sg) + sg->length - 1 > ISA_DMA_THRESHOLD) - BAD_SG_DMA(SCpnt, scsi_sglist(SCpnt), sg_count, i); any2scsi(cptr[i].datalen, sg->length); }; any2scsi(ccb[mbo].datalen, sg_count * sizeof(struct chain)); @@ -1133,16 +1115,9 @@ static int __init aha1542_detect(struct scsi_host_template * tpnt) release_region(bases[indx], 4); continue; } - /* For now we do this - until kmalloc is more intelligent - we are resigned to stupid hacks like this */ - if (SCSI_BUF_PA(shpnt) >= ISA_DMA_THRESHOLD) { - printk(KERN_ERR "Invalid address for shpnt with 1542.\n"); - goto unregister; - } if (!aha1542_test_port(bases[indx], shpnt)) goto unregister; - base_io = bases[indx]; /* Set the Bus on/off-times as not to ruin floppy performance */ diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index ee4b6914667f..fda4de3440c4 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c @@ -716,7 +716,7 @@ static int _osd_req_list_objects(struct osd_request *or, return PTR_ERR(bio); } - bio->bi_rw &= ~(1 << BIO_RW); + bio->bi_rw &= ~REQ_WRITE; or->in.bio = bio; or->in.total_bytes = bio->bi_size; return 0; @@ -814,7 +814,7 @@ void osd_req_write(struct osd_request *or, { _osd_req_encode_common(or, OSD_ACT_WRITE, obj, offset, len); WARN_ON(or->out.bio || or->out.total_bytes); - WARN_ON(0 == bio_rw_flagged(bio, BIO_RW)); + WARN_ON(0 == (bio->bi_rw & REQ_WRITE)); or->out.bio = bio; or->out.total_bytes = len; } @@ -829,7 +829,7 @@ int osd_req_write_kern(struct osd_request *or, if (IS_ERR(bio)) return PTR_ERR(bio); - bio->bi_rw |= (1 << BIO_RW); /* FIXME: bio_set_dir() */ + bio->bi_rw |= REQ_WRITE; /* FIXME: bio_set_dir() */ osd_req_write(or, obj, offset, bio, len); return 0; } @@ -865,7 +865,7 @@ void osd_req_read(struct osd_request *or, { _osd_req_encode_common(or, OSD_ACT_READ, obj, offset, len); WARN_ON(or->in.bio || or->in.total_bytes); - WARN_ON(1 == bio_rw_flagged(bio, BIO_RW)); + WARN_ON(1 == (bio->bi_rw & REQ_WRITE)); or->in.bio = bio; or->in.total_bytes = len; } diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index a5d630f5f519..1b88af89d0c7 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -307,7 +307,7 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) (sshdr.asc == 0x04) && (sshdr.ascq == 0x02)) return FAILED; - if (blk_barrier_rq(scmd->request)) + if (scmd->request->cmd_flags & REQ_HARDBARRIER) /* * barrier requests should always retry on UA * otherwise block will get a spurious error @@ -1318,16 +1318,16 @@ int scsi_noretry_cmd(struct scsi_cmnd *scmd) case DID_OK: break; case DID_BUS_BUSY: - return blk_failfast_transport(scmd->request); + return (scmd->request->cmd_flags & REQ_FAILFAST_TRANSPORT); case DID_PARITY: - return blk_failfast_dev(scmd->request); + return (scmd->request->cmd_flags & REQ_FAILFAST_DEV); case DID_ERROR: if (msg_byte(scmd->result) == COMMAND_COMPLETE && status_byte(scmd->result) == RESERVATION_CONFLICT) return 0; /* fall through */ case DID_SOFT_ERROR: - return blk_failfast_driver(scmd->request); + return (scmd->request->cmd_flags & REQ_FAILFAST_DRIVER); } switch (status_byte(scmd->result)) { @@ -1336,7 +1336,7 @@ int scsi_noretry_cmd(struct scsi_cmnd *scmd) * assume caller has checked sense and determinted * the check condition was retryable. */ - return blk_failfast_dev(scmd->request); + return (scmd->request->cmd_flags & REQ_FAILFAST_DEV); } return 0; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 1646fe7cbd4b..b8de389636f8 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -85,7 +85,7 @@ static void scsi_unprep_request(struct request *req) { struct scsi_cmnd *cmd = req->special; - req->cmd_flags &= ~REQ_DONTPREP; + blk_unprep_request(req); req->special = NULL; scsi_put_command(cmd); @@ -722,7 +722,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) sense_deferred = scsi_sense_is_deferred(&sshdr); } - if (blk_pc_request(req)) { /* SG_IO ioctl from block level */ + if (req->cmd_type == REQ_TYPE_BLOCK_PC) { /* SG_IO ioctl from block level */ req->errors = result; if (result) { if (sense_valid && req->sense) { @@ -757,7 +757,8 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) } } - BUG_ON(blk_bidi_rq(req)); /* bidi not support for !blk_pc_request yet */ + /* no bidi support for !REQ_TYPE_BLOCK_PC yet */ + BUG_ON(blk_bidi_rq(req)); /* * Next deal with any sectors which we were able to correctly @@ -1010,11 +1011,8 @@ int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask) err_exit: scsi_release_buffers(cmd); - if (error == BLKPREP_KILL) - scsi_put_command(cmd); - else /* BLKPREP_DEFER */ - scsi_unprep_request(cmd->request); - + scsi_put_command(cmd); + cmd->request->special = NULL; return error; } EXPORT_SYMBOL(scsi_init_io); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 8802e48bc063..fc5d69a84af5 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -46,6 +46,7 @@ #include <linux/blkdev.h> #include <linux/blkpg.h> #include <linux/delay.h> +#include <linux/smp_lock.h> #include <linux/mutex.h> #include <linux/string_helpers.h> #include <linux/async.h> @@ -411,22 +412,26 @@ static void sd_prot_op(struct scsi_cmnd *scmd, unsigned int dif) } /** - * sd_prepare_discard - unmap blocks on thinly provisioned device + * scsi_setup_discard_cmnd - unmap blocks on thinly provisioned device + * @sdp: scsi device to operate one * @rq: Request to prepare * * Will issue either UNMAP or WRITE SAME(16) depending on preference * indicated by target device. **/ -static int sd_prepare_discard(struct request *rq) +static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) { struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); struct bio *bio = rq->bio; sector_t sector = bio->bi_sector; - unsigned int num = bio_sectors(bio); + unsigned int nr_sectors = bio_sectors(bio); + unsigned int len; + int ret; + struct page *page; if (sdkp->device->sector_size == 4096) { sector >>= 3; - num >>= 3; + nr_sectors >>= 3; } rq->cmd_type = REQ_TYPE_BLOCK_PC; @@ -434,31 +439,61 @@ static int sd_prepare_discard(struct request *rq) memset(rq->cmd, 0, rq->cmd_len); + page = alloc_page(GFP_ATOMIC | __GFP_ZERO); + if (!page) + return BLKPREP_DEFER; + if (sdkp->unmap) { - char *buf = kmap_atomic(bio_page(bio), KM_USER0); + char *buf = page_address(page); + rq->cmd_len = 10; rq->cmd[0] = UNMAP; rq->cmd[8] = 24; - rq->cmd_len = 10; - - /* Ensure that data length matches payload */ - rq->__data_len = bio->bi_size = bio->bi_io_vec->bv_len = 24; put_unaligned_be16(6 + 16, &buf[0]); put_unaligned_be16(16, &buf[2]); put_unaligned_be64(sector, &buf[8]); - put_unaligned_be32(num, &buf[16]); + put_unaligned_be32(nr_sectors, &buf[16]); - kunmap_atomic(buf, KM_USER0); + len = 24; } else { + rq->cmd_len = 16; rq->cmd[0] = WRITE_SAME_16; rq->cmd[1] = 0x8; /* UNMAP */ put_unaligned_be64(sector, &rq->cmd[2]); - put_unaligned_be32(num, &rq->cmd[10]); - rq->cmd_len = 16; + put_unaligned_be32(nr_sectors, &rq->cmd[10]); + + len = sdkp->device->sector_size; } - return BLKPREP_OK; + blk_add_request_payload(rq, page, len); + ret = scsi_setup_blk_pc_cmnd(sdp, rq); + rq->buffer = page_address(page); + if (ret != BLKPREP_OK) { + __free_page(page); + rq->buffer = NULL; + } + return ret; +} + +static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq) +{ + /* for now, we use REQ_TYPE_BLOCK_PC. */ + rq->cmd_type = REQ_TYPE_BLOCK_PC; + rq->timeout = SD_TIMEOUT; + rq->retries = SD_MAX_RETRIES; + rq->cmd[0] = SYNCHRONIZE_CACHE; + rq->cmd_len = 10; + + return scsi_setup_blk_pc_cmnd(sdp, rq); +} + +static void sd_unprep_fn(struct request_queue *q, struct request *rq) +{ + if (rq->cmd_flags & REQ_DISCARD) { + free_page((unsigned long)rq->buffer); + rq->buffer = NULL; + } } /** @@ -485,10 +520,13 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) * Discard request come in as REQ_TYPE_FS but we turn them into * block PC requests to make life easier. */ - if (blk_discard_rq(rq)) - ret = sd_prepare_discard(rq); - - if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { + if (rq->cmd_flags & REQ_DISCARD) { + ret = scsi_setup_discard_cmnd(sdp, rq); + goto out; + } else if (rq->cmd_flags & REQ_FLUSH) { + ret = scsi_setup_flush_cmnd(sdp, rq); + goto out; + } else if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { ret = scsi_setup_blk_pc_cmnd(sdp, rq); goto out; } else if (rq->cmd_type != REQ_TYPE_FS) { @@ -636,7 +674,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) SCpnt->cmnd[0] = VARIABLE_LENGTH_CMD; SCpnt->cmnd[7] = 0x18; SCpnt->cmnd[9] = (rq_data_dir(rq) == READ) ? READ_32 : WRITE_32; - SCpnt->cmnd[10] = protect | (blk_fua_rq(rq) ? 0x8 : 0); + SCpnt->cmnd[10] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0); /* LBA */ SCpnt->cmnd[12] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0; @@ -661,7 +699,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) SCpnt->cmnd[31] = (unsigned char) this_count & 0xff; } else if (block > 0xffffffff) { SCpnt->cmnd[0] += READ_16 - READ_6; - SCpnt->cmnd[1] = protect | (blk_fua_rq(rq) ? 0x8 : 0); + SCpnt->cmnd[1] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0); SCpnt->cmnd[2] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0; SCpnt->cmnd[3] = sizeof(block) > 4 ? (unsigned char) (block >> 48) & 0xff : 0; SCpnt->cmnd[4] = sizeof(block) > 4 ? (unsigned char) (block >> 40) & 0xff : 0; @@ -682,7 +720,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) this_count = 0xffff; SCpnt->cmnd[0] += READ_10 - READ_6; - SCpnt->cmnd[1] = protect | (blk_fua_rq(rq) ? 0x8 : 0); + SCpnt->cmnd[1] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0); SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff; SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff; SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff; @@ -691,7 +729,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff; SCpnt->cmnd[8] = (unsigned char) this_count & 0xff; } else { - if (unlikely(blk_fua_rq(rq))) { + if (unlikely(rq->cmd_flags & REQ_FUA)) { /* * This happens only if this drive failed * 10byte rw command with ILLEGAL_REQUEST @@ -745,6 +783,8 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) * or from within the kernel (e.g. as a result of a mount(1) ). * In the latter case @inode and @filp carry an abridged amount * of information as noted above. + * + * Locking: called with bdev->bd_mutex held. **/ static int sd_open(struct block_device *bdev, fmode_t mode) { @@ -795,7 +835,7 @@ static int sd_open(struct block_device *bdev, fmode_t mode) if (!scsi_device_online(sdev)) goto error_out; - if (!sdkp->openers++ && sdev->removable) { + if ((atomic_inc_return(&sdkp->openers) == 1) && sdev->removable) { if (scsi_block_when_processing_errors(sdev)) scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT); } @@ -817,6 +857,8 @@ error_out: * * Note: may block (uninterruptible) if error recovery is underway * on this disk. + * + * Locking: called with bdev->bd_mutex held. **/ static int sd_release(struct gendisk *disk, fmode_t mode) { @@ -825,7 +867,7 @@ static int sd_release(struct gendisk *disk, fmode_t mode) SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_release\n")); - if (!--sdkp->openers && sdev->removable) { + if (atomic_dec_return(&sdkp->openers) && sdev->removable) { if (scsi_block_when_processing_errors(sdev)) scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW); } @@ -896,7 +938,7 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, error = scsi_nonblockable_ioctl(sdp, cmd, p, (mode & FMODE_NDELAY) != 0); if (!scsi_block_when_processing_errors(sdp) || !error) - return error; + goto out; /* * Send SCSI addressing ioctls directly to mid level, send other @@ -906,13 +948,17 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, switch (cmd) { case SCSI_IOCTL_GET_IDLUN: case SCSI_IOCTL_GET_BUS_NUMBER: - return scsi_ioctl(sdp, cmd, p); + error = scsi_ioctl(sdp, cmd, p); + break; default: error = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, p); if (error != -ENOTTY) - return error; + break; + error = scsi_ioctl(sdp, cmd, p); + break; } - return scsi_ioctl(sdp, cmd, p); +out: + return error; } static void set_media_not_present(struct scsi_disk *sdkp) @@ -1037,15 +1083,6 @@ static int sd_sync_cache(struct scsi_disk *sdkp) return 0; } -static void sd_prepare_flush(struct request_queue *q, struct request *rq) -{ - rq->cmd_type = REQ_TYPE_BLOCK_PC; - rq->timeout = SD_TIMEOUT; - rq->retries = SD_MAX_RETRIES; - rq->cmd[0] = SYNCHRONIZE_CACHE; - rq->cmd_len = 10; -} - static void sd_rescan(struct device *dev) { struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); @@ -1095,7 +1132,7 @@ static const struct block_device_operations sd_fops = { .owner = THIS_MODULE, .open = sd_open, .release = sd_release, - .locked_ioctl = sd_ioctl, + .ioctl = sd_ioctl, .getgeo = sd_getgeo, #ifdef CONFIG_COMPAT .compat_ioctl = sd_compat_ioctl, @@ -1112,7 +1149,7 @@ static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd) u64 bad_lba; int info_valid; - if (!blk_fs_request(scmd->request)) + if (scmd->request->cmd_type != REQ_TYPE_FS) return 0; info_valid = scsi_get_sense_info_fld(scmd->sense_buffer, @@ -2113,7 +2150,7 @@ static int sd_revalidate_disk(struct gendisk *disk) else ordered = QUEUE_ORDERED_DRAIN; - blk_queue_ordered(sdkp->disk->queue, ordered, sd_prepare_flush); + blk_queue_ordered(sdkp->disk->queue, ordered); set_capacity(disk, sdkp->capacity); kfree(buffer); @@ -2226,6 +2263,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie) sd_revalidate_disk(gd); blk_queue_prep_rq(sdp->request_queue, sd_prep_fn); + blk_queue_unprep_rq(sdp->request_queue, sd_unprep_fn); gd->driverfs_dev = &sdp->sdev_gendev; gd->flags = GENHD_FL_EXT_DEVT; @@ -2305,7 +2343,7 @@ static int sd_probe(struct device *dev) sdkp->driver = &sd_template; sdkp->disk = gd; sdkp->index = index; - sdkp->openers = 0; + atomic_set(&sdkp->openers, 0); sdkp->previous_state = 1; if (!sdp->request_queue->rq_timeout) { @@ -2361,6 +2399,7 @@ static int sd_remove(struct device *dev) async_synchronize_full(); sdkp = dev_get_drvdata(dev); blk_queue_prep_rq(sdkp->device->request_queue, scsi_prep_fn); + blk_queue_unprep_rq(sdkp->device->request_queue, NULL); device_del(&sdkp->dev); del_gendisk(sdkp->disk); sd_shutdown(dev); diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 43d3caf268ef..f81a9309e6de 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -47,7 +47,7 @@ struct scsi_disk { struct scsi_device *device; struct device dev; struct gendisk *disk; - unsigned int openers; /* protected by BKL for now, yuck */ + atomic_t openers; sector_t capacity; /* size in 512-byte sectors */ u32 index; unsigned short hw_sector_size; diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 0a90abc7f140..ba9c3e0387ce 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -44,6 +44,7 @@ #include <linux/init.h> #include <linux/blkdev.h> #include <linux/mutex.h> +#include <linux/smp_lock.h> #include <linux/slab.h> #include <asm/uaccess.h> @@ -466,22 +467,27 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq) static int sr_block_open(struct block_device *bdev, fmode_t mode) { - struct scsi_cd *cd = scsi_cd_get(bdev->bd_disk); + struct scsi_cd *cd; int ret = -ENXIO; + lock_kernel(); + cd = scsi_cd_get(bdev->bd_disk); if (cd) { ret = cdrom_open(&cd->cdi, bdev, mode); if (ret) scsi_cd_put(cd); } + unlock_kernel(); return ret; } static int sr_block_release(struct gendisk *disk, fmode_t mode) { struct scsi_cd *cd = scsi_cd(disk); + lock_kernel(); cdrom_release(&cd->cdi, mode); scsi_cd_put(cd); + unlock_kernel(); return 0; } @@ -493,6 +499,8 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, void __user *argp = (void __user *)arg; int ret; + lock_kernel(); + /* * Send SCSI addressing ioctls directly to mid level, send other * ioctls to cdrom/block level. @@ -500,12 +508,13 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, switch (cmd) { case SCSI_IOCTL_GET_IDLUN: case SCSI_IOCTL_GET_BUS_NUMBER: - return scsi_ioctl(sdev, cmd, argp); + ret = scsi_ioctl(sdev, cmd, argp); + goto out; } ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg); if (ret != -ENOSYS) - return ret; + goto out; /* * ENODEV means that we didn't recognise the ioctl, or that we @@ -516,8 +525,12 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, ret = scsi_nonblockable_ioctl(sdev, cmd, argp, (mode & FMODE_NDELAY) != 0); if (ret != -ENODEV) - return ret; - return scsi_ioctl(sdev, cmd, argp); + goto out; + ret = scsi_ioctl(sdev, cmd, argp); + +out: + unlock_kernel(); + return ret; } static int sr_block_media_changed(struct gendisk *disk) @@ -531,7 +544,7 @@ static const struct block_device_operations sr_bdops = .owner = THIS_MODULE, .open = sr_block_open, .release = sr_block_release, - .locked_ioctl = sr_block_ioctl, + .ioctl = sr_block_ioctl, .media_changed = sr_block_media_changed, /* * No compat_ioctl for now because sr_block_ioctl never diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c index b5838d547c68..713620ed70d9 100644 --- a/drivers/scsi/sun3_NCR5380.c +++ b/drivers/scsi/sun3_NCR5380.c @@ -2022,7 +2022,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) if((count > SUN3_DMA_MINSIZE) && (sun3_dma_setup_done != cmd)) { - if(blk_fs_request(cmd->request)) { + if (cmd->request->cmd_type == REQ_TYPE_FS) { sun3scsi_dma_setup(d, count, rq_data_dir(cmd->request)); sun3_dma_setup_done = cmd; diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index e606cf0a2eb7..613f5880d135 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -524,7 +524,7 @@ static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted, struct scsi_cmnd *cmd, int write_flag) { - if(blk_fs_request(cmd->request)) + if (cmd->request->cmd_type == REQ_TYPE_FS) return wanted; else return 0; diff --git a/drivers/scsi/sun3_scsi_vme.c b/drivers/scsi/sun3_scsi_vme.c index aaa4fd0dd1b9..7c526b8e30ac 100644 --- a/drivers/scsi/sun3_scsi_vme.c +++ b/drivers/scsi/sun3_scsi_vme.c @@ -458,7 +458,7 @@ static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted, struct scsi_cmnd *cmd, int write_flag) { - if(blk_fs_request(cmd->request)) + if (cmd->request->cmd_type == REQ_TYPE_FS) return wanted; else return 0; diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c index 61bd0be5fb18..87a11c9293e9 100644 --- a/drivers/staging/hv/blkvsc_drv.c +++ b/drivers/staging/hv/blkvsc_drv.c @@ -25,6 +25,7 @@ #include <linux/major.h> #include <linux/delay.h> #include <linux/hdreg.h> +#include <linux/smp_lock.h> #include <linux/slab.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> @@ -823,7 +824,8 @@ static void blkvsc_init_rw(struct blkvsc_request *blkvsc_req) blkvsc_req->cmnd[0] = READ_16; } - blkvsc_req->cmnd[1] |= blk_fua_rq(blkvsc_req->req) ? 0x8 : 0; + blkvsc_req->cmnd[1] |= + (blkvsc_req->req->cmd_flags & REQ_FUA) ? 0x8 : 0; *(unsigned long long *)&blkvsc_req->cmnd[2] = cpu_to_be64(blkvsc_req->sector_start); @@ -839,7 +841,8 @@ static void blkvsc_init_rw(struct blkvsc_request *blkvsc_req) blkvsc_req->cmnd[0] = READ_10; } - blkvsc_req->cmnd[1] |= blk_fua_rq(blkvsc_req->req) ? 0x8 : 0; + blkvsc_req->cmnd[1] |= + (blkvsc_req->req->cmd_flags & REQ_FUA) ? 0x8 : 0; *(unsigned int *)&blkvsc_req->cmnd[2] = cpu_to_be32(blkvsc_req->sector_start); @@ -1286,7 +1289,7 @@ static void blkvsc_request(struct request_queue *queue) DPRINT_DBG(BLKVSC_DRV, "- req %p\n", req); blkdev = req->rq_disk->private_data; - if (blkdev->shutting_down || !blk_fs_request(req) || + if (blkdev->shutting_down || req->cmd_type != REQ_TYPE_FS || blkdev->media_not_present) { __blk_end_request_cur(req, 0); continue; @@ -1324,6 +1327,7 @@ static int blkvsc_open(struct block_device *bdev, fmode_t mode) DPRINT_DBG(BLKVSC_DRV, "- users %d disk %s\n", blkdev->users, blkdev->gd->disk_name); + lock_kernel(); spin_lock(&blkdev->lock); if (!blkdev->users && blkdev->device_type == DVD_TYPE) { @@ -1335,6 +1339,7 @@ static int blkvsc_open(struct block_device *bdev, fmode_t mode) blkdev->users++; spin_unlock(&blkdev->lock); + unlock_kernel(); return 0; } @@ -1345,6 +1350,7 @@ static int blkvsc_release(struct gendisk *disk, fmode_t mode) DPRINT_DBG(BLKVSC_DRV, "- users %d disk %s\n", blkdev->users, blkdev->gd->disk_name); + lock_kernel(); spin_lock(&blkdev->lock); if (blkdev->users == 1) { spin_unlock(&blkdev->lock); @@ -1355,6 +1361,7 @@ static int blkvsc_release(struct gendisk *disk, fmode_t mode) blkdev->users--; spin_unlock(&blkdev->lock); + unlock_kernel(); return 0; } |