Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 165843
b: refs/heads/master
c: 1a5aeee
h: refs/heads/master
i:
  165841: 86c161e
  165839: 814c9bd
v: v3
  • Loading branch information
Maciej Sosnowski authored and Dan Williams committed Sep 10, 2009
1 parent b9a3799 commit ebb2e1b
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 16 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: 9a8de639f35ca3951b910d5e3a2f92f4cf3afc8f
refs/heads/master: 1a5aeeecd550ee4344cfba1791f1134739b16dc6
122 changes: 109 additions & 13 deletions trunk/drivers/dca/dca-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,100 @@
#include <linux/device.h>
#include <linux/dca.h>

#define DCA_VERSION "1.8"
#define DCA_VERSION "1.12.1"

MODULE_VERSION(DCA_VERSION);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Intel Corporation");

static DEFINE_SPINLOCK(dca_lock);

static LIST_HEAD(dca_providers);
static LIST_HEAD(dca_domains);

static struct dca_provider *dca_find_provider_by_dev(struct device *dev)
static struct pci_bus *dca_pci_rc_from_dev(struct device *dev)
{
struct dca_provider *dca, *ret = NULL;
struct pci_dev *pdev = to_pci_dev(dev);
struct pci_bus *bus = pdev->bus;

list_for_each_entry(dca, &dca_providers, node) {
if ((!dev) || (dca->ops->dev_managed(dca, dev))) {
ret = dca;
break;
}
while (bus->parent)
bus = bus->parent;

return bus;
}

static struct dca_domain *dca_allocate_domain(struct pci_bus *rc)
{
struct dca_domain *domain;

domain = kzalloc(sizeof(*domain), GFP_NOWAIT);
if (!domain)
return NULL;

INIT_LIST_HEAD(&domain->dca_providers);
domain->pci_rc = rc;

return domain;
}

static void dca_free_domain(struct dca_domain *domain)
{
list_del(&domain->node);
kfree(domain);
}

static struct dca_domain *dca_find_domain(struct pci_bus *rc)
{
struct dca_domain *domain;

list_for_each_entry(domain, &dca_domains, node)
if (domain->pci_rc == rc)
return domain;

return NULL;
}

static struct dca_domain *dca_get_domain(struct device *dev)
{
struct pci_bus *rc;
struct dca_domain *domain;

rc = dca_pci_rc_from_dev(dev);
domain = dca_find_domain(rc);

if (!domain) {
domain = dca_allocate_domain(rc);
if (domain)
list_add(&domain->node, &dca_domains);
}

return domain;
}

static struct dca_provider *dca_find_provider_by_dev(struct device *dev)
{
struct dca_provider *dca;
struct pci_bus *rc;
struct dca_domain *domain;

if (dev) {
rc = dca_pci_rc_from_dev(dev);
domain = dca_find_domain(rc);
if (!domain)
return NULL;
} else {
if (!list_empty(&dca_domains))
domain = list_first_entry(&dca_domains,
struct dca_domain,
node);
else
return NULL;
}

return ret;
list_for_each_entry(dca, &domain->dca_providers, node)
if ((!dev) || (dca->ops->dev_managed(dca, dev)))
return dca;

return NULL;
}

/**
Expand All @@ -61,6 +133,8 @@ int dca_add_requester(struct device *dev)
struct dca_provider *dca;
int err, slot = -ENODEV;
unsigned long flags;
struct pci_bus *pci_rc;
struct dca_domain *domain;

if (!dev)
return -EFAULT;
Expand All @@ -74,7 +148,14 @@ int dca_add_requester(struct device *dev)
return -EEXIST;
}

list_for_each_entry(dca, &dca_providers, node) {
pci_rc = dca_pci_rc_from_dev(dev);
domain = dca_find_domain(pci_rc);
if (!domain) {
spin_unlock_irqrestore(&dca_lock, flags);
return -ENODEV;
}

list_for_each_entry(dca, &domain->dca_providers, node) {
slot = dca->ops->add_requester(dca, dev);
if (slot >= 0)
break;
Expand Down Expand Up @@ -222,13 +303,19 @@ int register_dca_provider(struct dca_provider *dca, struct device *dev)
{
int err;
unsigned long flags;
struct dca_domain *domain;

err = dca_sysfs_add_provider(dca, dev);
if (err)
return err;

spin_lock_irqsave(&dca_lock, flags);
list_add(&dca->node, &dca_providers);
domain = dca_get_domain(dev);
if (!domain) {
spin_unlock_irqrestore(&dca_lock, flags);
return -ENODEV;
}
list_add(&dca->node, &domain->dca_providers);
spin_unlock_irqrestore(&dca_lock, flags);

blocking_notifier_call_chain(&dca_provider_chain,
Expand All @@ -241,15 +328,24 @@ EXPORT_SYMBOL_GPL(register_dca_provider);
* unregister_dca_provider - remove a dca provider
* @dca - struct created by alloc_dca_provider()
*/
void unregister_dca_provider(struct dca_provider *dca)
void unregister_dca_provider(struct dca_provider *dca, struct device *dev)
{
unsigned long flags;
struct pci_bus *pci_rc;
struct dca_domain *domain;

blocking_notifier_call_chain(&dca_provider_chain,
DCA_PROVIDER_REMOVE, NULL);

spin_lock_irqsave(&dca_lock, flags);

list_del(&dca->node);

pci_rc = dca_pci_rc_from_dev(dev);
domain = dca_find_domain(pci_rc);
if (list_empty(&domain->dca_providers))
dca_free_domain(domain);

spin_unlock_irqrestore(&dca_lock, flags);

dca_sysfs_remove_provider(dca);
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/dma/ioat/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ static void __devexit ioat_remove(struct pci_dev *pdev)

dev_err(&pdev->dev, "Removing dma and dca services\n");
if (device->dca) {
unregister_dca_provider(device->dca);
unregister_dca_provider(device->dca, &pdev->dev);
free_dca_provider(device->dca);
device->dca = NULL;
}
Expand Down
11 changes: 10 additions & 1 deletion trunk/include/linux/dca.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
*/
#ifndef DCA_H
#define DCA_H

#include <linux/pci.h>

/* DCA Provider API */

/* DCA Notifier Interface */
Expand All @@ -36,6 +39,12 @@ struct dca_provider {
int id;
};

struct dca_domain {
struct list_head node;
struct list_head dca_providers;
struct pci_bus *pci_rc;
};

struct dca_ops {
int (*add_requester) (struct dca_provider *, struct device *);
int (*remove_requester) (struct dca_provider *, struct device *);
Expand All @@ -47,7 +56,7 @@ struct dca_ops {
struct dca_provider *alloc_dca_provider(struct dca_ops *ops, int priv_size);
void free_dca_provider(struct dca_provider *dca);
int register_dca_provider(struct dca_provider *dca, struct device *dev);
void unregister_dca_provider(struct dca_provider *dca);
void unregister_dca_provider(struct dca_provider *dca, struct device *dev);

static inline void *dca_priv(struct dca_provider *dca)
{
Expand Down

0 comments on commit ebb2e1b

Please sign in to comment.