Merge branch 'post-2.6.15' of git://brick.kernel.dk/data/git/linux-2.6-block
authorLinus Torvalds <torvalds@g5.osdl.org>
Fri, 6 Jan 2006 17:01:25 +0000 (09:01 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Fri, 6 Jan 2006 17:01:25 +0000 (09:01 -0800)
Manual fixup for merge with Jens' "Suspend support for libata", commit
ID 9b847548663ef1039dd49f0eb4463d001e596bc3.

Signed-off-by: Linus Torvalds <torvalds@osdl.org>
1  2 
drivers/block/nbd.c
drivers/message/i2o/i2o_block.c
drivers/s390/block/dasd.c
drivers/s390/char/tape_block.c
drivers/scsi/ata_piix.c
drivers/scsi/libata-core.c
drivers/scsi/libata-scsi.c
include/linux/ata.h
include/linux/libata.h
include/scsi/scsi_host.h

diff --combined drivers/block/nbd.c
index d5c8ee7d98153149325492c90aed1733e2784172,485345c8e6320199782aa01cdcd285b54e177482..33d6f237b2edc8fb4134413d55e58a7d5bb4d7ea
  #include <linux/errno.h>
  #include <linux/file.h>
  #include <linux/ioctl.h>
 +#include <linux/compiler.h>
 +#include <linux/err.h>
 +#include <linux/kernel.h>
  #include <net/sock.h>
  
  #include <linux/devfs_fs_kernel.h>
  
  #include <asm/uaccess.h>
 +#include <asm/system.h>
  #include <asm/types.h>
  
  #include <linux/nbd.h>
@@@ -140,7 -136,7 +140,7 @@@ static void nbd_end_request(struct requ
  
        spin_lock_irqsave(q->queue_lock, flags);
        if (!end_that_request_first(req, uptodate, req->nr_sectors)) {
-               end_that_request_last(req);
+               end_that_request_last(req, uptodate);
        }
        spin_unlock_irqrestore(q->queue_lock, flags);
  }
@@@ -234,6 -230,14 +234,6 @@@ static int nbd_send_req(struct nbd_devi
        request.len = htonl(size);
        memcpy(request.handle, &req, sizeof(req));
  
 -      down(&lo->tx_lock);
 -
 -      if (!sock || !lo->sock) {
 -              printk(KERN_ERR "%s: Attempted send on closed socket\n",
 -                              lo->disk->disk_name);
 -              goto error_out;
 -      }
 -
        dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%luB)\n",
                        lo->disk->disk_name, req,
                        nbdcmd_to_ascii(nbd_cmd(req)),
                        }
                }
        }
 -      up(&lo->tx_lock);
        return 0;
  
  error_out:
 -      up(&lo->tx_lock);
        return 1;
  }
  
@@@ -283,14 -289,9 +283,14 @@@ static struct request *nbd_find_request
        struct request *req;
        struct list_head *tmp;
        struct request *xreq;
 +      int err;
  
        memcpy(&xreq, handle, sizeof(xreq));
  
 +      err = wait_event_interruptible(lo->active_wq, lo->active_req != xreq);
 +      if (unlikely(err))
 +              goto out;
 +
        spin_lock(&lo->queue_lock);
        list_for_each(tmp, &lo->queue_head) {
                req = list_entry(tmp, struct request, queuelist);
                return req;
        }
        spin_unlock(&lo->queue_lock);
 -      return NULL;
 +
 +      err = -ENOENT;
 +
 +out:
 +      return ERR_PTR(err);
  }
  
  static inline int sock_recv_bvec(struct socket *sock, struct bio_vec *bvec)
@@@ -334,11 -331,7 +334,11 @@@ static struct request *nbd_read_stat(st
                goto harderror;
        }
        req = nbd_find_request(lo, reply.handle);
 -      if (req == NULL) {
 +      if (unlikely(IS_ERR(req))) {
 +              result = PTR_ERR(req);
 +              if (result != -ENOENT)
 +                      goto harderror;
 +
                printk(KERN_ERR "%s: Unexpected reply (%p)\n",
                                lo->disk->disk_name, reply.handle);
                result = -EBADR;
@@@ -402,24 -395,19 +402,24 @@@ static void nbd_clear_que(struct nbd_de
  
        BUG_ON(lo->magic != LO_MAGIC);
  
 -      do {
 -              req = NULL;
 -              spin_lock(&lo->queue_lock);
 -              if (!list_empty(&lo->queue_head)) {
 -                      req = list_entry(lo->queue_head.next, struct request, queuelist);
 -                      list_del_init(&req->queuelist);
 -              }
 -              spin_unlock(&lo->queue_lock);
 -              if (req) {
 -                      req->errors++;
 -                      nbd_end_request(req);
 -              }
 -      } while (req);
 +      /*
 +       * Because we have set lo->sock to NULL under the tx_lock, all
 +       * modifications to the list must have completed by now.  For
 +       * the same reason, the active_req must be NULL.
 +       *
 +       * As a consequence, we don't need to take the spin lock while
 +       * purging the list here.
 +       */
 +      BUG_ON(lo->sock);
 +      BUG_ON(lo->active_req);
 +
 +      while (!list_empty(&lo->queue_head)) {
 +              req = list_entry(lo->queue_head.next, struct request,
 +                               queuelist);
 +              list_del_init(&req->queuelist);
 +              req->errors++;
 +              nbd_end_request(req);
 +      }
  }
  
  /*
@@@ -447,6 -435,11 +447,6 @@@ static void do_nbd_request(request_queu
  
                BUG_ON(lo->magic != LO_MAGIC);
  
 -              if (!lo->file) {
 -                      printk(KERN_ERR "%s: Request when not-ready\n",
 -                                      lo->disk->disk_name);
 -                      goto error_out;
 -              }
                nbd_cmd(req) = NBD_CMD_READ;
                if (rq_data_dir(req) == WRITE) {
                        nbd_cmd(req) = NBD_CMD_WRITE;
                req->errors = 0;
                spin_unlock_irq(q->queue_lock);
  
 -              spin_lock(&lo->queue_lock);
 -
 -              if (!lo->file) {
 -                      spin_unlock(&lo->queue_lock);
 -                      printk(KERN_ERR "%s: failed between accept and semaphore, file lost\n",
 -                                      lo->disk->disk_name);
 +              down(&lo->tx_lock);
 +              if (unlikely(!lo->sock)) {
 +                      up(&lo->tx_lock);
 +                      printk(KERN_ERR "%s: Attempted send on closed socket\n",
 +                             lo->disk->disk_name);
                        req->errors++;
                        nbd_end_request(req);
                        spin_lock_irq(q->queue_lock);
                        continue;
                }
  
 -              list_add(&req->queuelist, &lo->queue_head);
 -              spin_unlock(&lo->queue_lock);
 +              lo->active_req = req;
  
                if (nbd_send_req(lo, req) != 0) {
                        printk(KERN_ERR "%s: Request send failed\n",
                                        lo->disk->disk_name);
 -                      if (nbd_find_request(lo, (char *)&req) != NULL) {
 -                              /* we still own req */
 -                              req->errors++;
 -                              nbd_end_request(req);
 -                      } else /* we're racing with nbd_clear_que */
 -                              printk(KERN_DEBUG "nbd: can't find req\n");
 +                      req->errors++;
 +                      nbd_end_request(req);
 +              } else {
 +                      spin_lock(&lo->queue_lock);
 +                      list_add(&req->queuelist, &lo->queue_head);
 +                      spin_unlock(&lo->queue_lock);
                }
  
 +              lo->active_req = NULL;
 +              up(&lo->tx_lock);
 +              wake_up_all(&lo->active_wq);
 +
                spin_lock_irq(q->queue_lock);
                continue;
  
@@@ -538,10 -529,17 +538,10 @@@ static int nbd_ioctl(struct inode *inod
                down(&lo->tx_lock);
                lo->sock = NULL;
                up(&lo->tx_lock);
 -              spin_lock(&lo->queue_lock);
                file = lo->file;
                lo->file = NULL;
 -              spin_unlock(&lo->queue_lock);
                nbd_clear_que(lo);
 -              spin_lock(&lo->queue_lock);
 -              if (!list_empty(&lo->queue_head)) {
 -                      printk(KERN_ERR "nbd: disconnect: some requests are in progress -> please try again.\n");
 -                      error = -EBUSY;
 -              }
 -              spin_unlock(&lo->queue_lock);
 +              BUG_ON(!list_empty(&lo->queue_head));
                if (file)
                        fput(file);
                return error;
                        lo->sock = NULL;
                }
                up(&lo->tx_lock);
 -              spin_lock(&lo->queue_lock);
                file = lo->file;
                lo->file = NULL;
 -              spin_unlock(&lo->queue_lock);
                nbd_clear_que(lo);
                printk(KERN_WARNING "%s: queue cleared\n", lo->disk->disk_name);
                if (file)
                        fput(file);
                return lo->harderror;
        case NBD_CLEAR_QUE:
 -              down(&lo->tx_lock);
 -              if (lo->sock) {
 -                      up(&lo->tx_lock);
 -                      return 0; /* probably should be error, but that would
 -                                 * break "nbd-client -d", so just return 0 */
 -              }
 -              up(&lo->tx_lock);
 -              nbd_clear_que(lo);
 +              /*
 +               * This is for compatibility only.  The queue is always cleared
 +               * by NBD_DO_IT or NBD_CLEAR_SOCK.
 +               */
 +              BUG_ON(!lo->sock && !list_empty(&lo->queue_head));
                return 0;
        case NBD_PRINT_DEBUG:
                printk(KERN_INFO "%s: next = %p, prev = %p, head = %p\n",
@@@ -685,7 -688,6 +685,7 @@@ static int __init nbd_init(void
                spin_lock_init(&nbd_dev[i].queue_lock);
                INIT_LIST_HEAD(&nbd_dev[i].queue_head);
                init_MUTEX(&nbd_dev[i].tx_lock);
 +              init_waitqueue_head(&nbd_dev[i].active_wq);
                nbd_dev[i].blksize = 1024;
                nbd_dev[i].bytesize = 0x7ffffc00ULL << 10; /* 2TB */
                disk->major = NBD_MAJOR;
index c5807d6e85cc0c9a982b1a7f8c0b8fb14b3db9e3,4f522527b7ed60cdff4f14dd40f45c3b49b69254..5b1febed313344e13370583ad799986f95fad700
  #include <linux/blkdev.h>
  #include <linux/hdreg.h>
  
 +#include <scsi/scsi.h>
 +
  #include "i2o_block.h"
  
  #define OSM_NAME      "block-osm"
 -#define OSM_VERSION   "1.287"
 +#define OSM_VERSION   "1.325"
  #define OSM_DESCRIPTION       "I2O Block Device OSM"
  
  static struct i2o_driver i2o_block_driver;
@@@ -132,20 -130,20 +132,20 @@@ static int i2o_block_remove(struct devi
   */
  static int i2o_block_device_flush(struct i2o_device *dev)
  {
 -      struct i2o_message __iomem *msg;
 -      u32 m;
 +      struct i2o_message *msg;
  
 -      m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
 -      if (m == I2O_QUEUE_EMPTY)
 -              return -ETIMEDOUT;
 +      msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
 +      if (IS_ERR(msg))
 +              return PTR_ERR(msg);
  
 -      writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
 -      writel(I2O_CMD_BLOCK_CFLUSH << 24 | HOST_TID << 12 | dev->lct_data.tid,
 -             &msg->u.head[1]);
 -      writel(60 << 16, &msg->body[0]);
 +      msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
 +      msg->u.head[1] =
 +          cpu_to_le32(I2O_CMD_BLOCK_CFLUSH << 24 | HOST_TID << 12 | dev->
 +                      lct_data.tid);
 +      msg->body[0] = cpu_to_le32(60 << 16);
        osm_debug("Flushing...\n");
  
 -      return i2o_msg_post_wait(dev->iop, m, 60);
 +      return i2o_msg_post_wait(dev->iop, msg, 60);
  };
  
  /**
@@@ -183,21 -181,21 +183,21 @@@ static int i2o_block_issue_flush(reques
   */
  static int i2o_block_device_mount(struct i2o_device *dev, u32 media_id)
  {
 -      struct i2o_message __iomem *msg;
 -      u32 m;
 -
 -      m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
 -      if (m == I2O_QUEUE_EMPTY)
 -              return -ETIMEDOUT;
 -
 -      writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
 -      writel(I2O_CMD_BLOCK_MMOUNT << 24 | HOST_TID << 12 | dev->lct_data.tid,
 -             &msg->u.head[1]);
 -      writel(-1, &msg->body[0]);
 -      writel(0, &msg->body[1]);
 +      struct i2o_message *msg;
 +
 +      msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
 +      if (IS_ERR(msg))
 +              return PTR_ERR(msg);
 +
 +      msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
 +      msg->u.head[1] =
 +          cpu_to_le32(I2O_CMD_BLOCK_MMOUNT << 24 | HOST_TID << 12 | dev->
 +                      lct_data.tid);
 +      msg->body[0] = cpu_to_le32(-1);
 +      msg->body[1] = cpu_to_le32(0x00000000);
        osm_debug("Mounting...\n");
  
 -      return i2o_msg_post_wait(dev->iop, m, 2);
 +      return i2o_msg_post_wait(dev->iop, msg, 2);
  };
  
  /**
   */
  static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id)
  {
 -      struct i2o_message __iomem *msg;
 -      u32 m;
 +      struct i2o_message *msg;
  
 -      m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
 -      if (m == I2O_QUEUE_EMPTY)
 -              return -ETIMEDOUT;
 +      msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
 +      if (IS_ERR(msg) == I2O_QUEUE_EMPTY)
 +              return PTR_ERR(msg);
  
 -      writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
 -      writel(I2O_CMD_BLOCK_MLOCK << 24 | HOST_TID << 12 | dev->lct_data.tid,
 -             &msg->u.head[1]);
 -      writel(-1, &msg->body[0]);
 +      msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
 +      msg->u.head[1] =
 +          cpu_to_le32(I2O_CMD_BLOCK_MLOCK << 24 | HOST_TID << 12 | dev->
 +                      lct_data.tid);
 +      msg->body[0] = cpu_to_le32(-1);
        osm_debug("Locking...\n");
  
 -      return i2o_msg_post_wait(dev->iop, m, 2);
 +      return i2o_msg_post_wait(dev->iop, msg, 2);
  };
  
  /**
   */
  static int i2o_block_device_unlock(struct i2o_device *dev, u32 media_id)
  {
 -      struct i2o_message __iomem *msg;
 -      u32 m;
 +      struct i2o_message *msg;
  
 -      m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
 -      if (m == I2O_QUEUE_EMPTY)
 -              return -ETIMEDOUT;
 +      msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
 +      if (IS_ERR(msg))
 +              return PTR_ERR(msg);
  
 -      writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
 -      writel(I2O_CMD_BLOCK_MUNLOCK << 24 | HOST_TID << 12 | dev->lct_data.tid,
 -             &msg->u.head[1]);
 -      writel(media_id, &msg->body[0]);
 +      msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
 +      msg->u.head[1] =
 +          cpu_to_le32(I2O_CMD_BLOCK_MUNLOCK << 24 | HOST_TID << 12 | dev->
 +                      lct_data.tid);
 +      msg->body[0] = cpu_to_le32(media_id);
        osm_debug("Unlocking...\n");
  
 -      return i2o_msg_post_wait(dev->iop, m, 2);
 +      return i2o_msg_post_wait(dev->iop, msg, 2);
  };
  
  /**
@@@ -269,21 -267,21 +269,21 @@@ static int i2o_block_device_power(struc
  {
        struct i2o_device *i2o_dev = dev->i2o_dev;
        struct i2o_controller *c = i2o_dev->iop;
 -      struct i2o_message __iomem *msg;
 -      u32 m;
 +      struct i2o_message *msg;
        int rc;
  
 -      m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
 -      if (m == I2O_QUEUE_EMPTY)
 -              return -ETIMEDOUT;
 +      msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
 +      if (IS_ERR(msg))
 +              return PTR_ERR(msg);
  
 -      writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
 -      writel(I2O_CMD_BLOCK_POWER << 24 | HOST_TID << 12 | i2o_dev->lct_data.
 -             tid, &msg->u.head[1]);
 -      writel(op << 24, &msg->body[0]);
 +      msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
 +      msg->u.head[1] =
 +          cpu_to_le32(I2O_CMD_BLOCK_POWER << 24 | HOST_TID << 12 | i2o_dev->
 +                      lct_data.tid);
 +      msg->body[0] = cpu_to_le32(op << 24);
        osm_debug("Power...\n");
  
 -      rc = i2o_msg_post_wait(c, m, 60);
 +      rc = i2o_msg_post_wait(c, msg, 60);
        if (!rc)
                dev->power = op;
  
@@@ -333,7 -331,7 +333,7 @@@ static inline void i2o_block_request_fr
   */
  static inline int i2o_block_sglist_alloc(struct i2o_controller *c,
                                         struct i2o_block_request *ireq,
 -                                       u32 __iomem ** mptr)
 +                                       u32 ** mptr)
  {
        int nents;
        enum dma_data_direction direction;
@@@ -468,7 -466,7 +468,7 @@@ static void i2o_block_end_request(struc
  
        spin_lock_irqsave(q->queue_lock, flags);
  
-       end_that_request_last(req);
+       end_that_request_last(req, uptodate);
  
        if (likely(dev)) {
                dev->open_queue_depth--;
@@@ -747,9 -745,10 +747,9 @@@ static int i2o_block_transfer(struct re
        struct i2o_block_device *dev = req->rq_disk->private_data;
        struct i2o_controller *c;
        int tid = dev->i2o_dev->lct_data.tid;
 -      struct i2o_message __iomem *msg;
 -      u32 __iomem *mptr;
 +      struct i2o_message *msg;
 +      u32 *mptr;
        struct i2o_block_request *ireq = req->special;
 -      u32 m;
        u32 tcntxt;
        u32 sgl_offset = SGL_OFFSET_8;
        u32 ctl_flags = 0x00000000;
  
        c = dev->i2o_dev->iop;
  
 -      m = i2o_msg_get(c, &msg);
 -      if (m == I2O_QUEUE_EMPTY) {
 -              rc = -EBUSY;
 +      msg = i2o_msg_get(c);
 +      if (IS_ERR(msg)) {
 +              rc = PTR_ERR(msg);
                goto exit;
        }
  
                goto nop_msg;
        }
  
 -      writel(i2o_block_driver.context, &msg->u.s.icntxt);
 -      writel(tcntxt, &msg->u.s.tcntxt);
 +      msg->u.s.icntxt = cpu_to_le32(i2o_block_driver.context);
 +      msg->u.s.tcntxt = cpu_to_le32(tcntxt);
  
        mptr = &msg->body[0];
  
  
                sgl_offset = SGL_OFFSET_12;
  
 -              writel(I2O_CMD_PRIVATE << 24 | HOST_TID << 12 | tid,
 -                     &msg->u.head[1]);
 +              msg->u.head[1] =
 +                  cpu_to_le32(I2O_CMD_PRIVATE << 24 | HOST_TID << 12 | tid);
  
 -              writel(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC, mptr++);
 -              writel(tid, mptr++);
 +              *mptr++ = cpu_to_le32(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC);
 +              *mptr++ = cpu_to_le32(tid);
  
                /*
                 * ENABLE_DISCONNECT
                 * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME
                 */
                if (rq_data_dir(req) == READ) {
 -                      cmd[0] = 0x28;
 +                      cmd[0] = READ_10;
                        scsi_flags = 0x60a0000a;
                } else {
 -                      cmd[0] = 0x2A;
 +                      cmd[0] = WRITE_10;
                        scsi_flags = 0xa0a0000a;
                }
  
 -              writel(scsi_flags, mptr++);
 +              *mptr++ = cpu_to_le32(scsi_flags);
  
                *((u32 *) & cmd[2]) = cpu_to_be32(req->sector * hwsec);
                *((u16 *) & cmd[7]) = cpu_to_be16(req->nr_sectors * hwsec);
  
 -              memcpy_toio(mptr, cmd, 10);
 +              memcpy(mptr, cmd, 10);
                mptr += 4;
 -              writel(req->nr_sectors << KERNEL_SECTOR_SHIFT, mptr++);
 +              *mptr++ = cpu_to_le32(req->nr_sectors << KERNEL_SECTOR_SHIFT);
        } else
  #endif
        {
 -              writel(cmd | HOST_TID << 12 | tid, &msg->u.head[1]);
 -              writel(ctl_flags, mptr++);
 -              writel(req->nr_sectors << KERNEL_SECTOR_SHIFT, mptr++);
 -              writel((u32) (req->sector << KERNEL_SECTOR_SHIFT), mptr++);
 -              writel(req->sector >> (32 - KERNEL_SECTOR_SHIFT), mptr++);
 +              msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid);
 +              *mptr++ = cpu_to_le32(ctl_flags);
 +              *mptr++ = cpu_to_le32(req->nr_sectors << KERNEL_SECTOR_SHIFT);
 +              *mptr++ =
 +                  cpu_to_le32((u32) (req->sector << KERNEL_SECTOR_SHIFT));
 +              *mptr++ =
 +                  cpu_to_le32(req->sector >> (32 - KERNEL_SECTOR_SHIFT));
        }
  
        if (!i2o_block_sglist_alloc(c, ireq, &mptr)) {
                goto context_remove;
        }
  
 -      writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) |
 -             sgl_offset, &msg->u.head[0]);
 +      msg->u.head[0] =
 +          cpu_to_le32(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset);
  
        list_add_tail(&ireq->queue, &dev->open_queue);
        dev->open_queue_depth++;
  
 -      i2o_msg_post(c, m);
 +      i2o_msg_post(c, msg);
  
        return 0;
  
        i2o_cntxt_list_remove(c, req);
  
        nop_msg:
 -      i2o_msg_nop(c, m);
 +      i2o_msg_nop(c, msg);
  
        exit:
        return rc;
@@@ -981,12 -978,13 +981,12 @@@ static struct i2o_block_device *i2o_blo
        struct request_queue *queue;
        int rc;
  
 -      dev = kmalloc(sizeof(*dev), GFP_KERNEL);
 +      dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (!dev) {
                osm_err("Insufficient memory to allocate I2O Block disk.\n");
                rc = -ENOMEM;
                goto exit;
        }
 -      memset(dev, 0, sizeof(*dev));
  
        INIT_LIST_HEAD(&dev->open_queue);
        spin_lock_init(&dev->lock);
@@@ -1051,8 -1049,8 +1051,8 @@@ static int i2o_block_probe(struct devic
        int rc;
        u64 size;
        u32 blocksize;
 -      u32 flags, status;
        u16 body_size = 4;
 +      u16 power;
        unsigned short max_sectors;
  
  #ifdef CONFIG_I2O_EXT_ADAPTEC
         *      Ask for the current media data. If that isn't supported
         *      then we ask for the device capacity data
         */
 -      if (i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) ||
 -          i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) {
 -              blk_queue_hardsect_size(queue, blocksize);
 +      if (!i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) ||
 +          !i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) {
 +              blk_queue_hardsect_size(queue, le32_to_cpu(blocksize));
        } else
                osm_warn("unable to get blocksize of %s\n", gd->disk_name);
  
 -      if (i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) ||
 -          i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) {
 -              set_capacity(gd, size >> KERNEL_SECTOR_SHIFT);
 +      if (!i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) ||
 +          !i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) {
 +              set_capacity(gd, le64_to_cpu(size) >> KERNEL_SECTOR_SHIFT);
        } else
                osm_warn("could not get size of %s\n", gd->disk_name);
  
 -      if (!i2o_parm_field_get(i2o_dev, 0x0000, 2, &i2o_blk_dev->power, 2))
 -              i2o_blk_dev->power = 0;
 -      i2o_parm_field_get(i2o_dev, 0x0000, 5, &flags, 4);
 -      i2o_parm_field_get(i2o_dev, 0x0000, 6, &status, 4);
 +      if (!i2o_parm_field_get(i2o_dev, 0x0000, 2, &power, 2))
 +              i2o_blk_dev->power = power;
  
        i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0xffffffff);
  
index 041e1a621885803b1d6bba97f0194c5703a92841,fdb61380c5237679047a34719f801c3427552deb..f779f674dfa0414b498f1cf0be497e4a87a89291
@@@ -7,7 -7,7 +7,7 @@@
   * Bugreports.to..: <Linux390@de.ibm.com>
   * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
   *
 - * $Revision: 1.167 $
 + * $Revision: 1.172 $
   */
  
  #include <linux/config.h>
@@@ -604,7 -604,7 +604,7 @@@ dasd_smalloc_request(char *magic, int c
  void
  dasd_kfree_request(struct dasd_ccw_req * cqr, struct dasd_device * device)
  {
 -#ifdef CONFIG_ARCH_S390X
 +#ifdef CONFIG_64BIT
        struct ccw1 *ccw;
  
        /* Clear any idals used for the request. */
@@@ -1035,7 -1035,7 +1035,7 @@@ dasd_end_request(struct request *req, i
        if (end_that_request_first(req, uptodate, req->hard_nr_sectors))
                BUG();
        add_disk_randomness(req->rq_disk);
-       end_that_request_last(req);
+       end_that_request_last(req, uptodate);
  }
  
  /*
@@@ -1224,12 -1224,6 +1224,12 @@@ __dasd_start_head(struct dasd_device * 
        if (list_empty(&device->ccw_queue))
                return;
        cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list);
 +        /* check FAILFAST */
 +      if (device->stopped & ~DASD_STOPPED_PENDING &&
 +          test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags)) {
 +              cqr->status = DASD_CQR_FAILED;
 +              dasd_schedule_bh(device);
 +      }
        if ((cqr->status == DASD_CQR_QUEUED) &&
            (!device->stopped)) {
                /* try to start the first I/O that can be started */
@@@ -1329,7 -1323,7 +1329,7 @@@ voi
  dasd_schedule_bh(struct dasd_device * device)
  {
        /* Protect against rescheduling. */
 -      if (atomic_compare_and_swap (0, 1, &device->tasklet_scheduled))
 +      if (atomic_cmpxchg (&device->tasklet_scheduled, 0, 1) != 0)
                return;
        dasd_get_device(device);
        tasklet_hi_schedule(&device->tasklet);
@@@ -1756,10 -1750,8 +1756,10 @@@ dasd_exit(void
   * SECTION: common functions for ccw_driver use
   */
  
 -/* initial attempt at a probe function. this can be simplified once
 - * the other detection code is gone */
 +/*
 + * Initial attempt at a probe function. this can be simplified once
 + * the other detection code is gone.
 + */
  int
  dasd_generic_probe (struct ccw_device *cdev,
                    struct dasd_discipline *discipline)
        return ret;
  }
  
 -/* this will one day be called from a global not_oper handler.
 - * It is also used by driver_unregister during module unload */
 +/*
 + * This will one day be called from a global not_oper handler.
 + * It is also used by driver_unregister during module unload.
 + */
  void
  dasd_generic_remove (struct ccw_device *cdev)
  {
        dasd_delete_device(device);
  }
  
 -/* activate a device. This is called from dasd_{eckd,fba}_probe() when either
 +/*
 + * Activate a device. This is called from dasd_{eckd,fba}_probe() when either
   * the device is detected for the first time and is supposed to be used
 - * or the user has started activation through sysfs */
 + * or the user has started activation through sysfs.
 + */
  int
  dasd_generic_set_online (struct ccw_device *cdev,
                         struct dasd_discipline *discipline)
@@@ -1929,6 -1917,7 +1929,6 @@@ dasd_generic_notify(struct ccw_device *
                                if (cqr->status == DASD_CQR_IN_IO)
                                        cqr->status = DASD_CQR_FAILED;
                        device->stopped |= DASD_STOPPED_DC_EIO;
 -                      dasd_schedule_bh(device);
                } else {
                        list_for_each_entry(cqr, &device->ccw_queue, list)
                                if (cqr->status == DASD_CQR_IN_IO) {
                        device->stopped |= DASD_STOPPED_DC_WAIT;
                        dasd_set_timer(device, 0);
                }
 +              dasd_schedule_bh(device);
                ret = 1;
                break;
        case CIO_OPER:
index 482e07e388c80cdf4568f7f634b3018f0bde9eee,559d51490e2fe8526fca657421b36637fdfaf447..5ced2725d6c705fda1529cafece44847d83df96b
@@@ -65,7 -65,7 +65,7 @@@ static voi
  tapeblock_trigger_requeue(struct tape_device *device)
  {
        /* Protect against rescheduling. */
 -      if (atomic_compare_and_swap(0, 1, &device->blk_data.requeue_scheduled))
 +      if (atomic_cmpxchg(&device->blk_data.requeue_scheduled, 0, 1) != 0)
                return;
        schedule_work(&device->blk_data.requeue_task);
  }
@@@ -78,7 -78,7 +78,7 @@@ tapeblock_end_request(struct request *r
  {
        if (end_that_request_first(req, uptodate, req->hard_nr_sectors))
                BUG();
-       end_that_request_last(req);
+       end_that_request_last(req, uptodate);
  }
  
  static void
diff --combined drivers/scsi/ata_piix.c
index f79630340028e6cc30ae62f95e4e72b6382c54dc,4b647eefc9a99a8427b0f1a5ee81f20bbec19555..557788ec4eec12cb09e51028bf6926363ff36589
@@@ -166,8 -166,6 +166,8 @@@ static struct pci_driver piix_pci_drive
        .id_table               = piix_pci_tbl,
        .probe                  = piix_init_one,
        .remove                 = ata_pci_remove_one,
 +      .suspend                = ata_pci_device_suspend,
 +      .resume                 = ata_pci_device_resume,
  };
  
  static struct scsi_host_template piix_sht = {
        .dma_boundary           = ATA_DMA_BOUNDARY,
        .slave_configure        = ata_scsi_slave_config,
        .bios_param             = ata_std_bios_param,
-       .ordered_flush          = 1,
 +      .resume                 = ata_scsi_device_resume,
 +      .suspend                = ata_scsi_device_suspend,
  };
  
  static const struct ata_port_operations piix_pata_ops = {
index 9c66d405939911d9329b7209b95fdb2b40fae30d,bdfb0a88cd6f675975cc44a172484c8e9085b2f2..f55b9b3f7b37f1e8b4ad71e8c9950d8a1f3a9797
@@@ -562,16 -562,28 +562,28 @@@ static const u8 ata_rw_cmds[] = 
        ATA_CMD_WRITE_MULTI,
        ATA_CMD_READ_MULTI_EXT,
        ATA_CMD_WRITE_MULTI_EXT,
+       0,
+       0,
+       0,
+       ATA_CMD_WRITE_MULTI_FUA_EXT,
        /* pio */
        ATA_CMD_PIO_READ,
        ATA_CMD_PIO_WRITE,
        ATA_CMD_PIO_READ_EXT,
        ATA_CMD_PIO_WRITE_EXT,
+       0,
+       0,
+       0,
+       0,
        /* dma */
        ATA_CMD_READ,
        ATA_CMD_WRITE,
        ATA_CMD_READ_EXT,
-       ATA_CMD_WRITE_EXT
+       ATA_CMD_WRITE_EXT,
+       0,
+       0,
+       0,
+       ATA_CMD_WRITE_FUA_EXT
  };
  
  /**
   *    LOCKING:
   *    caller.
   */
void ata_rwcmd_protocol(struct ata_queued_cmd *qc)
int ata_rwcmd_protocol(struct ata_queued_cmd *qc)
  {
        struct ata_taskfile *tf = &qc->tf;
        struct ata_device *dev = qc->dev;
+       u8 cmd;
  
-       int index, lba48, write;
+       int index, fua, lba48, write;
   
+       fua = (tf->flags & ATA_TFLAG_FUA) ? 4 : 0;
        lba48 = (tf->flags & ATA_TFLAG_LBA48) ? 2 : 0;
        write = (tf->flags & ATA_TFLAG_WRITE) ? 1 : 0;
  
        if (dev->flags & ATA_DFLAG_PIO) {
                tf->protocol = ATA_PROT_PIO;
-               index = dev->multi_count ? 0 : 4;
+               index = dev->multi_count ? 0 : 8;
        } else {
                tf->protocol = ATA_PROT_DMA;
-               index = 8;
+               index = 16;
        }
  
-       tf->command = ata_rw_cmds[index + lba48 + write];
+       cmd = ata_rw_cmds[index + fua + lba48 + write];
+       if (cmd) {
+               tf->command = cmd;
+               return 0;
+       }
+       return -1;
  }
  
  static const char * const xfer_mode_str[] = {
@@@ -4154,96 -4173,6 +4173,96 @@@ err_out
   *    Inherited from caller.
   */
  
 +/*
 + * Execute a 'simple' command, that only consists of the opcode 'cmd' itself,
 + * without filling any other registers
 + */
 +static int ata_do_simple_cmd(struct ata_port *ap, struct ata_device *dev,
 +                           u8 cmd)
 +{
 +      struct ata_taskfile tf;
 +      int err;
 +
 +      ata_tf_init(ap, &tf, dev->devno);
 +
 +      tf.command = cmd;
 +      tf.flags |= ATA_TFLAG_DEVICE;
 +      tf.protocol = ATA_PROT_NODATA;
 +
 +      err = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0);
 +      if (err)
 +              printk(KERN_ERR "%s: ata command failed: %d\n",
 +                              __FUNCTION__, err);
 +
 +      return err;
 +}
 +
 +static int ata_flush_cache(struct ata_port *ap, struct ata_device *dev)
 +{
 +      u8 cmd;
 +
 +      if (!ata_try_flush_cache(dev))
 +              return 0;
 +
 +      if (ata_id_has_flush_ext(dev->id))
 +              cmd = ATA_CMD_FLUSH_EXT;
 +      else
 +              cmd = ATA_CMD_FLUSH;
 +
 +      return ata_do_simple_cmd(ap, dev, cmd);
 +}
 +
 +static int ata_standby_drive(struct ata_port *ap, struct ata_device *dev)
 +{
 +      return ata_do_simple_cmd(ap, dev, ATA_CMD_STANDBYNOW1);
 +}
 +
 +static int ata_start_drive(struct ata_port *ap, struct ata_device *dev)
 +{
 +      return ata_do_simple_cmd(ap, dev, ATA_CMD_IDLEIMMEDIATE);
 +}
 +
 +/**
 + *    ata_device_resume - wakeup a previously suspended devices
 + *
 + *    Kick the drive back into action, by sending it an idle immediate
 + *    command and making sure its transfer mode matches between drive
 + *    and host.
 + *
 + */
 +int ata_device_resume(struct ata_port *ap, struct ata_device *dev)
 +{
 +      if (ap->flags & ATA_FLAG_SUSPENDED) {
 +              ap->flags &= ~ATA_FLAG_SUSPENDED;
 +              ata_set_mode(ap);
 +      }
 +      if (!ata_dev_present(dev))
 +              return 0;
 +      if (dev->class == ATA_DEV_ATA)
 +              ata_start_drive(ap, dev);
 +
 +      return 0;
 +}
 +
 +/**
 + *    ata_device_suspend - prepare a device for suspend
 + *
 + *    Flush the cache on the drive, if appropriate, then issue a
 + *    standbynow command.
 + *
 + */
 +int ata_device_suspend(struct ata_port *ap, struct ata_device *dev)
 +{
 +      if (!ata_dev_present(dev))
 +              return 0;
 +      if (dev->class == ATA_DEV_ATA)
 +              ata_flush_cache(ap, dev);
 +
 +      ata_standby_drive(ap, dev);
 +      ap->flags |= ATA_FLAG_SUSPENDED;
 +      return 0;
 +}
 +
  int ata_port_start (struct ata_port *ap)
  {
        struct device *dev = ap->host_set->dev;
@@@ -4992,23 -4921,6 +5011,23 @@@ int pci_test_config_bits(struct pci_de
  
        return (tmp == bits->val) ? 1 : 0;
  }
 +
 +int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state)
 +{
 +      pci_save_state(pdev);
 +      pci_disable_device(pdev);
 +      pci_set_power_state(pdev, PCI_D3hot);
 +      return 0;
 +}
 +
 +int ata_pci_device_resume(struct pci_dev *pdev)
 +{
 +      pci_set_power_state(pdev, PCI_D0);
 +      pci_restore_state(pdev);
 +      pci_enable_device(pdev);
 +      pci_set_master(pdev);
 +      return 0;
 +}
  #endif /* CONFIG_PCI */
  
  
@@@ -5112,11 -5024,4 +5131,11 @@@ EXPORT_SYMBOL_GPL(ata_pci_host_stop)
  EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
  EXPORT_SYMBOL_GPL(ata_pci_init_one);
  EXPORT_SYMBOL_GPL(ata_pci_remove_one);
 +EXPORT_SYMBOL_GPL(ata_pci_device_suspend);
 +EXPORT_SYMBOL_GPL(ata_pci_device_resume);
  #endif /* CONFIG_PCI */
 +
 +EXPORT_SYMBOL_GPL(ata_device_suspend);
 +EXPORT_SYMBOL_GPL(ata_device_resume);
 +EXPORT_SYMBOL_GPL(ata_scsi_device_suspend);
 +EXPORT_SYMBOL_GPL(ata_scsi_device_resume);
index c1ebede14a481076e3fa2844210c86c17b59f080,2c644cbb6e9c4bb966a9bbeb217597490e03a703..cfbceb5047183e3096bb494bc3e2419c8956cd93
@@@ -396,22 -396,6 +396,22 @@@ void ata_dump_status(unsigned id, struc
        }
  }
  
 +int ata_scsi_device_resume(struct scsi_device *sdev)
 +{
 +      struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0];
 +      struct ata_device *dev = &ap->device[sdev->id];
 +
 +      return ata_device_resume(ap, dev);
 +}
 +
 +int ata_scsi_device_suspend(struct scsi_device *sdev)
 +{
 +      struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0];
 +      struct ata_device *dev = &ap->device[sdev->id];
 +
 +      return ata_device_suspend(ap, dev);
 +}
 +
  /**
   *    ata_to_sense_error - convert ATA error to SCSI error
   *    @id: ATA device number
@@@ -1096,11 -1080,13 +1096,13 @@@ static unsigned int ata_scsi_rw_xlat(st
            scsicmd[0] == WRITE_16)
                tf->flags |= ATA_TFLAG_WRITE;
  
-       /* Calculate the SCSI LBA and transfer length. */
+       /* Calculate the SCSI LBA, transfer length and FUA. */
        switch (scsicmd[0]) {
        case READ_10:
        case WRITE_10:
                scsi_10_lba_len(scsicmd, &block, &n_block);
+               if (unlikely(scsicmd[1] & (1 << 3)))
+                       tf->flags |= ATA_TFLAG_FUA;
                break;
        case READ_6:
        case WRITE_6:
        case READ_16:
        case WRITE_16:
                scsi_16_lba_len(scsicmd, &block, &n_block);
+               if (unlikely(scsicmd[1] & (1 << 3)))
+                       tf->flags |= ATA_TFLAG_FUA;
                break;
        default:
                DPRINTK("no-byte command\n");
                        tf->device |= (block >> 24) & 0xf;
                }
  
-               ata_rwcmd_protocol(qc);
+               if (unlikely(ata_rwcmd_protocol(qc) < 0))
+                       goto invalid_fld;
  
                qc->nsect = n_block;
                tf->nsect = n_block & 0xff;
                if ((block >> 28) || (n_block > 256))
                        goto out_of_range;
  
-               ata_rwcmd_protocol(qc);
+               if (unlikely(ata_rwcmd_protocol(qc) < 0))
+                       goto invalid_fld;
  
                /* Convert LBA to CHS */
                track = (u32)block / dev->sectors;
@@@ -1711,6 -1701,7 +1717,7 @@@ static unsigned int ata_msense_rw_recov
  unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
                                  unsigned int buflen)
  {
+       struct ata_device *dev = args->dev;
        u8 *scsicmd = args->cmd->cmnd, *p, *last;
        const u8 sat_blk_desc[] = {
                0, 0, 0, 0,     /* number of blocks: sat unspecified */
        };
        u8 pg, spg;
        unsigned int ebd, page_control, six_byte, output_len, alloc_len, minlen;
+       u8 dpofua;
  
        VPRINTK("ENTER\n");
  
  
        if (minlen < 1)
                return 0;
+       dpofua = 0;
+       if (ata_id_has_fua(args->id) && dev->flags & ATA_DFLAG_LBA48 &&
+           (!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count))
+               dpofua = 1 << 4;
        if (six_byte) {
                output_len--;
                rbuf[0] = output_len;
+               if (minlen > 2)
+                       rbuf[2] |= dpofua;
                if (ebd) {
                        if (minlen > 3)
                                rbuf[3] = sizeof(sat_blk_desc);
                rbuf[0] = output_len >> 8;
                if (minlen > 1)
                        rbuf[1] = output_len;
+               if (minlen > 3)
+                       rbuf[3] |= dpofua;
                if (ebd) {
                        if (minlen > 7)
                                rbuf[7] = sizeof(sat_blk_desc);
@@@ -2462,7 -2464,7 +2480,7 @@@ int ata_scsi_queuecmd(struct scsi_cmnd 
                if (xlat_func)
                        ata_scsi_translate(ap, dev, cmd, done, xlat_func);
                else
-                       ata_scsi_simulate(dev->id, cmd, done);
+                       ata_scsi_simulate(ap, dev, cmd, done);
        } else
                ata_scsi_translate(ap, dev, cmd, done, atapi_xlat);
  
@@@ -2485,14 -2487,16 +2503,16 @@@ out_unlock
   *    spin_lock_irqsave(host_set lock)
   */
  
- void ata_scsi_simulate(u16 *id,
+ void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
                      struct scsi_cmnd *cmd,
                      void (*done)(struct scsi_cmnd *))
  {
        struct ata_scsi_args args;
        const u8 *scsicmd = cmd->cmnd;
  
-       args.id = id;
+       args.ap = ap;
+       args.dev = dev;
+       args.id = dev->id;
        args.cmd = cmd;
        args.done = done;
  
diff --combined include/linux/ata.h
index 3eb80c391b396714efb91fecd3474203baa5750a,f63dad4165b1d98f907306258a2cb3297406dcbd..94f77cce27fa10d634b7ffdbeb415d31613833b5
@@@ -129,6 -129,7 +129,7 @@@ enum 
        ATA_CMD_READ_EXT        = 0x25,
        ATA_CMD_WRITE           = 0xCA,
        ATA_CMD_WRITE_EXT       = 0x35,
+       ATA_CMD_WRITE_FUA_EXT   = 0x3D,
        ATA_CMD_PIO_READ        = 0x20,
        ATA_CMD_PIO_READ_EXT    = 0x24,
        ATA_CMD_PIO_WRITE       = 0x30,
        ATA_CMD_READ_MULTI_EXT  = 0x29,
        ATA_CMD_WRITE_MULTI     = 0xC5,
        ATA_CMD_WRITE_MULTI_EXT = 0x39,
+       ATA_CMD_WRITE_MULTI_FUA_EXT = 0xCE,
        ATA_CMD_SET_FEATURES    = 0xEF,
        ATA_CMD_PACKET          = 0xA0,
        ATA_CMD_VERIFY          = 0x40,
        ATA_CMD_VERIFY_EXT      = 0x42,
 +      ATA_CMD_STANDBYNOW1     = 0xE0,
 +      ATA_CMD_IDLEIMMEDIATE   = 0xE1,
        ATA_CMD_INIT_DEV_PARAMS = 0x91,
  
        /* SETFEATURES stuff */
        ATA_TFLAG_DEVICE        = (1 << 2), /* enable r/w to device reg */
        ATA_TFLAG_WRITE         = (1 << 3), /* data dir: host->dev==1 (write) */
        ATA_TFLAG_LBA           = (1 << 4), /* enable LBA */
+       ATA_TFLAG_FUA           = (1 << 5), /* enable FUA */
  };
  
  enum ata_tf_protocols {
@@@ -247,7 -248,8 +250,8 @@@ struct ata_taskfile 
  #define ata_id_is_sata(id)    ((id)[93] == 0)
  #define ata_id_rahead_enabled(id) ((id)[85] & (1 << 6))
  #define ata_id_wcache_enabled(id) ((id)[85] & (1 << 5))
- #define ata_id_has_flush(id) ((id)[83] & (1 << 12))
+ #define ata_id_has_fua(id)    ((id)[84] & (1 << 6))
+ #define ata_id_has_flush(id)  ((id)[83] & (1 << 12))
  #define ata_id_has_flush_ext(id) ((id)[83] & (1 << 13))
  #define ata_id_has_lba48(id)  ((id)[83] & (1 << 10))
  #define ata_id_has_wcache(id) ((id)[82] & (1 << 5))
diff --combined include/linux/libata.h
index cdab75c209a014d7963af466fa33c16734c90e22,6db2c0845731e09a50df4d4209039705575c6f16..a43c95f8f968b8e7be0f648ea38a2475b71d3d07
@@@ -124,8 -124,6 +124,8 @@@ enum 
        ATA_FLAG_DEBUGMSG       = (1 << 10),
        ATA_FLAG_NO_ATAPI       = (1 << 11), /* No ATAPI support */
  
 +      ATA_FLAG_SUSPENDED      = (1 << 12), /* port is suspended */
 +
        ATA_QCFLAG_ACTIVE       = (1 << 1), /* cmd not yet ack'd to scsi lyer */
        ATA_QCFLAG_SG           = (1 << 3), /* have s/g table? */
        ATA_QCFLAG_SINGLE       = (1 << 4), /* no s/g, just a single buffer */
@@@ -438,8 -436,6 +438,8 @@@ extern void ata_std_ports(struct ata_io
  extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
                             unsigned int n_ports);
  extern void ata_pci_remove_one (struct pci_dev *pdev);
 +extern int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state);
 +extern int ata_pci_device_resume(struct pci_dev *pdev);
  #endif /* CONFIG_PCI */
  extern int ata_device_add(const struct ata_probe_ent *ent);
  extern void ata_host_set_remove(struct ata_host_set *host_set);
@@@ -449,10 -445,6 +449,10 @@@ extern int ata_scsi_queuecmd(struct scs
  extern int ata_scsi_error(struct Scsi_Host *host);
  extern int ata_scsi_release(struct Scsi_Host *host);
  extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
 +extern int ata_scsi_device_resume(struct scsi_device *);
 +extern int ata_scsi_device_suspend(struct scsi_device *);
 +extern int ata_device_resume(struct ata_port *, struct ata_device *);
 +extern int ata_device_suspend(struct ata_port *, struct ata_device *);
  extern int ata_ratelimit(void);
  
  /*
@@@ -488,7 -480,8 +488,8 @@@ extern u8   ata_bmdma_status(struct ata
  extern void ata_bmdma_irq_clear(struct ata_port *ap);
  extern void ata_qc_complete(struct ata_queued_cmd *qc);
  extern void ata_eng_timeout(struct ata_port *ap);
- extern void ata_scsi_simulate(u16 *id, struct scsi_cmnd *cmd,
+ extern void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
+                             struct scsi_cmnd *cmd,
                              void (*done)(struct scsi_cmnd *));
  extern int ata_std_bios_param(struct scsi_device *sdev,
                              struct block_device *bdev,
diff --combined include/scsi/scsi_host.h
index 6297885a35e778639274eae587ce72fc4e7dfa4d,25f637bd38b937a2765c5dc47ed5fb1d3f6b6c72..230bc55c0bfa163be4c47437aa8ba82f6bb7e476
@@@ -295,12 -295,6 +295,12 @@@ struct scsi_host_template 
         */
        int (*proc_info)(struct Scsi_Host *, char *, char **, off_t, int, int);
  
 +      /*
 +       * suspend support
 +       */
 +      int (*resume)(struct scsi_device *);
 +      int (*suspend)(struct scsi_device *);
 +
        /*
         * Name of proc directory
         */
        /*
         * ordered write support
         */
-       unsigned ordered_flush:1;
        unsigned ordered_tag:1;
  
        /*