]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 15 Jul 2008 18:15:36 +0000 (11:15 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 15 Jul 2008 18:15:36 +0000 (11:15 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6: (80 commits)
  ide-floppy: fix unfortunate function naming
  ide-tape: unify idetape_create_read/write_cmd
  ide: add ide_pc_intr() helper
  ide-{floppy,scsi}: read Status Register before stopping DMA engine
  ide-scsi: add more debugging to idescsi_pc_intr()
  ide-scsi: use pc->callback
  ide-floppy: add more debugging to idefloppy_pc_intr()
  ide-tape: always log debug info in idetape_pc_intr() if debugging is enabled
  ide-tape: add ide_tape_io_buffers() helper
  ide-tape: factor out DSC handling from idetape_pc_intr()
  ide-{floppy,tape}: move checking of ->failed_pc to ->callback
  ide: add ide_issue_pc() helper
  ide: add PC_FLAG_DRQ_INTERRUPT pc flag
  ide-scsi: move idescsi_map_sg() call out from idescsi_issue_pc()
  ide: add ide_transfer_pc() helper
  ide-scsi: set drive->scsi flag for devices handled by the driver
  ide-{cd,floppy,tape}: remove checking for drive->scsi
  ide: add PC_FLAG_ZIP_DRIVE pc flag
  ide-tape: factor out waiting for good ireason from idetape_transfer_pc()
  ide-tape: set PC_FLAG_DMA_IN_PROGRESS flag in idetape_transfer_pc()
  ...

1  2 
Documentation/kernel-parameters.txt
block/blk-core.c
drivers/ide/ide-tape.c
include/linux/blkdev.h

index 4720f8ca211a1a61546cd07b7f5b7713dedd1c2b,faeea507cdca7b3889fab39ff99a11978cff80dd..312fe77764a48cba9fb04e000fc2dffeba7fa978
@@@ -271,17 -271,6 +271,17 @@@ and is between 256 and 4096 characters
        aic79xx=        [HW,SCSI]
                        See Documentation/scsi/aic79xx.txt.
  
 +      amd_iommu=      [HW,X86-84]
 +                      Pass parameters to the AMD IOMMU driver in the system.
 +                      Possible values are:
 +                      isolate - enable device isolation (each device, as far
 +                                as possible, will get its own protection
 +                                domain)
 +      amd_iommu_size= [HW,X86-64]
 +                      Define the size of the aperture for the AMD IOMMU
 +                      driver. Possible values are:
 +                      '32M', '64M' (default), '128M', '256M', '512M', '1G'
 +
        amijoy.map=     [HW,JOY] Amiga joystick support
                        Map of devices attached to JOY0DAT and JOY1DAT
                        Format: <a>,<b>
  
        debug_objects   [KNL] Enable object debugging
  
 +      debugpat        [X86] Enable PAT debugging
 +
        decnet.addr=    [HW,NET]
                        Format: <area>[,<node>]
                        See also Documentation/networking/decnet.txt.
                        See drivers/char/README.epca and
                        Documentation/digiepca.txt.
  
 +      disable_mtrr_cleanup [X86]
 +      enable_mtrr_cleanup [X86]
 +                      The kernel tries to adjust MTRR layout from continuous
 +                      to discrete, to make X server driver able to add WB
 +                      entry later. This parameter enables/disables that.
 +
 +      mtrr_chunk_size=nn[KMG] [X86]
 +                      used for mtrr cleanup. It is largest continous chunk
 +                      that could hold holes aka. UC entries.
 +
 +      mtrr_gran_size=nn[KMG] [X86]
 +                      Used for mtrr cleanup. It is granularity of mtrr block.
 +                      Default is 1.
 +                      Large value could prevent small alignment from
 +                      using up MTRRs.
 +
 +      mtrr_spare_reg_nr=n [X86]
 +                      Format: <integer>
 +                      Range: 0,7 : spare reg number
 +                      Default : 1
 +                      Used for mtrr cleanup. It is spare mtrr entries number.
 +                      Set to 2 or more if your graphical card needs more.
 +
        disable_mtrr_trim [X86, Intel and AMD only]
                        By default the kernel will trim any uncacheable
                        memory out of your available memory pool based on
        hd=             [EIDE] (E)IDE hard drive subsystem geometry
                        Format: <cyl>,<head>,<sect>
  
-       hd?=            [HW] (E)IDE subsystem
-       hd?lun=         See Documentation/ide/ide.txt.
        highmem=nn[KMG] [KNL,BOOT] forces the highmem zone to have an exact
                        size of <nn>. This works even on boxes that have no
                        highmem otherwise. This also works to reduce highmem
        mtdparts=       [MTD]
                        See drivers/mtd/cmdlinepart.c.
  
 +      mtdset=         [ARM]
 +                      ARM/S3C2412 JIVE boot control
 +
 +                      See arch/arm/mach-s3c2412/mach-jive.c
 +
        mtouchusb.raw_coordinates=
                        [HW] Make the MicroTouch USB driver use raw coordinates
                        ('y', default) or cooked coordinates ('n')
                        Format: { parport<nr> | timid | 0 }
                        See also Documentation/parport.txt.
  
 +      pmtmr=          [X86] Manual setup of pmtmr I/O Port. 
 +                      Override pmtimer IOPort with a hex value.
 +                      e.g. pmtmr=0x508
 +
        pnpacpi=        [ACPI]
                        { off }
  
        usbhid.mousepoll=
                        [USBHID] The interval which mice are to be polled at.
  
 +      add_efi_memmap  [EFI; x86-32,X86-64] Include EFI memory map in
 +                      kernel's map of available physical RAM.
 +
        vdso=           [X86-32,SH,x86-64]
                        vdso=2: enable compat VDSO (default with COMPAT_VDSO)
                        vdso=1: enable VDSO (default)
diff --combined block/blk-core.c
index c6e536597c8a824bbe29c6a8ac6296d6d87d1a6b,ac83cf9a19ae1308cf25e5f6dc07ab4241632be1..fef79ccb2a118da2f6f3144c993c8338c7205351
@@@ -143,10 -143,6 +143,10 @@@ static void req_bio_endio(struct reques
  
                bio->bi_size -= nbytes;
                bio->bi_sector += (nbytes >> 9);
 +
 +              if (bio_integrity(bio))
 +                      bio_integrity_advance(bio, nbytes);
 +
                if (bio->bi_size == 0)
                        bio_endio(bio, error);
        } else {
@@@ -205,7 -201,8 +205,7 @@@ void blk_plug_device(struct request_que
        if (blk_queue_stopped(q))
                return;
  
 -      if (!test_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) {
 -              __set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags);
 +      if (!queue_flag_test_and_set(QUEUE_FLAG_PLUGGED, q)) {
                mod_timer(&q->unplug_timer, jiffies + q->unplug_delay);
                blk_add_trace_generic(q, NULL, 0, BLK_TA_PLUG);
        }
@@@ -220,9 -217,10 +220,9 @@@ int blk_remove_plug(struct request_queu
  {
        WARN_ON(!irqs_disabled());
  
 -      if (!test_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags))
 +      if (!queue_flag_test_and_clear(QUEUE_FLAG_PLUGGED, q))
                return 0;
  
 -      queue_flag_clear(QUEUE_FLAG_PLUGGED, q);
        del_timer(&q->unplug_timer);
        return 1;
  }
@@@ -326,7 -324,8 +326,7 @@@ void blk_start_queue(struct request_que
         * one level of recursion is ok and is much faster than kicking
         * the unplug handling
         */
 -      if (!test_bit(QUEUE_FLAG_REENTER, &q->queue_flags)) {
 -              queue_flag_set(QUEUE_FLAG_REENTER, q);
 +      if (!queue_flag_test_and_set(QUEUE_FLAG_REENTER, q)) {
                q->request_fn(q);
                queue_flag_clear(QUEUE_FLAG_REENTER, q);
        } else {
@@@ -391,7 -390,8 +391,7 @@@ void __blk_run_queue(struct request_que
         * handling reinvoke the handler shortly if we already got there.
         */
        if (!elv_queue_empty(q)) {
 -              if (!test_bit(QUEUE_FLAG_REENTER, &q->queue_flags)) {
 -                      queue_flag_set(QUEUE_FLAG_REENTER, q);
 +              if (!queue_flag_test_and_set(QUEUE_FLAG_REENTER, q)) {
                        q->request_fn(q);
                        queue_flag_clear(QUEUE_FLAG_REENTER, q);
                } else {
@@@ -1042,15 -1042,9 +1042,9 @@@ void blk_put_request(struct request *re
        unsigned long flags;
        struct request_queue *q = req->q;
  
-       /*
-        * Gee, IDE calls in w/ NULL q.  Fix IDE and remove the
-        * following if (q) test.
-        */
-       if (q) {
-               spin_lock_irqsave(q->queue_lock, flags);
-               __blk_put_request(q, req);
-               spin_unlock_irqrestore(q->queue_lock, flags);
-       }
+       spin_lock_irqsave(q->queue_lock, flags);
+       __blk_put_request(q, req);
+       spin_unlock_irqrestore(q->queue_lock, flags);
  }
  EXPORT_SYMBOL(blk_put_request);
  
@@@ -1381,9 -1375,6 +1375,9 @@@ end_io
                 */
                blk_partition_remap(bio);
  
 +              if (bio_integrity_enabled(bio) && bio_integrity_prep(bio))
 +                      goto end_io;
 +
                if (old_sector != -1)
                        blk_add_trace_remap(q, bio, old_dev, bio->bi_sector,
                                            old_sector);
@@@ -2048,7 -2039,7 +2042,7 @@@ int __init blk_dev_init(void
        for_each_possible_cpu(i)
                INIT_LIST_HEAD(&per_cpu(blk_cpu_done, i));
  
 -      open_softirq(BLOCK_SOFTIRQ, blk_done_softirq, NULL);
 +      open_softirq(BLOCK_SOFTIRQ, blk_done_softirq);
        register_hotcpu_notifier(&blk_cpu_notifier);
  
        return 0;
diff --combined drivers/ide/ide-tape.c
index a3d228302d2019ece45d2b4253cffafab226dd90,6e1233bdf3a0701243bccad7c5d316bf941631f6..f9cf1670e4e18d7a2b55d1c171ff3bbe859db31f
@@@ -144,9 -144,6 +144,6 @@@ enum 
  
  /*************************** End of tunable parameters ***********************/
  
- /* Read/Write error simulation */
- #define SIMULATE_ERRORS                       0
  /* tape directions */
  enum {
        IDETAPE_DIR_NONE  = (1 << 0),
@@@ -442,7 -439,7 +439,7 @@@ static void idetape_output_buffers(ide_
        }
  }
  
- static void idetape_update_buffers(struct ide_atapi_pc *pc)
+ static void idetape_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc)
  {
        struct idetape_bh *bh = pc->bh;
        int count;
@@@ -506,18 -503,6 +503,6 @@@ static struct request *idetape_next_rq_
        return (&tape->rq_stack[tape->rq_stack_index++]);
  }
  
- static void idetape_init_pc(struct ide_atapi_pc *pc)
- {
-       memset(pc->c, 0, 12);
-       pc->retries = 0;
-       pc->flags = 0;
-       pc->req_xfer = 0;
-       pc->buf = pc->pc_buf;
-       pc->buf_size = IDETAPE_PC_BUFFER_SIZE;
-       pc->bh = NULL;
-       pc->b_data = NULL;
- }
  /*
   * called on each failed packet command retry to analyze the request sense. We
   * currently do not utilize this information.
@@@ -538,8 -523,8 +523,8 @@@ static void idetape_analyze_error(ide_d
        if (pc->flags & PC_FLAG_DMA_ERROR) {
                pc->xferred = pc->req_xfer -
                        tape->blk_size *
-                       be32_to_cpu(get_unaligned((u32 *)&sense[3]));
-               idetape_update_buffers(pc);
+                       get_unaligned_be32(&sense[3]);
+               idetape_update_buffers(drive, pc);
        }
  
        /*
@@@ -634,21 -619,78 +619,78 @@@ static int idetape_end_request(ide_driv
        return 0;
  }
  
- static ide_startstop_t idetape_request_sense_callback(ide_drive_t *drive)
+ static void ide_tape_callback(ide_drive_t *drive)
  {
        idetape_tape_t *tape = drive->driver_data;
+       struct ide_atapi_pc *pc = tape->pc;
+       int uptodate = pc->error ? 0 : 1;
  
        debug_log(DBG_PROCS, "Enter %s\n", __func__);
  
-       if (!tape->pc->error) {
-               idetape_analyze_error(drive, tape->pc->buf);
-               idetape_end_request(drive, 1, 0);
-       } else {
-               printk(KERN_ERR "ide-tape: Error in REQUEST SENSE itself - "
-                               "Aborting request!\n");
-               idetape_end_request(drive, 0, 0);
+       if (tape->failed_pc == pc)
+               tape->failed_pc = NULL;
+       if (pc->c[0] == REQUEST_SENSE) {
+               if (uptodate)
+                       idetape_analyze_error(drive, pc->buf);
+               else
+                       printk(KERN_ERR "ide-tape: Error in REQUEST SENSE "
+                                       "itself - Aborting request!\n");
+       } else if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) {
+               struct request *rq = drive->hwif->hwgroup->rq;
+               int blocks = pc->xferred / tape->blk_size;
+               tape->avg_size += blocks * tape->blk_size;
+               if (time_after_eq(jiffies, tape->avg_time + HZ)) {
+                       tape->avg_speed = tape->avg_size * HZ /
+                               (jiffies - tape->avg_time) / 1024;
+                       tape->avg_size = 0;
+                       tape->avg_time = jiffies;
+               }
+               tape->first_frame += blocks;
+               rq->current_nr_sectors -= blocks;
+               if (pc->error)
+                       uptodate = pc->error;
+       } else if (pc->c[0] == READ_POSITION && uptodate) {
+               u8 *readpos = tape->pc->buf;
+               debug_log(DBG_SENSE, "BOP - %s\n",
+                               (readpos[0] & 0x80) ? "Yes" : "No");
+               debug_log(DBG_SENSE, "EOP - %s\n",
+                               (readpos[0] & 0x40) ? "Yes" : "No");
+               if (readpos[0] & 0x4) {
+                       printk(KERN_INFO "ide-tape: Block location is unknown"
+                                        "to the tape\n");
+                       clear_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags);
+                       uptodate = 0;
+               } else {
+                       debug_log(DBG_SENSE, "Block Location - %u\n",
+                                       be32_to_cpu(*(u32 *)&readpos[4]));
+                       tape->partition = readpos[1];
+                       tape->first_frame = be32_to_cpu(*(u32 *)&readpos[4]);
+                       set_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags);
+               }
        }
-       return ide_stopped;
+       idetape_end_request(drive, uptodate, 0);
+ }
+ static void idetape_init_pc(struct ide_atapi_pc *pc)
+ {
+       memset(pc->c, 0, 12);
+       pc->retries = 0;
+       pc->flags = 0;
+       pc->req_xfer = 0;
+       pc->buf = pc->pc_buf;
+       pc->buf_size = IDETAPE_PC_BUFFER_SIZE;
+       pc->bh = NULL;
+       pc->b_data = NULL;
+       pc->callback = ide_tape_callback;
  }
  
  static void idetape_create_request_sense_cmd(struct ide_atapi_pc *pc)
        pc->c[0] = REQUEST_SENSE;
        pc->c[4] = 20;
        pc->req_xfer = 20;
-       pc->idetape_callback = &idetape_request_sense_callback;
  }
  
  static void idetape_init_rq(struct request *rq, u8 cmd)
@@@ -688,9 -729,10 +729,10 @@@ static void idetape_queue_pc_head(ide_d
        struct ide_tape_obj *tape = drive->driver_data;
  
        idetape_init_rq(rq, REQ_IDETAPE_PC1);
+       rq->cmd_flags |= REQ_PREEMPT;
        rq->buffer = (char *) pc;
        rq->rq_disk = tape->disk;
-       (void) ide_do_drive_cmd(drive, rq, ide_preempt);
+       ide_do_drive_cmd(drive, rq);
  }
  
  /*
   *    last packet command. We queue a request sense packet command in
   *    the head of the request list.
   */
- static ide_startstop_t idetape_retry_pc (ide_drive_t *drive)
+ static void idetape_retry_pc(ide_drive_t *drive)
  {
        idetape_tape_t *tape = drive->driver_data;
        struct ide_atapi_pc *pc;
        idetape_create_request_sense_cmd(pc);
        set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags);
        idetape_queue_pc_head(drive, pc, rq);
-       return ide_stopped;
  }
  
  /*
@@@ -727,7 -768,26 +768,26 @@@ static void idetape_postpone_request(id
        ide_stall_queue(drive, tape->dsc_poll_freq);
  }
  
- typedef void idetape_io_buf(ide_drive_t *, struct ide_atapi_pc *, unsigned int);
+ static void ide_tape_handle_dsc(ide_drive_t *drive)
+ {
+       idetape_tape_t *tape = drive->driver_data;
+       /* Media access command */
+       tape->dsc_polling_start = jiffies;
+       tape->dsc_poll_freq = IDETAPE_DSC_MA_FAST;
+       tape->dsc_timeout = jiffies + IDETAPE_DSC_MA_TIMEOUT;
+       /* Allow ide.c to handle other requests */
+       idetape_postpone_request(drive);
+ }
+ static void ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
+                               unsigned int bcount, int write)
+ {
+       if (write)
+               idetape_output_buffers(drive, pc, bcount);
+       else
+               idetape_input_buffers(drive, pc, bcount);
+ }
  
  /*
   * This is the usual interrupt handler which will be called during a packet
   */
  static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
  {
-       ide_hwif_t *hwif = drive->hwif;
        idetape_tape_t *tape = drive->driver_data;
-       struct ide_atapi_pc *pc = tape->pc;
-       xfer_func_t *xferfunc;
-       idetape_io_buf *iobuf;
-       unsigned int temp;
- #if SIMULATE_ERRORS
-       static int error_sim_count;
- #endif
-       u16 bcount;
-       u8 stat, ireason;
-       debug_log(DBG_PROCS, "Enter %s - interrupt handler\n", __func__);
-       /* Clear the interrupt */
-       stat = ide_read_status(drive);
-       if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
-               if (hwif->dma_ops->dma_end(drive) || (stat & ERR_STAT)) {
-                       /*
-                        * A DMA error is sometimes expected. For example,
-                        * if the tape is crossing a filemark during a
-                        * READ command, it will issue an irq and position
-                        * itself before the filemark, so that only a partial
-                        * data transfer will occur (which causes the DMA
-                        * error). In that case, we will later ask the tape
-                        * how much bytes of the original request were
-                        * actually transferred (we can't receive that
-                        * information from the DMA engine on most chipsets).
-                        */
-                       /*
-                        * On the contrary, a DMA error is never expected;
-                        * it usually indicates a hardware error or abort.
-                        * If the tape crosses a filemark during a READ
-                        * command, it will issue an irq and position itself
-                        * after the filemark (not before). Only a partial
-                        * data transfer will occur, but no DMA error.
-                        * (AS, 19 Apr 2001)
-                        */
-                       pc->flags |= PC_FLAG_DMA_ERROR;
-               } else {
-                       pc->xferred = pc->req_xfer;
-                       idetape_update_buffers(pc);
-               }
-               debug_log(DBG_PROCS, "DMA finished\n");
-       }
-       /* No more interrupts */
-       if ((stat & DRQ_STAT) == 0) {
-               debug_log(DBG_SENSE, "Packet command completed, %d bytes"
-                               " transferred\n", pc->xferred);
-               pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
-               local_irq_enable();
  
- #if SIMULATE_ERRORS
-               if ((pc->c[0] == WRITE_6 || pc->c[0] == READ_6) &&
-                   (++error_sim_count % 100) == 0) {
-                       printk(KERN_INFO "ide-tape: %s: simulating error\n",
-                               tape->name);
-                       stat |= ERR_STAT;
-               }
- #endif
-               if ((stat & ERR_STAT) && pc->c[0] == REQUEST_SENSE)
-                       stat &= ~ERR_STAT;
-               if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) {
-                       /* Error detected */
-                       debug_log(DBG_ERR, "%s: I/O error\n", tape->name);
-                       if (pc->c[0] == REQUEST_SENSE) {
-                               printk(KERN_ERR "ide-tape: I/O error in request"
-                                               " sense command\n");
-                               return ide_do_reset(drive);
-                       }
-                       debug_log(DBG_ERR, "[cmd %x]: check condition\n",
-                                       pc->c[0]);
-                       /* Retry operation */
-                       return idetape_retry_pc(drive);
-               }
-               pc->error = 0;
-               if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) &&
-                   (stat & SEEK_STAT) == 0) {
-                       /* Media access command */
-                       tape->dsc_polling_start = jiffies;
-                       tape->dsc_poll_freq = IDETAPE_DSC_MA_FAST;
-                       tape->dsc_timeout = jiffies + IDETAPE_DSC_MA_TIMEOUT;
-                       /* Allow ide.c to handle other requests */
-                       idetape_postpone_request(drive);
-                       return ide_stopped;
-               }
-               if (tape->failed_pc == pc)
-                       tape->failed_pc = NULL;
-               /* Command finished - Call the callback function */
-               return pc->idetape_callback(drive);
-       }
-       if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
-               pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
-               printk(KERN_ERR "ide-tape: The tape wants to issue more "
-                               "interrupts in DMA mode\n");
-               printk(KERN_ERR "ide-tape: DMA disabled, reverting to PIO\n");
-               ide_dma_off(drive);
-               return ide_do_reset(drive);
-       }
-       /* Get the number of bytes to transfer on this interrupt. */
-       bcount = (hwif->INB(hwif->io_ports.lbah_addr) << 8) |
-                 hwif->INB(hwif->io_ports.lbam_addr);
-       ireason = hwif->INB(hwif->io_ports.nsect_addr);
-       if (ireason & CD) {
-               printk(KERN_ERR "ide-tape: CoD != 0 in %s\n", __func__);
-               return ide_do_reset(drive);
-       }
-       if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) {
-               /* Hopefully, we will never get here */
-               printk(KERN_ERR "ide-tape: We wanted to %s, ",
-                               (ireason & IO) ? "Write" : "Read");
-               printk(KERN_ERR "ide-tape: but the tape wants us to %s !\n",
-                               (ireason & IO) ? "Read" : "Write");
-               return ide_do_reset(drive);
-       }
-       if (!(pc->flags & PC_FLAG_WRITING)) {
-               /* Reading - Check that we have enough space */
-               temp = pc->xferred + bcount;
-               if (temp > pc->req_xfer) {
-                       if (temp > pc->buf_size) {
-                               printk(KERN_ERR "ide-tape: The tape wants to "
-                                       "send us more data than expected "
-                                       "- discarding data\n");
-                               ide_pad_transfer(drive, 0, bcount);
-                               ide_set_handler(drive, &idetape_pc_intr,
-                                               IDETAPE_WAIT_CMD, NULL);
-                               return ide_started;
-                       }
-                       debug_log(DBG_SENSE, "The tape wants to send us more "
-                               "data than expected - allowing transfer\n");
-               }
-               iobuf = &idetape_input_buffers;
-               xferfunc = hwif->input_data;
-       } else {
-               iobuf = &idetape_output_buffers;
-               xferfunc = hwif->output_data;
-       }
-       if (pc->bh)
-               iobuf(drive, pc, bcount);
-       else
-               xferfunc(drive, NULL, pc->cur_pos, bcount);
-       /* Update the current position */
-       pc->xferred += bcount;
-       pc->cur_pos += bcount;
-       debug_log(DBG_SENSE, "[cmd %x] transferred %d bytes on that intr.\n",
-                       pc->c[0], bcount);
-       /* And set the interrupt handler again */
-       ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
-       return ide_started;
+       return ide_pc_intr(drive, tape->pc, idetape_pc_intr, IDETAPE_WAIT_CMD,
+                          NULL, idetape_update_buffers, idetape_retry_pc,
+                          ide_tape_handle_dsc, ide_tape_io_buffers);
  }
  
  /*
   */
  static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
  {
-       ide_hwif_t *hwif = drive->hwif;
        idetape_tape_t *tape = drive->driver_data;
-       struct ide_atapi_pc *pc = tape->pc;
-       int retries = 100;
-       ide_startstop_t startstop;
-       u8 ireason;
-       if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) {
-               printk(KERN_ERR "ide-tape: Strange, packet command initiated "
-                               "yet DRQ isn't asserted\n");
-               return startstop;
-       }
-       ireason = hwif->INB(hwif->io_ports.nsect_addr);
-       while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) {
-               printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing "
-                               "a packet command, retrying\n");
-               udelay(100);
-               ireason = hwif->INB(hwif->io_ports.nsect_addr);
-               if (retries == 0) {
-                       printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while "
-                                       "issuing a packet command, ignoring\n");
-                       ireason |= CD;
-                       ireason &= ~IO;
-               }
-       }
-       if ((ireason & CD) == 0 || (ireason & IO)) {
-               printk(KERN_ERR "ide-tape: (IO,CoD) != (0,1) while issuing "
-                               "a packet command\n");
-               return ide_do_reset(drive);
-       }
-       /* Set the interrupt routine */
-       ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
- #ifdef CONFIG_BLK_DEV_IDEDMA
-       /* Begin DMA, if necessary */
-       if (pc->flags & PC_FLAG_DMA_IN_PROGRESS)
-               hwif->dma_ops->dma_start(drive);
- #endif
-       /* Send the actual packet */
-       hwif->output_data(drive, NULL, pc->c, 12);
  
-       return ide_started;
+       return ide_transfer_pc(drive, tape->pc, idetape_pc_intr,
+                              IDETAPE_WAIT_CMD, NULL);
  }
  
  static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
                struct ide_atapi_pc *pc)
  {
-       ide_hwif_t *hwif = drive->hwif;
        idetape_tape_t *tape = drive->driver_data;
-       int dma_ok = 0;
-       u16 bcount;
  
        if (tape->pc->c[0] == REQUEST_SENSE &&
            pc->c[0] == REQUEST_SENSE) {
                        pc->error = IDETAPE_ERROR_GENERAL;
                }
                tape->failed_pc = NULL;
-               return pc->idetape_callback(drive);
+               pc->callback(drive);
+               return ide_stopped;
        }
        debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]);
  
        pc->retries++;
-       /* We haven't transferred any data yet */
-       pc->xferred = 0;
-       pc->cur_pos = pc->buf;
-       /* Request to transfer the entire buffer at once */
-       bcount = pc->req_xfer;
  
-       if (pc->flags & PC_FLAG_DMA_ERROR) {
-               pc->flags &= ~PC_FLAG_DMA_ERROR;
-               printk(KERN_WARNING "ide-tape: DMA disabled, "
-                               "reverting to PIO\n");
-               ide_dma_off(drive);
-       }
-       if ((pc->flags & PC_FLAG_DMA_RECOMMENDED) && drive->using_dma)
-               dma_ok = !hwif->dma_ops->dma_setup(drive);
-       ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK |
-                          IDE_TFLAG_OUT_DEVICE, bcount, dma_ok);
-       if (dma_ok)
-               /* Will begin DMA later */
-               pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
-       if (test_bit(IDETAPE_FLAG_DRQ_INTERRUPT, &tape->flags)) {
-               ide_execute_command(drive, WIN_PACKETCMD, &idetape_transfer_pc,
-                                   IDETAPE_WAIT_CMD, NULL);
-               return ide_started;
-       } else {
-               ide_execute_pkt_cmd(drive);
-               return idetape_transfer_pc(drive);
-       }
- }
- static ide_startstop_t idetape_pc_callback(ide_drive_t *drive)
- {
-       idetape_tape_t *tape = drive->driver_data;
-       debug_log(DBG_PROCS, "Enter %s\n", __func__);
-       idetape_end_request(drive, tape->pc->error ? 0 : 1, 0);
-       return ide_stopped;
+       return ide_issue_pc(drive, pc, idetape_transfer_pc,
+                           IDETAPE_WAIT_CMD, NULL);
  }
  
  /* A mode sense command is used to "sense" tape parameters. */
@@@ -1096,7 -923,6 +923,6 @@@ static void idetape_create_mode_sense_c
                pc->req_xfer = 24;
        else
                pc->req_xfer = 50;
-       pc->idetape_callback = &idetape_pc_callback;
  }
  
  static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
                                printk(KERN_ERR "ide-tape: %s: I/O error, ",
                                                tape->name);
                        /* Retry operation */
-                       return idetape_retry_pc(drive);
+                       idetape_retry_pc(drive);
+                       return ide_stopped;
                }
                pc->error = 0;
-               if (tape->failed_pc == pc)
-                       tape->failed_pc = NULL;
        } else {
                pc->error = IDETAPE_ERROR_GENERAL;
                tape->failed_pc = NULL;
        }
-       return pc->idetape_callback(drive);
- }
- static ide_startstop_t idetape_rw_callback(ide_drive_t *drive)
- {
-       idetape_tape_t *tape = drive->driver_data;
-       struct request *rq = HWGROUP(drive)->rq;
-       int blocks = tape->pc->xferred / tape->blk_size;
-       tape->avg_size += blocks * tape->blk_size;
-       if (time_after_eq(jiffies, tape->avg_time + HZ)) {
-               tape->avg_speed = tape->avg_size * HZ /
-                               (jiffies - tape->avg_time) / 1024;
-               tape->avg_size = 0;
-               tape->avg_time = jiffies;
-       }
-       debug_log(DBG_PROCS, "Enter %s\n", __func__);
-       tape->first_frame += blocks;
-       rq->current_nr_sectors -= blocks;
-       if (!tape->pc->error)
-               idetape_end_request(drive, 1, 0);
-       else
-               idetape_end_request(drive, tape->pc->error, 0);
+       pc->callback(drive);
        return ide_stopped;
  }
  
- static void idetape_create_read_cmd(idetape_tape_t *tape,
-               struct ide_atapi_pc *pc,
-               unsigned int length, struct idetape_bh *bh)
+ static void ide_tape_create_rw_cmd(idetape_tape_t *tape,
+               struct ide_atapi_pc *pc, unsigned int length,
+               struct idetape_bh *bh, u8 opcode)
  {
        idetape_init_pc(pc);
-       pc->c[0] = READ_6;
        put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
        pc->c[1] = 1;
-       pc->idetape_callback = &idetape_rw_callback;
        pc->bh = bh;
-       atomic_set(&bh->b_count, 0);
        pc->buf = NULL;
        pc->buf_size = length * tape->blk_size;
        pc->req_xfer = pc->buf_size;
        if (pc->req_xfer == tape->buffer_size)
-               pc->flags |= PC_FLAG_DMA_RECOMMENDED;
- }
+               pc->flags |= PC_FLAG_DMA_OK;
  
- static void idetape_create_write_cmd(idetape_tape_t *tape,
-               struct ide_atapi_pc *pc,
-               unsigned int length, struct idetape_bh *bh)
- {
-       idetape_init_pc(pc);
-       pc->c[0] = WRITE_6;
-       put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
-       pc->c[1] = 1;
-       pc->idetape_callback = &idetape_rw_callback;
-       pc->flags |= PC_FLAG_WRITING;
-       pc->bh = bh;
-       pc->b_data = bh->b_data;
-       pc->b_count = atomic_read(&bh->b_count);
-       pc->buf = NULL;
-       pc->buf_size = length * tape->blk_size;
-       pc->req_xfer = pc->buf_size;
-       if (pc->req_xfer == tape->buffer_size)
-               pc->flags |= PC_FLAG_DMA_RECOMMENDED;
+       if (opcode == READ_6) {
+               pc->c[0] = READ_6;
+               atomic_set(&bh->b_count, 0);
+       } else if (opcode == WRITE_6) {
+               pc->c[0] = WRITE_6;
+               pc->flags |= PC_FLAG_WRITING;
+               pc->b_data = bh->b_data;
+               pc->b_count = atomic_read(&bh->b_count);
+       }
  }
  
  static ide_startstop_t idetape_do_request(ide_drive_t *drive,
        }
  
        /* Retry a failed packet command */
-       if (tape->failed_pc && tape->pc->c[0] == REQUEST_SENSE)
-               return idetape_issue_pc(drive, tape->failed_pc);
+       if (tape->failed_pc && tape->pc->c[0] == REQUEST_SENSE) {
+               pc = tape->failed_pc;
+               goto out;
+       }
  
        if (postponed_rq != NULL)
                if (rq != postponed_rq) {
        }
        if (rq->cmd[0] & REQ_IDETAPE_READ) {
                pc = idetape_next_pc_storage(drive);
-               idetape_create_read_cmd(tape, pc, rq->current_nr_sectors,
-                                       (struct idetape_bh *)rq->special);
+               ide_tape_create_rw_cmd(tape, pc, rq->current_nr_sectors,
+                                       (struct idetape_bh *)rq->special,
+                                       READ_6);
                goto out;
        }
        if (rq->cmd[0] & REQ_IDETAPE_WRITE) {
                pc = idetape_next_pc_storage(drive);
-               idetape_create_write_cmd(tape, pc, rq->current_nr_sectors,
-                                        (struct idetape_bh *)rq->special);
+               ide_tape_create_rw_cmd(tape, pc, rq->current_nr_sectors,
+                                        (struct idetape_bh *)rq->special,
+                                        WRITE_6);
                goto out;
        }
        if (rq->cmd[0] & REQ_IDETAPE_PC1) {
        }
        BUG();
  out:
+       if (test_bit(IDETAPE_FLAG_DRQ_INTERRUPT, &tape->flags))
+               pc->flags |= PC_FLAG_DRQ_INTERRUPT;
        return idetape_issue_pc(drive, pc);
  }
  
@@@ -1447,40 -1241,6 +1241,6 @@@ static void idetape_init_merge_buffer(i
        }
  }
  
- static ide_startstop_t idetape_read_position_callback(ide_drive_t *drive)
- {
-       idetape_tape_t *tape = drive->driver_data;
-       u8 *readpos = tape->pc->buf;
-       debug_log(DBG_PROCS, "Enter %s\n", __func__);
-       if (!tape->pc->error) {
-               debug_log(DBG_SENSE, "BOP - %s\n",
-                               (readpos[0] & 0x80) ? "Yes" : "No");
-               debug_log(DBG_SENSE, "EOP - %s\n",
-                               (readpos[0] & 0x40) ? "Yes" : "No");
-               if (readpos[0] & 0x4) {
-                       printk(KERN_INFO "ide-tape: Block location is unknown"
-                                        "to the tape\n");
-                       clear_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags);
-                       idetape_end_request(drive, 0, 0);
-               } else {
-                       debug_log(DBG_SENSE, "Block Location - %u\n",
-                                       be32_to_cpu(*(u32 *)&readpos[4]));
-                       tape->partition = readpos[1];
-                       tape->first_frame =
-                               be32_to_cpu(*(u32 *)&readpos[4]);
-                       set_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags);
-                       idetape_end_request(drive, 1, 0);
-               }
-       } else {
-               idetape_end_request(drive, 0, 0);
-       }
-       return ide_stopped;
- }
  /*
   * Write a filemark if write_filemark=1. Flush the device buffers without
   * writing a filemark otherwise.
@@@ -1492,14 -1252,12 +1252,12 @@@ static void idetape_create_write_filema
        pc->c[0] = WRITE_FILEMARKS;
        pc->c[4] = write_filemark;
        pc->flags |= PC_FLAG_WAIT_FOR_DSC;
-       pc->idetape_callback = &idetape_pc_callback;
  }
  
  static void idetape_create_test_unit_ready_cmd(struct ide_atapi_pc *pc)
  {
        idetape_init_pc(pc);
        pc->c[0] = TEST_UNIT_READY;
-       pc->idetape_callback = &idetape_pc_callback;
  }
  
  /*
  static int idetape_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc)
  {
        struct ide_tape_obj *tape = drive->driver_data;
-       struct request rq;
+       struct request *rq;
+       int error;
  
-       idetape_init_rq(&rq, REQ_IDETAPE_PC1);
-       rq.buffer = (char *) pc;
-       rq.rq_disk = tape->disk;
-       return ide_do_drive_cmd(drive, &rq, ide_wait);
+       rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+       rq->cmd_type = REQ_TYPE_SPECIAL;
+       rq->cmd[0] = REQ_IDETAPE_PC1;
+       rq->buffer = (char *)pc;
+       error = blk_execute_rq(drive->queue, tape->disk, rq, 0);
+       blk_put_request(rq);
+       return error;
  }
  
  static void idetape_create_load_unload_cmd(ide_drive_t *drive,
        pc->c[0] = START_STOP;
        pc->c[4] = cmd;
        pc->flags |= PC_FLAG_WAIT_FOR_DSC;
-       pc->idetape_callback = &idetape_pc_callback;
  }
  
  static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
@@@ -1585,7 -1346,6 +1346,6 @@@ static void idetape_create_read_positio
        idetape_init_pc(pc);
        pc->c[0] = READ_POSITION;
        pc->req_xfer = 20;
-       pc->idetape_callback = &idetape_read_position_callback;
  }
  
  static int idetape_read_position(ide_drive_t *drive)
@@@ -1613,7 -1373,6 +1373,6 @@@ static void idetape_create_locate_cmd(i
        put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[3]);
        pc->c[8] = partition;
        pc->flags |= PC_FLAG_WAIT_FOR_DSC;
-       pc->idetape_callback = &idetape_pc_callback;
  }
  
  static int idetape_create_prevent_cmd(ide_drive_t *drive,
        idetape_init_pc(pc);
        pc->c[0] = ALLOW_MEDIUM_REMOVAL;
        pc->c[4] = prevent;
-       pc->idetape_callback = &idetape_pc_callback;
        return 1;
  }
  
@@@ -1700,26 -1458,33 +1458,33 @@@ static int idetape_queue_rw_tail(ide_dr
                                 struct idetape_bh *bh)
  {
        idetape_tape_t *tape = drive->driver_data;
-       struct request rq;
+       struct request *rq;
+       int ret, errors;
  
        debug_log(DBG_SENSE, "%s: cmd=%d\n", __func__, cmd);
  
-       idetape_init_rq(&rq, cmd);
-       rq.rq_disk = tape->disk;
-       rq.special = (void *)bh;
-       rq.sector = tape->first_frame;
-       rq.nr_sectors           = blocks;
-       rq.current_nr_sectors   = blocks;
-       (void) ide_do_drive_cmd(drive, &rq, ide_wait);
+       rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+       rq->cmd_type = REQ_TYPE_SPECIAL;
+       rq->cmd[0] = cmd;
+       rq->rq_disk = tape->disk;
+       rq->special = (void *)bh;
+       rq->sector = tape->first_frame;
+       rq->nr_sectors = blocks;
+       rq->current_nr_sectors = blocks;
+       blk_execute_rq(drive->queue, tape->disk, rq, 0);
+       errors = rq->errors;
+       ret = tape->blk_size * (blocks - rq->current_nr_sectors);
+       blk_put_request(rq);
  
        if ((cmd & (REQ_IDETAPE_READ | REQ_IDETAPE_WRITE)) == 0)
                return 0;
  
        if (tape->merge_bh)
                idetape_init_merge_buffer(tape);
-       if (rq.errors == IDETAPE_ERROR_GENERAL)
+       if (errors == IDETAPE_ERROR_GENERAL)
                return -EIO;
-       return (tape->blk_size * (blocks-rq.current_nr_sectors));
+       return ret;
  }
  
  static void idetape_create_inquiry_cmd(struct ide_atapi_pc *pc)
        pc->c[0] = INQUIRY;
        pc->c[4] = 254;
        pc->req_xfer = 254;
-       pc->idetape_callback = &idetape_pc_callback;
  }
  
  static void idetape_create_rewind_cmd(ide_drive_t *drive,
        idetape_init_pc(pc);
        pc->c[0] = REZERO_UNIT;
        pc->flags |= PC_FLAG_WAIT_FOR_DSC;
-       pc->idetape_callback = &idetape_pc_callback;
  }
  
  static void idetape_create_erase_cmd(struct ide_atapi_pc *pc)
        pc->c[0] = ERASE;
        pc->c[1] = 1;
        pc->flags |= PC_FLAG_WAIT_FOR_DSC;
-       pc->idetape_callback = &idetape_pc_callback;
  }
  
  static void idetape_create_space_cmd(struct ide_atapi_pc *pc, int count, u8 cmd)
        put_unaligned(cpu_to_be32(count), (unsigned int *) &pc->c[1]);
        pc->c[1] = cmd;
        pc->flags |= PC_FLAG_WAIT_FOR_DSC;
-       pc->idetape_callback = &idetape_pc_callback;
  }
  
  /* Queue up a character device originated write request. */
@@@ -2421,12 -2182,9 +2182,12 @@@ static int idetape_chrdev_open(struct i
        if (i >= MAX_HWIFS * MAX_DRIVES)
                return -ENXIO;
  
 +      lock_kernel();
        tape = ide_tape_chrdev_get(i);
 -      if (!tape)
 +      if (!tape) {
 +              unlock_kernel();
                return -ENXIO;
 +      }
  
        debug_log(DBG_CHRDEV, "Enter %s\n", __func__);
  
                        }
                }
        }
 +      unlock_kernel();
        return 0;
  
  out_put_tape:
        ide_tape_put(tape);
 +      unlock_kernel();
        return retval;
  }
  
@@@ -2751,9 -2507,8 +2512,8 @@@ static void idetape_setup(ide_drive_t *
         * Ensure that the number we got makes sense; limit it within
         * IDETAPE_DSC_RW_MIN and IDETAPE_DSC_RW_MAX.
         */
-       tape->best_dsc_rw_freq = max_t(unsigned long,
-                               min_t(unsigned long, t, IDETAPE_DSC_RW_MAX),
-                               IDETAPE_DSC_RW_MIN);
+       tape->best_dsc_rw_freq = clamp_t(unsigned long, t, IDETAPE_DSC_RW_MIN,
+                                        IDETAPE_DSC_RW_MAX);
        printk(KERN_INFO "ide-tape: %s <-> %s: %dKBps, %d*%dkB buffer, "
                "%lums tDSC%s\n",
                drive->name, tape->name, *(u16 *)&tape->caps[14],
@@@ -2905,11 -2660,6 +2665,6 @@@ static int ide_tape_probe(ide_drive_t *
                                " the driver\n", drive->name);
                goto failed;
        }
-       if (drive->scsi) {
-               printk(KERN_INFO "ide-tape: passing drive %s to ide-scsi"
-                                " emulation.\n", drive->name);
-               goto failed;
-       }
        tape = kzalloc(sizeof(idetape_tape_t), GFP_KERNEL);
        if (tape == NULL) {
                printk(KERN_ERR "ide-tape: %s: Can't allocate a tape struct\n",
diff --combined include/linux/blkdev.h
index 1ffd8bfdc4c94956fa14bb8e6c880d79e0953918,1171abd7eb173d215210663e32fbc800985e1272..32a441b05fd5fbedf33748e7151cec38ea27dd90
@@@ -23,6 -23,7 +23,6 @@@
  struct scsi_ioctl_command;
  
  struct request_queue;
 -typedef struct request_queue request_queue_t __deprecated;
  struct elevator_queue;
  typedef struct elevator_queue elevator_t;
  struct request_pm_state;
@@@ -33,6 -34,12 +33,6 @@@ struct sg_io_hdr
  #define BLKDEV_MIN_RQ 4
  #define BLKDEV_MAX_RQ 128     /* Default maximum */
  
 -int put_io_context(struct io_context *ioc);
 -void exit_io_context(void);
 -struct io_context *get_io_context(gfp_t gfp_flags, int node);
 -struct io_context *alloc_io_context(gfp_t gfp_flags, int node);
 -void copy_io_context(struct io_context **pdst, struct io_context **psrc);
 -
  struct request;
  typedef void (rq_end_io_fn)(struct request *, int);
  
@@@ -106,7 -113,6 +106,7 @@@ enum rq_flag_bits 
        __REQ_ALLOCED,          /* request came from our alloc pool */
        __REQ_RW_META,          /* metadata io request */
        __REQ_COPY_USER,        /* contains copies of user pages */
 +      __REQ_INTEGRITY,        /* integrity metadata has been remapped */
        __REQ_NR_BITS,          /* stops here */
  };
  
  #define REQ_ALLOCED   (1 << __REQ_ALLOCED)
  #define REQ_RW_META   (1 << __REQ_RW_META)
  #define REQ_COPY_USER (1 << __REQ_COPY_USER)
 +#define REQ_INTEGRITY (1 << __REQ_INTEGRITY)
  
  #define BLK_MAX_CDB   16
  
@@@ -254,14 -259,7 +254,14 @@@ typedef int (prep_rq_fn) (struct reques
  typedef void (unplug_fn) (struct request_queue *);
  
  struct bio_vec;
 -typedef int (merge_bvec_fn) (struct request_queue *, struct bio *, struct bio_vec *);
 +struct bvec_merge_data {
 +      struct block_device *bi_bdev;
 +      sector_t bi_sector;
 +      unsigned bi_size;
 +      unsigned long bi_rw;
 +};
 +typedef int (merge_bvec_fn) (struct request_queue *, struct bvec_merge_data *,
 +                           struct bio_vec *);
  typedef void (prepare_flush_fn) (struct request_queue *, struct request *);
  typedef void (softirq_done_fn)(struct request *);
  typedef int (dma_drain_needed_fn)(struct request *);
@@@ -428,32 -426,6 +428,32 @@@ static inline void queue_flag_set_unloc
        __set_bit(flag, &q->queue_flags);
  }
  
 +static inline int queue_flag_test_and_clear(unsigned int flag,
 +                                          struct request_queue *q)
 +{
 +      WARN_ON_ONCE(!queue_is_locked(q));
 +
 +      if (test_bit(flag, &q->queue_flags)) {
 +              __clear_bit(flag, &q->queue_flags);
 +              return 1;
 +      }
 +
 +      return 0;
 +}
 +
 +static inline int queue_flag_test_and_set(unsigned int flag,
 +                                        struct request_queue *q)
 +{
 +      WARN_ON_ONCE(!queue_is_locked(q));
 +
 +      if (!test_bit(flag, &q->queue_flags)) {
 +              __set_bit(flag, &q->queue_flags);
 +              return 0;
 +      }
 +
 +      return 1;
 +}
 +
  static inline void queue_flag_set(unsigned int flag, struct request_queue *q)
  {
        WARN_ON_ONCE(!queue_is_locked(q));
@@@ -651,7 -623,6 +651,6 @@@ extern void generic_make_request(struc
  extern void blk_rq_init(struct request_queue *q, struct request *rq);
  extern void blk_put_request(struct request *);
  extern void __blk_put_request(struct request_queue *, struct request *);
- extern void blk_end_sync_rq(struct request *rq, int error);
  extern struct request *blk_get_request(struct request_queue *, int, gfp_t);
  extern void blk_insert_request(struct request_queue *, struct request *, int, void *);
  extern void blk_requeue_request(struct request_queue *, struct request *);
@@@ -704,6 -675,7 +703,6 @@@ extern int blk_execute_rq(struct reques
                          struct request *, int);
  extern void blk_execute_rq_nowait(struct request_queue *, struct gendisk *,
                                  struct request *, int, rq_end_io_fn *);
 -extern int blk_verify_command(unsigned char *, int);
  extern void blk_unplug(struct request_queue *q);
  
  static inline struct request_queue *bdev_get_queue(struct block_device *bdev)
@@@ -776,7 -748,6 +775,7 @@@ extern void blk_queue_max_segment_size(
  extern void blk_queue_hardsect_size(struct request_queue *, unsigned short);
  extern void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b);
  extern void blk_queue_dma_pad(struct request_queue *, unsigned int);
 +extern void blk_queue_update_dma_pad(struct request_queue *, unsigned int);
  extern int blk_queue_dma_drain(struct request_queue *q,
                               dma_drain_needed_fn *dma_drain_needed,
                               void *buf, unsigned int size);
@@@ -830,15 -801,6 +829,15 @@@ static inline struct request *blk_map_q
  
  extern int blkdev_issue_flush(struct block_device *, sector_t *);
  
 +/*
 +* command filter functions
 +*/
 +extern int blk_verify_command(struct file *file, unsigned char *cmd);
 +extern int blk_cmd_filter_verify_command(struct blk_scsi_cmd_filter *filter,
 +                                       unsigned char *cmd, mode_t *f_mode);
 +extern int blk_register_filter(struct gendisk *disk);
 +extern void blk_unregister_filter(struct gendisk *disk);
 +
  #define MAX_PHYS_SEGMENTS 128
  #define MAX_HW_SEGMENTS 128
  #define SAFE_MAX_SECTORS 255
@@@ -902,116 -864,28 +901,116 @@@ void kblockd_flush_work(struct work_str
  #define MODULE_ALIAS_BLOCKDEV_MAJOR(major) \
        MODULE_ALIAS("block-major-" __stringify(major) "-*")
  
 +#if defined(CONFIG_BLK_DEV_INTEGRITY)
  
 -#else /* CONFIG_BLOCK */
 -/*
 - * stubs for when the block layer is configured out
 - */
 -#define buffer_heads_over_limit 0
 +#define INTEGRITY_FLAG_READ   2       /* verify data integrity on read */
 +#define INTEGRITY_FLAG_WRITE  4       /* generate data integrity on write */
  
 -static inline long nr_blockdev_pages(void)
 +struct blk_integrity_exchg {
 +      void                    *prot_buf;
 +      void                    *data_buf;
 +      sector_t                sector;
 +      unsigned int            data_size;
 +      unsigned short          sector_size;
 +      const char              *disk_name;
 +};
 +
 +typedef void (integrity_gen_fn) (struct blk_integrity_exchg *);
 +typedef int (integrity_vrfy_fn) (struct blk_integrity_exchg *);
 +typedef void (integrity_set_tag_fn) (void *, void *, unsigned int);
 +typedef void (integrity_get_tag_fn) (void *, void *, unsigned int);
 +
 +struct blk_integrity {
 +      integrity_gen_fn        *generate_fn;
 +      integrity_vrfy_fn       *verify_fn;
 +      integrity_set_tag_fn    *set_tag_fn;
 +      integrity_get_tag_fn    *get_tag_fn;
 +
 +      unsigned short          flags;
 +      unsigned short          tuple_size;
 +      unsigned short          sector_size;
 +      unsigned short          tag_size;
 +
 +      const char              *name;
 +
 +      struct kobject          kobj;
 +};
 +
 +extern int blk_integrity_register(struct gendisk *, struct blk_integrity *);
 +extern void blk_integrity_unregister(struct gendisk *);
 +extern int blk_integrity_compare(struct block_device *, struct block_device *);
 +extern int blk_rq_map_integrity_sg(struct request *, struct scatterlist *);
 +extern int blk_rq_count_integrity_sg(struct request *);
 +
 +static inline unsigned short blk_integrity_tuple_size(struct blk_integrity *bi)
  {
 +      if (bi)
 +              return bi->tuple_size;
 +
        return 0;
  }
  
 -static inline void exit_io_context(void)
 +static inline struct blk_integrity *bdev_get_integrity(struct block_device *bdev)
  {
 +      return bdev->bd_disk->integrity;
  }
  
 -struct io_context;
 -static inline int put_io_context(struct io_context *ioc)
 +static inline unsigned int bdev_get_tag_size(struct block_device *bdev)
  {
 -      return 1;
 +      struct blk_integrity *bi = bdev_get_integrity(bdev);
 +
 +      if (bi)
 +              return bi->tag_size;
 +
 +      return 0;
 +}
 +
 +static inline int bdev_integrity_enabled(struct block_device *bdev, int rw)
 +{
 +      struct blk_integrity *bi = bdev_get_integrity(bdev);
 +
 +      if (bi == NULL)
 +              return 0;
 +
 +      if (rw == READ && bi->verify_fn != NULL &&
 +          (bi->flags & INTEGRITY_FLAG_READ))
 +              return 1;
 +
 +      if (rw == WRITE && bi->generate_fn != NULL &&
 +          (bi->flags & INTEGRITY_FLAG_WRITE))
 +              return 1;
 +
 +      return 0;
  }
  
 +static inline int blk_integrity_rq(struct request *rq)
 +{
 +      return bio_integrity(rq->bio);
 +}
 +
 +#else /* CONFIG_BLK_DEV_INTEGRITY */
 +
 +#define blk_integrity_rq(rq)                  (0)
 +#define blk_rq_count_integrity_sg(a)          (0)
 +#define blk_rq_map_integrity_sg(a, b)         (0)
 +#define bdev_get_integrity(a)                 (0)
 +#define bdev_get_tag_size(a)                  (0)
 +#define blk_integrity_compare(a, b)           (0)
 +#define blk_integrity_register(a, b)          (0)
 +#define blk_integrity_unregister(a)           do { } while (0);
 +
 +#endif /* CONFIG_BLK_DEV_INTEGRITY */
 +
 +#else /* CONFIG_BLOCK */
 +/*
 + * stubs for when the block layer is configured out
 + */
 +#define buffer_heads_over_limit 0
 +
 +static inline long nr_blockdev_pages(void)
 +{
 +      return 0;
 +}
  
  #endif /* CONFIG_BLOCK */