diff options
author | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2011-07-19 19:40:51 -0400 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2011-07-19 20:58:35 -0400 |
commit | a92336a1176b2119eaa990a1e8bf3109665fdbc6 (patch) | |
tree | af8ac49b47136acddb5320b9a62be2361bfaf99c /drivers/xen/xen-pciback/pciback_ops.c | |
parent | c288b67b9b4d65790e1a1a1fd982330730b68f46 (diff) |
xen/pciback: Drop two backends, squash and cleanup some code.
- Remove the slot and controller controller backend as they
are not used.
- Document the find pciback_[read|write]_config_[byte|word|dword]
to make it easier to find.
- Collapse the code from conf_space_capability_msi into pciback_ops.c
- Collapse conf_space_capability_[pm|vpd].c in conf_space_capability.c
[and remove the conf_space_capability.h file]
- Rename all visible functions from pciback to xen_pcibk.
- Rename all the printk/pr_info, etc that use the "pciback" to say
"xen-pciback".
- Convert functions that are not referenced outside the code to be
static to save on name space.
- Do the same thing for structures that are internal to the driver.
- Run checkpatch.pl after the renames and fixup its warnings and
fix any compile errors caused by the variable rename
- Cleanup any structs that checkpath.pl commented about or just
look odd.
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/xen/xen-pciback/pciback_ops.c')
-rw-r--r-- | drivers/xen/xen-pciback/pciback_ops.c | 198 |
1 files changed, 167 insertions, 31 deletions
diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c index 28a2a5584831..8c95c3415b75 100644 --- a/drivers/xen/xen-pciback/pciback_ops.c +++ b/drivers/xen/xen-pciback/pciback_ops.c @@ -10,16 +10,19 @@ #include <linux/sched.h> #include "pciback.h" +#define DRV_NAME "xen-pciback" int verbose_request; module_param(verbose_request, int, 0644); +static irqreturn_t xen_pcibk_guest_interrupt(int irq, void *dev_id); + /* Ensure a device is has the fake IRQ handler "turned on/off" and is - * ready to be exported. This MUST be run after pciback_reset_device + * ready to be exported. This MUST be run after xen_pcibk_reset_device * which does the actual PCI device enable/disable. */ -void pciback_control_isr(struct pci_dev *dev, int reset) +static void xen_pcibk_control_isr(struct pci_dev *dev, int reset) { - struct pciback_dev_data *dev_data; + struct xen_pcibk_dev_data *dev_data; int rc; int enable = 0; @@ -66,7 +69,7 @@ void pciback_control_isr(struct pci_dev *dev, int reset) if (enable) { rc = request_irq(dev_data->irq, - pciback_guest_interrupt, IRQF_SHARED, + xen_pcibk_guest_interrupt, IRQF_SHARED, dev_data->irq_name, dev); if (rc) { dev_err(&dev->dev, "%s: failed to install fake IRQ " \ @@ -92,14 +95,14 @@ out: } /* Ensure a device is "turned off" and ready to be exported. - * (Also see pciback_config_reset to ensure virtual configuration space is + * (Also see xen_pcibk_config_reset to ensure virtual configuration space is * ready to be re-exported) */ -void pciback_reset_device(struct pci_dev *dev) +void xen_pcibk_reset_device(struct pci_dev *dev) { u16 cmd; - pciback_control_isr(dev, 1 /* reset device */); + xen_pcibk_control_isr(dev, 1 /* reset device */); /* Disable devices (but not bridges) */ if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) { @@ -126,43 +129,176 @@ void pciback_reset_device(struct pci_dev *dev) } } } + +#ifdef CONFIG_PCI_MSI +static +int xen_pcibk_enable_msi(struct xen_pcibk_device *pdev, + struct pci_dev *dev, struct xen_pci_op *op) +{ + struct xen_pcibk_dev_data *dev_data; + int otherend = pdev->xdev->otherend_id; + int status; + + if (unlikely(verbose_request)) + printk(KERN_DEBUG DRV_NAME ": %s: enable MSI\n", pci_name(dev)); + + status = pci_enable_msi(dev); + + if (status) { + printk(KERN_ERR "error enable msi for guest %x status %x\n", + otherend, status); + op->value = 0; + return XEN_PCI_ERR_op_failed; + } + + /* The value the guest needs is actually the IDT vector, not the + * the local domain's IRQ number. */ + + op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0; + if (unlikely(verbose_request)) + printk(KERN_DEBUG DRV_NAME ": %s: MSI: %d\n", pci_name(dev), + op->value); + + dev_data = pci_get_drvdata(dev); + if (dev_data) + dev_data->ack_intr = 0; + + return 0; +} + +static +int xen_pcibk_disable_msi(struct xen_pcibk_device *pdev, + struct pci_dev *dev, struct xen_pci_op *op) +{ + struct xen_pcibk_dev_data *dev_data; + + if (unlikely(verbose_request)) + printk(KERN_DEBUG DRV_NAME ": %s: disable MSI\n", + pci_name(dev)); + pci_disable_msi(dev); + + op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0; + if (unlikely(verbose_request)) + printk(KERN_DEBUG DRV_NAME ": %s: MSI: %d\n", pci_name(dev), + op->value); + dev_data = pci_get_drvdata(dev); + if (dev_data) + dev_data->ack_intr = 1; + return 0; +} + +static +int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev, + struct pci_dev *dev, struct xen_pci_op *op) +{ + struct xen_pcibk_dev_data *dev_data; + int i, result; + struct msix_entry *entries; + + if (unlikely(verbose_request)) + printk(KERN_DEBUG DRV_NAME ": %s: enable MSI-X\n", + pci_name(dev)); + if (op->value > SH_INFO_MAX_VEC) + return -EINVAL; + + entries = kmalloc(op->value * sizeof(*entries), GFP_KERNEL); + if (entries == NULL) + return -ENOMEM; + + for (i = 0; i < op->value; i++) { + entries[i].entry = op->msix_entries[i].entry; + entries[i].vector = op->msix_entries[i].vector; + } + + result = pci_enable_msix(dev, entries, op->value); + + if (result == 0) { + for (i = 0; i < op->value; i++) { + op->msix_entries[i].entry = entries[i].entry; + if (entries[i].vector) + op->msix_entries[i].vector = + xen_pirq_from_irq(entries[i].vector); + if (unlikely(verbose_request)) + printk(KERN_DEBUG DRV_NAME ": %s: " \ + "MSI-X[%d]: %d\n", + pci_name(dev), i, + op->msix_entries[i].vector); + } + } else { + printk(KERN_WARNING DRV_NAME ": %s: failed to enable MSI-X: err %d!\n", + pci_name(dev), result); + } + kfree(entries); + + op->value = result; + dev_data = pci_get_drvdata(dev); + if (dev_data) + dev_data->ack_intr = 0; + + return result; +} + +static +int xen_pcibk_disable_msix(struct xen_pcibk_device *pdev, + struct pci_dev *dev, struct xen_pci_op *op) +{ + struct xen_pcibk_dev_data *dev_data; + if (unlikely(verbose_request)) + printk(KERN_DEBUG DRV_NAME ": %s: disable MSI-X\n", + pci_name(dev)); + pci_disable_msix(dev); + + /* + * SR-IOV devices (which don't have any legacy IRQ) have + * an undefined IRQ value of zero. + */ + op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0; + if (unlikely(verbose_request)) + printk(KERN_DEBUG DRV_NAME ": %s: MSI-X: %d\n", pci_name(dev), + op->value); + dev_data = pci_get_drvdata(dev); + if (dev_data) + dev_data->ack_intr = 1; + return 0; +} +#endif /* * Now the same evtchn is used for both pcifront conf_read_write request * as well as pcie aer front end ack. We use a new work_queue to schedule -* pciback conf_read_write service for avoiding confict with aer_core +* xen_pcibk conf_read_write service for avoiding confict with aer_core * do_recovery job which also use the system default work_queue */ -void test_and_schedule_op(struct pciback_device *pdev) +void xen_pcibk_test_and_schedule_op(struct xen_pcibk_device *pdev) { /* Check that frontend is requesting an operation and that we are not * already processing a request */ if (test_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags) && !test_and_set_bit(_PDEVF_op_active, &pdev->flags)) { - queue_work(pciback_wq, &pdev->op_work); + queue_work(xen_pcibk_wq, &pdev->op_work); } /*_XEN_PCIB_active should have been cleared by pcifront. And also make - sure pciback is waiting for ack by checking _PCIB_op_pending*/ + sure xen_pcibk is waiting for ack by checking _PCIB_op_pending*/ if (!test_bit(_XEN_PCIB_active, (unsigned long *)&pdev->sh_info->flags) && test_bit(_PCIB_op_pending, &pdev->flags)) { - wake_up(&aer_wait_queue); + wake_up(&xen_pcibk_aer_wait_queue); } } /* Performing the configuration space reads/writes must not be done in atomic * context because some of the pci_* functions can sleep (mostly due to ACPI * use of semaphores). This function is intended to be called from a work - * queue in process context taking a struct pciback_device as a parameter */ + * queue in process context taking a struct xen_pcibk_device as a parameter */ -void pciback_do_op(struct work_struct *data) +void xen_pcibk_do_op(struct work_struct *data) { - struct pciback_device *pdev = - container_of(data, struct pciback_device, op_work); + struct xen_pcibk_device *pdev = + container_of(data, struct xen_pcibk_device, op_work); struct pci_dev *dev; - struct pciback_dev_data *dev_data = NULL; + struct xen_pcibk_dev_data *dev_data = NULL; struct xen_pci_op *op = &pdev->sh_info->op; int test_intx = 0; - dev = pciback_get_pci_dev(pdev, op->domain, op->bus, op->devfn); + dev = xen_pcibk_get_pci_dev(pdev, op->domain, op->bus, op->devfn); if (dev == NULL) op->err = XEN_PCI_ERR_dev_not_found; @@ -172,25 +308,25 @@ void pciback_do_op(struct work_struct *data) test_intx = dev_data->enable_intx; switch (op->cmd) { case XEN_PCI_OP_conf_read: - op->err = pciback_config_read(dev, + op->err = xen_pcibk_config_read(dev, op->offset, op->size, &op->value); break; case XEN_PCI_OP_conf_write: - op->err = pciback_config_write(dev, + op->err = xen_pcibk_config_write(dev, op->offset, op->size, op->value); break; #ifdef CONFIG_PCI_MSI case XEN_PCI_OP_enable_msi: - op->err = pciback_enable_msi(pdev, dev, op); + op->err = xen_pcibk_enable_msi(pdev, dev, op); break; case XEN_PCI_OP_disable_msi: - op->err = pciback_disable_msi(pdev, dev, op); + op->err = xen_pcibk_disable_msi(pdev, dev, op); break; case XEN_PCI_OP_enable_msix: - op->err = pciback_enable_msix(pdev, dev, op); + op->err = xen_pcibk_enable_msix(pdev, dev, op); break; case XEN_PCI_OP_disable_msix: - op->err = pciback_disable_msix(pdev, dev, op); + op->err = xen_pcibk_disable_msix(pdev, dev, op); break; #endif default: @@ -201,7 +337,7 @@ void pciback_do_op(struct work_struct *data) if (!op->err && dev && dev_data) { /* Transition detected */ if ((dev_data->enable_intx != test_intx)) - pciback_control_isr(dev, 0 /* no reset */); + xen_pcibk_control_isr(dev, 0 /* no reset */); } /* Tell the driver domain that we're done. */ wmb(); @@ -216,21 +352,21 @@ void pciback_do_op(struct work_struct *data) /* Check to see if the driver domain tried to start another request in * between clearing _XEN_PCIF_active and clearing _PDEVF_op_active. */ - test_and_schedule_op(pdev); + xen_pcibk_test_and_schedule_op(pdev); } -irqreturn_t pciback_handle_event(int irq, void *dev_id) +irqreturn_t xen_pcibk_handle_event(int irq, void *dev_id) { - struct pciback_device *pdev = dev_id; + struct xen_pcibk_device *pdev = dev_id; - test_and_schedule_op(pdev); + xen_pcibk_test_and_schedule_op(pdev); return IRQ_HANDLED; } -irqreturn_t pciback_guest_interrupt(int irq, void *dev_id) +static irqreturn_t xen_pcibk_guest_interrupt(int irq, void *dev_id) { struct pci_dev *dev = (struct pci_dev *)dev_id; - struct pciback_dev_data *dev_data = pci_get_drvdata(dev); + struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev); if (dev_data->isr_on && dev_data->ack_intr) { dev_data->handled++; |