diff options
| author | Linus Torvalds <torvalds@home.transmeta.com> | 2002-10-17 21:02:57 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2002-10-17 21:02:57 -0700 |
| commit | d103bdbf34d5ab76a92fc0d1a4aae7b1af5c8493 (patch) | |
| tree | 06a02f574b4a3fc284d036a319271eac3be40a47 | |
| parent | c055ad89ad3cd9e2a0da51307212517226a929f7 (diff) | |
| parent | 0aa8a47e7eb0ec3e23fcb27c7eac5e4d9dcf3ef9 (diff) | |
Merge Al/Jens clashes
| -rw-r--r-- | drivers/block/ll_rw_blk.c | 24 | ||||
| -rw-r--r-- | drivers/cdrom/cdrom.c | 6 | ||||
| -rw-r--r-- | drivers/ide/ide-cd.c | 7 | ||||
| -rw-r--r-- | drivers/scsi/scsi_lib.c | 4 | ||||
| -rw-r--r-- | drivers/scsi/scsi_merge.c | 19 | ||||
| -rw-r--r-- | drivers/scsi/sd.c | 45 | ||||
| -rw-r--r-- | drivers/scsi/sr.c | 29 | ||||
| -rw-r--r-- | include/linux/blkdev.h | 1 |
8 files changed, 106 insertions, 29 deletions
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index eb877e50a8d1..c5697e05a6b8 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -670,12 +670,10 @@ void blk_dump_rq_flags(struct request *rq, char *msg) bit++; } while (bit < __REQ_NR_BITS); - if (rq->flags & REQ_CMD) - printk("sector %llu, nr/cnr %lu/%u\n", (unsigned long long)rq->sector, + printk("sector %llu, nr/cnr %lu/%u\n", (unsigned long long)rq->sector, rq->nr_sectors, rq->current_nr_sectors); - - printk("\n"); + printk("bio %p, biotail %p\n", rq->bio, rq->biotail); } void blk_recount_segments(request_queue_t *q, struct bio *bio) @@ -1927,7 +1925,7 @@ inline void blk_recalc_rq_segments(struct request *rq) inline void blk_recalc_rq_sectors(struct request *rq, int nsect) { - if (rq->flags & REQ_CMD) { + if (rq->bio) { rq->hard_sector += nsect; rq->nr_sectors = rq->hard_nr_sectors -= nsect; rq->sector = rq->hard_sector; @@ -1968,20 +1966,28 @@ int end_that_request_first(struct request *req, int uptodate, int nr_sectors) req->errors = 0; if (!uptodate) { - printk("end_request: I/O error, dev %s, sector %llu\n", - kdevname(req->rq_dev), (unsigned long long)req->sector); error = -EIO; + if (!(req->flags & REQ_QUIET)) + printk("end_request: I/O error, dev %s, sector %llu\n", + kdevname(req->rq_dev), + (unsigned long long)req->sector); } while ((bio = req->bio)) { - const int nsect = bio_iovec(bio)->bv_len >> 9; - int new_bio = 0; + int new_bio = 0, nsect; + + if (unlikely(bio->bi_idx >= bio->bi_vcnt)) { + printk("%s: bio idx %d >= vcnt %d\n", __FUNCTION__, + bio->bi_idx, bio->bi_vcnt); + break; + } BIO_BUG_ON(bio_iovec(bio)->bv_len > bio->bi_size); /* * not a complete bvec done */ + nsect = bio_iovec(bio)->bv_len >> 9; if (unlikely(nsect > nr_sectors)) { int partial = nr_sectors << 9; diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index ee0ff76e153c..a4f52acc1e9e 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -267,6 +267,7 @@ #include <linux/blkpg.h> #include <linux/init.h> #include <linux/fcntl.h> +#include <linux/blkdev.h> #include <asm/uaccess.h> @@ -1436,6 +1437,11 @@ int cdrom_ioctl(struct cdrom_device_info *cdi, struct inode *ip, struct cdrom_device_ops *cdo = cdi->ops; int ret; + /* Try the generic SCSI command ioctl's first.. */ + ret = scsi_cmd_ioctl(ip->i_bdev, cmd, arg); + if (ret != -ENOTTY) + return ret; + /* the first few commands do not deal with audio drive_info, but only with routines in cdrom device operations. */ switch (cmd) { diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index ccb51d03e809..864053a676dd 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -3026,14 +3026,7 @@ int ide_cdrom_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) { struct cdrom_info *info = drive->driver_data; - int error; - /* Try the generic SCSI command ioctl's first.. */ - error = scsi_cmd_ioctl(inode->i_bdev, cmd, arg); - if (error != -ENOTTY) - return error; - - /* Then the generic cdrom ioctl's.. */ return cdrom_ioctl(&info->devinfo, inode, cmd, arg); } diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index a73a677e6818..dfa18e0c0eb9 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -857,7 +857,7 @@ void scsi_request_fn(request_queue_t * q) scsi_init_cmd_from_req(SCpnt, SRpnt); } - } else if (req->flags & REQ_CMD) { + } else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) { SRpnt = NULL; STpnt = scsi_get_request_dev(req); if (!STpnt) { @@ -919,7 +919,7 @@ void scsi_request_fn(request_queue_t * q) req = NULL; spin_unlock_irq(q->queue_lock); - if (SCpnt->request->flags & REQ_CMD) { + if (SCpnt->request->flags & (REQ_CMD | REQ_BLOCK_PC)) { /* * This will do a couple of things: * 1) Fill in the actual SCSI command. diff --git a/drivers/scsi/scsi_merge.c b/drivers/scsi/scsi_merge.c index 980d7047e6e9..ac79b081270c 100644 --- a/drivers/scsi/scsi_merge.c +++ b/drivers/scsi/scsi_merge.c @@ -62,16 +62,28 @@ int scsi_init_io(Scsi_Cmnd *SCpnt) int count, gfp_mask; /* - * First we need to know how many scatter gather segments are needed. + * non-sg block request. FIXME: check bouncing for isa hosts! */ - count = req->nr_phys_segments; + if ((req->flags & REQ_BLOCK_PC) && !req->bio) { + /* + * FIXME: isa bouncing + */ + if (SCpnt->host->unchecked_isa_dma) + goto fail; + + SCpnt->request_bufflen = req->data_len; + SCpnt->request_buffer = req->data; + req->buffer = req->data; + SCpnt->use_sg = 0; + return 1; + } /* * we used to not use scatter-gather for single segment request, * but now we do (it makes highmem I/O easier to support without * kmapping pages) */ - SCpnt->use_sg = count; + SCpnt->use_sg = req->nr_phys_segments; gfp_mask = GFP_NOIO; if (in_interrupt()) { @@ -111,6 +123,7 @@ int scsi_init_io(Scsi_Cmnd *SCpnt) /* * kill it. there should be no leftover blocks in this request */ +fail: SCpnt = scsi_end_request(SCpnt, 0, req->nr_sectors); BUG_ON(SCpnt); return 0; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 32300bedc779..f3c9f9a920b7 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -191,6 +191,7 @@ static int sd_ioctl(struct inode * inode, struct file * filp, Scsi_Device *sdp = sdkp->device; struct Scsi_Host *host; int diskinfo[4]; + int error; SCSI_LOG_IOCTL(1, printk("sd_ioctl: disk=%s, cmd=0x%x\n", disk->disk_name, cmd)); @@ -206,6 +207,10 @@ static int sd_ioctl(struct inode * inode, struct file * filp, if( !scsi_block_when_processing_errors(sdp) ) return -ENODEV; + error = scsi_cmd_ioctl(inode->i_bdev, cmd, arg); + if (error != -ENOTTY) + return error; + switch (cmd) { case HDIO_GETGEO: /* Return BIOS disk parameters */ @@ -273,12 +278,41 @@ static struct gendisk **sd_disks; **/ static int sd_init_command(Scsi_Cmnd * SCpnt) { - int this_count; + int this_count, timeout; struct gendisk *disk; sector_t block; - Scsi_Device *sdp; + Scsi_Device *sdp = SCpnt->device; + + timeout = SD_TIMEOUT; + if (SCpnt->device->type != TYPE_DISK) + timeout = SD_MOD_TIMEOUT; + + /* + * these are already setup, just copy cdb basically + */ + if (SCpnt->request->flags & REQ_BLOCK_PC) { + struct request *rq = SCpnt->request; + + if (sizeof(rq->cmd) > sizeof(SCpnt->cmnd)) + return 0; + + memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd)); + if (rq_data_dir(rq) == WRITE) + SCpnt->sc_data_direction = SCSI_DATA_WRITE; + else if (rq->data_len) + SCpnt->sc_data_direction = SCSI_DATA_READ; + else + SCpnt->sc_data_direction = SCSI_DATA_NONE; + + this_count = rq->data_len; + if (rq->timeout) + timeout = rq->timeout; + + goto queue; + } + /* - * don't support specials for nwo + * we only do REQ_CMD and REQ_BLOCK_PC */ if (!(SCpnt->request->flags & REQ_CMD)) return 0; @@ -290,7 +324,6 @@ static int sd_init_command(Scsi_Cmnd * SCpnt) SCSI_LOG_HLQUEUE(1, printk("sd_command_init: disk=%s, block=%llu, " "count=%d\n", disk->disk_name, (unsigned long long)block, this_count)); - sdp = SCpnt->device; if (!sdp || !sdp->online || block + SCpnt->request->nr_sectors > get_capacity(disk)) { SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n", @@ -398,12 +431,12 @@ static int sd_init_command(Scsi_Cmnd * SCpnt) * host adapter, it's safe to assume that we can at least transfer * this many bytes between each connect / disconnect. */ +queue: SCpnt->transfersize = sdp->sector_size; SCpnt->underflow = this_count << 9; SCpnt->allowed = MAX_RETRIES; - SCpnt->timeout_per_command = (SCpnt->device->type == TYPE_DISK ? - SD_TIMEOUT : SD_MOD_TIMEOUT); + SCpnt->timeout_per_command = timeout; /* * This is the completion routine we use. This is matched in terms diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 5c0a4bd0a9df..6942bcc4ff56 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -247,7 +247,7 @@ static void rw_intr(Scsi_Cmnd * SCpnt) static int sr_init_command(Scsi_Cmnd * SCpnt) { - int block=0, this_count, s_size; + int block=0, this_count, s_size, timeout = SR_TIMEOUT; Scsi_CD *cd = SCpnt->request->rq_disk->private_data; SCSI_LOG_HLQUEUE(1, printk("Doing sr request, dev = %s, block = %d\n", disk->disk_name, block)); @@ -266,6 +266,30 @@ static int sr_init_command(Scsi_Cmnd * SCpnt) return 0; } + /* + * these are already setup, just copy cdb basically + */ + if (SCpnt->request->flags & REQ_BLOCK_PC) { + struct request *rq = SCpnt->request; + + if (sizeof(rq->cmd) > sizeof(SCpnt->cmnd)) + return 0; + + memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd)); + if (rq_data_dir(rq) == WRITE) + SCpnt->sc_data_direction = SCSI_DATA_WRITE; + else if (rq->data_len) + SCpnt->sc_data_direction = SCSI_DATA_READ; + else + SCpnt->sc_data_direction = SCSI_DATA_NONE; + + this_count = rq->data_len; + if (rq->timeout) + timeout = rq->timeout; + + goto queue; + } + if (!(SCpnt->request->flags & REQ_CMD)) { blk_dump_rq_flags(SCpnt->request, "sr unsup command"); return 0; @@ -336,11 +360,12 @@ static int sr_init_command(Scsi_Cmnd * SCpnt) * host adapter, it's safe to assume that we can at least transfer * this many bytes between each connect / disconnect. */ +queue: SCpnt->transfersize = cd->device->sector_size; SCpnt->underflow = this_count << 9; SCpnt->allowed = MAX_RETRIES; - SCpnt->timeout_per_command = SR_TIMEOUT; + SCpnt->timeout_per_command = timeout; /* * This is the completion routine we use. This is matched in terms diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index ccb56d58de6a..42e81a4a0cab 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -235,6 +235,7 @@ struct request_queue #define blk_queue_tagged(q) test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags) #define blk_queue_empty(q) elv_queue_empty(q) #define blk_fs_request(rq) ((rq)->flags & REQ_CMD) +#define blk_pc_request(rq) ((rq)->flags & REQ_BLOCK_PC) #define list_entry_rq(ptr) list_entry((ptr), struct request, queuelist) #define rq_data_dir(rq) ((rq)->flags & 1) |
