aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAndy Whitcroft <apw@canonical.com>2012-03-08 11:32:35 +0000
committerLeann Ogasawara <leann.ogasawara@canonical.com>2012-05-21 06:45:31 -0700
commit93bf0ceec4e9d1d47c745fea09c38d3a3537ba4b (patch)
tree3dcca9fc738c6c0349daf4a191ffed56d670e42a /drivers
parentec11e2092a04bb0740b4235b621f0dc1509ab2aa (diff)
UBUNTU: SAUCE: ata_piix: defer disks to the Hyper-V drivers by default
When we are hosted on a Microsoft Hyper-V hypervisor the guest disks are exposed both via the Hyper-V paravirtualised drivers and via an emulated SATA disk drive. In this case we want to use the paravirtualised drivers if we can as they are much more efficient. Note that the Hyper-V paravirtualised drivers only expose the virtual hard disk devices, the CDROM/DVD devices must still be enumerated. Check the disk type when picking up its ID and if it appears to be a disk just report it disconnected. BugLink: http://bugs.launchpad.net/bugs/929545 BugLink: http://bugs.launchpad.net/bugs/942316 Signed-off-by: Andy Whitcroft <apw@canonical.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/ata_piix.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 7857e8fd0a3..de29a866cef 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -94,6 +94,9 @@
#include <scsi/scsi_host.h>
#include <linux/libata.h>
#include <linux/dmi.h>
+#ifdef CONFIG_X86
+#include <asm/hypervisor.h>
+#endif
#define DRV_NAME "ata_piix"
#define DRV_VERSION "2.13"
@@ -188,6 +191,29 @@ static int piix_pci_device_resume(struct pci_dev *pdev);
static unsigned int in_module_init = 1;
+static int prefer_ms_hyperv = 1;
+
+unsigned int ata_piix_read_id(struct ata_device *dev,
+ struct ata_taskfile *tf, u16 *id)
+{
+ int ret = ata_do_dev_read_id(dev, tf, id);
+
+#ifdef CONFIG_X86
+ /* XXX: note that the device id is in little-endian order, the caller
+ * will shift it to host order, but we are working with little-endian.
+ * As this is _only_ used on x86 we can actually directly access it
+ * as host is also little-endian.
+ */
+ if (!ret && prefer_ms_hyperv && x86_hyper == &x86_hyper_ms_hyperv &&
+ ata_id_is_ata(id)) {
+ ata_dev_printk(dev, KERN_WARNING, "ATA disk ignored deferring to Hyper-V paravirt driver\n");
+
+ return AC_ERR_DEV|AC_ERR_NODEV_HINT;
+ }
+#endif
+ return ret;
+}
+
static const struct pci_device_id piix_pci_tbl[] = {
/* Intel PIIX3 for the 430HX etc */
{ 0x8086, 0x7010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_mwdma },
@@ -361,6 +387,7 @@ static struct ata_port_operations piix_pata_ops = {
.set_piomode = piix_set_piomode,
.set_dmamode = piix_set_dmamode,
.prereset = piix_pata_prereset,
+ .read_id = ata_piix_read_id,
};
static struct ata_port_operations piix_vmw_ops = {
@@ -1705,3 +1732,5 @@ static void __exit piix_exit(void)
module_init(piix_init);
module_exit(piix_exit);
+
+module_param(prefer_ms_hyperv, int, 0);