[Skiboot] [PATCH] interrupts: Convert P8 IRQ assignment to functions
Alistair Popple
alistair at popple.id.au
Mon Sep 14 17:15:33 AEST 2015
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 */
> > -
More information about the Skiboot
mailing list