Path: blob/master/arch/x86/xen/platform-pci-unplug.c
10817 views
/******************************************************************************1* platform-pci-unplug.c2*3* Xen platform PCI device driver4* Copyright (c) 2010, Citrix5*6* This program is free software; you can redistribute it and/or modify it7* under the terms and conditions of the GNU General Public License,8* version 2, as published by the Free Software Foundation.9*10* This program is distributed in the hope it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for13* more details.14*15* You should have received a copy of the GNU General Public License along with16* this program; if not, write to the Free Software Foundation, Inc., 59 Temple17* Place - Suite 330, Boston, MA 02111-1307 USA.18*19*/2021#include <linux/init.h>22#include <linux/io.h>23#include <linux/module.h>2425#include <xen/platform_pci.h>2627#define XEN_PLATFORM_ERR_MAGIC -128#define XEN_PLATFORM_ERR_PROTOCOL -229#define XEN_PLATFORM_ERR_BLACKLIST -33031/* store the value of xen_emul_unplug after the unplug is done */32int xen_platform_pci_unplug;33EXPORT_SYMBOL_GPL(xen_platform_pci_unplug);34#ifdef CONFIG_XEN_PVHVM35static int xen_emul_unplug;3637static int __init check_platform_magic(void)38{39short magic;40char protocol;4142magic = inw(XEN_IOPORT_MAGIC);43if (magic != XEN_IOPORT_MAGIC_VAL) {44printk(KERN_ERR "Xen Platform PCI: unrecognised magic value\n");45return XEN_PLATFORM_ERR_MAGIC;46}4748protocol = inb(XEN_IOPORT_PROTOVER);4950printk(KERN_DEBUG "Xen Platform PCI: I/O protocol version %d\n",51protocol);5253switch (protocol) {54case 1:55outw(XEN_IOPORT_LINUX_PRODNUM, XEN_IOPORT_PRODNUM);56outl(XEN_IOPORT_LINUX_DRVVER, XEN_IOPORT_DRVVER);57if (inw(XEN_IOPORT_MAGIC) != XEN_IOPORT_MAGIC_VAL) {58printk(KERN_ERR "Xen Platform: blacklisted by host\n");59return XEN_PLATFORM_ERR_BLACKLIST;60}61break;62default:63printk(KERN_WARNING "Xen Platform PCI: unknown I/O protocol version");64return XEN_PLATFORM_ERR_PROTOCOL;65}6667return 0;68}6970void xen_unplug_emulated_devices(void)71{72int r;7374/* user explicitly requested no unplug */75if (xen_emul_unplug & XEN_UNPLUG_NEVER)76return;77/* check the version of the xen platform PCI device */78r = check_platform_magic();79/* If the version matches enable the Xen platform PCI driver.80* Also enable the Xen platform PCI driver if the host does81* not support the unplug protocol (XEN_PLATFORM_ERR_MAGIC)82* but the user told us that unplugging is unnecessary. */83if (r && !(r == XEN_PLATFORM_ERR_MAGIC &&84(xen_emul_unplug & XEN_UNPLUG_UNNECESSARY)))85return;86/* Set the default value of xen_emul_unplug depending on whether or87* not the Xen PV frontends and the Xen platform PCI driver have88* been compiled for this kernel (modules or built-in are both OK). */89if (!xen_emul_unplug) {90if (xen_must_unplug_nics()) {91printk(KERN_INFO "Netfront and the Xen platform PCI driver have "92"been compiled for this kernel: unplug emulated NICs.\n");93xen_emul_unplug |= XEN_UNPLUG_ALL_NICS;94}95if (xen_must_unplug_disks()) {96printk(KERN_INFO "Blkfront and the Xen platform PCI driver have "97"been compiled for this kernel: unplug emulated disks.\n"98"You might have to change the root device\n"99"from /dev/hd[a-d] to /dev/xvd[a-d]\n"100"in your root= kernel command line option\n");101xen_emul_unplug |= XEN_UNPLUG_ALL_IDE_DISKS;102}103}104/* Now unplug the emulated devices */105if (!(xen_emul_unplug & XEN_UNPLUG_UNNECESSARY))106outw(xen_emul_unplug, XEN_IOPORT_UNPLUG);107xen_platform_pci_unplug = xen_emul_unplug;108}109110static int __init parse_xen_emul_unplug(char *arg)111{112char *p, *q;113int l;114115for (p = arg; p; p = q) {116q = strchr(p, ',');117if (q) {118l = q - p;119q++;120} else {121l = strlen(p);122}123if (!strncmp(p, "all", l))124xen_emul_unplug |= XEN_UNPLUG_ALL;125else if (!strncmp(p, "ide-disks", l))126xen_emul_unplug |= XEN_UNPLUG_ALL_IDE_DISKS;127else if (!strncmp(p, "aux-ide-disks", l))128xen_emul_unplug |= XEN_UNPLUG_AUX_IDE_DISKS;129else if (!strncmp(p, "nics", l))130xen_emul_unplug |= XEN_UNPLUG_ALL_NICS;131else if (!strncmp(p, "unnecessary", l))132xen_emul_unplug |= XEN_UNPLUG_UNNECESSARY;133else if (!strncmp(p, "never", l))134xen_emul_unplug |= XEN_UNPLUG_NEVER;135else136printk(KERN_WARNING "unrecognised option '%s' "137"in parameter 'xen_emul_unplug'\n", p);138}139return 0;140}141early_param("xen_emul_unplug", parse_xen_emul_unplug);142#endif143144145