Patchwork [RFC] ata_piix: ignore disks in a hyper-v guest

login
register
mail settings
Submitter Olaf Hering
Date Sept. 1, 2011, 3:43 p.m.
Message ID <20110901154340.GA12375@aepfle.de>
Download mbox | patch
Permalink /patch/112939/
State Not Applicable
Delegated to: David Miller
Headers show

Comments

Olaf Hering - Sept. 1, 2011, 3:43 p.m.
On Wed, Aug 31, Olaf Hering wrote:

> After some more testing it looks like the hv_blkvsc driver claimed the
> ide major #3, so the ide_core could not bind to the emulated IDE
> hardware. The modprobe.conf rules prevented that ata_piix gets loaded.
> If I force a module load order of 'ata_piix ;hv_blkvsc' both ata_piix
> and hv_blkvsc will bind to the same drive, just as shown in my previous
> mail. So there is appearently no way to shutdown the IDE ports like it
> is done with xen_emul_unplug= option for Xen guests.
> 
> Maybe some hack is needed for a hyper-v specific unplug if Windows does
> indeed lack that feature. Now that ata_piix is compiled into the kernel,
> there is nothing to a modprobe.conf rule can "fix".

Here is an attempt to ignore disks in a hyper-v disks, and let ata_piix
handle only the configured cdrom devices (iso of physical).
If the disks are not ignored, they will appear twice, once through
ata_piix and once through hv_storvsc.

Once hv_storvsc can also handle the configured cdrom devices, the added
piix_pata_read_id() function can be removed again. Only the check in
piix_init() or something similar needs to be done.

Maybe there is a better way enable only ATA_DEV_ATAPI?


Signed-off-by: Olaf Hering <olaf@aepfle.de>

---
 drivers/ata/ata_piix.c |   54 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

--
To unsubscribe from this list: send the line "unsubscribe linux-ide" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -98,6 +98,10 @@ 
 #define DRV_NAME	"ata_piix"
 #define DRV_VERSION	"2.13"
 
+#if defined(CONFIG_HYPERV_STORAGE) || defined(CONFIG_HYPERV_STORAGE_MODULE)
+#define PIIX_IGNORE_ATA_ON_HYPERV 1
+#endif
+
 enum {
 	PIIX_IOCFG		= 0x54, /* IDE I/O configuration register */
 	ICH5_PMR		= 0x90, /* port mapping register */
@@ -164,6 +168,7 @@  struct piix_host_priv {
 static int piix_init_one(struct pci_dev *pdev,
 			 const struct pci_device_id *ent);
 static void piix_remove_one(struct pci_dev *pdev);
+static unsigned int piix_pata_read_id(struct ata_device *adev, struct ata_taskfile *tf, u16 *id);
 static int piix_pata_prereset(struct ata_link *link, unsigned long deadline);
 static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev);
 static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev);
@@ -346,6 +351,7 @@  static struct ata_port_operations piix_p
 	.set_piomode		= piix_set_piomode,
 	.set_dmamode		= piix_set_dmamode,
 	.prereset		= piix_pata_prereset,
+	.read_id		= piix_pata_read_id,
 };
 
 static struct ata_port_operations piix_vmw_ops = {
@@ -619,6 +625,24 @@  MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
 MODULE_VERSION(DRV_VERSION);
 
+#if defined(PIIX_IGNORE_ATA_ON_HYPERV)
+static int piix_msft_hyperv(void)
+{
+	static const struct dmi_system_id hv_dmi_ident[]  = {
+		{
+			.ident = "Hyper-V",
+			.matches = {
+				DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+				DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
+				DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
+			},
+		},
+		{ }	/* terminate list */
+	};
+	return !!dmi_check_system(hv_dmi_ident);
+}
+#endif
+
 struct ich_laptop {
 	u16 device;
 	u16 subvendor;
@@ -702,6 +726,29 @@  static int piix_pata_prereset(struct ata
 	return ata_sff_prereset(link, deadline);
 }
 
+/**
+ *
+ */
+static unsigned int piix_pata_read_id(struct ata_device *adev, struct ata_taskfile *tf, u16 *id)
+{
+	unsigned int err_mask = ata_do_dev_read_id(adev, tf, id);
+#if defined(PIIX_IGNORE_ATA_ON_HYPERV)
+	/*
+	 * Ignore disks in a hyper-v guest.
+	 * There is no unplug protocol like it is done with xen_emul_unplug= option.
+	 * Emulate the unplug by ignoring disks when the hv_storvsc driver is enabled.
+	 * If the disks are not ignored, they will appear twice: once through piix and once through hv_storvsc.
+	 * Because hv_storvsc does not handle ATAPI devices, the piix driver is still required.
+	 * Once hv_storvsc handles all devices, this function can be removed and the whole driver should be disabled in a hyper-v guest.
+	 */
+	if (ata_id_is_ata(id) && piix_msft_hyperv()) {
+		ata_dev_printk(adev, KERN_WARNING, "ATA device ignored in Hyper-V guest\n");
+		id[ATA_ID_CONFIG] |= (1 << 15);
+	}
+#endif
+	return err_mask;
+}
+
 static DEFINE_SPINLOCK(piix_lock);
 
 /**
@@ -1679,6 +1726,13 @@  static int __init piix_init(void)
 {
 	int rc;
 
+#if defined(PIIX_IGNORE_ATA_ON_HYPERV)
+	/* disabled until hv_storvsc drives also cdrom devices */
+	if (0 && piix_msft_hyperv()) {
+		printk(KERN_DEBUG "%s: hv_storvsc will bind to storage\n", __func__);
+		return -ENODEV;
+	}
+#endif
 	DPRINTK("pci_register_driver\n");
 	rc = pci_register_driver(&piix_pci_driver);
 	if (rc)