aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Whitcroft <apw@canonical.com>2012-03-08 11:32:35 +0000
committerJohn Rigby <john.rigby@linaro.org>2012-06-25 12:17:07 -0600
commitca1f02934fe9e787964e697af602ba06d0c962fd (patch)
tree7ae12c3ae9a5f8f517a426e20a246a82c6c9fd6b
parentf9b761cb9967b2dbca7e22c2e73bbbd3356681ef (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>
-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);