mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-27 17:11:46 +00:00
Merge branch 'bsg' of git://git.kernel.dk/data/git/linux-2.6-block
* 'bsg' of git://git.kernel.dk/data/git/linux-2.6-block: (25 commits) bsg: Kconfig updates bsg: add SCSI transport-level request support bsg: add bidi support add a struct request pointer to the request structure bsg: fix the deadlock on discarding done commands bsg: fix a blocking read bug bsg: minor bug fixes improve bsg device allocation bind bsg to all SCSI devices bsg: bind bsg to request_queue instead of gendisk bsg: add a request_queue argument to scsi_cmd_ioctl() bsg: simplify __bsg_alloc_command failpath bsg: add cheasy error checks for sysfs stuff Add queue resizing support Replace s32, u32 and u64 with __s32, __u32 and __u64 in bsg.h for userspace bsg: silence a bogus gcc warning bsg: style cleanup bsg: use u32 etc instead of uint32_t bsg: add SG_IO to SG v4 bsg: replace SG v3 with SG v4 ...
This commit is contained in:
commit
e245befce7
13 changed files with 1341 additions and 91 deletions
|
@ -51,4 +51,12 @@ config LSF
|
||||||
|
|
||||||
endif # BLOCK
|
endif # BLOCK
|
||||||
|
|
||||||
|
config BLK_DEV_BSG
|
||||||
|
bool "Block layer SG support"
|
||||||
|
depends on SCSI && EXPERIMENTAL
|
||||||
|
default y
|
||||||
|
---help---
|
||||||
|
Saying Y here will enable generic SG (SCSI generic) v4
|
||||||
|
support for any block device.
|
||||||
|
|
||||||
source block/Kconfig.iosched
|
source block/Kconfig.iosched
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
obj-$(CONFIG_BLOCK) := elevator.o ll_rw_blk.o ioctl.o genhd.o scsi_ioctl.o
|
obj-$(CONFIG_BLOCK) := elevator.o ll_rw_blk.o ioctl.o genhd.o scsi_ioctl.o
|
||||||
|
|
||||||
|
obj-$(CONFIG_BLK_DEV_BSG) += bsg.o
|
||||||
obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o
|
obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o
|
||||||
obj-$(CONFIG_IOSCHED_AS) += as-iosched.o
|
obj-$(CONFIG_IOSCHED_AS) += as-iosched.o
|
||||||
obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o
|
obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o
|
||||||
|
|
1114
block/bsg.c
Normal file
1114
block/bsg.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -256,6 +256,7 @@ static void rq_init(request_queue_t *q, struct request *rq)
|
||||||
rq->end_io = NULL;
|
rq->end_io = NULL;
|
||||||
rq->end_io_data = NULL;
|
rq->end_io_data = NULL;
|
||||||
rq->completion_data = NULL;
|
rq->completion_data = NULL;
|
||||||
|
rq->next_rq = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -41,8 +41,6 @@ const unsigned char scsi_command_size[8] =
|
||||||
|
|
||||||
EXPORT_SYMBOL(scsi_command_size);
|
EXPORT_SYMBOL(scsi_command_size);
|
||||||
|
|
||||||
#define BLK_DEFAULT_TIMEOUT (60 * HZ)
|
|
||||||
|
|
||||||
#include <scsi/sg.h>
|
#include <scsi/sg.h>
|
||||||
|
|
||||||
static int sg_get_version(int __user *p)
|
static int sg_get_version(int __user *p)
|
||||||
|
@ -114,7 +112,7 @@ static int sg_emulated_host(request_queue_t *q, int __user *p)
|
||||||
#define safe_for_read(cmd) [cmd] = CMD_READ_SAFE
|
#define safe_for_read(cmd) [cmd] = CMD_READ_SAFE
|
||||||
#define safe_for_write(cmd) [cmd] = CMD_WRITE_SAFE
|
#define safe_for_write(cmd) [cmd] = CMD_WRITE_SAFE
|
||||||
|
|
||||||
static int verify_command(struct file *file, unsigned char *cmd)
|
int blk_verify_command(unsigned char *cmd, int has_write_perm)
|
||||||
{
|
{
|
||||||
static unsigned char cmd_type[256] = {
|
static unsigned char cmd_type[256] = {
|
||||||
|
|
||||||
|
@ -193,18 +191,11 @@ static int verify_command(struct file *file, unsigned char *cmd)
|
||||||
safe_for_write(GPCMD_SET_STREAMING),
|
safe_for_write(GPCMD_SET_STREAMING),
|
||||||
};
|
};
|
||||||
unsigned char type = cmd_type[cmd[0]];
|
unsigned char type = cmd_type[cmd[0]];
|
||||||
int has_write_perm = 0;
|
|
||||||
|
|
||||||
/* Anybody who can open the device can do a read-safe command */
|
/* Anybody who can open the device can do a read-safe command */
|
||||||
if (type & CMD_READ_SAFE)
|
if (type & CMD_READ_SAFE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
|
||||||
* file can be NULL from ioctl_by_bdev()...
|
|
||||||
*/
|
|
||||||
if (file)
|
|
||||||
has_write_perm = file->f_mode & FMODE_WRITE;
|
|
||||||
|
|
||||||
/* Write-safe commands just require a writable open.. */
|
/* Write-safe commands just require a writable open.. */
|
||||||
if ((type & CMD_WRITE_SAFE) && has_write_perm)
|
if ((type & CMD_WRITE_SAFE) && has_write_perm)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -221,25 +212,96 @@ static int verify_command(struct file *file, unsigned char *cmd)
|
||||||
/* Otherwise fail it with an "Operation not permitted" */
|
/* Otherwise fail it with an "Operation not permitted" */
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(blk_verify_command);
|
||||||
|
|
||||||
|
int blk_fill_sghdr_rq(request_queue_t *q, struct request *rq,
|
||||||
|
struct sg_io_hdr *hdr, int has_write_perm)
|
||||||
|
{
|
||||||
|
memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
|
||||||
|
|
||||||
|
if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len))
|
||||||
|
return -EFAULT;
|
||||||
|
if (blk_verify_command(rq->cmd, has_write_perm))
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fill in request structure
|
||||||
|
*/
|
||||||
|
rq->cmd_len = hdr->cmd_len;
|
||||||
|
rq->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||||
|
|
||||||
|
rq->timeout = (hdr->timeout * HZ) / 1000;
|
||||||
|
if (!rq->timeout)
|
||||||
|
rq->timeout = q->sg_timeout;
|
||||||
|
if (!rq->timeout)
|
||||||
|
rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(blk_fill_sghdr_rq);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* unmap a request that was previously mapped to this sg_io_hdr. handles
|
||||||
|
* both sg and non-sg sg_io_hdr.
|
||||||
|
*/
|
||||||
|
int blk_unmap_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr)
|
||||||
|
{
|
||||||
|
blk_rq_unmap_user(rq->bio);
|
||||||
|
blk_put_request(rq);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(blk_unmap_sghdr_rq);
|
||||||
|
|
||||||
|
int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
|
||||||
|
struct bio *bio)
|
||||||
|
{
|
||||||
|
int r, ret = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fill in all the output members
|
||||||
|
*/
|
||||||
|
hdr->status = rq->errors & 0xff;
|
||||||
|
hdr->masked_status = status_byte(rq->errors);
|
||||||
|
hdr->msg_status = msg_byte(rq->errors);
|
||||||
|
hdr->host_status = host_byte(rq->errors);
|
||||||
|
hdr->driver_status = driver_byte(rq->errors);
|
||||||
|
hdr->info = 0;
|
||||||
|
if (hdr->masked_status || hdr->host_status || hdr->driver_status)
|
||||||
|
hdr->info |= SG_INFO_CHECK;
|
||||||
|
hdr->resid = rq->data_len;
|
||||||
|
hdr->sb_len_wr = 0;
|
||||||
|
|
||||||
|
if (rq->sense_len && hdr->sbp) {
|
||||||
|
int len = min((unsigned int) hdr->mx_sb_len, rq->sense_len);
|
||||||
|
|
||||||
|
if (!copy_to_user(hdr->sbp, rq->sense, len))
|
||||||
|
hdr->sb_len_wr = len;
|
||||||
|
else
|
||||||
|
ret = -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
rq->bio = bio;
|
||||||
|
r = blk_unmap_sghdr_rq(rq, hdr);
|
||||||
|
if (ret)
|
||||||
|
r = ret;
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(blk_complete_sghdr_rq);
|
||||||
|
|
||||||
static int sg_io(struct file *file, request_queue_t *q,
|
static int sg_io(struct file *file, request_queue_t *q,
|
||||||
struct gendisk *bd_disk, struct sg_io_hdr *hdr)
|
struct gendisk *bd_disk, struct sg_io_hdr *hdr)
|
||||||
{
|
{
|
||||||
unsigned long start_time, timeout;
|
unsigned long start_time;
|
||||||
int writing = 0, ret = 0;
|
int writing = 0, ret = 0, has_write_perm = 0;
|
||||||
struct request *rq;
|
struct request *rq;
|
||||||
char sense[SCSI_SENSE_BUFFERSIZE];
|
char sense[SCSI_SENSE_BUFFERSIZE];
|
||||||
unsigned char cmd[BLK_MAX_CDB];
|
|
||||||
struct bio *bio;
|
struct bio *bio;
|
||||||
|
|
||||||
if (hdr->interface_id != 'S')
|
if (hdr->interface_id != 'S')
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (hdr->cmd_len > BLK_MAX_CDB)
|
if (hdr->cmd_len > BLK_MAX_CDB)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (copy_from_user(cmd, hdr->cmdp, hdr->cmd_len))
|
|
||||||
return -EFAULT;
|
|
||||||
if (verify_command(file, cmd))
|
|
||||||
return -EPERM;
|
|
||||||
|
|
||||||
if (hdr->dxfer_len > (q->max_hw_sectors << 9))
|
if (hdr->dxfer_len > (q->max_hw_sectors << 9))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
@ -260,25 +322,13 @@ static int sg_io(struct file *file, request_queue_t *q,
|
||||||
if (!rq)
|
if (!rq)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/*
|
if (file)
|
||||||
* fill in request structure
|
has_write_perm = file->f_mode & FMODE_WRITE;
|
||||||
*/
|
|
||||||
rq->cmd_len = hdr->cmd_len;
|
|
||||||
memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
|
|
||||||
memcpy(rq->cmd, cmd, hdr->cmd_len);
|
|
||||||
|
|
||||||
memset(sense, 0, sizeof(sense));
|
if (blk_fill_sghdr_rq(q, rq, hdr, has_write_perm)) {
|
||||||
rq->sense = sense;
|
blk_put_request(rq);
|
||||||
rq->sense_len = 0;
|
return -EFAULT;
|
||||||
|
}
|
||||||
rq->cmd_type = REQ_TYPE_BLOCK_PC;
|
|
||||||
|
|
||||||
timeout = msecs_to_jiffies(hdr->timeout);
|
|
||||||
rq->timeout = (timeout < INT_MAX) ? timeout : INT_MAX;
|
|
||||||
if (!rq->timeout)
|
|
||||||
rq->timeout = q->sg_timeout;
|
|
||||||
if (!rq->timeout)
|
|
||||||
rq->timeout = BLK_DEFAULT_TIMEOUT;
|
|
||||||
|
|
||||||
if (hdr->iovec_count) {
|
if (hdr->iovec_count) {
|
||||||
const int size = sizeof(struct sg_iovec) * hdr->iovec_count;
|
const int size = sizeof(struct sg_iovec) * hdr->iovec_count;
|
||||||
|
@ -306,6 +356,9 @@ static int sg_io(struct file *file, request_queue_t *q,
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
bio = rq->bio;
|
bio = rq->bio;
|
||||||
|
memset(sense, 0, sizeof(sense));
|
||||||
|
rq->sense = sense;
|
||||||
|
rq->sense_len = 0;
|
||||||
rq->retries = 0;
|
rq->retries = 0;
|
||||||
|
|
||||||
start_time = jiffies;
|
start_time = jiffies;
|
||||||
|
@ -316,31 +369,9 @@ static int sg_io(struct file *file, request_queue_t *q,
|
||||||
*/
|
*/
|
||||||
blk_execute_rq(q, bd_disk, rq, 0);
|
blk_execute_rq(q, bd_disk, rq, 0);
|
||||||
|
|
||||||
/* write to all output members */
|
|
||||||
hdr->status = 0xff & rq->errors;
|
|
||||||
hdr->masked_status = status_byte(rq->errors);
|
|
||||||
hdr->msg_status = msg_byte(rq->errors);
|
|
||||||
hdr->host_status = host_byte(rq->errors);
|
|
||||||
hdr->driver_status = driver_byte(rq->errors);
|
|
||||||
hdr->info = 0;
|
|
||||||
if (hdr->masked_status || hdr->host_status || hdr->driver_status)
|
|
||||||
hdr->info |= SG_INFO_CHECK;
|
|
||||||
hdr->resid = rq->data_len;
|
|
||||||
hdr->duration = ((jiffies - start_time) * 1000) / HZ;
|
hdr->duration = ((jiffies - start_time) * 1000) / HZ;
|
||||||
hdr->sb_len_wr = 0;
|
|
||||||
|
|
||||||
if (rq->sense_len && hdr->sbp) {
|
return blk_complete_sghdr_rq(rq, hdr, bio);
|
||||||
int len = min((unsigned int) hdr->mx_sb_len, rq->sense_len);
|
|
||||||
|
|
||||||
if (!copy_to_user(hdr->sbp, rq->sense, len))
|
|
||||||
hdr->sb_len_wr = len;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (blk_rq_unmap_user(bio))
|
|
||||||
ret = -EFAULT;
|
|
||||||
|
|
||||||
/* may not have succeeded, but output values written to control
|
|
||||||
* structure (struct sg_io_hdr). */
|
|
||||||
out:
|
out:
|
||||||
blk_put_request(rq);
|
blk_put_request(rq);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -427,7 +458,7 @@ int sg_scsi_ioctl(struct file *file, struct request_queue *q,
|
||||||
if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
|
if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
err = verify_command(file, rq->cmd);
|
err = blk_verify_command(rq->cmd, file->f_mode & FMODE_WRITE);
|
||||||
if (err)
|
if (err)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
@ -454,7 +485,7 @@ int sg_scsi_ioctl(struct file *file, struct request_queue *q,
|
||||||
rq->retries = 1;
|
rq->retries = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rq->timeout = BLK_DEFAULT_TIMEOUT;
|
rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -501,7 +532,7 @@ static int __blk_send_generic(request_queue_t *q, struct gendisk *bd_disk, int c
|
||||||
rq->cmd_type = REQ_TYPE_BLOCK_PC;
|
rq->cmd_type = REQ_TYPE_BLOCK_PC;
|
||||||
rq->data = NULL;
|
rq->data = NULL;
|
||||||
rq->data_len = 0;
|
rq->data_len = 0;
|
||||||
rq->timeout = BLK_DEFAULT_TIMEOUT;
|
rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
|
||||||
memset(rq->cmd, 0, sizeof(rq->cmd));
|
memset(rq->cmd, 0, sizeof(rq->cmd));
|
||||||
rq->cmd[0] = cmd;
|
rq->cmd[0] = cmd;
|
||||||
rq->cmd[4] = data;
|
rq->cmd[4] = data;
|
||||||
|
@ -517,16 +548,12 @@ static inline int blk_send_start_stop(request_queue_t *q, struct gendisk *bd_dis
|
||||||
return __blk_send_generic(q, bd_disk, GPCMD_START_STOP_UNIT, data);
|
return __blk_send_generic(q, bd_disk, GPCMD_START_STOP_UNIT, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int scsi_cmd_ioctl(struct file *file, struct gendisk *bd_disk, unsigned int cmd, void __user *arg)
|
int scsi_cmd_ioctl(struct file *file, struct request_queue *q,
|
||||||
|
struct gendisk *bd_disk, unsigned int cmd, void __user *arg)
|
||||||
{
|
{
|
||||||
request_queue_t *q;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
q = bd_disk->queue;
|
if (!q || blk_get_queue(q))
|
||||||
if (!q)
|
|
||||||
return -ENXIO;
|
|
||||||
|
|
||||||
if (blk_get_queue(q))
|
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
|
|
|
@ -1709,7 +1709,7 @@ static int ub_bd_ioctl(struct inode *inode, struct file *filp,
|
||||||
struct gendisk *disk = inode->i_bdev->bd_disk;
|
struct gendisk *disk = inode->i_bdev->bd_disk;
|
||||||
void __user *usermem = (void __user *) arg;
|
void __user *usermem = (void __user *) arg;
|
||||||
|
|
||||||
return scsi_cmd_ioctl(filp, disk, cmd, usermem);
|
return scsi_cmd_ioctl(filp, disk->queue, disk, cmd, usermem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -2695,11 +2695,12 @@ int cdrom_ioctl(struct file * file, struct cdrom_device_info *cdi,
|
||||||
{
|
{
|
||||||
void __user *argp = (void __user *)arg;
|
void __user *argp = (void __user *)arg;
|
||||||
int ret;
|
int ret;
|
||||||
|
struct gendisk *disk = ip->i_bdev->bd_disk;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try the generic SCSI command ioctl's first.
|
* Try the generic SCSI command ioctl's first.
|
||||||
*/
|
*/
|
||||||
ret = scsi_cmd_ioctl(file, ip->i_bdev->bd_disk, cmd, argp);
|
ret = scsi_cmd_ioctl(file, disk->queue, disk, cmd, argp);
|
||||||
if (ret != -ENOTTY)
|
if (ret != -ENOTTY)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
|
@ -1258,19 +1258,25 @@ static void idefloppy_create_rw_cmd (idefloppy_floppy_t *floppy, idefloppy_pc_t
|
||||||
set_bit(PC_DMA_RECOMMENDED, &pc->flags);
|
set_bit(PC_DMA_RECOMMENDED, &pc->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct request *rq)
|
idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct request *rq)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* just support eject for now, it would not be hard to make the
|
|
||||||
* REQ_BLOCK_PC support fully-featured
|
|
||||||
*/
|
|
||||||
if (rq->cmd[0] != IDEFLOPPY_START_STOP_CMD)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
idefloppy_init_pc(pc);
|
idefloppy_init_pc(pc);
|
||||||
|
pc->callback = &idefloppy_rw_callback;
|
||||||
memcpy(pc->c, rq->cmd, sizeof(pc->c));
|
memcpy(pc->c, rq->cmd, sizeof(pc->c));
|
||||||
return 0;
|
pc->rq = rq;
|
||||||
|
pc->b_count = rq->data_len;
|
||||||
|
if (rq->data_len && rq_data_dir(rq) == WRITE)
|
||||||
|
set_bit(PC_WRITING, &pc->flags);
|
||||||
|
pc->buffer = rq->data;
|
||||||
|
if (rq->bio)
|
||||||
|
set_bit(PC_DMA_RECOMMENDED, &pc->flags);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* possibly problematic, doesn't look like ide-floppy correctly
|
||||||
|
* handled scattered requests if dma fails...
|
||||||
|
*/
|
||||||
|
pc->request_transfer = pc->buffer_size = rq->data_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1317,10 +1323,7 @@ static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request
|
||||||
pc = (idefloppy_pc_t *) rq->buffer;
|
pc = (idefloppy_pc_t *) rq->buffer;
|
||||||
} else if (blk_pc_request(rq)) {
|
} else if (blk_pc_request(rq)) {
|
||||||
pc = idefloppy_next_pc_storage(drive);
|
pc = idefloppy_next_pc_storage(drive);
|
||||||
if (idefloppy_blockpc_cmd(floppy, pc, rq)) {
|
idefloppy_blockpc_cmd(floppy, pc, rq);
|
||||||
idefloppy_do_end_request(drive, 0, 0);
|
|
||||||
return ide_stopped;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
blk_dump_rq_flags(rq,
|
blk_dump_rq_flags(rq,
|
||||||
"ide-floppy: unsupported command in queue");
|
"ide-floppy: unsupported command in queue");
|
||||||
|
|
|
@ -1049,9 +1049,13 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
ide_driver_t *drv;
|
ide_driver_t *drv;
|
||||||
void __user *p = (void __user *)arg;
|
void __user *p = (void __user *)arg;
|
||||||
int err = 0, (*setfunc)(ide_drive_t *, int);
|
int err, (*setfunc)(ide_drive_t *, int);
|
||||||
u8 *val;
|
u8 *val;
|
||||||
|
|
||||||
|
err = scsi_cmd_ioctl(file, bdev->bd_disk->queue, bdev->bd_disk, cmd, p);
|
||||||
|
if (err != -ENOTTY)
|
||||||
|
return err;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case HDIO_GET_32BIT: val = &drive->io_32bit; goto read_val;
|
case HDIO_GET_32BIT: val = &drive->io_32bit; goto read_val;
|
||||||
case HDIO_GET_KEEPSETTINGS: val = &drive->keep_settings; goto read_val;
|
case HDIO_GET_KEEPSETTINGS: val = &drive->keep_settings; goto read_val;
|
||||||
|
@ -1171,10 +1175,6 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CDROMEJECT:
|
|
||||||
case CDROMCLOSETRAY:
|
|
||||||
return scsi_cmd_ioctl(file, bdev->bd_disk, cmd, p);
|
|
||||||
|
|
||||||
case HDIO_GET_BUSSTATE:
|
case HDIO_GET_BUSSTATE:
|
||||||
if (!capable(CAP_SYS_ADMIN))
|
if (!capable(CAP_SYS_ADMIN))
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
|
|
|
@ -684,7 +684,7 @@ static int sd_ioctl(struct inode * inode, struct file * filp,
|
||||||
case SCSI_IOCTL_GET_BUS_NUMBER:
|
case SCSI_IOCTL_GET_BUS_NUMBER:
|
||||||
return scsi_ioctl(sdp, cmd, p);
|
return scsi_ioctl(sdp, cmd, p);
|
||||||
default:
|
default:
|
||||||
error = scsi_cmd_ioctl(filp, disk, cmd, p);
|
error = scsi_cmd_ioctl(filp, disk->queue, disk, cmd, p);
|
||||||
if (error != -ENOTTY)
|
if (error != -ENOTTY)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3549,7 +3549,8 @@ static int st_ioctl(struct inode *inode, struct file *file,
|
||||||
!capable(CAP_SYS_RAWIO))
|
!capable(CAP_SYS_RAWIO))
|
||||||
i = -EPERM;
|
i = -EPERM;
|
||||||
else
|
else
|
||||||
i = scsi_cmd_ioctl(file, STp->disk, cmd_in, p);
|
i = scsi_cmd_ioctl(file, STp->disk->queue,
|
||||||
|
STp->disk, cmd_in, p);
|
||||||
if (i != -ENOTTY)
|
if (i != -ENOTTY)
|
||||||
return i;
|
return i;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <linux/bio.h>
|
#include <linux/bio.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/stringify.h>
|
#include <linux/stringify.h>
|
||||||
|
#include <linux/bsg.h>
|
||||||
|
|
||||||
#include <asm/scatterlist.h>
|
#include <asm/scatterlist.h>
|
||||||
|
|
||||||
|
@ -41,6 +42,8 @@ struct elevator_queue;
|
||||||
typedef struct elevator_queue elevator_t;
|
typedef struct elevator_queue elevator_t;
|
||||||
struct request_pm_state;
|
struct request_pm_state;
|
||||||
struct blk_trace;
|
struct blk_trace;
|
||||||
|
struct request;
|
||||||
|
struct sg_io_hdr;
|
||||||
|
|
||||||
#define BLKDEV_MIN_RQ 4
|
#define BLKDEV_MIN_RQ 4
|
||||||
#define BLKDEV_MAX_RQ 128 /* Default maximum */
|
#define BLKDEV_MAX_RQ 128 /* Default maximum */
|
||||||
|
@ -314,6 +317,9 @@ struct request {
|
||||||
*/
|
*/
|
||||||
rq_end_io_fn *end_io;
|
rq_end_io_fn *end_io;
|
||||||
void *end_io_data;
|
void *end_io_data;
|
||||||
|
|
||||||
|
/* for bidi */
|
||||||
|
struct request *next_rq;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -468,6 +474,10 @@ struct request_queue
|
||||||
unsigned int bi_size;
|
unsigned int bi_size;
|
||||||
|
|
||||||
struct mutex sysfs_lock;
|
struct mutex sysfs_lock;
|
||||||
|
|
||||||
|
#if defined(CONFIG_BLK_DEV_BSG)
|
||||||
|
struct bsg_class_device bsg_dev;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#define QUEUE_FLAG_CLUSTER 0 /* cluster several segments into 1 */
|
#define QUEUE_FLAG_CLUSTER 0 /* cluster several segments into 1 */
|
||||||
|
@ -479,6 +489,7 @@ struct request_queue
|
||||||
#define QUEUE_FLAG_REENTER 6 /* Re-entrancy avoidance */
|
#define QUEUE_FLAG_REENTER 6 /* Re-entrancy avoidance */
|
||||||
#define QUEUE_FLAG_PLUGGED 7 /* queue is plugged */
|
#define QUEUE_FLAG_PLUGGED 7 /* queue is plugged */
|
||||||
#define QUEUE_FLAG_ELVSWITCH 8 /* don't use elevator, just do FIFO */
|
#define QUEUE_FLAG_ELVSWITCH 8 /* don't use elevator, just do FIFO */
|
||||||
|
#define QUEUE_FLAG_BIDI 9 /* queue supports bidi requests */
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
/*
|
/*
|
||||||
|
@ -543,6 +554,7 @@ enum {
|
||||||
#define blk_sorted_rq(rq) ((rq)->cmd_flags & REQ_SORTED)
|
#define blk_sorted_rq(rq) ((rq)->cmd_flags & REQ_SORTED)
|
||||||
#define blk_barrier_rq(rq) ((rq)->cmd_flags & REQ_HARDBARRIER)
|
#define blk_barrier_rq(rq) ((rq)->cmd_flags & REQ_HARDBARRIER)
|
||||||
#define blk_fua_rq(rq) ((rq)->cmd_flags & REQ_FUA)
|
#define blk_fua_rq(rq) ((rq)->cmd_flags & REQ_FUA)
|
||||||
|
#define blk_bidi_rq(rq) ((rq)->next_rq != NULL)
|
||||||
|
|
||||||
#define list_entry_rq(ptr) list_entry((ptr), struct request, queuelist)
|
#define list_entry_rq(ptr) list_entry((ptr), struct request, queuelist)
|
||||||
|
|
||||||
|
@ -607,6 +619,11 @@ extern unsigned long blk_max_low_pfn, blk_max_pfn;
|
||||||
#define BLK_BOUNCE_ANY ((u64)blk_max_pfn << PAGE_SHIFT)
|
#define BLK_BOUNCE_ANY ((u64)blk_max_pfn << PAGE_SHIFT)
|
||||||
#define BLK_BOUNCE_ISA (ISA_DMA_THRESHOLD)
|
#define BLK_BOUNCE_ISA (ISA_DMA_THRESHOLD)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* default timeout for SG_IO if none specified
|
||||||
|
*/
|
||||||
|
#define BLK_DEFAULT_SG_TIMEOUT (60 * HZ)
|
||||||
|
|
||||||
#ifdef CONFIG_MMU
|
#ifdef CONFIG_MMU
|
||||||
extern int init_emergency_isa_pool(void);
|
extern int init_emergency_isa_pool(void);
|
||||||
extern void blk_queue_bounce(request_queue_t *q, struct bio **bio);
|
extern void blk_queue_bounce(request_queue_t *q, struct bio **bio);
|
||||||
|
@ -637,7 +654,8 @@ extern void blk_requeue_request(request_queue_t *, struct request *);
|
||||||
extern void blk_plug_device(request_queue_t *);
|
extern void blk_plug_device(request_queue_t *);
|
||||||
extern int blk_remove_plug(request_queue_t *);
|
extern int blk_remove_plug(request_queue_t *);
|
||||||
extern void blk_recount_segments(request_queue_t *, struct bio *);
|
extern void blk_recount_segments(request_queue_t *, struct bio *);
|
||||||
extern int scsi_cmd_ioctl(struct file *, struct gendisk *, unsigned int, void __user *);
|
extern int scsi_cmd_ioctl(struct file *, struct request_queue *,
|
||||||
|
struct gendisk *, unsigned int, void __user *);
|
||||||
extern int sg_scsi_ioctl(struct file *, struct request_queue *,
|
extern int sg_scsi_ioctl(struct file *, struct request_queue *,
|
||||||
struct gendisk *, struct scsi_ioctl_command __user *);
|
struct gendisk *, struct scsi_ioctl_command __user *);
|
||||||
|
|
||||||
|
@ -680,6 +698,12 @@ extern int blk_execute_rq(request_queue_t *, struct gendisk *,
|
||||||
struct request *, int);
|
struct request *, int);
|
||||||
extern void blk_execute_rq_nowait(request_queue_t *, struct gendisk *,
|
extern void blk_execute_rq_nowait(request_queue_t *, struct gendisk *,
|
||||||
struct request *, int, rq_end_io_fn *);
|
struct request *, int, rq_end_io_fn *);
|
||||||
|
extern int blk_fill_sghdr_rq(request_queue_t *, struct request *,
|
||||||
|
struct sg_io_hdr *, int);
|
||||||
|
extern int blk_unmap_sghdr_rq(struct request *, struct sg_io_hdr *);
|
||||||
|
extern int blk_complete_sghdr_rq(struct request *, struct sg_io_hdr *,
|
||||||
|
struct bio *);
|
||||||
|
extern int blk_verify_command(unsigned char *, int);
|
||||||
|
|
||||||
static inline request_queue_t *bdev_get_queue(struct block_device *bdev)
|
static inline request_queue_t *bdev_get_queue(struct block_device *bdev)
|
||||||
{
|
{
|
||||||
|
|
70
include/linux/bsg.h
Normal file
70
include/linux/bsg.h
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
#ifndef BSG_H
|
||||||
|
#define BSG_H
|
||||||
|
|
||||||
|
#define BSG_PROTOCOL_SCSI 0
|
||||||
|
|
||||||
|
#define BSG_SUB_PROTOCOL_SCSI_CMD 0
|
||||||
|
#define BSG_SUB_PROTOCOL_SCSI_TMF 1
|
||||||
|
#define BSG_SUB_PROTOCOL_SCSI_TRANSPORT 2
|
||||||
|
|
||||||
|
struct sg_io_v4 {
|
||||||
|
__s32 guard; /* [i] 'Q' to differentiate from v3 */
|
||||||
|
__u32 protocol; /* [i] 0 -> SCSI , .... */
|
||||||
|
__u32 subprotocol; /* [i] 0 -> SCSI command, 1 -> SCSI task
|
||||||
|
management function, .... */
|
||||||
|
|
||||||
|
__u32 request_len; /* [i] in bytes */
|
||||||
|
__u64 request; /* [i], [*i] {SCSI: cdb} */
|
||||||
|
__u32 request_attr; /* [i] {SCSI: task attribute} */
|
||||||
|
__u32 request_tag; /* [i] {SCSI: task tag (only if flagged)} */
|
||||||
|
__u32 request_priority; /* [i] {SCSI: task priority} */
|
||||||
|
__u32 max_response_len; /* [i] in bytes */
|
||||||
|
__u64 response; /* [i], [*o] {SCSI: (auto)sense data} */
|
||||||
|
|
||||||
|
/* "din_" for data in (from device); "dout_" for data out (to device) */
|
||||||
|
__u32 dout_xfer_len; /* [i] bytes to be transferred to device */
|
||||||
|
__u32 din_xfer_len; /* [i] bytes to be transferred from device */
|
||||||
|
__u64 dout_xferp; /* [i], [*i] */
|
||||||
|
__u64 din_xferp; /* [i], [*o] */
|
||||||
|
|
||||||
|
__u32 timeout; /* [i] units: millisecond */
|
||||||
|
__u32 flags; /* [i] bit mask */
|
||||||
|
__u64 usr_ptr; /* [i->o] unused internally */
|
||||||
|
__u32 spare_in; /* [i] */
|
||||||
|
|
||||||
|
__u32 driver_status; /* [o] 0 -> ok */
|
||||||
|
__u32 transport_status; /* [o] 0 -> ok */
|
||||||
|
__u32 device_status; /* [o] {SCSI: command completion status} */
|
||||||
|
__u32 retry_delay; /* [o] {SCSI: status auxiliary information} */
|
||||||
|
__u32 info; /* [o] additional information */
|
||||||
|
__u32 duration; /* [o] time to complete, in milliseconds */
|
||||||
|
__u32 response_len; /* [o] bytes of response actually written */
|
||||||
|
__s32 din_resid; /* [o] actual_din_xfer_len - din_xfer_len */
|
||||||
|
__u32 generated_tag; /* [o] {SCSI: task tag that transport chose} */
|
||||||
|
__u32 spare_out; /* [o] */
|
||||||
|
|
||||||
|
__u32 padding;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
|
#if defined(CONFIG_BLK_DEV_BSG)
|
||||||
|
struct bsg_class_device {
|
||||||
|
struct class_device *class_dev;
|
||||||
|
struct device *dev;
|
||||||
|
int minor;
|
||||||
|
struct list_head list;
|
||||||
|
struct request_queue *queue;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int bsg_register_queue(struct request_queue *, const char *);
|
||||||
|
extern void bsg_unregister_queue(struct request_queue *);
|
||||||
|
#else
|
||||||
|
struct bsg_class_device { };
|
||||||
|
#define bsg_register_queue(disk, name) (0)
|
||||||
|
#define bsg_unregister_queue(disk) do { } while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __KERNEL__ */
|
||||||
|
|
||||||
|
#endif
|
Loading…
Add table
Add a link
Reference in a new issue