From 0991b55f3a296b59e58361303f3f3e7eb953ce4c Mon Sep 17 00:00:00 2001 From: Ross Philipson Date: Wed, 25 Mar 2009 13:54:31 -0400 Subject: [PATCH] FLR - intermediate checkin 3 3/25 - added noflr settings to allow device level control. Changes to be committed: modified: drivers/xen/pciback/pci_stub.c modified: drivers/xen/pciback/pciback.h modified: drivers/xen/pciback/pciback_ops.c --- drivers/xen/pciback/pci_stub.c | 46 +++++++++++++++++++++++++------ drivers/xen/pciback/pciback.h | 1 + drivers/xen/pciback/pciback_ops.c | 5 ++++ 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/drivers/xen/pciback/pci_stub.c b/drivers/xen/pciback/pci_stub.c index 55932a42..a17f24db 100644 --- a/drivers/xen/pciback/pci_stub.c +++ b/drivers/xen/pciback/pci_stub.c @@ -17,21 +17,22 @@ static char *pci_devs_to_hide = NULL; module_param_named(hide, pci_devs_to_hide, charp, S_IRUGO); -static int disable_flr = 0; -module_param_named(noflr, disable_flr, int, S_IRUGO); - static char *pci_devs_use_sbr = NULL; module_param_named(sbr, pci_devs_use_sbr, charp, S_IRUGO); static char *pci_devs_use_d3r = NULL; module_param_named(d3r, pci_devs_use_d3r, charp, S_IRUGO); +static char *pci_devs_no_flr = NULL; +module_param_named(noflr, pci_devs_no_flr, charp, S_IRUGO); + /* Device id list holding different device type listings * for hiding devices and reset logic. */ #define PCIBACK_ID_TYPE_HIDE 1 #define PCIBACK_ID_TYPE_SBR 2 #define PCIBACK_ID_TYPE_D3R 3 +#define PCIBACK_ID_TYPE_NOFLR 4 struct pcistub_device_id { struct list_head slot_list; @@ -64,6 +65,8 @@ static LIST_HEAD(pcistub_devices); static int initialize_devices = 0; static LIST_HEAD(seized_devices); +static int disable_all_flr = 0; + static struct pcistub_device *pcistub_device_alloc(struct pci_dev *dev) { struct pcistub_device *psdev; @@ -244,7 +247,7 @@ void pcistub_put_pci_dev(struct pci_dev *dev, int do_flr) /* For pass-through devices, do an FLR (or approximate) for the device * before it is put back and ready for the next domain */ - if (!disable_flr && do_flr) + if (!disable_all_flr && do_flr) pciback_flr_device(dev); /* Cleanup our device @@ -384,8 +387,11 @@ static int __devinit pcistub_init_device(struct pci_dev *dev) * values if SBR/D3R reset logic was requested. */ pciback_classify_device(dev); - dev_data->use_sbr = pcistub_match(dev, PCIBACK_ID_TYPE_SBR); - dev_data->use_d3r = pcistub_match(dev, PCIBACK_ID_TYPE_D3R); + dev_data->no_flr = pcistub_match(dev, PCIBACK_ID_TYPE_NOFLR); + if (!dev_data->no_flr) { + dev_data->use_sbr = pcistub_match(dev, PCIBACK_ID_TYPE_SBR); + dev_data->use_d3r = pcistub_match(dev, PCIBACK_ID_TYPE_D3R); + } /* Store the config space here where the device is off and ready to be * exported before any FLRs or other resets are done @@ -718,7 +724,12 @@ static int pcistub_device_do_flr(int domain, int bus, int slot, int func) /* Do an FLR (or approximate) for the device on demand and * reload config */ - pciback_flr_device(dev); + if (!disable_all_flr) { + dev_info(&dev->dev, "FLR invoked for device\n"); + pciback_flr_device(dev); + } + else + dev_info(&dev->dev, "FLR disabled for all devices\n"); out: return err; @@ -943,20 +954,29 @@ static ssize_t pcistub_resets(struct device_driver *drv, const char *buf, size_t count) { int domain, bus, slot, func; - int type, err; + int type, err = 0; - /* string begins with reset type specifier sbr=|dr3= */ + /* string begins with reset type specifier sbr=|dr3=|noflr= */ if (!strncmp(buf, "sbr=", 4)) { type = PCIBACK_ID_TYPE_SBR; buf += 4; } else if (!strncmp(buf, "d3r=", 4)) { type = PCIBACK_ID_TYPE_D3R; buf += 4; + } else if (!strncmp(buf, "noflr=", 6)) { + type = PCIBACK_ID_TYPE_NOFLR; + buf += 6; } else { err = -EINVAL; goto out; } + /* check special wildcard noflr */ + if (type == PCIBACK_ID_TYPE_NOFLR && !strncmp(buf, "*", 1)) { + disable_all_flr = 1; + goto out; + } + err = str_to_slot(buf, &domain, &bus, &slot, &func); if (err) goto out; @@ -1019,6 +1039,14 @@ static int __init pcistub_init(void) if (err) goto out; + if (pci_devs_no_flr && *pci_devs_no_flr && !strncmp(pci_devs_no_flr, "*", 1)) + disable_all_flr = 1; /* check special wildcard noflr */ + else + err = pciback_parse_device_params(pci_devs_no_flr, PCIBACK_ID_TYPE_NOFLR, pcistub_device_id_add); + if (err) + goto out; + + /* If we're the first PCI Device Driver to register, we're the * first one to get offered PCI devices as they become * available (and thus we can be the first to grab them) diff --git a/drivers/xen/pciback/pciback.h b/drivers/xen/pciback/pciback.h index 7086ca6f..7b75878a 100644 --- a/drivers/xen/pciback/pciback.h +++ b/drivers/xen/pciback/pciback.h @@ -55,6 +55,7 @@ struct pciback_dev_data { int permissive; int warned_on_write; u32 dev_type; + int no_flr; int exp_flr_offset; int af_flr_offset; int use_sbr; diff --git a/drivers/xen/pciback/pciback_ops.c b/drivers/xen/pciback/pciback_ops.c index 07fae104..15b0e0a0 100644 --- a/drivers/xen/pciback/pciback_ops.c +++ b/drivers/xen/pciback/pciback_ops.c @@ -277,6 +277,11 @@ void pciback_flr_device(struct pci_dev *dev) struct pciback_dev_data *dev_data = pci_get_drvdata(dev); int err = 0; + if (dev_data->no_flr) { + dev_dbg(&dev->dev, "FLR disabled for device\n"); + return; + } + do { /* First, always try to do an FLR */ if (dev_data->dev_type == PCIBACK_TYPE_PCIe_ENDPOINT && -- 2.39.5