summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.transmeta.com>2002-10-17 21:02:57 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2002-10-17 21:02:57 -0700
commitd103bdbf34d5ab76a92fc0d1a4aae7b1af5c8493 (patch)
tree06a02f574b4a3fc284d036a319271eac3be40a47
parentc055ad89ad3cd9e2a0da51307212517226a929f7 (diff)
parent0aa8a47e7eb0ec3e23fcb27c7eac5e4d9dcf3ef9 (diff)
Merge Al/Jens clashes
-rw-r--r--drivers/block/ll_rw_blk.c24
-rw-r--r--drivers/cdrom/cdrom.c6
-rw-r--r--drivers/ide/ide-cd.c7
-rw-r--r--drivers/scsi/scsi_lib.c4
-rw-r--r--drivers/scsi/scsi_merge.c19
-rw-r--r--drivers/scsi/sd.c45
-rw-r--r--drivers/scsi/sr.c29
-rw-r--r--include/linux/blkdev.h1
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)