Message ID | 1442213382-2528-1-git-send-email-alistair@popple.id.au |
---|---|
State | Superseded |
Headers | show |
On Mon, 2015-09-14 at 16:49 +1000, Alistair Popple wrote: > Interrupts on P8 are currently hard-coded using macros in > include/interrupts.h. The new P8NVL processor has an extra PHB > meaning > it supports 4 PHBs in total which leads to the following assert fail > when booting P8NVL based systems: > > [6614913194,3] register IRQ source overlap ! > [6620562844,3] new: 2000..27f7 old: 2000..27f7 > [6870377440,0] Assert fail: core/interrupts.c:67:0 > > This patch converts the existing macros to function calls so that > different platforms can support extra PHBs at the expense of a > reduced > maximum number of chips. > > Signed-off-by: Alistair Popple <alistair@popple.id.au> > --- > core/cpu.c | 4 +++- > core/interrupts.c | 58 > ++++++++++++++++++++++++++++++++++++++++++++++++++-- > hw/phb3.c | 24 +++++++++++----------- > include/interrupts.h | 44 ++++++++++++++++++++++----------------- > include/phb3.h | 6 +++--- > include/skiboot.h | 4 +++- > 6 files changed, 102 insertions(+), 38 deletions(-) > > diff --git a/core/cpu.c b/core/cpu.c > index 8b0f861..c9dcd8f 100644 > --- a/core/cpu.c > +++ b/core/cpu.c > @@ -403,10 +403,12 @@ void init_boot_cpu(void) > case PVR_TYPE_P8: > proc_gen = proc_gen_p8; > hile_supported = PVR_VERS_MAJ(mfspr(SPR_PVR)) >= 2; > + p8_chip_id_bits = 6; > break; > case PVR_TYPE_P8NVL: > proc_gen = proc_gen_p8; > hile_supported = true; > + p8_chip_id_bits = 5; > break; > default: I would keep that local to interrupts.c and static, or even just use a get_chip_id_bits() helper that uses struct proc_chip -> type > proc_gen = proc_gen_unknown; > @@ -544,7 +546,7 @@ void cpu_bringup(void) > > op_display(OP_LOG, OP_MOD_CPU, 0x0000); > > - /* Tell everybody to chime in ! */ > + /* Tell everybody to chime in ! */ Unrelated change ? > prlog(PR_INFO, "CPU: Calling in all processors...\n"); > cpu_secondary_start = 1; > sync(); > diff --git a/core/interrupts.c b/core/interrupts.c > index 32f43ef..d2e5096 100644 > --- a/core/interrupts.c > +++ b/core/interrupts.c > @@ -30,6 +30,9 @@ > #define ICP_CPPR 0x4 /* 8-bit access */ > #define ICP_MFRR 0xc /* 8-bit access */ > > +/* Number of bits to use for the chips ids. */ > +uint32_t p8_chip_id_bits; > + > struct irq_source { > uint32_t start; > uint32_t end; > @@ -121,7 +124,7 @@ uint32_t get_psi_interrupt(uint32_t chip_id) > irq |= P7_PSI_IRQ_BUID << 4; > break; > case proc_gen_p8: > - irq = P8_CHIP_IRQ_BLOCK_BASE(chip_id, > P8_IRQ_BLOCK_MISC); > + irq = p8_chip_irq_block_base(chip_id, > P8_IRQ_BLOCK_MISC); > irq += P8_IRQ_MISC_PSI_BASE; > break; > default: > @@ -253,6 +256,58 @@ void icp_kick_cpu(struct cpu_thread *cpu) > out_8(icp + ICP_MFRR, 0); > } > > +/* The chip id mask is the upper p8_chip_id_bits of the irq number > */ > +static uint32_t chip_id_mask(void) > +{ > + uint32_t chip_id_mask = ((1 << p8_chip_id_bits) - 1); > + chip_id_mask <<= P8_IRQ_BITS - p8_chip_id_bits; > + return chip_id_mask; > +} > + > +/* The block mask is what remains of the 19 bit irq number after > + * removing the upper 5 or 6 bits for the chip# and the lower 11 > bits > + * for the number of bits per block. */ > +static uint32_t block_mask(void) > +{ > + uint32_t irq_block_mask = P8_IRQ_BITS - p8_chip_id_bits - > P8_IVE_BITS; > + irq_block_mask = ((1 << irq_block_mask) - 1) << P8_IVE_BITS; > + return irq_block_mask; > +} > + > +uint32_t p8_chip_irq_block_base(uint32_t chip, uint32_t block) > +{ > + uint32_t irq; > + > + assert(chip < (1 << p8_chip_id_bits)); > + irq = SETFIELD(chip_id_mask(), 0, chip); > + irq = SETFIELD(block_mask(), irq, block); > + > + return irq; > +} > + > +uint32_t p8_chip_irq_phb_base(uint32_t chip, uint32_t phb) > +{ > + assert(chip < (1 << p8_chip_id_bits)); > + > + return p8_chip_irq_block_base(chip, phb + > P8_IRQ_BLOCK_PHB_BASE); > +} > + > +uint32_t p8_irq_to_chip(uint32_t irq) > +{ > + return GETFIELD(chip_id_mask(), irq); > +} > + > +uint32_t p8_irq_to_block(uint32_t irq) > +{ > + > + return GETFIELD(block_mask(), irq); > +} > + > +uint32_t p8_irq_to_phb(uint32_t irq) > +{ > + return p8_irq_to_block(irq) - P8_IRQ_BLOCK_PHB_BASE; > +} > + > static struct irq_source *irq_find_source(uint32_t isn) > { > struct irq_source *is; > @@ -340,4 +395,3 @@ void init_interrupts(void) > } > } > } > - > diff --git a/hw/phb3.c b/hw/phb3.c > index 5fd0130..77a84ed 100644 > --- a/hw/phb3.c > +++ b/hw/phb3.c > @@ -1550,8 +1550,8 @@ static int64_t phb3_msi_get_xive(void *data, > uint32_t chip, index, irq; > uint64_t ive; > > - chip = P8_IRQ_TO_CHIP(isn); > - index = P8_IRQ_TO_PHB(isn); > + chip = p8_irq_to_chip(isn); > + index = p8_irq_to_phb(isn); > irq = PHB3_IRQ_NUM(isn); > > if (chip != p->chip_id || > @@ -1580,8 +1580,8 @@ static int64_t phb3_msi_set_xive(void *data, > uint64_t *cache, ive_num, data64, m_server, m_prio; > uint32_t *ive; > > - chip = P8_IRQ_TO_CHIP(isn); > - index = P8_IRQ_TO_PHB(isn); > + chip = p8_irq_to_chip(isn); > + index = p8_irq_to_phb(isn); > ive_num = PHB3_IRQ_NUM(isn); > > if (p->state == PHB3_STATE_BROKEN || !p->tbl_rtt) > @@ -1642,8 +1642,8 @@ static int64_t phb3_lsi_get_xive(void *data, > uint32_t chip, index, irq; > uint64_t lxive; > > - chip = P8_IRQ_TO_CHIP(isn); > - index = P8_IRQ_TO_PHB(isn); > + chip = p8_irq_to_chip(isn); > + index = p8_irq_to_phb(isn); > irq = PHB3_IRQ_NUM(isn); > > if (chip != p->chip_id || > @@ -1668,8 +1668,8 @@ static int64_t phb3_lsi_set_xive(void *data, > uint32_t chip, index, irq, entry; > uint64_t lxive; > > - chip = P8_IRQ_TO_CHIP(isn); > - index = P8_IRQ_TO_PHB(isn); > + chip = p8_irq_to_chip(isn); > + index = p8_irq_to_phb(isn); > irq = PHB3_IRQ_NUM(isn); > > if (p->state == PHB3_STATE_BROKEN) > @@ -1935,7 +1935,7 @@ static void phb3_setup_for_link_down(struct > phb3 *p) > static void phb3_setup_for_link_up(struct phb3 *p) > { > uint32_t reg32; > - > + > /* Clear AER receiver error status */ > phb3_pcicfg_write32(&p->phb, 0, p->aercap + > PCIECAP_AER_CE_STATUS, > PCIECAP_AER_CE_RECVR_ERR); > @@ -3041,7 +3041,7 @@ static int64_t phb3_err_inject_dma64(struct > phb3 *p, uint32_t pe_no, > uint64_t addr, uint64_t mask, > bool is_write) > { > - return phb3_err_inject_dma(p, pe_no, addr, mask, is_write, > true); > + return phb3_err_inject_dma(p, pe_no, addr, mask, is_write, > true); > } > > static int64_t phb3_err_inject(struct phb *phb, uint32_t pe_no, > @@ -3443,7 +3443,7 @@ static void phb3_setup_aib(struct phb3 *p) > phb3_write_reg_asb(p, PHB_AIB_RX_CMD_CRED, 0x > 0020000100020001); > else > phb3_write_reg_asb(p, PHB_AIB_RX_CMD_CRED, 0x > 0020000100010001); > - > + > /* Init_4 - AIB rx data credit register */ > if (p->rev >= PHB3_REV_VENICE_DD20) > phb3_write_reg_asb(p, PHB_AIB_RX_DATA_CRED, 0 > x0020002000010001); > @@ -4444,7 +4444,7 @@ static void phb3_probe_pbcq(struct dt_node > *pbcq) > /* Set the interrupt routing stuff, 8 relevant bits in mask > * (11 bits per PHB) > */ > - val = P8_CHIP_IRQ_PHB_BASE(gcid, pno); > + val = p8_chip_irq_phb_base(gcid, pno); > val = (val << 45); > xscom_write(gcid, pe_xscom + 0x1a, val); > xscom_write(gcid, pe_xscom + 0x1b, 0xff00000000000000ul); > diff --git a/include/interrupts.h b/include/interrupts.h > index 9239b86..276a936 100644 > --- a/include/interrupts.h > +++ b/include/interrupts.h > @@ -78,7 +78,7 @@ > * > * TBD > * > - * > + * > * Additional note about routing of interrupts in P7 and P7+ > * ========================================================= > * > @@ -152,19 +152,26 @@ > * are naturally power-of-two aligned > * > * Our P8 Interrupt map consits thus of dividing the chip space > - * into 4 "blocks" of 2048 interrupts. Block 0 is for random chip > + * into "blocks" of 2048 interrupts. Block 0 is for random chip > * interrupt sources (NX, PSI, OCC, ...) and keeps sources 0..15 > - * clear to avoid conflits with IPIs etc.... Block 1..3 are assigned > - * to PHB 0..2 respectively. > + * clear to avoid conflits with IPIs etc.... Block 1..n are assigned > + * to PHB 0..n respectively. The number of blocks is determined by > the > + * number of bits assigned to chips. > * > * That gives us an interrupt number made of: > - * 18 13 12 11 10 0 > + * 18 n+1 n 11 10 0 > * | | | | | | > * +--------------------+------+-----------------------------+ > * | Chip# | PHB# | IVE# | > * +--------------------+------+-----------------------------+ > * > - * We can thus support a max of 2^6 = 64 chips > + * Where n = 18 - p8_chip_id_bits > + * > + * For P8 we have 6 bits for Chip# as defined by p8_chip_id_bits. We > + * therefore support a max of 2^6 = 64 chips. > + * > + * For P8NVL we have an extra PHB and so we assign 5 bits for Chip# > + * and therefore support a max of 32 chips. > * > * Each PHB supports 2K interrupt sources, which is shared by > * LSI and MSI. With default configuration, MSI would use range > @@ -174,21 +181,20 @@ > * > */ > > -#define P8_CHIP_IRQ_BASE(chip) ((chip) << 13) > -#define P8_CHIP_IRQ_BLOCK_BASE(chip, block) (P8_CHIP_IRQ_BASE > (chip) \ > - | ((block) << 11)) > -#define P8_IRQ_BLOCK_MISC 0 > -#define P8_IRQ_BLOCK_PHB0 1 > -#define P8_IRQ_BLOCK_PHB1 2 > -#define P8_IRQ_BLOCK_PHB2 3 > +uint32_t p8_chip_irq_block_base(uint32_t chip, uint32_t block); > +uint32_t p8_chip_irq_phb_base(uint32_t chip, uint32_t phb); > +uint32_t p8_irq_to_chip(uint32_t irq); > +uint32_t p8_irq_to_block(uint32_t irq); > +uint32_t p8_irq_to_phb(uint32_t irq); > + > +/* Total number of bits in the P8 interrupt space */ > +#define P8_IRQ_BITS 19 > > -#define P8_CHIP_IRQ_PHB_BASE(chip, phb) (P8_CHIP_IRQ_ > BLOCK_BASE(chip,\ > - (phb) + > P8_IRQ_BLOCK_PHB0)) > +/* Number of bits per block */ > +#define P8_IVE_BITS 11 > > -#define P8_IRQ_TO_CHIP(irq) (((irq) >> 13) & > 0x3f) > -#define P8_IRQ_TO_BLOCK(irq) (((irq) >> 11) & > 0x03) > -#define P8_IRQ_TO_PHB(irq) (P8_IRQ_TO_BLOCK(i > rq) - \ > - P8_IRQ_BLOCK_PHB0) > +#define P8_IRQ_BLOCK_MISC 0 > +#define P8_IRQ_BLOCK_PHB_BASE 1 > > /* Assignment of the "MISC" block: > * ------------------------------- > diff --git a/include/phb3.h b/include/phb3.h > index 3accd9e..982f847 100644 > --- a/include/phb3.h > +++ b/include/phb3.h > @@ -52,9 +52,9 @@ > #define PHB3_LSI_IRQ_COUNT 8 > #define PHB3_LSI_IRQ_MAX (PHB3_LSI_IRQ_MIN+PHB3_LSI_I > RQ_COUNT-1) > > -#define PHB3_MSI_IRQ_BASE(chip, phb) (P8_CHIP_IRQ_PHB_BASE(ch > ip, phb) | \ > +#define PHB3_MSI_IRQ_BASE(chip, phb) (p8_chip_irq_phb_base(ch > ip, phb) | \ > PHB3_MSI_IRQ_MIN) > -#define PHB3_LSI_IRQ_BASE(chip, phb) (P8_CHIP_IRQ_PHB_BASE(ch > ip, phb) | \ > +#define PHB3_LSI_IRQ_BASE(chip, phb) (p8_chip_irq_phb_base(ch > ip, phb) | \ > PHB3_LSI_IRQ_MIN) > #define PHB3_IRQ_NUM(irq) (irq & 0x7FF) > > @@ -94,7 +94,7 @@ > * All those tables have to be naturally aligned > */ > > -/* RTT Table : 128KB - Maps RID to PE# > +/* RTT Table : 128KB - Maps RID to PE# > * > * Entries are 2 bytes indexed by PCIe RID > */ > diff --git a/include/skiboot.h b/include/skiboot.h > index 4b58597..cdc5a10 100644 > --- a/include/skiboot.h > +++ b/include/skiboot.h > @@ -125,6 +125,9 @@ enum proc_gen { > }; > extern enum proc_gen proc_gen; > > +/* Number of chip id bits available */ > +extern uint32_t p8_chip_id_bits; > + > /* Convert a 4-bit number to a hex char */ > extern char __attrconst tohex(uint8_t nibble); > > @@ -263,4 +266,3 @@ extern bool slw_timer_ok(void); > extern void fake_rtc_init(void); > > #endif /* __SKIBOOT_H */ > -
On Mon, 14 Sep 2015 17:02:34 Benjamin Herrenschmidt wrote: > On Mon, 2015-09-14 at 16:49 +1000, Alistair Popple wrote: snip > > --- > > core/cpu.c | 4 +++- > > core/interrupts.c | 58 > > ++++++++++++++++++++++++++++++++++++++++++++++++++-- > > hw/phb3.c | 24 +++++++++++----------- > > include/interrupts.h | 44 ++++++++++++++++++++++----------------- > > include/phb3.h | 6 +++--- > > include/skiboot.h | 4 +++- > > 6 files changed, 102 insertions(+), 38 deletions(-) > > > > diff --git a/core/cpu.c b/core/cpu.c > > index 8b0f861..c9dcd8f 100644 > > --- a/core/cpu.c > > +++ b/core/cpu.c > > @@ -403,10 +403,12 @@ void init_boot_cpu(void) > > case PVR_TYPE_P8: > > proc_gen = proc_gen_p8; > > hile_supported = PVR_VERS_MAJ(mfspr(SPR_PVR)) >= 2; > > + p8_chip_id_bits = 6; > > break; > > case PVR_TYPE_P8NVL: > > proc_gen = proc_gen_p8; > > hile_supported = true; > > + p8_chip_id_bits = 5; > > break; > > default: > > I would keep that local to interrupts.c and static, or even just use > a get_chip_id_bits() helper that uses struct proc_chip -> type Are you suggesting we add a proc_gen_p8vnl to the proc_gen enum used for struct proc_chip -> type or just reading the PVR again in get_chip_id_bits()? It looked like adding another processor to the enum would be a pain hence the ugliness above, but reading the PVR is easy enough. > > proc_gen = proc_gen_unknown; > > @@ -544,7 +546,7 @@ void cpu_bringup(void) > > > > op_display(OP_LOG, OP_MOD_CPU, 0x0000); > > > > - /* Tell everybody to chime in ! */ > > + /* Tell everybody to chime in ! */ > > Unrelated change ? Sorry, missed that one. It's due to having (add-hook 'before-save-hook 'delete-trailing-whitespace) in my .emacs ;) > > prlog(PR_INFO, "CPU: Calling in all processors...\n"); > > cpu_secondary_start = 1; > > sync(); > > diff --git a/core/interrupts.c b/core/interrupts.c > > index 32f43ef..d2e5096 100644 > > --- a/core/interrupts.c > > +++ b/core/interrupts.c > > @@ -30,6 +30,9 @@ > > #define ICP_CPPR 0x4 /* 8-bit access */ > > #define ICP_MFRR 0xc /* 8-bit access */ > > > > +/* Number of bits to use for the chips ids. */ > > +uint32_t p8_chip_id_bits; > > + > > struct irq_source { > > uint32_t start; > > uint32_t end; > > @@ -121,7 +124,7 @@ uint32_t get_psi_interrupt(uint32_t chip_id) > > irq |= P7_PSI_IRQ_BUID << 4; > > break; > > case proc_gen_p8: > > - irq = P8_CHIP_IRQ_BLOCK_BASE(chip_id, > > P8_IRQ_BLOCK_MISC); > > + irq = p8_chip_irq_block_base(chip_id, > > P8_IRQ_BLOCK_MISC); > > irq += P8_IRQ_MISC_PSI_BASE; > > break; > > default: > > @@ -253,6 +256,58 @@ void icp_kick_cpu(struct cpu_thread *cpu) > > out_8(icp + ICP_MFRR, 0); > > } > > > > +/* The chip id mask is the upper p8_chip_id_bits of the irq number > > */ > > +static uint32_t chip_id_mask(void) > > +{ > > + uint32_t chip_id_mask = ((1 << p8_chip_id_bits) - 1); > > + chip_id_mask <<= P8_IRQ_BITS - p8_chip_id_bits; > > + return chip_id_mask; > > +} > > + > > +/* The block mask is what remains of the 19 bit irq number after > > + * removing the upper 5 or 6 bits for the chip# and the lower 11 > > bits > > + * for the number of bits per block. */ > > +static uint32_t block_mask(void) > > +{ > > + uint32_t irq_block_mask = P8_IRQ_BITS - p8_chip_id_bits - > > P8_IVE_BITS; > > + irq_block_mask = ((1 << irq_block_mask) - 1) << P8_IVE_BITS; > > + return irq_block_mask; > > +} > > + > > +uint32_t p8_chip_irq_block_base(uint32_t chip, uint32_t block) > > +{ > > + uint32_t irq; > > + > > + assert(chip < (1 << p8_chip_id_bits)); > > + irq = SETFIELD(chip_id_mask(), 0, chip); > > + irq = SETFIELD(block_mask(), irq, block); > > + > > + return irq; > > +} > > + > > +uint32_t p8_chip_irq_phb_base(uint32_t chip, uint32_t phb) > > +{ > > + assert(chip < (1 << p8_chip_id_bits)); > > + > > + return p8_chip_irq_block_base(chip, phb + > > P8_IRQ_BLOCK_PHB_BASE); > > +} > > + > > +uint32_t p8_irq_to_chip(uint32_t irq) > > +{ > > + return GETFIELD(chip_id_mask(), irq); > > +} > > + > > +uint32_t p8_irq_to_block(uint32_t irq) > > +{ > > + > > + return GETFIELD(block_mask(), irq); > > +} > > + > > +uint32_t p8_irq_to_phb(uint32_t irq) > > +{ > > + return p8_irq_to_block(irq) - P8_IRQ_BLOCK_PHB_BASE; > > +} > > + > > static struct irq_source *irq_find_source(uint32_t isn) > > { > > struct irq_source *is; > > @@ -340,4 +395,3 @@ void init_interrupts(void) > > } > > } > > } > > - > > diff --git a/hw/phb3.c b/hw/phb3.c > > index 5fd0130..77a84ed 100644 > > --- a/hw/phb3.c > > +++ b/hw/phb3.c > > @@ -1550,8 +1550,8 @@ static int64_t phb3_msi_get_xive(void *data, > > uint32_t chip, index, irq; > > uint64_t ive; > > > > - chip = P8_IRQ_TO_CHIP(isn); > > - index = P8_IRQ_TO_PHB(isn); > > + chip = p8_irq_to_chip(isn); > > + index = p8_irq_to_phb(isn); > > irq = PHB3_IRQ_NUM(isn); > > > > if (chip != p->chip_id || > > @@ -1580,8 +1580,8 @@ static int64_t phb3_msi_set_xive(void *data, > > uint64_t *cache, ive_num, data64, m_server, m_prio; > > uint32_t *ive; > > > > - chip = P8_IRQ_TO_CHIP(isn); > > - index = P8_IRQ_TO_PHB(isn); > > + chip = p8_irq_to_chip(isn); > > + index = p8_irq_to_phb(isn); > > ive_num = PHB3_IRQ_NUM(isn); > > > > if (p->state == PHB3_STATE_BROKEN || !p->tbl_rtt) > > @@ -1642,8 +1642,8 @@ static int64_t phb3_lsi_get_xive(void *data, > > uint32_t chip, index, irq; > > uint64_t lxive; > > > > - chip = P8_IRQ_TO_CHIP(isn); > > - index = P8_IRQ_TO_PHB(isn); > > + chip = p8_irq_to_chip(isn); > > + index = p8_irq_to_phb(isn); > > irq = PHB3_IRQ_NUM(isn); > > > > if (chip != p->chip_id || > > @@ -1668,8 +1668,8 @@ static int64_t phb3_lsi_set_xive(void *data, > > uint32_t chip, index, irq, entry; > > uint64_t lxive; > > > > - chip = P8_IRQ_TO_CHIP(isn); > > - index = P8_IRQ_TO_PHB(isn); > > + chip = p8_irq_to_chip(isn); > > + index = p8_irq_to_phb(isn); > > irq = PHB3_IRQ_NUM(isn); > > > > if (p->state == PHB3_STATE_BROKEN) > > @@ -1935,7 +1935,7 @@ static void phb3_setup_for_link_down(struct > > phb3 *p) > > static void phb3_setup_for_link_up(struct phb3 *p) > > { > > uint32_t reg32; > > - > > + > > /* Clear AER receiver error status */ > > phb3_pcicfg_write32(&p->phb, 0, p->aercap + > > PCIECAP_AER_CE_STATUS, > > PCIECAP_AER_CE_RECVR_ERR); > > @@ -3041,7 +3041,7 @@ static int64_t phb3_err_inject_dma64(struct > > phb3 *p, uint32_t pe_no, > > uint64_t addr, uint64_t mask, > > bool is_write) > > { > > - return phb3_err_inject_dma(p, pe_no, addr, mask, is_write, > > true); > > + return phb3_err_inject_dma(p, pe_no, addr, mask, is_write, > > true); > > } > > > > static int64_t phb3_err_inject(struct phb *phb, uint32_t pe_no, > > @@ -3443,7 +3443,7 @@ static void phb3_setup_aib(struct phb3 *p) > > phb3_write_reg_asb(p, PHB_AIB_RX_CMD_CRED, 0x > > 0020000100020001); > > else > > phb3_write_reg_asb(p, PHB_AIB_RX_CMD_CRED, 0x > > 0020000100010001); > > - > > + > > /* Init_4 - AIB rx data credit register */ > > if (p->rev >= PHB3_REV_VENICE_DD20) > > phb3_write_reg_asb(p, PHB_AIB_RX_DATA_CRED, 0 > > x0020002000010001); > > @@ -4444,7 +4444,7 @@ static void phb3_probe_pbcq(struct dt_node > > *pbcq) > > /* Set the interrupt routing stuff, 8 relevant bits in mask > > * (11 bits per PHB) > > */ > > - val = P8_CHIP_IRQ_PHB_BASE(gcid, pno); > > + val = p8_chip_irq_phb_base(gcid, pno); > > val = (val << 45); > > xscom_write(gcid, pe_xscom + 0x1a, val); > > xscom_write(gcid, pe_xscom + 0x1b, 0xff00000000000000ul); > > diff --git a/include/interrupts.h b/include/interrupts.h > > index 9239b86..276a936 100644 > > --- a/include/interrupts.h > > +++ b/include/interrupts.h > > @@ -78,7 +78,7 @@ > > * > > * TBD > > * > > - * > > + * > > * Additional note about routing of interrupts in P7 and P7+ > > * ========================================================= > > * > > @@ -152,19 +152,26 @@ > > * are naturally power-of-two aligned > > * > > * Our P8 Interrupt map consits thus of dividing the chip space > > - * into 4 "blocks" of 2048 interrupts. Block 0 is for random chip > > + * into "blocks" of 2048 interrupts. Block 0 is for random chip > > * interrupt sources (NX, PSI, OCC, ...) and keeps sources 0..15 > > - * clear to avoid conflits with IPIs etc.... Block 1..3 are assigned > > - * to PHB 0..2 respectively. > > + * clear to avoid conflits with IPIs etc.... Block 1..n are assigned > > + * to PHB 0..n respectively. The number of blocks is determined by > > the > > + * number of bits assigned to chips. > > * > > * That gives us an interrupt number made of: > > - * 18 13 12 11 10 0 > > + * 18 n+1 n 11 10 0 > > * | | | | | | > > * +--------------------+------+-----------------------------+ > > * | Chip# | PHB# | IVE# | > > * +--------------------+------+-----------------------------+ > > * > > - * We can thus support a max of 2^6 = 64 chips > > + * Where n = 18 - p8_chip_id_bits > > + * > > + * For P8 we have 6 bits for Chip# as defined by p8_chip_id_bits. We > > + * therefore support a max of 2^6 = 64 chips. > > + * > > + * For P8NVL we have an extra PHB and so we assign 5 bits for Chip# > > + * and therefore support a max of 32 chips. > > * > > * Each PHB supports 2K interrupt sources, which is shared by > > * LSI and MSI. With default configuration, MSI would use range > > @@ -174,21 +181,20 @@ > > * > > */ > > > > -#define P8_CHIP_IRQ_BASE(chip) ((chip) << 13) > > -#define P8_CHIP_IRQ_BLOCK_BASE(chip, block) (P8_CHIP_IRQ_BASE > > (chip) \ > > - | ((block) << 11)) > > -#define P8_IRQ_BLOCK_MISC 0 > > -#define P8_IRQ_BLOCK_PHB0 1 > > -#define P8_IRQ_BLOCK_PHB1 2 > > -#define P8_IRQ_BLOCK_PHB2 3 > > +uint32_t p8_chip_irq_block_base(uint32_t chip, uint32_t block); > > +uint32_t p8_chip_irq_phb_base(uint32_t chip, uint32_t phb); > > +uint32_t p8_irq_to_chip(uint32_t irq); > > +uint32_t p8_irq_to_block(uint32_t irq); > > +uint32_t p8_irq_to_phb(uint32_t irq); > > + > > +/* Total number of bits in the P8 interrupt space */ > > +#define P8_IRQ_BITS 19 > > > > -#define P8_CHIP_IRQ_PHB_BASE(chip, phb) (P8_CHIP_IRQ_ > > BLOCK_BASE(chip,\ > > - (phb) + > > P8_IRQ_BLOCK_PHB0)) > > +/* Number of bits per block */ > > +#define P8_IVE_BITS 11 > > > > -#define P8_IRQ_TO_CHIP(irq) (((irq) >> 13) & > > 0x3f) > > -#define P8_IRQ_TO_BLOCK(irq) (((irq) >> 11) & > > 0x03) > > -#define P8_IRQ_TO_PHB(irq) (P8_IRQ_TO_BLOCK(i > > rq) - \ > > - P8_IRQ_BLOCK_PHB0) > > +#define P8_IRQ_BLOCK_MISC 0 > > +#define P8_IRQ_BLOCK_PHB_BASE 1 > > > > /* Assignment of the "MISC" block: > > * ------------------------------- > > diff --git a/include/phb3.h b/include/phb3.h > > index 3accd9e..982f847 100644 > > --- a/include/phb3.h > > +++ b/include/phb3.h > > @@ -52,9 +52,9 @@ > > #define PHB3_LSI_IRQ_COUNT 8 > > #define PHB3_LSI_IRQ_MAX (PHB3_LSI_IRQ_MIN+PHB3_LSI_I > > RQ_COUNT-1) > > > > -#define PHB3_MSI_IRQ_BASE(chip, phb) (P8_CHIP_IRQ_PHB_BASE(ch > > ip, phb) | \ > > +#define PHB3_MSI_IRQ_BASE(chip, phb) (p8_chip_irq_phb_base(ch > > ip, phb) | \ > > PHB3_MSI_IRQ_MIN) > > -#define PHB3_LSI_IRQ_BASE(chip, phb) (P8_CHIP_IRQ_PHB_BASE(ch > > ip, phb) | \ > > +#define PHB3_LSI_IRQ_BASE(chip, phb) (p8_chip_irq_phb_base(ch > > ip, phb) | \ > > PHB3_LSI_IRQ_MIN) > > #define PHB3_IRQ_NUM(irq) (irq & 0x7FF) > > > > @@ -94,7 +94,7 @@ > > * All those tables have to be naturally aligned > > */ > > > > -/* RTT Table : 128KB - Maps RID to PE# > > +/* RTT Table : 128KB - Maps RID to PE# > > * > > * Entries are 2 bytes indexed by PCIe RID > > */ > > diff --git a/include/skiboot.h b/include/skiboot.h > > index 4b58597..cdc5a10 100644 > > --- a/include/skiboot.h > > +++ b/include/skiboot.h > > @@ -125,6 +125,9 @@ enum proc_gen { > > }; > > extern enum proc_gen proc_gen; > > > > +/* Number of chip id bits available */ > > +extern uint32_t p8_chip_id_bits; > > + > > /* Convert a 4-bit number to a hex char */ > > extern char __attrconst tohex(uint8_t nibble); > > > > @@ -263,4 +266,3 @@ extern bool slw_timer_ok(void); > > extern void fake_rtc_init(void); > > > > #endif /* __SKIBOOT_H */ > > -
On Mon, 2015-09-14 at 17:15 +1000, Alistair Popple wrote: > Are you suggesting we add a proc_gen_p8vnl to the proc_gen enum used > for > struct proc_chip -> type or just reading the PVR again in > get_chip_id_bits()? > It looked like adding another processor to the enum would be a pain > hence the > ugliness above, but reading the PVR is easy enough. No, we already have this: /* Chip type */ enum proc_chip_type { PROC_CHIP_UNKNOWN, PROC_CHIP_P7, PROC_CHIP_P7P, PROC_CHIP_P8_MURANO, PROC_CHIP_P8_VENICE, PROC_CHIP_P8_NAPLES, };
diff --git a/core/cpu.c b/core/cpu.c index 8b0f861..c9dcd8f 100644 --- a/core/cpu.c +++ b/core/cpu.c @@ -403,10 +403,12 @@ void init_boot_cpu(void) case PVR_TYPE_P8: proc_gen = proc_gen_p8; hile_supported = PVR_VERS_MAJ(mfspr(SPR_PVR)) >= 2; + p8_chip_id_bits = 6; break; case PVR_TYPE_P8NVL: proc_gen = proc_gen_p8; hile_supported = true; + p8_chip_id_bits = 5; break; default: proc_gen = proc_gen_unknown; @@ -544,7 +546,7 @@ void cpu_bringup(void) op_display(OP_LOG, OP_MOD_CPU, 0x0000); - /* Tell everybody to chime in ! */ + /* Tell everybody to chime in ! */ prlog(PR_INFO, "CPU: Calling in all processors...\n"); cpu_secondary_start = 1; sync(); diff --git a/core/interrupts.c b/core/interrupts.c index 32f43ef..d2e5096 100644 --- a/core/interrupts.c +++ b/core/interrupts.c @@ -30,6 +30,9 @@ #define ICP_CPPR 0x4 /* 8-bit access */ #define ICP_MFRR 0xc /* 8-bit access */ +/* Number of bits to use for the chips ids. */ +uint32_t p8_chip_id_bits; + struct irq_source { uint32_t start; uint32_t end; @@ -121,7 +124,7 @@ uint32_t get_psi_interrupt(uint32_t chip_id) irq |= P7_PSI_IRQ_BUID << 4; break; case proc_gen_p8: - irq = P8_CHIP_IRQ_BLOCK_BASE(chip_id, P8_IRQ_BLOCK_MISC); + irq = p8_chip_irq_block_base(chip_id, P8_IRQ_BLOCK_MISC); irq += P8_IRQ_MISC_PSI_BASE; break; default: @@ -253,6 +256,58 @@ void icp_kick_cpu(struct cpu_thread *cpu) out_8(icp + ICP_MFRR, 0); } +/* The chip id mask is the upper p8_chip_id_bits of the irq number */ +static uint32_t chip_id_mask(void) +{ + uint32_t chip_id_mask = ((1 << p8_chip_id_bits) - 1); + chip_id_mask <<= P8_IRQ_BITS - p8_chip_id_bits; + return chip_id_mask; +} + +/* The block mask is what remains of the 19 bit irq number after + * removing the upper 5 or 6 bits for the chip# and the lower 11 bits + * for the number of bits per block. */ +static uint32_t block_mask(void) +{ + uint32_t irq_block_mask = P8_IRQ_BITS - p8_chip_id_bits - P8_IVE_BITS; + irq_block_mask = ((1 << irq_block_mask) - 1) << P8_IVE_BITS; + return irq_block_mask; +} + +uint32_t p8_chip_irq_block_base(uint32_t chip, uint32_t block) +{ + uint32_t irq; + + assert(chip < (1 << p8_chip_id_bits)); + irq = SETFIELD(chip_id_mask(), 0, chip); + irq = SETFIELD(block_mask(), irq, block); + + return irq; +} + +uint32_t p8_chip_irq_phb_base(uint32_t chip, uint32_t phb) +{ + assert(chip < (1 << p8_chip_id_bits)); + + return p8_chip_irq_block_base(chip, phb + P8_IRQ_BLOCK_PHB_BASE); +} + +uint32_t p8_irq_to_chip(uint32_t irq) +{ + return GETFIELD(chip_id_mask(), irq); +} + +uint32_t p8_irq_to_block(uint32_t irq) +{ + + return GETFIELD(block_mask(), irq); +} + +uint32_t p8_irq_to_phb(uint32_t irq) +{ + return p8_irq_to_block(irq) - P8_IRQ_BLOCK_PHB_BASE; +} + static struct irq_source *irq_find_source(uint32_t isn) { struct irq_source *is; @@ -340,4 +395,3 @@ void init_interrupts(void) } } } - diff --git a/hw/phb3.c b/hw/phb3.c index 5fd0130..77a84ed 100644 --- a/hw/phb3.c +++ b/hw/phb3.c @@ -1550,8 +1550,8 @@ static int64_t phb3_msi_get_xive(void *data, uint32_t chip, index, irq; uint64_t ive; - chip = P8_IRQ_TO_CHIP(isn); - index = P8_IRQ_TO_PHB(isn); + chip = p8_irq_to_chip(isn); + index = p8_irq_to_phb(isn); irq = PHB3_IRQ_NUM(isn); if (chip != p->chip_id || @@ -1580,8 +1580,8 @@ static int64_t phb3_msi_set_xive(void *data, uint64_t *cache, ive_num, data64, m_server, m_prio; uint32_t *ive; - chip = P8_IRQ_TO_CHIP(isn); - index = P8_IRQ_TO_PHB(isn); + chip = p8_irq_to_chip(isn); + index = p8_irq_to_phb(isn); ive_num = PHB3_IRQ_NUM(isn); if (p->state == PHB3_STATE_BROKEN || !p->tbl_rtt) @@ -1642,8 +1642,8 @@ static int64_t phb3_lsi_get_xive(void *data, uint32_t chip, index, irq; uint64_t lxive; - chip = P8_IRQ_TO_CHIP(isn); - index = P8_IRQ_TO_PHB(isn); + chip = p8_irq_to_chip(isn); + index = p8_irq_to_phb(isn); irq = PHB3_IRQ_NUM(isn); if (chip != p->chip_id || @@ -1668,8 +1668,8 @@ static int64_t phb3_lsi_set_xive(void *data, uint32_t chip, index, irq, entry; uint64_t lxive; - chip = P8_IRQ_TO_CHIP(isn); - index = P8_IRQ_TO_PHB(isn); + chip = p8_irq_to_chip(isn); + index = p8_irq_to_phb(isn); irq = PHB3_IRQ_NUM(isn); if (p->state == PHB3_STATE_BROKEN) @@ -1935,7 +1935,7 @@ static void phb3_setup_for_link_down(struct phb3 *p) static void phb3_setup_for_link_up(struct phb3 *p) { uint32_t reg32; - + /* Clear AER receiver error status */ phb3_pcicfg_write32(&p->phb, 0, p->aercap + PCIECAP_AER_CE_STATUS, PCIECAP_AER_CE_RECVR_ERR); @@ -3041,7 +3041,7 @@ static int64_t phb3_err_inject_dma64(struct phb3 *p, uint32_t pe_no, uint64_t addr, uint64_t mask, bool is_write) { - return phb3_err_inject_dma(p, pe_no, addr, mask, is_write, true); + return phb3_err_inject_dma(p, pe_no, addr, mask, is_write, true); } static int64_t phb3_err_inject(struct phb *phb, uint32_t pe_no, @@ -3443,7 +3443,7 @@ static void phb3_setup_aib(struct phb3 *p) phb3_write_reg_asb(p, PHB_AIB_RX_CMD_CRED, 0x0020000100020001); else phb3_write_reg_asb(p, PHB_AIB_RX_CMD_CRED, 0x0020000100010001); - + /* Init_4 - AIB rx data credit register */ if (p->rev >= PHB3_REV_VENICE_DD20) phb3_write_reg_asb(p, PHB_AIB_RX_DATA_CRED, 0x0020002000010001); @@ -4444,7 +4444,7 @@ static void phb3_probe_pbcq(struct dt_node *pbcq) /* Set the interrupt routing stuff, 8 relevant bits in mask * (11 bits per PHB) */ - val = P8_CHIP_IRQ_PHB_BASE(gcid, pno); + val = p8_chip_irq_phb_base(gcid, pno); val = (val << 45); xscom_write(gcid, pe_xscom + 0x1a, val); xscom_write(gcid, pe_xscom + 0x1b, 0xff00000000000000ul); diff --git a/include/interrupts.h b/include/interrupts.h index 9239b86..276a936 100644 --- a/include/interrupts.h +++ b/include/interrupts.h @@ -78,7 +78,7 @@ * * TBD * - * + * * Additional note about routing of interrupts in P7 and P7+ * ========================================================= * @@ -152,19 +152,26 @@ * are naturally power-of-two aligned * * Our P8 Interrupt map consits thus of dividing the chip space - * into 4 "blocks" of 2048 interrupts. Block 0 is for random chip + * into "blocks" of 2048 interrupts. Block 0 is for random chip * interrupt sources (NX, PSI, OCC, ...) and keeps sources 0..15 - * clear to avoid conflits with IPIs etc.... Block 1..3 are assigned - * to PHB 0..2 respectively. + * clear to avoid conflits with IPIs etc.... Block 1..n are assigned + * to PHB 0..n respectively. The number of blocks is determined by the + * number of bits assigned to chips. * * That gives us an interrupt number made of: - * 18 13 12 11 10 0 + * 18 n+1 n 11 10 0 * | | | | | | * +--------------------+------+-----------------------------+ * | Chip# | PHB# | IVE# | * +--------------------+------+-----------------------------+ * - * We can thus support a max of 2^6 = 64 chips + * Where n = 18 - p8_chip_id_bits + * + * For P8 we have 6 bits for Chip# as defined by p8_chip_id_bits. We + * therefore support a max of 2^6 = 64 chips. + * + * For P8NVL we have an extra PHB and so we assign 5 bits for Chip# + * and therefore support a max of 32 chips. * * Each PHB supports 2K interrupt sources, which is shared by * LSI and MSI. With default configuration, MSI would use range @@ -174,21 +181,20 @@ * */ -#define P8_CHIP_IRQ_BASE(chip) ((chip) << 13) -#define P8_CHIP_IRQ_BLOCK_BASE(chip, block) (P8_CHIP_IRQ_BASE(chip) \ - | ((block) << 11)) -#define P8_IRQ_BLOCK_MISC 0 -#define P8_IRQ_BLOCK_PHB0 1 -#define P8_IRQ_BLOCK_PHB1 2 -#define P8_IRQ_BLOCK_PHB2 3 +uint32_t p8_chip_irq_block_base(uint32_t chip, uint32_t block); +uint32_t p8_chip_irq_phb_base(uint32_t chip, uint32_t phb); +uint32_t p8_irq_to_chip(uint32_t irq); +uint32_t p8_irq_to_block(uint32_t irq); +uint32_t p8_irq_to_phb(uint32_t irq); + +/* Total number of bits in the P8 interrupt space */ +#define P8_IRQ_BITS 19 -#define P8_CHIP_IRQ_PHB_BASE(chip, phb) (P8_CHIP_IRQ_BLOCK_BASE(chip,\ - (phb) + P8_IRQ_BLOCK_PHB0)) +/* Number of bits per block */ +#define P8_IVE_BITS 11 -#define P8_IRQ_TO_CHIP(irq) (((irq) >> 13) & 0x3f) -#define P8_IRQ_TO_BLOCK(irq) (((irq) >> 11) & 0x03) -#define P8_IRQ_TO_PHB(irq) (P8_IRQ_TO_BLOCK(irq) - \ - P8_IRQ_BLOCK_PHB0) +#define P8_IRQ_BLOCK_MISC 0 +#define P8_IRQ_BLOCK_PHB_BASE 1 /* Assignment of the "MISC" block: * ------------------------------- diff --git a/include/phb3.h b/include/phb3.h index 3accd9e..982f847 100644 --- a/include/phb3.h +++ b/include/phb3.h @@ -52,9 +52,9 @@ #define PHB3_LSI_IRQ_COUNT 8 #define PHB3_LSI_IRQ_MAX (PHB3_LSI_IRQ_MIN+PHB3_LSI_IRQ_COUNT-1) -#define PHB3_MSI_IRQ_BASE(chip, phb) (P8_CHIP_IRQ_PHB_BASE(chip, phb) | \ +#define PHB3_MSI_IRQ_BASE(chip, phb) (p8_chip_irq_phb_base(chip, phb) | \ PHB3_MSI_IRQ_MIN) -#define PHB3_LSI_IRQ_BASE(chip, phb) (P8_CHIP_IRQ_PHB_BASE(chip, phb) | \ +#define PHB3_LSI_IRQ_BASE(chip, phb) (p8_chip_irq_phb_base(chip, phb) | \ PHB3_LSI_IRQ_MIN) #define PHB3_IRQ_NUM(irq) (irq & 0x7FF) @@ -94,7 +94,7 @@ * All those tables have to be naturally aligned */ -/* RTT Table : 128KB - Maps RID to PE# +/* RTT Table : 128KB - Maps RID to PE# * * Entries are 2 bytes indexed by PCIe RID */ diff --git a/include/skiboot.h b/include/skiboot.h index 4b58597..cdc5a10 100644 --- a/include/skiboot.h +++ b/include/skiboot.h @@ -125,6 +125,9 @@ enum proc_gen { }; extern enum proc_gen proc_gen; +/* Number of chip id bits available */ +extern uint32_t p8_chip_id_bits; + /* Convert a 4-bit number to a hex char */ extern char __attrconst tohex(uint8_t nibble); @@ -263,4 +266,3 @@ extern bool slw_timer_ok(void); extern void fake_rtc_init(void); #endif /* __SKIBOOT_H */ -
Interrupts on P8 are currently hard-coded using macros in include/interrupts.h. The new P8NVL processor has an extra PHB meaning it supports 4 PHBs in total which leads to the following assert fail when booting P8NVL based systems: [6614913194,3] register IRQ source overlap ! [6620562844,3] new: 2000..27f7 old: 2000..27f7 [6870377440,0] Assert fail: core/interrupts.c:67:0 This patch converts the existing macros to function calls so that different platforms can support extra PHBs at the expense of a reduced maximum number of chips. Signed-off-by: Alistair Popple <alistair@popple.id.au> --- core/cpu.c | 4 +++- core/interrupts.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++-- hw/phb3.c | 24 +++++++++++----------- include/interrupts.h | 44 ++++++++++++++++++++++----------------- include/phb3.h | 6 +++--- include/skiboot.h | 4 +++- 6 files changed, 102 insertions(+), 38 deletions(-)