]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'upstream'
authorJeff Garzik <jgarzik@pobox.com>
Tue, 17 Jan 2006 15:26:28 +0000 (10:26 -0500)
committerJeff Garzik <jgarzik@pobox.com>
Tue, 17 Jan 2006 15:26:28 +0000 (10:26 -0500)
1  2 
drivers/scsi/libata-scsi.c
include/linux/ata.h

index 094c9c88a095944b18dc9e9d4cebe324fc7074d3,cfbceb5047183e3096bb494bc3e2419c8956cd93..0e65bfe92e6fd7c860a14bddf71b51d00abd3989
@@@ -396,6 -396,22 +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
@@@ -969,13 -985,9 +985,13 @@@ static unsigned int ata_scsi_verify_xla
        if (dev->flags & ATA_DFLAG_LBA) {
                tf->flags |= ATA_TFLAG_LBA;
  
 -              if (dev->flags & ATA_DFLAG_LBA48) {
 -                      if (n_block > (64 * 1024))
 -                              goto invalid_fld;
 +              if (lba_28_ok(block, n_block)) {
 +                      /* use LBA28 */
 +                      tf->command = ATA_CMD_VERIFY;
 +                      tf->device |= (block >> 24) & 0xf;
 +              } else if (lba_48_ok(block, n_block)) {
 +                      if (!(dev->flags & ATA_DFLAG_LBA48))
 +                              goto out_of_range;
  
                        /* use LBA48 */
                        tf->flags |= ATA_TFLAG_LBA48;
                        tf->hob_lbah = (block >> 40) & 0xff;
                        tf->hob_lbam = (block >> 32) & 0xff;
                        tf->hob_lbal = (block >> 24) & 0xff;
 -              } else {
 -                      if (n_block > 256)
 -                              goto invalid_fld;
 -
 -                      /* use LBA28 */
 -                      tf->command = ATA_CMD_VERIFY;
 -
 -                      tf->device |= (block >> 24) & 0xf;
 -              }
 +              } else
 +                      /* request too large even for LBA48 */
 +                      goto out_of_range;
  
                tf->nsect = n_block & 0xff;
  
                /* CHS */
                u32 sect, head, cyl, track;
  
 -              if (n_block > 256)
 -                      goto invalid_fld;
 +              if (!lba_28_ok(block, n_block))
 +                      goto out_of_range;
  
                /* Convert LBA to CHS */
                track = (u32)block / dev->sectors;
@@@ -1078,11 -1096,13 +1094,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");
        if (dev->flags & ATA_DFLAG_LBA) {
                tf->flags |= ATA_TFLAG_LBA;
  
 -              if (dev->flags & ATA_DFLAG_LBA48) {
 -                      /* The request -may- be too large for LBA48. */
 -                      if ((block >> 48) || (n_block > 65536))
 +              if (lba_28_ok(block, n_block)) {
 +                      /* use LBA28 */
 +                      tf->device |= (block >> 24) & 0xf;
 +              } else if (lba_48_ok(block, n_block)) {
 +                      if (!(dev->flags & ATA_DFLAG_LBA48))
                                goto out_of_range;
  
                        /* use LBA48 */
                        tf->hob_lbah = (block >> 40) & 0xff;
                        tf->hob_lbam = (block >> 32) & 0xff;
                        tf->hob_lbal = (block >> 24) & 0xff;
 -              } else { 
 -                      /* use LBA28 */
 -
 -                      /* The request -may- be too large for LBA28. */
 -                      if ((block >> 28) || (n_block > 256))
 -                              goto out_of_range;
 -
 -                      tf->device |= (block >> 24) & 0xf;
 -              }
 +              } else
 +                      /* request too large even for LBA48 */
 +                      goto out_of_range;
  
-               ata_rwcmd_protocol(qc);
+               if (unlikely(ata_rwcmd_protocol(qc) < 0))
+                       goto invalid_fld;
  
                qc->nsect = n_block;
                tf->nsect = n_block & 0xff;
                u32 sect, head, cyl, track;
  
                /* The request -may- be too large for CHS addressing. */
 -              if ((block >> 28) || (n_block > 256))
 +              if (!lba_28_ok(block, n_block))
                        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;
@@@ -1689,6 -1717,7 +1711,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);
@@@ -2440,7 -2480,7 +2474,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);
  
@@@ -2463,14 -2503,16 +2497,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 9245b97845aa16e54a87dac03ae9d715593569f9,94f77cce27fa10d634b7ffdbeb415d31613833b5..a8155ca4947fadfda0cc6c09f0b098c6f54628fc
@@@ -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 {
@@@ -245,7 -250,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))
@@@ -296,16 -302,4 +302,16 @@@ static inline int ata_ok(u8 status
                        == ATA_DRDY);
  }
  
 +static inline int lba_28_ok(u64 block, u32 n_block)
 +{
 +      /* check the ending block number */
 +      return ((block + n_block - 1) < ((u64)1 << 28)) && (n_block <= 256);
 +}
 +
 +static inline int lba_48_ok(u64 block, u32 n_block)
 +{
 +      /* check the ending block number */
 +      return ((block + n_block - 1) < ((u64)1 << 48)) && (n_block <= 65536);
 +}
 +
  #endif /* __LINUX_ATA_H__ */