Commit 414633a6 authored by Jens Axboe's avatar Jens Axboe

[PATCH] make SCSI understand REQ_BLOCK_PC

Make SCSI layer understand REQ_BLOCK_PC requests
parent 5a7728c6
...@@ -857,7 +857,7 @@ void scsi_request_fn(request_queue_t * q) ...@@ -857,7 +857,7 @@ void scsi_request_fn(request_queue_t * q)
scsi_init_cmd_from_req(SCpnt, SRpnt); scsi_init_cmd_from_req(SCpnt, SRpnt);
} }
} else if (req->flags & REQ_CMD) { } else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
SRpnt = NULL; SRpnt = NULL;
STpnt = scsi_get_request_dev(req); STpnt = scsi_get_request_dev(req);
if (!STpnt) { if (!STpnt) {
...@@ -919,7 +919,7 @@ void scsi_request_fn(request_queue_t * q) ...@@ -919,7 +919,7 @@ void scsi_request_fn(request_queue_t * q)
req = NULL; req = NULL;
spin_unlock_irq(q->queue_lock); 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: * This will do a couple of things:
* 1) Fill in the actual SCSI command. * 1) Fill in the actual SCSI command.
......
...@@ -62,16 +62,28 @@ int scsi_init_io(Scsi_Cmnd *SCpnt) ...@@ -62,16 +62,28 @@ int scsi_init_io(Scsi_Cmnd *SCpnt)
int count, gfp_mask; 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, * we used to not use scatter-gather for single segment request,
* but now we do (it makes highmem I/O easier to support without * but now we do (it makes highmem I/O easier to support without
* kmapping pages) * kmapping pages)
*/ */
SCpnt->use_sg = count; SCpnt->use_sg = req->nr_phys_segments;
gfp_mask = GFP_NOIO; gfp_mask = GFP_NOIO;
if (in_interrupt()) { if (in_interrupt()) {
...@@ -111,6 +123,7 @@ int scsi_init_io(Scsi_Cmnd *SCpnt) ...@@ -111,6 +123,7 @@ int scsi_init_io(Scsi_Cmnd *SCpnt)
/* /*
* kill it. there should be no leftover blocks in this request * kill it. there should be no leftover blocks in this request
*/ */
fail:
SCpnt = scsi_end_request(SCpnt, 0, req->nr_sectors); SCpnt = scsi_end_request(SCpnt, 0, req->nr_sectors);
BUG_ON(SCpnt); BUG_ON(SCpnt);
return 0; return 0;
......
...@@ -193,6 +193,7 @@ static int sd_ioctl(struct inode * inode, struct file * filp, ...@@ -193,6 +193,7 @@ static int sd_ioctl(struct inode * inode, struct file * filp,
Scsi_Device * sdp; Scsi_Device * sdp;
int diskinfo[4]; int diskinfo[4];
int dsk_nr = DEVICE_NR(dev); int dsk_nr = DEVICE_NR(dev);
int error;
SCSI_LOG_IOCTL(1, printk("sd_ioctl: dsk_nr=%d, cmd=0x%x\n", SCSI_LOG_IOCTL(1, printk("sd_ioctl: dsk_nr=%d, cmd=0x%x\n",
dsk_nr, cmd)); dsk_nr, cmd));
...@@ -209,6 +210,10 @@ static int sd_ioctl(struct inode * inode, struct file * filp, ...@@ -209,6 +210,10 @@ static int sd_ioctl(struct inode * inode, struct file * filp,
if( !scsi_block_when_processing_errors(sdp) ) if( !scsi_block_when_processing_errors(sdp) )
return -ENODEV; return -ENODEV;
error = scsi_cmd_ioctl(inode->i_bdev, cmd, arg);
if (error != -ENOTTY)
return error;
switch (cmd) switch (cmd)
{ {
case HDIO_GETGEO: /* Return BIOS disk parameters */ case HDIO_GETGEO: /* Return BIOS disk parameters */
...@@ -299,14 +304,43 @@ static struct gendisk **sd_disks; ...@@ -299,14 +304,43 @@ static struct gendisk **sd_disks;
**/ **/
static int sd_init_command(Scsi_Cmnd * SCpnt) static int sd_init_command(Scsi_Cmnd * SCpnt)
{ {
int dsk_nr, part_nr, this_count; int dsk_nr, part_nr, this_count, timeout;
sector_t block; sector_t block;
Scsi_Device *sdp; Scsi_Device *sdp = SCpnt->device;
#if CONFIG_SCSI_LOGGING #if CONFIG_SCSI_LOGGING
char nbuff[6]; char nbuff[6];
#endif #endif
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)) if (!(SCpnt->request->flags & REQ_CMD))
return 0; return 0;
...@@ -320,7 +354,6 @@ static int sd_init_command(Scsi_Cmnd * SCpnt) ...@@ -320,7 +354,6 @@ static int sd_init_command(Scsi_Cmnd * SCpnt)
SCSI_LOG_HLQUEUE(1, printk("sd_command_init: dsk_nr=%d, block=%llu, " SCSI_LOG_HLQUEUE(1, printk("sd_command_init: dsk_nr=%d, block=%llu, "
"count=%d\n", dsk_nr, (unsigned long long)block, this_count)); "count=%d\n", dsk_nr, (unsigned long long)block, this_count));
sdp = SCpnt->device;
/* >>>>> the "(part_nr & 0xf)" excludes 15th partition, why?? */ /* >>>>> the "(part_nr & 0xf)" excludes 15th partition, why?? */
/* >>>>> this change is not in the lk 2.5 series */ /* >>>>> this change is not in the lk 2.5 series */
if (part_nr >= (sd_template.dev_max << 4) || (part_nr & 0xf) || if (part_nr >= (sd_template.dev_max << 4) || (part_nr & 0xf) ||
...@@ -433,12 +466,12 @@ static int sd_init_command(Scsi_Cmnd * SCpnt) ...@@ -433,12 +466,12 @@ static int sd_init_command(Scsi_Cmnd * SCpnt)
* host adapter, it's safe to assume that we can at least transfer * host adapter, it's safe to assume that we can at least transfer
* this many bytes between each connect / disconnect. * this many bytes between each connect / disconnect.
*/ */
queue:
SCpnt->transfersize = sdp->sector_size; SCpnt->transfersize = sdp->sector_size;
SCpnt->underflow = this_count << 9; SCpnt->underflow = this_count << 9;
SCpnt->allowed = MAX_RETRIES; SCpnt->allowed = MAX_RETRIES;
SCpnt->timeout_per_command = (SCpnt->device->type == TYPE_DISK ? SCpnt->timeout_per_command = timeout;
SD_TIMEOUT : SD_MOD_TIMEOUT);
/* /*
* This is the completion routine we use. This is matched in terms * This is the completion routine we use. This is matched in terms
......
...@@ -262,7 +262,7 @@ static request_queue_t *sr_find_queue(kdev_t dev) ...@@ -262,7 +262,7 @@ static request_queue_t *sr_find_queue(kdev_t dev)
static int sr_init_command(Scsi_Cmnd * SCpnt) static int sr_init_command(Scsi_Cmnd * SCpnt)
{ {
int dev, devm, block=0, this_count, s_size; int dev, devm, block=0, this_count, s_size, timeout = SR_TIMEOUT;
Scsi_CD *cd; Scsi_CD *cd;
devm = minor(SCpnt->request->rq_dev); devm = minor(SCpnt->request->rq_dev);
...@@ -285,6 +285,30 @@ static int sr_init_command(Scsi_Cmnd * SCpnt) ...@@ -285,6 +285,30 @@ static int sr_init_command(Scsi_Cmnd * SCpnt)
return 0; 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)) { if (!(SCpnt->request->flags & REQ_CMD)) {
blk_dump_rq_flags(SCpnt->request, "sr unsup command"); blk_dump_rq_flags(SCpnt->request, "sr unsup command");
return 0; return 0;
...@@ -357,11 +381,12 @@ static int sr_init_command(Scsi_Cmnd * SCpnt) ...@@ -357,11 +381,12 @@ static int sr_init_command(Scsi_Cmnd * SCpnt)
* host adapter, it's safe to assume that we can at least transfer * host adapter, it's safe to assume that we can at least transfer
* this many bytes between each connect / disconnect. * this many bytes between each connect / disconnect.
*/ */
queue:
SCpnt->transfersize = cd->device->sector_size; SCpnt->transfersize = cd->device->sector_size;
SCpnt->underflow = this_count << 9; SCpnt->underflow = this_count << 9;
SCpnt->allowed = MAX_RETRIES; 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 * This is the completion routine we use. This is matched in terms
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment