* Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz)
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/smp_lock.h>
+#include <linux/msi.h>
+#include <linux/irq.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/ebus.h>
#include <asm/isa.h>
+#include <asm/prom.h>
unsigned long pci_memspace_mask = 0xffffffffUL;
}
/* Probe for all PCI controllers in the system. */
-extern void sabre_init(int, char *);
-extern void psycho_init(int, char *);
-extern void schizo_init(int, char *);
-extern void schizo_plus_init(int, char *);
-extern void tomatillo_init(int, char *);
-extern void sun4v_pci_init(int, char *);
+extern void sabre_init(struct device_node *, const char *);
+extern void psycho_init(struct device_node *, const char *);
+extern void schizo_init(struct device_node *, const char *);
+extern void schizo_plus_init(struct device_node *, const char *);
+extern void tomatillo_init(struct device_node *, const char *);
+extern void sun4v_pci_init(struct device_node *, const char *);
static struct {
char *model_name;
- void (*init)(int, char *);
+ void (*init)(struct device_node *, const char *);
} pci_controller_table[] __initdata = {
{ "SUNW,sabre", sabre_init },
{ "pci108e,a000", sabre_init },
#define PCI_NUM_CONTROLLER_TYPES (sizeof(pci_controller_table) / \
sizeof(pci_controller_table[0]))
-static int __init pci_controller_init(char *model_name, int namelen, int node)
+static int __init pci_controller_init(const char *model_name, int namelen, struct device_node *dp)
{
int i;
if (!strncmp(model_name,
pci_controller_table[i].model_name,
namelen)) {
- pci_controller_table[i].init(node, model_name);
+ pci_controller_table[i].init(dp, model_name);
return 1;
}
}
- printk("PCI: Warning unknown controller, model name [%s]\n",
- model_name);
- printk("PCI: Ignoring controller...\n");
return 0;
}
-static int __init pci_is_controller(char *model_name, int namelen, int node)
+static int __init pci_is_controller(const char *model_name, int namelen, struct device_node *dp)
{
int i;
return 0;
}
-static int __init pci_controller_scan(int (*handler)(char *, int, int))
+static int __init pci_controller_scan(int (*handler)(const char *, int, struct device_node *))
{
- char namebuf[64];
- int node;
+ struct device_node *dp;
int count = 0;
- node = prom_getchild(prom_root_node);
- while ((node = prom_searchsiblings(node, "pci")) != 0) {
+ for_each_node_by_name(dp, "pci") {
+ struct property *prop;
int len;
- if ((len = prom_getproperty(node, "model", namebuf, sizeof(namebuf))) > 0 ||
- (len = prom_getproperty(node, "compatible", namebuf, sizeof(namebuf))) > 0) {
+ prop = of_find_property(dp, "model", &len);
+ if (!prop)
+ prop = of_find_property(dp, "compatible", &len);
+
+ if (prop) {
+ const char *model = prop->value;
int item_len = 0;
/* Our value may be a multi-valued string in the
* case of some compatible properties. For sanity,
- * only try the first one. */
-
- while (namebuf[item_len] && len) {
+ * only try the first one.
+ */
+ while (model[item_len] && len) {
len--;
item_len++;
}
- if (handler(namebuf, item_len, node))
+ if (handler(model, item_len, dp))
count++;
}
-
- node = prom_getsibling(node);
- if (!node)
- break;
}
return count;
p->scan_bus(p);
}
-extern void clock_probe(void);
extern void power_init(void);
static int __init pcibios_init(void)
isa_init();
ebus_init();
- clock_probe();
power_init();
return 0;
}
void pcibios_align_resource(void *data, struct resource *res,
- unsigned long size, unsigned long align)
+ resource_size_t size, resource_size_t align)
{
}
}
EXPORT_SYMBOL(pci_domain_nr);
-int pcibios_prep_mwi(struct pci_dev *dev)
+#ifdef CONFIG_PCI_MSI
+int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
{
- /* We set correct PCI_CACHE_LINE_SIZE register values for every
- * device probed on this platform. So there is nothing to check
- * and this always succeeds.
- */
- return 0;
+ struct pcidev_cookie *pcp = pdev->sysdata;
+ struct pci_pbm_info *pbm = pcp->pbm;
+ struct pci_controller_info *p = pbm->parent;
+ int virt_irq, err;
+
+ if (!pbm->msi_num || !p->setup_msi_irq)
+ return -EINVAL;
+
+ err = p->setup_msi_irq(&virt_irq, pdev, desc);
+ if (err < 0)
+ return err;
+
+ return virt_irq;
+}
+
+void arch_teardown_msi_irq(unsigned int virt_irq)
+{
+ struct msi_desc *entry = get_irq_data(virt_irq);
+ struct pci_dev *pdev = entry->dev;
+ struct pcidev_cookie *pcp = pdev->sysdata;
+ struct pci_pbm_info *pbm = pcp->pbm;
+ struct pci_controller_info *p = pbm->parent;
+
+ if (!pbm->msi_num || !p->setup_msi_irq)
+ return;
+
+ return p->teardown_msi_irq(virt_irq, pdev);
}
+#endif /* !(CONFIG_PCI_MSI) */
#endif /* !(CONFIG_PCI) */