Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 255275
b: refs/heads/master
c: 0513fe9
h: refs/heads/master
i:
  255273: 39ba918
  255271: 01bbbc0
v: v3
  • Loading branch information
Konrad Rzeszutek Wilk committed Jul 20, 2011
1 parent 10b9b5d commit b7c2e56
Show file tree
Hide file tree
Showing 6 changed files with 224 additions and 6 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a2be65fd363831502afdf0babdf48149b3959cde
refs/heads/master: 0513fe9e5b54e47e37217ea078dd870e3825e02d
17 changes: 17 additions & 0 deletions trunk/drivers/xen/xen-pciback/conf_space_capability_msi.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
int pciback_enable_msi(struct pciback_device *pdev,
struct pci_dev *dev, struct xen_pci_op *op)
{
struct pciback_dev_data *dev_data;
int otherend = pdev->xdev->otherend_id;
int status;

Expand All @@ -28,21 +29,29 @@ int pciback_enable_msi(struct pciback_device *pdev,
* the local domain's IRQ number. */

op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
dev_data = pci_get_drvdata(dev);
if (dev_data)
dev_data->ack_intr = 0;
return 0;
}

int pciback_disable_msi(struct pciback_device *pdev,
struct pci_dev *dev, struct xen_pci_op *op)
{
struct pciback_dev_data *dev_data;
pci_disable_msi(dev);

op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
dev_data = pci_get_drvdata(dev);
if (dev_data)
dev_data->ack_intr = 1;
return 0;
}

int pciback_enable_msix(struct pciback_device *pdev,
struct pci_dev *dev, struct xen_pci_op *op)
{
struct pciback_dev_data *dev_data;
int i, result;
struct msix_entry *entries;

Expand Down Expand Up @@ -74,13 +83,17 @@ int pciback_enable_msix(struct pciback_device *pdev,
kfree(entries);

op->value = result;
dev_data = pci_get_drvdata(dev);
if (dev_data)
dev_data->ack_intr = 0;

return result;
}

int pciback_disable_msix(struct pciback_device *pdev,
struct pci_dev *dev, struct xen_pci_op *op)
{
struct pciback_dev_data *dev_data;

pci_disable_msix(dev);

Expand All @@ -89,6 +102,10 @@ int pciback_disable_msix(struct pciback_device *pdev,
* an undefined IRQ value of zero.
*/
op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
dev_data = pci_get_drvdata(dev);
if (dev_data)
dev_data->ack_intr = 1;

return 0;
}

6 changes: 6 additions & 0 deletions trunk/drivers/xen/xen-pciback/conf_space_header.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,26 @@ static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data)

static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
{
struct pciback_dev_data *dev_data;
int err;

dev_data = pci_get_drvdata(dev);
if (!pci_is_enabled(dev) && is_enable_cmd(value)) {
if (unlikely(verbose_request))
printk(KERN_DEBUG "pciback: %s: enable\n",
pci_name(dev));
err = pci_enable_device(dev);
if (err)
return err;
if (dev_data)
dev_data->enable_intx = 1;
} else if (pci_is_enabled(dev) && !is_enable_cmd(value)) {
if (unlikely(verbose_request))
printk(KERN_DEBUG "pciback: %s: disable\n",
pci_name(dev));
pci_disable_device(dev);
if (dev_data)
dev_data->enable_intx = 0;
}

if (!dev->is_busmaster && is_master_cmd(value)) {
Expand Down
90 changes: 87 additions & 3 deletions trunk/drivers/xen/xen-pciback/pci_stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include "conf_space.h"
#include "conf_space_quirks.h"

#define DRV_NAME "pciback"

static char *pci_devs_to_hide;
wait_queue_head_t aer_wait_queue;
/*Add sem for sync AER handling and pciback remove/reconfigue ops,
Expand Down Expand Up @@ -290,13 +292,20 @@ static int __devinit pcistub_init_device(struct pci_dev *dev)
* would need to be called somewhere to free the memory allocated
* here and then to call kfree(pci_get_drvdata(psdev->dev)).
*/
dev_data = kzalloc(sizeof(*dev_data), GFP_ATOMIC);
dev_data = kzalloc(sizeof(*dev_data) + strlen(DRV_NAME "[]")
+ strlen(pci_name(dev)) + 1, GFP_ATOMIC);
if (!dev_data) {
err = -ENOMEM;
goto out;
}
pci_set_drvdata(dev, dev_data);

/*
* Setup name for fake IRQ handler. It will only be enabled
* once the device is turned on by the guest.
*/
sprintf(dev_data->irq_name, DRV_NAME "[%s]", pci_name(dev));

dev_dbg(&dev->dev, "initializing config\n");

init_waitqueue_head(&aer_wait_queue);
Expand Down Expand Up @@ -837,7 +846,7 @@ static struct pci_error_handlers pciback_error_handler = {
*/

static struct pci_driver pciback_pci_driver = {
.name = "pciback",
.name = DRV_NAME,
.id_table = pcistub_ids,
.probe = pcistub_probe,
.remove = pcistub_remove,
Expand Down Expand Up @@ -1029,6 +1038,72 @@ static ssize_t pcistub_slot_show(struct device_driver *drv, char *buf)

DRIVER_ATTR(slots, S_IRUSR, pcistub_slot_show, NULL);

static ssize_t pcistub_irq_handler_show(struct device_driver *drv, char *buf)
{
struct pcistub_device *psdev;
struct pciback_dev_data *dev_data;
size_t count = 0;
unsigned long flags;

spin_lock_irqsave(&pcistub_devices_lock, flags);
list_for_each_entry(psdev, &pcistub_devices, dev_list) {
if (count >= PAGE_SIZE)
break;
if (!psdev->dev)
continue;
dev_data = pci_get_drvdata(psdev->dev);
if (!dev_data)
continue;
count +=
scnprintf(buf + count, PAGE_SIZE - count,
"%s:%s:%sing:%ld\n",
pci_name(psdev->dev),
dev_data->isr_on ? "on" : "off",
dev_data->ack_intr ? "ack" : "not ack",
dev_data->handled);
}
spin_unlock_irqrestore(&pcistub_devices_lock, flags);
return count;
}

DRIVER_ATTR(irq_handlers, S_IRUSR, pcistub_irq_handler_show, NULL);

static ssize_t pcistub_irq_handler_switch(struct device_driver *drv,
const char *buf,
size_t count)
{
struct pcistub_device *psdev;
struct pciback_dev_data *dev_data;
int domain, bus, slot, func;
int err = -ENOENT;

err = str_to_slot(buf, &domain, &bus, &slot, &func);
if (err)
goto out;

psdev = pcistub_device_find(domain, bus, slot, func);

if (!psdev)
goto out;

dev_data = pci_get_drvdata(psdev->dev);
if (!dev_data)
goto out;

dev_dbg(&psdev->dev->dev, "%s fake irq handler: %d->%d\n",
dev_data->irq_name, dev_data->isr_on,
!dev_data->isr_on);

dev_data->isr_on = !(dev_data->isr_on);
if (dev_data->isr_on)
dev_data->ack_intr = 1;
out:
if (!err)
err = count;
return err;
}
DRIVER_ATTR(irq_handler_state, S_IWUSR, NULL, pcistub_irq_handler_switch);

static ssize_t pcistub_quirk_add(struct device_driver *drv, const char *buf,
size_t count)
{
Expand Down Expand Up @@ -1168,7 +1243,10 @@ static void pcistub_exit(void)
driver_remove_file(&pciback_pci_driver.driver, &driver_attr_slots);
driver_remove_file(&pciback_pci_driver.driver, &driver_attr_quirks);
driver_remove_file(&pciback_pci_driver.driver, &driver_attr_permissive);

driver_remove_file(&pciback_pci_driver.driver,
&driver_attr_irq_handlers);
driver_remove_file(&pciback_pci_driver.driver,
&driver_attr_irq_handler_state);
pci_unregister_driver(&pciback_pci_driver);
}

Expand Down Expand Up @@ -1227,6 +1305,12 @@ static int __init pcistub_init(void)
err = driver_create_file(&pciback_pci_driver.driver,
&driver_attr_permissive);

if (!err)
err = driver_create_file(&pciback_pci_driver.driver,
&driver_attr_irq_handlers);
if (!err)
err = driver_create_file(&pciback_pci_driver.driver,
&driver_attr_irq_handler_state);
if (err)
pcistub_exit();

Expand Down
13 changes: 11 additions & 2 deletions trunk/drivers/xen/xen-pciback/pciback.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,14 @@ struct pciback_device {

struct pciback_dev_data {
struct list_head config_fields;
int permissive;
int warned_on_write;
unsigned int permissive:1;
unsigned int warned_on_write:1;
unsigned int enable_intx:1;
unsigned int isr_on:1; /* Whether the IRQ handler is installed. */
unsigned int ack_intr:1; /* .. and ACK-ing */
unsigned long handled;
unsigned int irq; /* Saved in case device transitions to MSI/MSI-X */
char irq_name[0]; /* pciback[000:04:00.0] */
};

/* Used by XenBus and pciback_ops.c */
Expand Down Expand Up @@ -131,3 +137,6 @@ extern int verbose_request;
void test_and_schedule_op(struct pciback_device *pdev);
#endif

/* Handles shared IRQs that can to device domain and control domain. */
void pciback_irq_handler(struct pci_dev *dev, int reset);
irqreturn_t pciback_guest_interrupt(int irq, void *dev_id);
Loading

0 comments on commit b7c2e56

Please sign in to comment.