Commit d3ae4b5b authored by David S. Miller's avatar David S. Miller

sparc64: Get rid of pci_controller_info.

It is just used as a parent to encapsulate two PBM objects.

But that layout is only really relevant and necessary for
psycho PCI controllers, which unlike all the others share
a single IOMMU instance between sibling PCI busses.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ab138c03
...@@ -48,6 +48,9 @@ struct strbuf { ...@@ -48,6 +48,9 @@ struct strbuf {
unsigned long strbuf_control; unsigned long strbuf_control;
unsigned long strbuf_pflush; unsigned long strbuf_pflush;
unsigned long strbuf_fsync; unsigned long strbuf_fsync;
unsigned long strbuf_err_stat;
unsigned long strbuf_tag_diag;
unsigned long strbuf_line_diag;
unsigned long strbuf_ctxflush; unsigned long strbuf_ctxflush;
unsigned long strbuf_ctxmatch_base; unsigned long strbuf_ctxmatch_base;
unsigned long strbuf_flushflag_pa; unsigned long strbuf_flushflag_pa;
......
...@@ -977,14 +977,14 @@ int pcibus_to_node(struct pci_bus *pbus) ...@@ -977,14 +977,14 @@ int pcibus_to_node(struct pci_bus *pbus)
EXPORT_SYMBOL(pcibus_to_node); EXPORT_SYMBOL(pcibus_to_node);
#endif #endif
/* Return the domain nuber for this pci bus */ /* Return the domain number for this pci bus */
int pci_domain_nr(struct pci_bus *pbus) int pci_domain_nr(struct pci_bus *pbus)
{ {
struct pci_pbm_info *pbm = pbus->sysdata; struct pci_pbm_info *pbm = pbus->sysdata;
int ret; int ret;
if (pbm == NULL || pbm->parent == NULL) { if (!pbm) {
ret = -ENXIO; ret = -ENXIO;
} else { } else {
ret = pbm->index; ret = pbm->index;
......
...@@ -431,22 +431,13 @@ static void pci_fire_hw_init(struct pci_pbm_info *pbm) ...@@ -431,22 +431,13 @@ static void pci_fire_hw_init(struct pci_pbm_info *pbm)
fire_write(pbm->pbm_regs + FIRE_PEC_IENAB, ~(u64)0); fire_write(pbm->pbm_regs + FIRE_PEC_IENAB, ~(u64)0);
} }
static int __init pci_fire_pbm_init(struct pci_controller_info *p, static int __init pci_fire_pbm_init(struct pci_pbm_info *pbm,
struct of_device *op, u32 portid) struct of_device *op, u32 portid)
{ {
const struct linux_prom64_registers *regs; const struct linux_prom64_registers *regs;
struct device_node *dp = op->node; struct device_node *dp = op->node;
struct pci_pbm_info *pbm;
int err; int err;
if ((portid & 1) == 0)
pbm = &p->pbm_A;
else
pbm = &p->pbm_B;
pbm->next = pci_pbm_root;
pci_pbm_root = pbm;
pbm->numa_node = -1; pbm->numa_node = -1;
pbm->pci_ops = &sun4u_pci_ops; pbm->pci_ops = &sun4u_pci_ops;
...@@ -455,7 +446,6 @@ static int __init pci_fire_pbm_init(struct pci_controller_info *p, ...@@ -455,7 +446,6 @@ static int __init pci_fire_pbm_init(struct pci_controller_info *p,
pbm->index = pci_num_pbms++; pbm->index = pci_num_pbms++;
pbm->portid = portid; pbm->portid = portid;
pbm->parent = p;
pbm->prom_node = dp; pbm->prom_node = dp;
pbm->name = dp->full_name; pbm->name = dp->full_name;
...@@ -481,13 +471,9 @@ static int __init pci_fire_pbm_init(struct pci_controller_info *p, ...@@ -481,13 +471,9 @@ static int __init pci_fire_pbm_init(struct pci_controller_info *p,
/* XXX register error interrupt handlers XXX */ /* XXX register error interrupt handlers XXX */
return 0; pbm->next = pci_pbm_root;
} pci_pbm_root = pbm;
static inline int portid_compare(u32 x, u32 y)
{
if (x == (y ^ 1))
return 1;
return 0; return 0;
} }
...@@ -495,48 +481,41 @@ static int __devinit fire_probe(struct of_device *op, ...@@ -495,48 +481,41 @@ static int __devinit fire_probe(struct of_device *op,
const struct of_device_id *match) const struct of_device_id *match)
{ {
struct device_node *dp = op->node; struct device_node *dp = op->node;
struct pci_controller_info *p;
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
struct iommu *iommu; struct iommu *iommu;
u32 portid; u32 portid;
int err; int err;
portid = of_getintprop_default(dp, "portid", 0xff); portid = of_getintprop_default(dp, "portid", 0xff);
for (pbm = pci_pbm_root; pbm; pbm = pbm->next) {
if (portid_compare(pbm->portid, portid))
return pci_fire_pbm_init(pbm->parent, op, portid);
}
err = -ENOMEM; err = -ENOMEM;
p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); pbm = kzalloc(sizeof(*pbm), GFP_KERNEL);
if (!p) { if (!pbm) {
printk(KERN_ERR PFX "Cannot allocate controller info.\n"); printk(KERN_ERR PFX "Cannot allocate pci_pbminfo.\n");
goto out_err; goto out_err;
} }
iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL);
if (!iommu) { if (!iommu) {
printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n");
goto out_free_controller; goto out_free_controller;
} }
p->pbm_A.iommu = iommu; pbm->iommu = iommu;
iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); err = pci_fire_pbm_init(pbm, op, portid);
if (!iommu) { if (err)
printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); goto out_free_iommu;
goto out_free_iommu_A;
}
p->pbm_B.iommu = iommu; dev_set_drvdata(&op->dev, pbm);
return pci_fire_pbm_init(p, op, portid); return 0;
out_free_iommu_A: out_free_iommu:
kfree(p->pbm_A.iommu); kfree(pbm->iommu);
out_free_controller: out_free_controller:
kfree(p); kfree(pbm);
out_err: out_err:
return err; return err;
......
...@@ -56,15 +56,11 @@ struct sparc64_msiq_cookie { ...@@ -56,15 +56,11 @@ struct sparc64_msiq_cookie {
}; };
#endif #endif
struct pci_controller_info;
struct pci_pbm_info { struct pci_pbm_info {
struct pci_pbm_info *next; struct pci_pbm_info *next;
struct pci_pbm_info *sibling;
int index; int index;
/* PCI controller we sit under. */
struct pci_controller_info *parent;
/* Physical address base of controller registers. */ /* Physical address base of controller registers. */
unsigned long controller_regs; unsigned long controller_regs;
...@@ -107,6 +103,10 @@ struct pci_pbm_info { ...@@ -107,6 +103,10 @@ struct pci_pbm_info {
/* This will be 12 on PCI-E controllers, 8 elsewhere. */ /* This will be 12 on PCI-E controllers, 8 elsewhere. */
unsigned long config_space_reg_bits; unsigned long config_space_reg_bits;
unsigned long pci_afsr;
unsigned long pci_afar;
unsigned long pci_csr;
/* State of 66MHz capabilities on this PBM. */ /* State of 66MHz capabilities on this PBM. */
int is_66mhz_capable; int is_66mhz_capable;
int all_devs_66mhz; int all_devs_66mhz;
...@@ -151,12 +151,6 @@ struct pci_pbm_info { ...@@ -151,12 +151,6 @@ struct pci_pbm_info {
int numa_node; int numa_node;
}; };
struct pci_controller_info {
/* The PCI bus modules controlled by us. */
struct pci_pbm_info pbm_A;
struct pci_pbm_info pbm_B;
};
extern struct pci_pbm_info *pci_pbm_root; extern struct pci_pbm_info *pci_pbm_root;
extern int pci_num_pbms; extern int pci_num_pbms;
......
...@@ -146,24 +146,16 @@ static unsigned long stc_error_buf[128]; ...@@ -146,24 +146,16 @@ static unsigned long stc_error_buf[128];
static unsigned long stc_tag_buf[16]; static unsigned long stc_tag_buf[16];
static unsigned long stc_line_buf[16]; static unsigned long stc_line_buf[16];
static void __psycho_check_one_stc(struct pci_pbm_info *pbm, static void psycho_check_stc_error(struct pci_pbm_info *pbm)
int is_pbm_a)
{ {
struct strbuf *strbuf = &pbm->stc; struct strbuf *strbuf = &pbm->stc;
unsigned long regbase = pbm->controller_regs;
unsigned long err_base, tag_base, line_base; unsigned long err_base, tag_base, line_base;
u64 control; u64 control;
int i; int i;
if (is_pbm_a) { err_base = strbuf->strbuf_err_stat;
err_base = regbase + PSYCHO_STC_ERR_A; tag_base = strbuf->strbuf_tag_diag;
tag_base = regbase + PSYCHO_STC_TAG_A; line_base = strbuf->strbuf_line_diag;
line_base = regbase + PSYCHO_STC_LINE_A;
} else {
err_base = regbase + PSYCHO_STC_ERR_B;
tag_base = regbase + PSYCHO_STC_TAG_B;
line_base = regbase + PSYCHO_STC_LINE_B;
}
spin_lock(&stc_buf_lock); spin_lock(&stc_buf_lock);
...@@ -239,15 +231,6 @@ static void __psycho_check_one_stc(struct pci_pbm_info *pbm, ...@@ -239,15 +231,6 @@ static void __psycho_check_one_stc(struct pci_pbm_info *pbm,
spin_unlock(&stc_buf_lock); spin_unlock(&stc_buf_lock);
} }
static void __psycho_check_stc_error(struct pci_pbm_info *pbm,
unsigned long afsr,
unsigned long afar,
enum psycho_error_type type)
{
__psycho_check_one_stc(pbm,
(pbm == &pbm->parent->pbm_A));
}
/* When an Uncorrectable Error or a PCI Error happens, we /* When an Uncorrectable Error or a PCI Error happens, we
* interrogate the IOMMU state to see if it is the cause. * interrogate the IOMMU state to see if it is the cause.
*/ */
...@@ -386,7 +369,7 @@ static void psycho_check_iommu_error(struct pci_pbm_info *pbm, ...@@ -386,7 +369,7 @@ static void psycho_check_iommu_error(struct pci_pbm_info *pbm,
(data & PSYCHO_IOMMU_DATA_PPAGE) << IOMMU_PAGE_SHIFT); (data & PSYCHO_IOMMU_DATA_PPAGE) << IOMMU_PAGE_SHIFT);
} }
} }
__psycho_check_stc_error(pbm, afsr, afar, type); psycho_check_stc_error(pbm);
spin_unlock_irqrestore(&iommu->lock, flags); spin_unlock_irqrestore(&iommu->lock, flags);
} }
...@@ -412,7 +395,6 @@ static void psycho_check_iommu_error(struct pci_pbm_info *pbm, ...@@ -412,7 +395,6 @@ static void psycho_check_iommu_error(struct pci_pbm_info *pbm,
static irqreturn_t psycho_ue_intr(int irq, void *dev_id) static irqreturn_t psycho_ue_intr(int irq, void *dev_id)
{ {
struct pci_pbm_info *pbm = dev_id; struct pci_pbm_info *pbm = dev_id;
struct pci_controller_info *p = pbm->parent;
unsigned long afsr_reg = pbm->controller_regs + PSYCHO_UE_AFSR; unsigned long afsr_reg = pbm->controller_regs + PSYCHO_UE_AFSR;
unsigned long afar_reg = pbm->controller_regs + PSYCHO_UE_AFAR; unsigned long afar_reg = pbm->controller_regs + PSYCHO_UE_AFAR;
unsigned long afsr, afar, error_bits; unsigned long afsr, afar, error_bits;
...@@ -465,8 +447,9 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id) ...@@ -465,8 +447,9 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id)
printk("]\n"); printk("]\n");
/* Interrogate both IOMMUs for error status. */ /* Interrogate both IOMMUs for error status. */
psycho_check_iommu_error(&p->pbm_A, afsr, afar, UE_ERR); psycho_check_iommu_error(pbm, afsr, afar, UE_ERR);
psycho_check_iommu_error(&p->pbm_B, afsr, afar, UE_ERR); if (pbm->sibling)
psycho_check_iommu_error(pbm->sibling, afsr, afar, UE_ERR);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -573,23 +556,18 @@ static irqreturn_t psycho_ce_intr(int irq, void *dev_id) ...@@ -573,23 +556,18 @@ static irqreturn_t psycho_ce_intr(int irq, void *dev_id)
#define PSYCHO_PCI_AFAR_A 0x2018UL #define PSYCHO_PCI_AFAR_A 0x2018UL
#define PSYCHO_PCI_AFAR_B 0x4018UL #define PSYCHO_PCI_AFAR_B 0x4018UL
static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm, int is_pbm_a) static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm)
{ {
unsigned long csr_reg, csr, csr_error_bits; unsigned long csr, csr_error_bits;
irqreturn_t ret = IRQ_NONE; irqreturn_t ret = IRQ_NONE;
u16 stat; u16 stat;
if (is_pbm_a) { csr = psycho_read(pbm->pci_csr);
csr_reg = pbm->controller_regs + PSYCHO_PCIA_CTRL;
} else {
csr_reg = pbm->controller_regs + PSYCHO_PCIB_CTRL;
}
csr = psycho_read(csr_reg);
csr_error_bits = csr_error_bits =
csr & (PSYCHO_PCICTRL_SBH_ERR | PSYCHO_PCICTRL_SERR); csr & (PSYCHO_PCICTRL_SBH_ERR | PSYCHO_PCICTRL_SERR);
if (csr_error_bits) { if (csr_error_bits) {
/* Clear the errors. */ /* Clear the errors. */
psycho_write(csr_reg, csr); psycho_write(pbm->pci_csr, csr);
/* Log 'em. */ /* Log 'em. */
if (csr_error_bits & PSYCHO_PCICTRL_SBH_ERR) if (csr_error_bits & PSYCHO_PCICTRL_SBH_ERR)
...@@ -616,19 +594,12 @@ static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm, int is_pbm ...@@ -616,19 +594,12 @@ static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm, int is_pbm
static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id)
{ {
struct pci_pbm_info *pbm = dev_id; struct pci_pbm_info *pbm = dev_id;
struct pci_controller_info *p = pbm->parent;
unsigned long afsr_reg, afar_reg; unsigned long afsr_reg, afar_reg;
unsigned long afsr, afar, error_bits; unsigned long afsr, afar, error_bits;
int is_pbm_a, reported; int reported;
is_pbm_a = (pbm == &pbm->parent->pbm_A); afsr_reg = pbm->pci_afsr;
if (is_pbm_a) { afar_reg = pbm->pci_afar;
afsr_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFSR_A;
afar_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFAR_A;
} else {
afsr_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFSR_B;
afar_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFAR_B;
}
/* Latch error status. */ /* Latch error status. */
afar = psycho_read(afar_reg); afar = psycho_read(afar_reg);
...@@ -641,7 +612,7 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) ...@@ -641,7 +612,7 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id)
PSYCHO_PCIAFSR_SMA | PSYCHO_PCIAFSR_STA | PSYCHO_PCIAFSR_SMA | PSYCHO_PCIAFSR_STA |
PSYCHO_PCIAFSR_SRTRY | PSYCHO_PCIAFSR_SPERR); PSYCHO_PCIAFSR_SRTRY | PSYCHO_PCIAFSR_SPERR);
if (!error_bits) if (!error_bits)
return psycho_pcierr_intr_other(pbm, is_pbm_a); return psycho_pcierr_intr_other(pbm);
psycho_write(afsr_reg, error_bits); psycho_write(afsr_reg, error_bits);
/* Log the error. */ /* Log the error. */
...@@ -923,10 +894,16 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, ...@@ -923,10 +894,16 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm,
pbm->stc.strbuf_control = base + PSYCHO_STRBUF_CONTROL_A; pbm->stc.strbuf_control = base + PSYCHO_STRBUF_CONTROL_A;
pbm->stc.strbuf_pflush = base + PSYCHO_STRBUF_FLUSH_A; pbm->stc.strbuf_pflush = base + PSYCHO_STRBUF_FLUSH_A;
pbm->stc.strbuf_fsync = base + PSYCHO_STRBUF_FSYNC_A; pbm->stc.strbuf_fsync = base + PSYCHO_STRBUF_FSYNC_A;
pbm->stc.strbuf_err_stat = base + PSYCHO_STC_ERR_A;
pbm->stc.strbuf_tag_diag = base + PSYCHO_STC_TAG_A;
pbm->stc.strbuf_line_diag= base + PSYCHO_STC_LINE_A;
} else { } else {
pbm->stc.strbuf_control = base + PSYCHO_STRBUF_CONTROL_B; pbm->stc.strbuf_control = base + PSYCHO_STRBUF_CONTROL_B;
pbm->stc.strbuf_pflush = base + PSYCHO_STRBUF_FLUSH_B; pbm->stc.strbuf_pflush = base + PSYCHO_STRBUF_FLUSH_B;
pbm->stc.strbuf_fsync = base + PSYCHO_STRBUF_FSYNC_B; pbm->stc.strbuf_fsync = base + PSYCHO_STRBUF_FSYNC_B;
pbm->stc.strbuf_err_stat = base + PSYCHO_STC_ERR_B;
pbm->stc.strbuf_tag_diag = base + PSYCHO_STC_TAG_B;
pbm->stc.strbuf_line_diag= base + PSYCHO_STC_LINE_B;
} }
/* PSYCHO's streaming buffer lacks ctx flushing. */ /* PSYCHO's streaming buffer lacks ctx flushing. */
pbm->stc.strbuf_ctxflush = 0; pbm->stc.strbuf_ctxflush = 0;
...@@ -971,16 +948,10 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, ...@@ -971,16 +948,10 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm,
#define PSYCHO_MEMSPACE_B 0x180000000UL #define PSYCHO_MEMSPACE_B 0x180000000UL
#define PSYCHO_MEMSPACE_SIZE 0x07fffffffUL #define PSYCHO_MEMSPACE_SIZE 0x07fffffffUL
static void __init psycho_pbm_init(struct pci_controller_info *p, static void __init psycho_pbm_init(struct pci_pbm_info *pbm,
struct of_device *op, int is_pbm_a) struct of_device *op, int is_pbm_a)
{ {
struct device_node *dp = op->node; struct device_node *dp = op->node;
struct pci_pbm_info *pbm;
if (is_pbm_a)
pbm = &p->pbm_A;
else
pbm = &p->pbm_B;
pbm->next = pci_pbm_root; pbm->next = pci_pbm_root;
pci_pbm_root = pbm; pci_pbm_root = pbm;
...@@ -996,7 +967,6 @@ static void __init psycho_pbm_init(struct pci_controller_info *p, ...@@ -996,7 +967,6 @@ static void __init psycho_pbm_init(struct pci_controller_info *p,
pbm->chip_version = of_getintprop_default(dp, "version#", 0); pbm->chip_version = of_getintprop_default(dp, "version#", 0);
pbm->chip_revision = of_getintprop_default(dp, "module-revision#", 0); pbm->chip_revision = of_getintprop_default(dp, "module-revision#", 0);
pbm->parent = p;
pbm->prom_node = dp; pbm->prom_node = dp;
pbm->name = dp->full_name; pbm->name = dp->full_name;
...@@ -1013,6 +983,17 @@ static void __init psycho_pbm_init(struct pci_controller_info *p, ...@@ -1013,6 +983,17 @@ static void __init psycho_pbm_init(struct pci_controller_info *p,
psycho_scan_bus(pbm, &op->dev); psycho_scan_bus(pbm, &op->dev);
} }
static struct pci_pbm_info * __devinit psycho_find_sibling(u32 upa_portid)
{
struct pci_pbm_info *pbm;
for (pbm = pci_pbm_root; pbm; pbm = pbm->next) {
if (pbm->portid == upa_portid)
return pbm;
}
return NULL;
}
#define PSYCHO_CONFIGSPACE 0x001000000UL #define PSYCHO_CONFIGSPACE 0x001000000UL
static int __devinit psycho_probe(struct of_device *op, static int __devinit psycho_probe(struct of_device *op,
...@@ -1020,7 +1001,6 @@ static int __devinit psycho_probe(struct of_device *op, ...@@ -1020,7 +1001,6 @@ static int __devinit psycho_probe(struct of_device *op,
{ {
const struct linux_prom64_registers *pr_regs; const struct linux_prom64_registers *pr_regs;
struct device_node *dp = op->node; struct device_node *dp = op->node;
struct pci_controller_info *p;
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
struct iommu *iommu; struct iommu *iommu;
int is_pbm_a, err; int is_pbm_a, err;
...@@ -1028,33 +1008,26 @@ static int __devinit psycho_probe(struct of_device *op, ...@@ -1028,33 +1008,26 @@ static int __devinit psycho_probe(struct of_device *op,
upa_portid = of_getintprop_default(dp, "upa-portid", 0xff); upa_portid = of_getintprop_default(dp, "upa-portid", 0xff);
for (pbm = pci_pbm_root; pbm; pbm = pbm->next) {
struct pci_controller_info *p = pbm->parent;
if (p->pbm_A.portid == upa_portid) {
is_pbm_a = (p->pbm_A.prom_node == NULL);
psycho_pbm_init(p, op, is_pbm_a);
return 0;
}
}
err = -ENOMEM; err = -ENOMEM;
p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); pbm = kzalloc(sizeof(*pbm), GFP_KERNEL);
if (!p) { if (!pbm) {
printk(KERN_ERR PFX "Cannot allocate controller info.\n"); printk(KERN_ERR PFX "Cannot allocate pci_pbm_info.\n");
goto out_err; goto out_err;
} }
iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); pbm->sibling = psycho_find_sibling(upa_portid);
if (pbm->sibling) {
iommu = pbm->sibling->iommu;
} else {
iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL);
if (!iommu) { if (!iommu) {
printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n");
goto out_free_controller; goto out_free_controller;
} }
}
p->pbm_A.iommu = p->pbm_B.iommu = iommu; pbm->iommu = iommu;
pbm->portid = upa_portid;
p->pbm_A.portid = upa_portid;
p->pbm_B.portid = upa_portid;
pr_regs = of_get_property(dp, "reg", NULL); pr_regs = of_get_property(dp, "reg", NULL);
err = -ENODEV; err = -ENODEV;
...@@ -1063,29 +1036,43 @@ static int __devinit psycho_probe(struct of_device *op, ...@@ -1063,29 +1036,43 @@ static int __devinit psycho_probe(struct of_device *op,
goto out_free_iommu; goto out_free_iommu;
} }
p->pbm_A.controller_regs = pr_regs[2].phys_addr; is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000);
p->pbm_B.controller_regs = pr_regs[2].phys_addr;
p->pbm_A.config_space = p->pbm_B.config_space = pbm->controller_regs = pr_regs[2].phys_addr;
(pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE); pbm->config_space = (pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE);
psycho_controller_hwinit(&p->pbm_A); if (is_pbm_a) {
pbm->pci_afsr = pbm->controller_regs + PSYCHO_PCI_AFSR_A;
pbm->pci_afar = pbm->controller_regs + PSYCHO_PCI_AFAR_A;
pbm->pci_csr = pbm->controller_regs + PSYCHO_PCIA_CTRL;
} else {
pbm->pci_afsr = pbm->controller_regs + PSYCHO_PCI_AFSR_B;
pbm->pci_afar = pbm->controller_regs + PSYCHO_PCI_AFAR_B;
pbm->pci_csr = pbm->controller_regs + PSYCHO_PCIB_CTRL;
}
err = psycho_iommu_init(&p->pbm_A); psycho_controller_hwinit(pbm);
if (!pbm->sibling) {
err = psycho_iommu_init(pbm);
if (err) if (err)
goto out_free_iommu; goto out_free_iommu;
}
is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); psycho_pbm_init(pbm, op, is_pbm_a);
if (pbm->sibling)
pbm->sibling->sibling = pbm;
psycho_pbm_init(p, op, is_pbm_a); dev_set_drvdata(&op->dev, pbm);
return 0; return 0;
out_free_iommu: out_free_iommu:
kfree(p->pbm_A.iommu); if (!pbm->sibling)
kfree(pbm->iommu);
out_free_controller: out_free_controller:
kfree(p); kfree(pbm);
out_err: out_err:
return err; return err;
......
...@@ -734,8 +734,8 @@ static int sabre_iommu_init(struct pci_pbm_info *pbm, ...@@ -734,8 +734,8 @@ static int sabre_iommu_init(struct pci_pbm_info *pbm,
return 0; return 0;
} }
static void __init sabre_pbm_init(struct pci_controller_info *p, static void __init sabre_pbm_init(struct pci_pbm_info *pbm,
struct pci_pbm_info *pbm, struct of_device *op) struct of_device *op)
{ {
struct device_node *dp = op->node; struct device_node *dp = op->node;
...@@ -750,7 +750,6 @@ static void __init sabre_pbm_init(struct pci_controller_info *p, ...@@ -750,7 +750,6 @@ static void __init sabre_pbm_init(struct pci_controller_info *p,
pbm->index = pci_num_pbms++; pbm->index = pci_num_pbms++;
pbm->chip_type = PBM_CHIP_TYPE_SABRE; pbm->chip_type = PBM_CHIP_TYPE_SABRE;
pbm->parent = p;
pbm->prom_node = dp; pbm->prom_node = dp;
pci_get_pbm_props(pbm); pci_get_pbm_props(pbm);
...@@ -764,7 +763,6 @@ static int __devinit sabre_probe(struct of_device *op, ...@@ -764,7 +763,6 @@ static int __devinit sabre_probe(struct of_device *op,
{ {
const struct linux_prom64_registers *pr_regs; const struct linux_prom64_registers *pr_regs;
struct device_node *dp = op->node; struct device_node *dp = op->node;
struct pci_controller_info *p;
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
u32 upa_portid, dma_mask; u32 upa_portid, dma_mask;
struct iommu *iommu; struct iommu *iommu;
...@@ -786,26 +784,22 @@ static int __devinit sabre_probe(struct of_device *op, ...@@ -786,26 +784,22 @@ static int __devinit sabre_probe(struct of_device *op,
} }
err = -ENOMEM; err = -ENOMEM;
p = kzalloc(sizeof(*p), GFP_ATOMIC); pbm = kzalloc(sizeof(*pbm), GFP_KERNEL);
if (!p) { if (!pbm) {
printk(KERN_ERR PFX "Cannot allocate controller info.\n"); printk(KERN_ERR PFX "Cannot allocate pci_pbm_info.\n");
goto out_err; goto out_err;
} }
iommu = kzalloc(sizeof(*iommu), GFP_ATOMIC); iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
if (!iommu) { if (!iommu) {
printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n");
goto out_free_controller; goto out_free_controller;
} }
pbm = &p->pbm_A;
pbm->iommu = iommu; pbm->iommu = iommu;
upa_portid = of_getintprop_default(dp, "upa-portid", 0xff); upa_portid = of_getintprop_default(dp, "upa-portid", 0xff);
pbm->next = pci_pbm_root;
pci_pbm_root = pbm;
pbm->portid = upa_portid; pbm->portid = upa_portid;
/* /*
...@@ -840,8 +834,7 @@ static int __devinit sabre_probe(struct of_device *op, ...@@ -840,8 +834,7 @@ static int __devinit sabre_probe(struct of_device *op,
SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN)); SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN));
/* Now map in PCI config space for entire SABRE. */ /* Now map in PCI config space for entire SABRE. */
pbm->config_space = pbm->config_space = pbm->controller_regs + SABRE_CONFIGSPACE;
(pbm->controller_regs + SABRE_CONFIGSPACE);
vdma = of_get_property(dp, "virtual-dma", NULL); vdma = of_get_property(dp, "virtual-dma", NULL);
if (!vdma) { if (!vdma) {
...@@ -876,14 +869,20 @@ static int __devinit sabre_probe(struct of_device *op, ...@@ -876,14 +869,20 @@ static int __devinit sabre_probe(struct of_device *op,
/* /*
* Look for APB underneath. * Look for APB underneath.
*/ */
sabre_pbm_init(p, pbm, op); sabre_pbm_init(pbm, op);
pbm->next = pci_pbm_root;
pci_pbm_root = pbm;
dev_set_drvdata(&op->dev, pbm);
return 0; return 0;
out_free_iommu: out_free_iommu:
kfree(p->pbm_A.iommu); kfree(pbm->iommu);
out_free_controller: out_free_controller:
kfree(p); kfree(pbm);
out_err: out_err:
return err; return err;
......
...@@ -358,11 +358,12 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, ...@@ -358,11 +358,12 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm,
spin_unlock_irqrestore(&iommu->lock, flags); spin_unlock_irqrestore(&iommu->lock, flags);
} }
static void schizo_check_iommu_error(struct pci_controller_info *p, static void schizo_check_iommu_error(struct pci_pbm_info *pbm,
enum schizo_error_type type) enum schizo_error_type type)
{ {
schizo_check_iommu_error_pbm(&p->pbm_A, type); schizo_check_iommu_error_pbm(pbm, type);
schizo_check_iommu_error_pbm(&p->pbm_B, type); if (pbm->sibling)
schizo_check_iommu_error_pbm(pbm->sibling, type);
} }
/* Uncorrectable ECC error status gathering. */ /* Uncorrectable ECC error status gathering. */
...@@ -387,7 +388,6 @@ static void schizo_check_iommu_error(struct pci_controller_info *p, ...@@ -387,7 +388,6 @@ static void schizo_check_iommu_error(struct pci_controller_info *p,
static irqreturn_t schizo_ue_intr(int irq, void *dev_id) static irqreturn_t schizo_ue_intr(int irq, void *dev_id)
{ {
struct pci_pbm_info *pbm = dev_id; struct pci_pbm_info *pbm = dev_id;
struct pci_controller_info *p = pbm->parent;
unsigned long afsr_reg = pbm->controller_regs + SCHIZO_UE_AFSR; unsigned long afsr_reg = pbm->controller_regs + SCHIZO_UE_AFSR;
unsigned long afar_reg = pbm->controller_regs + SCHIZO_UE_AFAR; unsigned long afar_reg = pbm->controller_regs + SCHIZO_UE_AFAR;
unsigned long afsr, afar, error_bits; unsigned long afsr, afar, error_bits;
...@@ -450,7 +450,7 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id) ...@@ -450,7 +450,7 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id)
printk("]\n"); printk("]\n");
/* Interrogate IOMMU for error status. */ /* Interrogate IOMMU for error status. */
schizo_check_iommu_error(p, UE_ERR); schizo_check_iommu_error(pbm, UE_ERR);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -651,7 +651,6 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) ...@@ -651,7 +651,6 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm)
static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id)
{ {
struct pci_pbm_info *pbm = dev_id; struct pci_pbm_info *pbm = dev_id;
struct pci_controller_info *p = pbm->parent;
unsigned long afsr_reg, afar_reg, base; unsigned long afsr_reg, afar_reg, base;
unsigned long afsr, afar, error_bits; unsigned long afsr, afar, error_bits;
int reported; int reported;
...@@ -745,7 +744,7 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) ...@@ -745,7 +744,7 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id)
* a bug in the IOMMU support code or a PCI device driver. * a bug in the IOMMU support code or a PCI device driver.
*/ */
if (error_bits & (SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_STA)) { if (error_bits & (SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_STA)) {
schizo_check_iommu_error(p, PCI_ERR); schizo_check_iommu_error(pbm, PCI_ERR);
pci_scan_for_target_abort(pbm, pbm->pci_bus); pci_scan_for_target_abort(pbm, pbm->pci_bus);
} }
if (error_bits & (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_SMA)) if (error_bits & (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_SMA))
...@@ -806,7 +805,6 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) ...@@ -806,7 +805,6 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id)
static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id) static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id)
{ {
struct pci_pbm_info *pbm = dev_id; struct pci_pbm_info *pbm = dev_id;
struct pci_controller_info *p = pbm->parent;
u64 errlog; u64 errlog;
errlog = schizo_read(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG); errlog = schizo_read(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG);
...@@ -822,7 +820,7 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id) ...@@ -822,7 +820,7 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id)
printk("%s: Safari/JBUS interrupt, UNMAPPED error, interrogating IOMMUs.\n", printk("%s: Safari/JBUS interrupt, UNMAPPED error, interrogating IOMMUs.\n",
pbm->name); pbm->name);
schizo_check_iommu_error(p, SAFARI_ERR); schizo_check_iommu_error(pbm, SAFARI_ERR);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -1329,13 +1327,12 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) ...@@ -1329,13 +1327,12 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm)
} }
} }
static int __devinit schizo_pbm_init(struct pci_controller_info *p, static int __devinit schizo_pbm_init(struct pci_pbm_info *pbm,
struct of_device *op, u32 portid, struct of_device *op, u32 portid,
int chip_type) int chip_type)
{ {
const struct linux_prom64_registers *regs; const struct linux_prom64_registers *regs;
struct device_node *dp = op->node; struct device_node *dp = op->node;
struct pci_pbm_info *pbm;
const char *chipset_name; const char *chipset_name;
int is_pbm_a, err; int is_pbm_a, err;
...@@ -1368,10 +1365,6 @@ static int __devinit schizo_pbm_init(struct pci_controller_info *p, ...@@ -1368,10 +1365,6 @@ static int __devinit schizo_pbm_init(struct pci_controller_info *p,
regs = of_get_property(dp, "reg", NULL); regs = of_get_property(dp, "reg", NULL);
is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000); is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000);
if (is_pbm_a)
pbm = &p->pbm_A;
else
pbm = &p->pbm_B;
pbm->next = pci_pbm_root; pbm->next = pci_pbm_root;
pci_pbm_root = pbm; pci_pbm_root = pbm;
...@@ -1384,7 +1377,6 @@ static int __devinit schizo_pbm_init(struct pci_controller_info *p, ...@@ -1384,7 +1377,6 @@ static int __devinit schizo_pbm_init(struct pci_controller_info *p,
pbm->index = pci_num_pbms++; pbm->index = pci_num_pbms++;
pbm->portid = portid; pbm->portid = portid;
pbm->parent = p;
pbm->prom_node = dp; pbm->prom_node = dp;
pbm->chip_type = chip_type; pbm->chip_type = chip_type;
...@@ -1430,10 +1422,21 @@ static inline int portid_compare(u32 x, u32 y, int chip_type) ...@@ -1430,10 +1422,21 @@ static inline int portid_compare(u32 x, u32 y, int chip_type)
return (x == y); return (x == y);
} }
static struct pci_pbm_info * __devinit schizo_find_sibling(u32 portid,
int chip_type)
{
struct pci_pbm_info *pbm;
for (pbm = pci_pbm_root; pbm; pbm = pbm->next) {
if (portid_compare(pbm->portid, portid, chip_type))
return pbm;
}
return NULL;
}
static int __devinit __schizo_init(struct of_device *op, unsigned long chip_type) static int __devinit __schizo_init(struct of_device *op, unsigned long chip_type)
{ {
struct device_node *dp = op->node; struct device_node *dp = op->node;
struct pci_controller_info *p;
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
struct iommu *iommu; struct iommu *iommu;
u32 portid; u32 portid;
...@@ -1442,50 +1445,37 @@ static int __devinit __schizo_init(struct of_device *op, unsigned long chip_type ...@@ -1442,50 +1445,37 @@ static int __devinit __schizo_init(struct of_device *op, unsigned long chip_type
portid = of_getintprop_default(dp, "portid", 0xff); portid = of_getintprop_default(dp, "portid", 0xff);
err = -ENOMEM; err = -ENOMEM;
for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { pbm = kzalloc(sizeof(*pbm), GFP_KERNEL);
if (portid_compare(pbm->portid, portid, chip_type)) { if (!pbm) {
if (schizo_pbm_init(pbm->parent, op, printk(KERN_ERR PFX "Cannot allocate pci_pbm_info.\n");
portid, chip_type))
goto out_err; goto out_err;
return 0;
}
} }
p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); pbm->sibling = schizo_find_sibling(portid, chip_type);
if (!p) {
printk(KERN_ERR PFX "Cannot allocate controller info.\n");
goto out_err;
}
iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL);
if (!iommu) { if (!iommu) {
printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n");
goto out_free_controller; goto out_free_pbm;
} }
p->pbm_A.iommu = iommu; pbm->iommu = iommu;
iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); if (schizo_pbm_init(pbm, op, portid, chip_type))
if (!iommu) { goto out_free_iommu;
printk(KERN_ERR PFX "Cannot allocate PBM B iommu.\n");
goto out_free_iommu_A;
}
p->pbm_B.iommu = iommu; if (pbm->sibling)
pbm->sibling->sibling = pbm;
if (schizo_pbm_init(p, op, portid, chip_type)) dev_set_drvdata(&op->dev, pbm);
goto out_free_iommu_B;
return 0; return 0;
out_free_iommu_B: out_free_iommu:
kfree(p->pbm_B.iommu); kfree(pbm->iommu);
out_free_iommu_A:
kfree(p->pbm_A.iommu);
out_free_controller: out_free_pbm:
kfree(p); kfree(pbm);
out_err: out_err:
return err; return err;
......
...@@ -42,6 +42,7 @@ struct iommu_batch { ...@@ -42,6 +42,7 @@ struct iommu_batch {
}; };
static DEFINE_PER_CPU(struct iommu_batch, iommu_batch); static DEFINE_PER_CPU(struct iommu_batch, iommu_batch);
static int iommu_batch_initialized;
/* Interrupts must be disabled. */ /* Interrupts must be disabled. */
static inline void iommu_batch_start(struct device *dev, unsigned long prot, unsigned long entry) static inline void iommu_batch_start(struct device *dev, unsigned long prot, unsigned long entry)
...@@ -887,21 +888,12 @@ static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) ...@@ -887,21 +888,12 @@ static void pci_sun4v_msi_init(struct pci_pbm_info *pbm)
} }
#endif /* !(CONFIG_PCI_MSI) */ #endif /* !(CONFIG_PCI_MSI) */
static int __init pci_sun4v_pbm_init(struct pci_controller_info *p, static int __init pci_sun4v_pbm_init(struct pci_pbm_info *pbm,
struct of_device *op, u32 devhandle) struct of_device *op, u32 devhandle)
{ {
struct device_node *dp = op->node; struct device_node *dp = op->node;
struct pci_pbm_info *pbm;
int err; int err;
if (devhandle & 0x40)
pbm = &p->pbm_B;
else
pbm = &p->pbm_A;
pbm->next = pci_pbm_root;
pci_pbm_root = pbm;
pbm->numa_node = of_node_to_nid(dp); pbm->numa_node = of_node_to_nid(dp);
pbm->pci_ops = &sun4v_pci_ops; pbm->pci_ops = &sun4v_pci_ops;
...@@ -909,7 +901,6 @@ static int __init pci_sun4v_pbm_init(struct pci_controller_info *p, ...@@ -909,7 +901,6 @@ static int __init pci_sun4v_pbm_init(struct pci_controller_info *p,
pbm->index = pci_num_pbms++; pbm->index = pci_num_pbms++;
pbm->parent = p;
pbm->prom_node = dp; pbm->prom_node = dp;
pbm->devhandle = devhandle; pbm->devhandle = devhandle;
...@@ -931,6 +922,9 @@ static int __init pci_sun4v_pbm_init(struct pci_controller_info *p, ...@@ -931,6 +922,9 @@ static int __init pci_sun4v_pbm_init(struct pci_controller_info *p,
pci_sun4v_scan_bus(pbm, &op->dev); pci_sun4v_scan_bus(pbm, &op->dev);
pbm->next = pci_pbm_root;
pci_pbm_root = pbm;
return 0; return 0;
} }
...@@ -939,7 +933,6 @@ static int __devinit pci_sun4v_probe(struct of_device *op, ...@@ -939,7 +933,6 @@ static int __devinit pci_sun4v_probe(struct of_device *op,
{ {
const struct linux_prom64_registers *regs; const struct linux_prom64_registers *regs;
static int hvapi_negotiated = 0; static int hvapi_negotiated = 0;
struct pci_controller_info *p;
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
struct device_node *dp; struct device_node *dp;
struct iommu *iommu; struct iommu *iommu;
...@@ -972,51 +965,46 @@ static int __devinit pci_sun4v_probe(struct of_device *op, ...@@ -972,51 +965,46 @@ static int __devinit pci_sun4v_probe(struct of_device *op,
} }
devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff; devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff;
for (pbm = pci_pbm_root; pbm; pbm = pbm->next) {
if (pbm->devhandle == (devhandle ^ 0x40)) {
return pci_sun4v_pbm_init(pbm->parent, op, devhandle);
}
}
err = -ENOMEM; err = -ENOMEM;
if (!iommu_batch_initialized) {
for_each_possible_cpu(i) { for_each_possible_cpu(i) {
unsigned long page = get_zeroed_page(GFP_ATOMIC); unsigned long page = get_zeroed_page(GFP_KERNEL);
if (!page) if (!page)
goto out_err; goto out_err;
per_cpu(iommu_batch, i).pglist = (u64 *) page; per_cpu(iommu_batch, i).pglist = (u64 *) page;
} }
iommu_batch_initialized = 1;
}
p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); pbm = kzalloc(sizeof(*pbm), GFP_KERNEL);
if (!p) { if (!pbm) {
printk(KERN_ERR PFX "Could not allocate pci_controller_info\n"); printk(KERN_ERR PFX "Could not allocate pci_pbm_info\n");
goto out_err; goto out_err;
} }
iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL);
if (!iommu) { if (!iommu) {
printk(KERN_ERR PFX "Could not allocate pbm A iommu\n"); printk(KERN_ERR PFX "Could not allocate pbm iommu\n");
goto out_free_controller; goto out_free_controller;
} }
p->pbm_A.iommu = iommu; pbm->iommu = iommu;
iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); err = pci_sun4v_pbm_init(pbm, op, devhandle);
if (!iommu) { if (err)
printk(KERN_ERR PFX "Could not allocate pbm B iommu\n"); goto out_free_iommu;
goto out_free_iommu_A;
}
p->pbm_B.iommu = iommu; dev_set_drvdata(&op->dev, pbm);
return pci_sun4v_pbm_init(p, op, devhandle); return 0;
out_free_iommu_A: out_free_iommu:
kfree(p->pbm_A.iommu); kfree(pbm->iommu);
out_free_controller: out_free_controller:
kfree(p); kfree(pbm);
out_err: out_err:
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment