lkml.org 
[lkml]   [2003]   [Apr]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH] 2.5.67-ac2 direct-IO for IDE taskfile ioctl (4/4)

    # Use direct-IO in ide_taskfile_ioctl() and in ide_cmd_ioctl().
    #
    # Detailed changelog:
    # - add ide_bio_taskfile() which is equivalent to ide_diag_taskfile()
    # for non-fs rq->bio based requests
    # - use direct-IO to user memory if possible in ide_taskfile_ioctl()
    # and in taskfile version of ide_cmd_ioctl()
    #
    # NOTE: user memory out/in buffers have to be hardsector (=512) aligned
    # to take advantage of direct-IO
    #
    # Bartlomiej Zolnierkiewicz <bzolnier@elka.pw.edu.pl>

    diff -uNr linux-2.5.67-ac2-dtf3/drivers/ide/ide-taskfile.c linux/drivers/ide/ide-taskfile.c
    --- linux-2.5.67-ac2-dtf3/drivers/ide/ide-taskfile.c Wed Apr 23 15:44:36 2003
    +++ linux/drivers/ide/ide-taskfile.c Wed Apr 23 16:22:12 2003
    @@ -1054,6 +1054,25 @@

    EXPORT_SYMBOL(ide_raw_taskfile);

    +/*
    + * Comments to ide_diag_taskfile() apply here as well.
    + */
    +static int ide_bio_taskfile (ide_drive_t *drive, ide_task_t *args,
    + request_queue_t *q, struct bio *bio)
    +{
    + struct request rq;
    +
    + ide_init_drive_taskfile(&rq);
    + blk_rq_bio_prep(q, &rq, bio);
    +
    + if (args->tf_out_flags.all == 0)
    + args->posthandler = ide_post_handler_parser(
    + (struct hd_drive_task_hdr *) args->tfRegister,
    + (struct hd_drive_hob_hdr *) args->hobRegister);
    + rq.special = args;
    + return ide_do_drive_cmd(drive, &rq, ide_wait);
    +}
    +
    #ifdef CONFIG_IDE_TASK_IOCTL_DEBUG
    char * ide_ioctl_verbose (unsigned int cmd)
    {
    @@ -1081,10 +1100,19 @@
    int tasksize = sizeof(struct ide_task_request_s);
    int taskin = 0;
    int taskout = 0;
    +
    + unsigned long outaddr, inaddr;
    + request_queue_t *q;
    + struct bio *outbio = NULL, *inbio = NULL;
    +
    u8 io_32bit = drive->io_32bit;

    // printk("IDE Taskfile ...\n");

    + q = bdev_get_queue(bdev);
    + if (!q)
    + return -ENXIO;
    +
    req_task = kmalloc(tasksize, GFP_KERNEL);
    if (req_task == NULL) return -ENOMEM;
    memset(req_task, 0, tasksize);
    @@ -1097,7 +1125,21 @@
    taskin = (int) req_task->in_size;

    if (taskout) {
    + outaddr = arg + tasksize;
    + /* writing to device -> reading from vm */
    + if (!access_ok(VERIFY_READ, (void *)outaddr, taskout)) {
    + kfree(req_task);
    + return -EFAULT;
    + }
    + outbio = bio_map_user(bdev, outaddr, taskout, 0);
    + if (outbio)
    + outbio->bi_rw |= (1 << BIO_RW);
    + }
    +
    + if (taskout && !outbio) {
    int outtotal = tasksize;
    + printk(KERN_INFO "%s: %s: taking OUT slow-path\n",
    + drive->name, __FUNCTION__);
    outbuf = kmalloc(taskout, GFP_KERNEL);
    if (outbuf == NULL) {
    err = -ENOMEM;
    @@ -1111,7 +1153,19 @@
    }

    if (taskin) {
    + inaddr = arg + tasksize + taskout;
    + /* reading from device -> writing to vm */
    + if (!access_ok(VERIFY_WRITE, (void *)inaddr, taskin)) {
    + kfree(req_task);
    + return -EFAULT;
    + }
    + inbio = bio_map_user(bdev, inaddr, taskin, 1);
    + }
    +
    + if (taskin && !inbio) {
    int intotal = tasksize + taskout;
    + printk(KERN_INFO "%s: %s: taking IN slow-path\n",
    + drive->name, __FUNCTION__);
    inbuf = kmalloc(taskin, GFP_KERNEL);
    if (inbuf == NULL) {
    err = -ENOMEM;
    @@ -1144,22 +1198,34 @@
    switch(req_task->data_phase) {
    case TASKFILE_OUT_DMAQ:
    case TASKFILE_OUT_DMA:
    - err = ide_diag_taskfile(drive, &args, taskout, outbuf);
    + if (outbio)
    + err = ide_bio_taskfile(drive, &args, q, outbio);
    + else
    + err = ide_diag_taskfile(drive, &args, taskout, outbuf);
    break;
    case TASKFILE_IN_DMAQ:
    case TASKFILE_IN_DMA:
    - err = ide_diag_taskfile(drive, &args, taskin, inbuf);
    + if (inbio)
    + err = ide_bio_taskfile(drive, &args, q, inbio);
    + else
    + err = ide_diag_taskfile(drive, &args, taskin, inbuf);
    break;
    case TASKFILE_IN_OUT:
    #if 0
    args.prehandler = &pre_task_out_intr;
    args.handler = &task_out_intr;
    args.posthandler = NULL;
    - err = ide_diag_taskfile(drive, &args, taskout, outbuf);
    + if (outbio)
    + err = ide_bio_taskfile(drive, &args, q, outbio);
    + else
    + err = ide_diag_taskfile(drive, &args, taskout, outbuf);
    args.prehandler = NULL;
    args.handler = &task_in_intr;
    args.posthandler = NULL;
    - err = ide_diag_taskfile(drive, &args, taskin, inbuf);
    + if (inbio)
    + err = ide_bio_taskfile(drive, &args, q, inbio);
    + else
    + err = ide_diag_taskfile(drive, &args, taskin, inbuf);
    break;
    #else
    err = -EFAULT;
    @@ -1176,12 +1242,18 @@
    }
    args.prehandler = &pre_task_mulout_intr;
    args.handler = &task_mulout_intr;
    - err = ide_diag_taskfile(drive, &args, taskout, outbuf);
    + if (outbio)
    + err = ide_bio_taskfile(drive, &args, q, outbio);
    + else
    + err = ide_diag_taskfile(drive, &args, taskout, outbuf);
    break;
    case TASKFILE_OUT:
    args.prehandler = &pre_task_out_intr;
    args.handler = &task_out_intr;
    - err = ide_diag_taskfile(drive, &args, taskout, outbuf);
    + if (outbio)
    + err = ide_bio_taskfile(drive, &args, q, outbio);
    + else
    + err = ide_diag_taskfile(drive, &args, taskout, outbuf);
    break;
    case TASKFILE_MULTI_IN:
    if (!drive->mult_count) {
    @@ -1193,11 +1265,17 @@
    goto abort;
    }
    args.handler = &task_mulin_intr;
    - err = ide_diag_taskfile(drive, &args, taskin, inbuf);
    + if (inbio)
    + err = ide_bio_taskfile(drive, &args, q, inbio);
    + else
    + err = ide_diag_taskfile(drive, &args, taskin, inbuf);
    break;
    case TASKFILE_IN:
    args.handler = &task_in_intr;
    - err = ide_diag_taskfile(drive, &args, taskin, inbuf);
    + if (inbio)
    + err = ide_bio_taskfile(drive, &args, q, inbio);
    + else
    + err = ide_diag_taskfile(drive, &args, taskin, inbuf);
    break;
    case TASKFILE_NO_DATA:
    args.handler = &task_no_data_intr;
    @@ -1208,6 +1286,11 @@
    goto abort;
    }

    + if (outbio)
    + bio_unmap_user(outbio, 0);
    + if (inbio)
    + bio_unmap_user(inbio, 1);
    +
    memcpy(req_task->io_ports, &(args.tfRegister), HDIO_DRIVE_TASK_HDR_SIZE);
    memcpy(req_task->hob_ports, &(args.hobRegister), HDIO_DRIVE_HOB_HDR_SIZE);
    req_task->in_flags = args.tf_in_flags;
    @@ -1217,14 +1300,14 @@
    err = -EFAULT;
    goto abort;
    }
    - if (taskout) {
    + if (outbuf) {
    int outtotal = tasksize;
    if (copy_to_user((void *)arg+outtotal, outbuf, taskout)) {
    err = -EFAULT;
    goto abort;
    }
    }
    - if (taskin) {
    + if (inbuf) {
    int intotal = tasksize + taskout;
    if (copy_to_user((void *)arg+intotal, inbuf, taskin)) {
    err = -EFAULT;
    @@ -1331,6 +1414,9 @@
    u8 xfer_rate = 0;
    int argsize = 0;
    ide_task_t tfargs;
    + int reading = 0, writing = 0;
    + request_queue_t *q;
    + struct bio *bio = NULL;

    if (NULL == (void *) arg) {
    struct request rq;
    @@ -1338,6 +1424,10 @@
    return ide_do_drive_cmd(drive, &rq, ide_wait);
    }

    + q = bdev_get_queue(bdev);
    + if (!q)
    + return -ENXIO;
    +
    if (copy_from_user(args, (void *)arg, 4))
    return -EFAULT;

    @@ -1357,21 +1447,51 @@
    if (drive->media != ide_disk && args[0] == WIN_IDENTIFY)
    tfargs.tfRegister[IDE_COMMAND_OFFSET] = WIN_PIDENTIFY;

    + if (set_transfer(drive, &tfargs)) {
    + xfer_rate = args[1];
    + if (ide_ata66_check(drive, &tfargs))
    + goto abort;
    + }
    +
    + tfargs.command_type = ide_cmd_type_parser(&tfargs);
    +
    if (args[3]) {
    argsize = (SECTOR_WORDS * 4 * args[3]);
    +
    + if (tfargs.command_type == IDE_DRIVE_TASK_OUT ||
    + tfargs.command_type == IDE_DRIVE_TASK_RAW_WRITE)
    + writing = 1;
    + else if (tfargs.command_type == IDE_DRIVE_TASK_IN)
    + reading = 1;
    + else
    + return -EPERM;
    +
    + if (writing && !access_ok(VERIFY_READ, arg+4, argsize))
    + return -EFAULT;
    + else if (reading && !access_ok(VERIFY_WRITE, arg+4, argsize))
    + return -EFAULT;
    +
    + bio = bio_map_user(bdev, arg+4, argsize, reading);
    + if (bio && writing)
    + bio->bi_rw |= (1 << BIO_RW);
    + }
    +
    + if (args[3] && !bio) {
    + printk(KERN_INFO "%s: %s: taking slow-path\n",
    + drive->name, __FUNCTION__);
    + argsize = (SECTOR_WORDS * 4 * args[3]);
    argbuf = kmalloc(argsize, GFP_KERNEL);
    if (argbuf == NULL)
    return -ENOMEM;
    }

    - if (set_transfer(drive, &tfargs)) {
    - xfer_rate = args[1];
    - if (ide_ata66_check(drive, &tfargs))
    - goto abort;
    - }
    + if (bio)
    + err = ide_bio_taskfile(drive, &tfargs, q, bio);
    + else
    + err = ide_raw_taskfile(drive, &tfargs, argbuf);

    - tfargs.command_type = ide_cmd_type_parser(&tfargs);
    - err = ide_raw_taskfile(drive, &tfargs, argbuf);
    + if (bio)
    + bio_unmap_user(bio, reading);

    if (!err && xfer_rate) {
    /* active-retuning-calls future */
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2005-03-22 13:34    [W:0.039 / U:0.244 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site