in dca-core.c [340:390]
int register_dca_provider(struct dca_provider *dca, struct device *dev)
{
int err;
unsigned long flags;
struct dca_domain *domain, *newdomain = NULL;
raw_spin_lock_irqsave(&dca_lock, flags);
if (dca_providers_blocked) {
raw_spin_unlock_irqrestore(&dca_lock, flags);
return -ENODEV;
}
raw_spin_unlock_irqrestore(&dca_lock, flags);
err = dca_sysfs_add_provider(dca, dev);
if (err)
return err;
raw_spin_lock_irqsave(&dca_lock, flags);
domain = dca_get_domain(dev);
if (!domain) {
struct pci_bus *rc;
if (dca_providers_blocked) {
raw_spin_unlock_irqrestore(&dca_lock, flags);
dca_sysfs_remove_provider(dca);
unregister_dca_providers();
return -ENODEV;
}
raw_spin_unlock_irqrestore(&dca_lock, flags);
rc = dca_pci_rc_from_dev(dev);
newdomain = dca_allocate_domain(rc);
if (!newdomain)
return -ENODEV;
raw_spin_lock_irqsave(&dca_lock, flags);
/* Recheck, we might have raced after dropping the lock */
domain = dca_get_domain(dev);
if (!domain) {
domain = newdomain;
newdomain = NULL;
list_add(&domain->node, &dca_domains);
}
}
list_add(&dca->node, &domain->dca_providers);
raw_spin_unlock_irqrestore(&dca_lock, flags);
blocking_notifier_call_chain(&dca_provider_chain,
DCA_PROVIDER_ADD, NULL);
kfree(newdomain);
return 0;
}