summaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-10-21 19:03:38 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-21 19:03:38 -0700
commite10117d36ef758da0690c95ecffc09d5dd7da479 (patch)
treef2bb867cfc33f24d9c6bbb36dd189869e62ecce2 /include/linux
parentf3270b16e00f0614fa418dcc50883da5949375b4 (diff)
parent89692c03226a066a017048cf7fbacbaa645f0e79 (diff)
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev: (26 commits) include/linux/libata.h: fix typo pata_bf54x: fix return type of bfin_set_devctl Drivers: ata: Makefile: replace the use of <module>-objs with <module>-y libahci: fix result_tf handling after an ATA PIO data-in command pata_sl82c105: implement sff_irq_check() method pata_sil680: implement sff_irq_check() method pata_pdc202xx_old: implement sff_irq_check() method pata_cmd640: implement sff_irq_check() method ata_piix: Add device ID for ICH4-L pata_sil680: make sil680_sff_exec_command() 'static' ata: Intel IDE-R support libata: reorder ata_queued_cmd to remove alignment padding on 64 bit builds libata: Signal that our SATL supports WRITE SAME(16) with UNMAP ata_piix: remove SIDPR locking libata: implement cross-port EH exclusion libata: add @ap to ata_wait_register() and introduce ata_msleep() ata_piix: implement LPM support libata: implement LPM support for port multipliers libata: reimplement link power management libata: implement sata_link_scr_lpm() and make ata_dev_set_feature() global ...
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/ata.h46
-rw-r--r--include/linux/libata.h65
2 files changed, 82 insertions, 29 deletions
diff --git a/include/linux/ata.h b/include/linux/ata.h
index fe6e681a9d7..0c4929fa34d 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -89,6 +89,7 @@ enum {
ATA_ID_SPG = 98,
ATA_ID_LBA_CAPACITY_2 = 100,
ATA_ID_SECTOR_SIZE = 106,
+ ATA_ID_LOGICAL_SECTOR_SIZE = 117, /* and 118 */
ATA_ID_LAST_LUN = 126,
ATA_ID_DLF = 128,
ATA_ID_CSFO = 129,
@@ -640,16 +641,49 @@ static inline int ata_id_flush_ext_enabled(const u16 *id)
return (id[ATA_ID_CFS_ENABLE_2] & 0x2400) == 0x2400;
}
-static inline int ata_id_has_large_logical_sectors(const u16 *id)
+static inline u32 ata_id_logical_sector_size(const u16 *id)
{
- if ((id[ATA_ID_SECTOR_SIZE] & 0xc000) != 0x4000)
- return 0;
- return id[ATA_ID_SECTOR_SIZE] & (1 << 13);
+ /* T13/1699-D Revision 6a, Sep 6, 2008. Page 128.
+ * IDENTIFY DEVICE data, word 117-118.
+ * 0xd000 ignores bit 13 (logical:physical > 1)
+ */
+ if ((id[ATA_ID_SECTOR_SIZE] & 0xd000) == 0x5000)
+ return (((id[ATA_ID_LOGICAL_SECTOR_SIZE+1] << 16)
+ + id[ATA_ID_LOGICAL_SECTOR_SIZE]) * sizeof(u16)) ;
+ return ATA_SECT_SIZE;
+}
+
+static inline u8 ata_id_log2_per_physical_sector(const u16 *id)
+{
+ /* T13/1699-D Revision 6a, Sep 6, 2008. Page 128.
+ * IDENTIFY DEVICE data, word 106.
+ * 0xe000 ignores bit 12 (logical sector > 512 bytes)
+ */
+ if ((id[ATA_ID_SECTOR_SIZE] & 0xe000) == 0x6000)
+ return (id[ATA_ID_SECTOR_SIZE] & 0xf);
+ return 0;
}
-static inline u16 ata_id_logical_per_physical_sectors(const u16 *id)
+/* Offset of logical sectors relative to physical sectors.
+ *
+ * If device has more than one logical sector per physical sector
+ * (aka 512 byte emulation), vendors might offset the "sector 0" address
+ * so sector 63 is "naturally aligned" - e.g. FAT partition table.
+ * This avoids Read/Mod/Write penalties when using FAT partition table
+ * and updating "well aligned" (FS perspective) physical sectors on every
+ * transaction.
+ */
+static inline u16 ata_id_logical_sector_offset(const u16 *id,
+ u8 log2_per_phys)
{
- return 1 << (id[ATA_ID_SECTOR_SIZE] & 0xf);
+ u16 word_209 = id[209];
+
+ if ((log2_per_phys > 1) && (word_209 & 0xc000) == 0x4000) {
+ u16 first = word_209 & 0x3fff;
+ if (first > 0)
+ return (1 << log2_per_phys) - first;
+ }
+ return 0;
}
static inline int ata_id_has_lba48(const u16 *id)
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 45fb2967b66..15b77b8dc7e 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -37,6 +37,7 @@
#include <scsi/scsi_host.h>
#include <linux/acpi.h>
#include <linux/cdrom.h>
+#include <linux/sched.h>
/*
* Define if arch has non-standard setup. This is a _PCI_ standard
@@ -172,6 +173,7 @@ enum {
ATA_LFLAG_NO_RETRY = (1 << 5), /* don't retry this link */
ATA_LFLAG_DISABLED = (1 << 6), /* link is disabled */
ATA_LFLAG_SW_ACTIVITY = (1 << 7), /* keep activity stats */
+ ATA_LFLAG_NO_LPM = (1 << 8), /* disable LPM on this link */
/* struct ata_port flags */
ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */
@@ -196,7 +198,7 @@ enum {
ATA_FLAG_ACPI_SATA = (1 << 17), /* need native SATA ACPI layout */
ATA_FLAG_AN = (1 << 18), /* controller supports AN */
ATA_FLAG_PMP = (1 << 19), /* controller supports PMP */
- ATA_FLAG_IPM = (1 << 20), /* driver can handle IPM */
+ ATA_FLAG_LPM = (1 << 20), /* driver can handle LPM */
ATA_FLAG_EM = (1 << 21), /* driver supports enclosure
* management */
ATA_FLAG_SW_ACTIVITY = (1 << 22), /* driver supports sw activity
@@ -324,12 +326,11 @@ enum {
ATA_EH_HARDRESET = (1 << 2), /* meaningful only in ->prereset */
ATA_EH_RESET = ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
ATA_EH_ENABLE_LINK = (1 << 3),
- ATA_EH_LPM = (1 << 4), /* link power management action */
ATA_EH_PARK = (1 << 5), /* unload heads and stop I/O */
ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE | ATA_EH_PARK,
ATA_EH_ALL_ACTIONS = ATA_EH_REVALIDATE | ATA_EH_RESET |
- ATA_EH_ENABLE_LINK | ATA_EH_LPM,
+ ATA_EH_ENABLE_LINK,
/* ata_eh_info->flags */
ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */
@@ -341,7 +342,7 @@ enum {
ATA_EHI_DID_HARDRESET = (1 << 17), /* already soft-reset this port */
ATA_EHI_PRINTINFO = (1 << 18), /* print configuration info */
ATA_EHI_SETMODE = (1 << 19), /* configure transfer mode */
- ATA_EHI_POST_SETMODE = (1 << 20), /* revaildating after setmode */
+ ATA_EHI_POST_SETMODE = (1 << 20), /* revalidating after setmode */
ATA_EHI_DID_RESET = ATA_EHI_DID_SOFTRESET | ATA_EHI_DID_HARDRESET,
@@ -377,7 +378,6 @@ enum {
ATA_HORKAGE_BROKEN_HPA = (1 << 4), /* Broken HPA */
ATA_HORKAGE_DISABLE = (1 << 5), /* Disable it */
ATA_HORKAGE_HPA_SIZE = (1 << 6), /* native size off by one */
- ATA_HORKAGE_IPM = (1 << 7), /* Link PM problems */
ATA_HORKAGE_IVB = (1 << 8), /* cbl det validity bit bugs */
ATA_HORKAGE_STUCK_ERR = (1 << 9), /* stuck ERR on next PACKET */
ATA_HORKAGE_BRIDGE_OK = (1 << 10), /* no bridge limits */
@@ -464,6 +464,22 @@ enum ata_completion_errors {
AC_ERR_NCQ = (1 << 10), /* marker for offending NCQ qc */
};
+/*
+ * Link power management policy: If you alter this, you also need to
+ * alter libata-scsi.c (for the ascii descriptions)
+ */
+enum ata_lpm_policy {
+ ATA_LPM_UNKNOWN,
+ ATA_LPM_MAX_POWER,
+ ATA_LPM_MED_POWER,
+ ATA_LPM_MIN_POWER,
+};
+
+enum ata_lpm_hints {
+ ATA_LPM_EMPTY = (1 << 0), /* port empty/probing */
+ ATA_LPM_HIPM = (1 << 1), /* may use HIPM */
+};
+
/* forward declarations */
struct scsi_device;
struct ata_port_operations;
@@ -478,16 +494,6 @@ typedef int (*ata_reset_fn_t)(struct ata_link *link, unsigned int *classes,
unsigned long deadline);
typedef void (*ata_postreset_fn_t)(struct ata_link *link, unsigned int *classes);
-/*
- * host pm policy: If you alter this, you also need to alter libata-scsi.c
- * (for the ascii descriptions)
- */
-enum link_pm {
- NOT_AVAILABLE,
- MIN_POWER,
- MAX_PERFORMANCE,
- MEDIUM_POWER,
-};
extern struct device_attribute dev_attr_link_power_management_policy;
extern struct device_attribute dev_attr_unload_heads;
extern struct device_attribute dev_attr_em_message_type;
@@ -530,6 +536,10 @@ struct ata_host {
void *private_data;
struct ata_port_operations *ops;
unsigned long flags;
+
+ struct mutex eh_mutex;
+ struct task_struct *eh_owner;
+
#ifdef CONFIG_ATA_ACPI
acpi_handle acpi_handle;
#endif
@@ -560,13 +570,13 @@ struct ata_queued_cmd {
unsigned int extrabytes;
unsigned int curbytes;
- struct scatterlist *cursg;
- unsigned int cursg_ofs;
-
struct scatterlist sgent;
struct scatterlist *sg;
+ struct scatterlist *cursg;
+ unsigned int cursg_ofs;
+
unsigned int err_mask;
struct ata_taskfile result_tf;
ata_qc_cb_t complete_fn;
@@ -604,6 +614,7 @@ struct ata_device {
union acpi_object *gtf_cache;
unsigned int gtf_filter;
#endif
+ struct device tdev;
/* n_sector is CLEAR_BEGIN, read comment above CLEAR_BEGIN */
u64 n_sectors; /* size of device, if ATA */
u64 n_native_sectors; /* native size, if ATA */
@@ -690,6 +701,7 @@ struct ata_link {
struct ata_port *ap;
int pmp; /* port multiplier port # */
+ struct device tdev;
unsigned int active_tag; /* active tag on this link */
u32 sactive; /* active NCQ commands */
@@ -699,6 +711,7 @@ struct ata_link {
unsigned int hw_sata_spd_limit;
unsigned int sata_spd_limit;
unsigned int sata_spd; /* current SATA PHY speed */
+ enum ata_lpm_policy lpm_policy;
/* record runtime error info, protected by host_set lock */
struct ata_eh_info eh_info;
@@ -707,6 +720,8 @@ struct ata_link {
struct ata_device device[ATA_MAX_DEVICES];
};
+#define ATA_LINK_CLEAR_BEGIN offsetof(struct ata_link, active_tag)
+#define ATA_LINK_CLEAR_END offsetof(struct ata_link, device[0])
struct ata_port {
struct Scsi_Host *scsi_host; /* our co-allocated scsi host */
@@ -752,6 +767,7 @@ struct ata_port {
struct ata_port_stats stats;
struct ata_host *host;
struct device *dev;
+ struct device tdev;
struct mutex scsi_scan_mutex;
struct delayed_work hotplug_task;
@@ -767,7 +783,7 @@ struct ata_port {
pm_message_t pm_mesg;
int *pm_result;
- enum link_pm pm_policy;
+ enum ata_lpm_policy target_lpm_policy;
struct timer_list fastdrain_timer;
unsigned long fastdrain_cnt;
@@ -833,8 +849,8 @@ struct ata_port_operations {
int (*scr_write)(struct ata_link *link, unsigned int sc_reg, u32 val);
void (*pmp_attach)(struct ata_port *ap);
void (*pmp_detach)(struct ata_port *ap);
- int (*enable_pm)(struct ata_port *ap, enum link_pm policy);
- void (*disable_pm)(struct ata_port *ap);
+ int (*set_lpm)(struct ata_link *link, enum ata_lpm_policy policy,
+ unsigned hints);
/*
* Start, stop, suspend and resume
@@ -946,6 +962,8 @@ extern int sata_link_debounce(struct ata_link *link,
const unsigned long *params, unsigned long deadline);
extern int sata_link_resume(struct ata_link *link, const unsigned long *params,
unsigned long deadline);
+extern int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
+ bool spm_wakeup);
extern int sata_link_hardreset(struct ata_link *link,
const unsigned long *timing, unsigned long deadline,
bool *online, int (*check_ready)(struct ata_link *));
@@ -991,8 +1009,9 @@ extern int ata_host_suspend(struct ata_host *host, pm_message_t mesg);
extern void ata_host_resume(struct ata_host *host);
#endif
extern int ata_ratelimit(void);
-extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
- unsigned long interval, unsigned long timeout);
+extern void ata_msleep(struct ata_port *ap, unsigned int msecs);
+extern u32 ata_wait_register(struct ata_port *ap, void __iomem *reg, u32 mask,
+ u32 val, unsigned long interval, unsigned long timeout);
extern int atapi_cmd_type(u8 opcode);
extern void ata_tf_to_fis(const struct ata_taskfile *tf,
u8 pmp, int is_cmd, u8 *fis);