Merge branch 'for-linus' into for-next
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Sun, 7 Jun 2009 12:27:11 +0000 (14:27 +0200)
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Sun, 7 Jun 2009 12:27:11 +0000 (14:27 +0200)
1  2 
drivers/ide/ide-disk.c
include/linux/ide.h

diff --combined drivers/ide/ide-disk.c
@@@ -302,14 -302,12 +302,12 @@@ static const struct drive_list_entry hp
        { NULL,         NULL }
  };
  
- static void idedisk_check_hpa(ide_drive_t *drive)
+ static u64 ide_disk_hpa_get_native_capacity(ide_drive_t *drive, int lba48)
  {
-       unsigned long long capacity, set_max;
-       int lba48 = ata_id_lba48_enabled(drive->id);
+       u64 capacity, set_max;
  
        capacity = drive->capacity64;
-       set_max = idedisk_read_native_max_address(drive, lba48);
+       set_max  = idedisk_read_native_max_address(drive, lba48);
  
        if (ide_in_drive_list(drive->id, hpa_list)) {
                /*
                        set_max--;
        }
  
+       return set_max;
+ }
+ static u64 ide_disk_hpa_set_capacity(ide_drive_t *drive, u64 set_max, int lba48)
+ {
+       set_max = idedisk_set_max_address(drive, set_max, lba48);
+       if (set_max)
+               drive->capacity64 = set_max;
+       return set_max;
+ }
+ static void idedisk_check_hpa(ide_drive_t *drive)
+ {
+       u64 capacity, set_max;
+       int lba48 = ata_id_lba48_enabled(drive->id);
+       capacity = drive->capacity64;
+       set_max  = ide_disk_hpa_get_native_capacity(drive, lba48);
        if (set_max <= capacity)
                return;
  
+       drive->probed_capacity = set_max;
        printk(KERN_INFO "%s: Host Protected Area detected.\n"
                         "\tcurrent capacity is %llu sectors (%llu MB)\n"
                         "\tnative  capacity is %llu sectors (%llu MB)\n",
                         capacity, sectors_to_MB(capacity),
                         set_max, sectors_to_MB(set_max));
  
-       set_max = idedisk_set_max_address(drive, set_max, lba48);
+       if ((drive->dev_flags & IDE_DFLAG_NOHPA) == 0)
+               return;
  
-       if (set_max) {
-               drive->capacity64 = set_max;
+       set_max = ide_disk_hpa_set_capacity(drive, set_max, lba48);
+       if (set_max)
                printk(KERN_INFO "%s: Host Protected Area disabled.\n",
                                 drive->name);
-       }
  }
  
  static int ide_disk_get_capacity(ide_drive_t *drive)
                drive->capacity64 = drive->cyl * drive->head * drive->sect;
        }
  
+       drive->probed_capacity = drive->capacity64;
        if (lba) {
                drive->dev_flags |= IDE_DFLAG_LBA;
  
                       "%llu sectors (%llu MB)\n",
                       drive->name, (unsigned long long)drive->capacity64,
                       sectors_to_MB(drive->capacity64));
-               drive->capacity64 = 1ULL << 28;
+               drive->probed_capacity = drive->capacity64 = 1ULL << 28;
        }
  
        if ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) &&
        return 0;
  }
  
+ static u64 ide_disk_set_capacity(ide_drive_t *drive, u64 capacity)
+ {
+       u64 set = min(capacity, drive->probed_capacity);
+       u16 *id = drive->id;
+       int lba48 = ata_id_lba48_enabled(id);
+       if ((drive->dev_flags & IDE_DFLAG_LBA) == 0 ||
+           ata_id_hpa_enabled(id) == 0)
+               goto out;
+       /*
+        * according to the spec the SET MAX ADDRESS command shall be
+        * immediately preceded by a READ NATIVE MAX ADDRESS command
+        */
+       capacity = ide_disk_hpa_get_native_capacity(drive, lba48);
+       if (capacity == 0)
+               goto out;
+       set = ide_disk_hpa_set_capacity(drive, set, lba48);
+       if (set) {
+               /* needed for ->resume to disable HPA */
+               drive->dev_flags |= IDE_DFLAG_NOHPA;
+               return set;
+       }
+ out:
+       return drive->capacity64;
+ }
  static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
  {
        ide_drive_t *drive = q->queuedata;
        cmd->protocol = ATA_PROT_NODATA;
  
        rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
 -      rq->cmd_flags |= REQ_SOFTBARRIER;
        rq->special = cmd;
  }
  
@@@ -428,14 -479,14 +478,14 @@@ static int set_multcount(ide_drive_t *d
        if (arg < 0 || arg > (drive->id[ATA_ID_MAX_MULTSECT] & 0xff))
                return -EINVAL;
  
 -      if (drive->special.b.set_multmode)
 +      if (drive->special_flags & IDE_SFLAG_SET_MULTMODE)
                return -EBUSY;
  
        rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
        rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
  
        drive->mult_req = arg;
 -      drive->special.b.set_multmode = 1;
 +      drive->special_flags |= IDE_SFLAG_SET_MULTMODE;
        error = blk_execute_rq(drive->queue, NULL, rq, 0);
        blk_put_request(rq);
  
@@@ -740,6 -791,7 +790,7 @@@ static int ide_disk_set_doorlock(ide_dr
  
  const struct ide_disk_ops ide_ata_disk_ops = {
        .check          = ide_disk_check,
+       .set_capacity   = ide_disk_set_capacity,
        .get_capacity   = ide_disk_get_capacity,
        .setup          = ide_disk_setup,
        .flush          = ide_disk_flush,
diff --combined include/linux/ide.h
@@@ -26,9 -26,6 +26,9 @@@
  #include <asm/io.h>
  #include <asm/mutex.h>
  
 +/* for request_sense */
 +#include <linux/cdrom.h>
 +
  #if defined(CONFIG_CRIS) || defined(CONFIG_FRV) || defined(CONFIG_MN10300)
  # define SUPPORT_VLB_SYNC 0
  #else
@@@ -178,7 -175,7 +178,7 @@@ typedef u8 hwif_chipset_t
  /*
   * Structure to hold all information about the location of this port
   */
 -typedef struct hw_regs_s {
 +struct ide_hw {
        union {
                struct ide_io_ports     io_ports;
                unsigned long           io_ports_array[IDE_NR_PORTS];
  
        int             irq;                    /* our irq number */
        ide_ack_intr_t  *ack_intr;              /* acknowledge interrupt */
 -      hwif_chipset_t  chipset;
        struct device   *dev, *parent;
        unsigned long   config;
 -} hw_regs_t;
 +};
  
 -static inline void ide_std_init_ports(hw_regs_t *hw,
 +static inline void ide_std_init_ports(struct ide_hw *hw,
                                      unsigned long io_addr,
                                      unsigned long ctl_addr)
  {
  
  /*
   * Special Driver Flags
 - *
 - * set_geometry       : respecify drive geometry
 - * recalibrate        : seek to cyl 0
 - * set_multmode       : set multmode count
 - * reserved   : unused
   */
 -typedef union {
 -      unsigned all                    : 8;
 -      struct {
 -              unsigned set_geometry   : 1;
 -              unsigned recalibrate    : 1;
 -              unsigned set_multmode   : 1;
 -              unsigned reserved       : 5;
 -      } b;
 -} special_t;
 +enum {
 +      IDE_SFLAG_SET_GEOMETRY          = (1 << 0),
 +      IDE_SFLAG_RECALIBRATE           = (1 << 1),
 +      IDE_SFLAG_SET_MULTMODE          = (1 << 2),
 +};
  
  /*
   * Status returned from various ide_ functions
@@@ -317,6 -324,7 +317,6 @@@ struct ide_cmd 
        unsigned int            cursg_ofs;
  
        struct request          *rq;            /* copy of request */
 -      void                    *special;       /* valid_t generally */
  };
  
  /* ATAPI packet command flags */
@@@ -352,7 -360,11 +352,7 @@@ struct ide_atapi_pc 
  
        /* data buffer */
        u8 *buf;
 -      /* current buffer position */
 -      u8 *cur_pos;
        int buf_size;
 -      /* missing/available data on the current buffer */
 -      int b_count;
  
        /* the corresponding request */
        struct request *rq;
         */
        u8 pc_buf[IDE_PC_BUFFER_SIZE];
  
 -      /* idetape only */
 -      struct idetape_bh *bh;
 -      char *b_data;
 -
        unsigned long timeout;
  };
  
@@@ -381,6 -397,7 +381,7 @@@ struct ide_drive_s
  struct ide_disk_ops {
        int             (*check)(struct ide_drive_s *, const char *);
        int             (*get_capacity)(struct ide_drive_s *);
+       u64             (*set_capacity)(struct ide_drive_s *, u64);
        void            (*setup)(struct ide_drive_s *);
        void            (*flush)(struct ide_drive_s *);
        int             (*init_media)(struct ide_drive_s *, struct gendisk *);
@@@ -458,6 -475,8 +459,8 @@@ enum 
        IDE_DFLAG_NICE1                 = (1 << 5),
        /* device is physically present */
        IDE_DFLAG_PRESENT               = (1 << 6),
+       /* disable Host Protected Area */
+       IDE_DFLAG_NOHPA                 = (1 << 7),
        /* id read from device (synthetic if not set) */
        IDE_DFLAG_ID_READ               = (1 << 8),
        IDE_DFLAG_NOPROBE               = (1 << 9),
@@@ -520,7 -539,7 +523,7 @@@ struct ide_drive_s 
        unsigned long sleep;            /* sleep until this time */
        unsigned long timeout;          /* max time to wait for irq */
  
 -      special_t       special;        /* special action flags */
 +      u8      special_flags;          /* special action flags */
  
        u8      select;                 /* basic drive/head select reg value */
        u8      retry_pio;              /* retrying dma capable host in pio */
        unsigned int    drive_data;     /* used by set_pio_mode/dev_select() */
        unsigned int    failures;       /* current failure count */
        unsigned int    max_failures;   /* maximum allowed failure count */
-       u64             probed_capacity;/* initial reported media capacity (ide-cd only currently) */
+       u64             probed_capacity;/* initial/native media capacity */
        u64             capacity64;     /* total number of sectors */
  
        int             lun;            /* logical unit */
        /* callback for packet commands */
        int  (*pc_callback)(struct ide_drive_s *, int);
  
 -      void (*pc_update_buffers)(struct ide_drive_s *, struct ide_atapi_pc *);
 -      int  (*pc_io_buffers)(struct ide_drive_s *, struct ide_atapi_pc *,
 -                            unsigned int, int);
 -
        ide_startstop_t (*irq_handler)(struct ide_drive_s *);
  
        unsigned long atapi_flags;
  
        struct ide_atapi_pc request_sense_pc;
 -      struct request request_sense_rq;
 +
 +      /* current sense rq and buffer */
 +      bool sense_rq_armed;
 +      struct request sense_rq;
 +      struct request_sense sense_data;
  };
  
  typedef struct ide_drive_s ide_drive_t;
@@@ -1158,10 -1176,7 +1160,10 @@@ int ide_do_test_unit_ready(ide_drive_t 
  int ide_do_start_stop(ide_drive_t *, struct gendisk *, int);
  int ide_set_media_lock(ide_drive_t *, struct gendisk *, int);
  void ide_create_request_sense_cmd(ide_drive_t *, struct ide_atapi_pc *);
 -void ide_retry_pc(ide_drive_t *, struct gendisk *);
 +void ide_retry_pc(ide_drive_t *drive);
 +
 +void ide_prep_sense(ide_drive_t *drive, struct request *rq);
 +int ide_queue_sense_rq(ide_drive_t *drive, void *special);
  
  int ide_cd_expiry(ide_drive_t *);
  
@@@ -1212,7 -1227,7 +1214,7 @@@ static inline int ide_pci_is_in_compati
  }
  
  void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *,
 -                       hw_regs_t *, hw_regs_t **);
 +                       struct ide_hw *, struct ide_hw **);
  void ide_setup_pci_noise(struct pci_dev *, const struct ide_port_info *);
  
  #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
@@@ -1456,12 -1471,11 +1458,12 @@@ void ide_undecoded_slave(ide_drive_t *)
  void ide_port_apply_params(ide_hwif_t *);
  int ide_sysfs_register_port(ide_hwif_t *);
  
 -struct ide_host *ide_host_alloc(const struct ide_port_info *, hw_regs_t **);
 +struct ide_host *ide_host_alloc(const struct ide_port_info *, struct ide_hw **,
 +                              unsigned int);
  void ide_host_free(struct ide_host *);
  int ide_host_register(struct ide_host *, const struct ide_port_info *,
 -                    hw_regs_t **);
 -int ide_host_add(const struct ide_port_info *, hw_regs_t **,
 +                    struct ide_hw **);
 +int ide_host_add(const struct ide_port_info *, struct ide_hw **, unsigned int,
                 struct ide_host **);
  void ide_host_remove(struct ide_host *);
  int ide_legacy_device_add(const struct ide_port_info *, unsigned long);