Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 776b23a0 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by James Bottomley
Browse files

[SCSI] always handle REQ_BLOCK_PC requests in common code



LLDDs should never see REQ_BLOCK_PC requests, we can handle them just
fine in the core code.  There is a small behaviour change in that some
check in sr's rw_intr are bypassed, but I consider the old behaviour
a bug.

Mike found this cleanup opportunity and provdided early patches, so all
the credit goes to him, even if I redid the patches from scratch beause
that was easier than forward-porting the old patches.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent d4054239
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -1212,7 +1212,7 @@ static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
	return -EOPNOTSUPP;
}

static void scsi_generic_done(struct scsi_cmnd *cmd)
static void scsi_blk_pc_done(struct scsi_cmnd *cmd)
{
	BUG_ON(!blk_pc_request(cmd->request));
	/*
@@ -1224,7 +1224,7 @@ static void scsi_generic_done(struct scsi_cmnd *cmd)
	scsi_io_completion(cmd, cmd->bufflen, 0);
}

void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd)
static void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd)
{
	struct request *req = cmd->request;

@@ -1241,8 +1241,8 @@ void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd)
	cmd->transfersize = req->data_len;
	cmd->allowed = req->retries;
	cmd->timeout_per_command = req->timeout;
	cmd->done = scsi_blk_pc_done;
}
EXPORT_SYMBOL_GPL(scsi_setup_blk_pc_cmnd);

static int scsi_prep_fn(struct request_queue *q, struct request *req)
{
@@ -1339,7 +1339,6 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
	 * happening now.
	 */
	if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
		struct scsi_driver *drv;
		int ret;

		/*
@@ -1371,16 +1370,17 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
		/*
		 * Initialize the actual SCSI command for this request.
		 */
		if (req->rq_disk) {
		if (req->flags & REQ_BLOCK_PC) {
			scsi_setup_blk_pc_cmnd(cmd);
		} else if (req->rq_disk) {
			struct scsi_driver *drv;

			drv = *(struct scsi_driver **)req->rq_disk->private_data;
			if (unlikely(!drv->init_command(cmd))) {
				scsi_release_buffers(cmd);
				scsi_put_command(cmd);
				goto kill;
			}
		} else {
			scsi_setup_blk_pc_cmnd(cmd);
			cmd->done = scsi_generic_done;
		}
	}

+5 −37
Original line number Diff line number Diff line
@@ -232,34 +232,12 @@ static void scsi_disk_put(struct scsi_disk *sdkp)
 **/
static int sd_init_command(struct scsi_cmnd * SCpnt)
{
	unsigned int this_count, timeout;
	struct gendisk *disk;
	sector_t block;
	struct scsi_device *sdp = SCpnt->device;
	struct request *rq = SCpnt->request;

	timeout = sdp->timeout;

	/*
	 * SG_IO from block layer already setup, just copy cdb basically
	 */
	if (blk_pc_request(rq)) {
		scsi_setup_blk_pc_cmnd(SCpnt);
		if (rq->timeout)
			timeout = rq->timeout;

		goto queue;
	}

	/*
	 * we only do REQ_CMD and REQ_BLOCK_PC
	 */
	if (!blk_fs_request(rq))
		return 0;

	disk = rq->rq_disk;
	block = rq->sector;
	this_count = SCpnt->request_bufflen >> 9;
	struct gendisk *disk = rq->rq_disk;
	sector_t block = rq->sector;
	unsigned int this_count = SCpnt->request_bufflen >> 9;
	unsigned int timeout = sdp->timeout;

	SCSI_LOG_HLQUEUE(1, printk("sd_init_command: disk=%s, block=%llu, "
			    "count=%d\n", disk->disk_name,
@@ -402,8 +380,6 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
	SCpnt->transfersize = sdp->sector_size;
	SCpnt->underflow = this_count << 9;
	SCpnt->allowed = SD_MAX_RETRIES;

queue:
	SCpnt->timeout_per_command = timeout;

	/*
@@ -837,15 +813,7 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt)
	   relatively rare error condition, no care is taken to avoid
	   unnecessary additional work such as memcpy's that could be avoided.
	 */

	/* 
	 * If SG_IO from block layer then set good_bytes to stop retries;
	 * else if errors, check them, and if necessary prepare for
	 * (partial) retries.
	 */
	if (blk_pc_request(SCpnt->request))
		good_bytes = this_count;
	else if (driver_byte(result) != 0 &&
	if (driver_byte(result) != 0 &&
		 sense_valid && !sense_deferred) {
		switch (sshdr.sense_key) {
		case MEDIUM_ERROR:
+0 −21
Original line number Diff line number Diff line
@@ -238,8 +238,6 @@ static void rw_intr(struct scsi_cmnd * SCpnt)
		case ILLEGAL_REQUEST:
			if (!(SCpnt->sense_buffer[0] & 0x90))
				break;
			if (!blk_fs_request(SCpnt->request))
				break;
			error_sector = (SCpnt->sense_buffer[3] << 24) |
				(SCpnt->sense_buffer[4] << 16) |
				(SCpnt->sense_buffer[5] << 8) |
@@ -317,23 +315,6 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
		return 0;
	}

	/*
	 * these are already setup, just copy cdb basically
	 */
	if (SCpnt->request->flags & REQ_BLOCK_PC) {
		scsi_setup_blk_pc_cmnd(SCpnt);

		if (SCpnt->timeout_per_command)
			timeout = SCpnt->timeout_per_command;

		goto queue;
	}

	if (!(SCpnt->request->flags & REQ_CMD)) {
		blk_dump_rq_flags(SCpnt->request, "sr unsup command");
		return 0;
	}

	/*
	 * we do lazy blocksize switching (when reading XA sectors,
	 * see CDROMREADMODE2 ioctl) 
@@ -422,8 +403,6 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
	 */
	SCpnt->transfersize = cd->device->sector_size;
	SCpnt->underflow = this_count << 9;

queue:
	SCpnt->allowed = MAX_RETRIES;
	SCpnt->timeout_per_command = timeout;

+0 −25
Original line number Diff line number Diff line
@@ -194,7 +194,6 @@ static int sgl_unmap_user_pages(struct scatterlist *, const unsigned int, int);

static int st_probe(struct device *);
static int st_remove(struct device *);
static int st_init_command(struct scsi_cmnd *);

static void do_create_driverfs_files(void);
static void do_remove_driverfs_files(void);
@@ -207,7 +206,6 @@ static struct scsi_driver st_template = {
		.probe		= st_probe,
		.remove		= st_remove,
	},
	.init_command		= st_init_command,
};

static int st_compression(struct scsi_tape *, int);
@@ -4181,29 +4179,6 @@ static void scsi_tape_release(struct kref *kref)
	return;
}

static void st_intr(struct scsi_cmnd *SCpnt)
{
	/*
	 * The caller should be checking the request's errors
	 * value.
	 */
	scsi_io_completion(SCpnt, SCpnt->bufflen, 0);
}

/*
 * st_init_command: only called via the scsi_cmd_ioctl (block SG_IO)
 * interface for REQ_BLOCK_PC commands.
 */
static int st_init_command(struct scsi_cmnd *SCpnt)
{
	if (!(SCpnt->request->flags & REQ_BLOCK_PC))
		return 0;

	scsi_setup_blk_pc_cmnd(SCpnt);
	SCpnt->done = st_intr;
	return 1;
}

static int __init init_st(void)
{
	validate_options();
+0 −1
Original line number Diff line number Diff line
@@ -151,6 +151,5 @@ extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t);
extern void scsi_put_command(struct scsi_cmnd *);
extern void scsi_io_completion(struct scsi_cmnd *, unsigned int, unsigned int);
extern void scsi_finish_command(struct scsi_cmnd *cmd);
extern void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd);

#endif /* _SCSI_SCSI_CMND_H */