Skip to content

Commit

Permalink
s390/pci: provide support for CPU directed interrupts
Browse files Browse the repository at this point in the history
Up until now all interrupts on s390 have been floating. For MSI interrupts
we've used a global summary bit vector (with a bit for each function) and
a per-function interrupt bit vector (with a bit per MSI).

This patch introduces a new IRQ delivery mode: CPU directed interrupts.
In this new mode a per-CPU interrupt bit vector is used (with a bit per
MSI per function). Further it is now possible to direct an IRQ to a
specific CPU so we can finally support IRQ affinity.

If an interrupt can't be delivered because the appointed CPU is occupied
by a hypervisor the interrupt is delivered floating. For this a global
summary bit vector is used (with a bit per CPU).

Signed-off-by: Sebastian Ott <sebott@linux.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Sebastian Ott authored and Martin Schwidefsky committed Apr 29, 2019
1 parent 414cbd1 commit e979ce7
Show file tree
Hide file tree
Showing 5 changed files with 368 additions and 63 deletions.
2 changes: 2 additions & 0 deletions arch/s390/include/asm/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ struct zpci_dev {
/* IRQ stuff */
u64 msi_addr; /* MSI address */
unsigned int max_msi; /* maximum number of MSI's */
unsigned int msi_first_bit;
unsigned int msi_nr_irqs;
struct airq_iv *aibv; /* adapter interrupt bit vector */
unsigned long aisb; /* number of the summary bit */

Expand Down
6 changes: 5 additions & 1 deletion arch/s390/include/asm/pci_clp.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,11 @@ struct clp_rsp_query_pci_grp {
u8 refresh : 1; /* TLB refresh mode */
u16 reserved2;
u16 mui;
u64 reserved3;
u16 : 16;
u16 maxfaal;
u16 : 4;
u16 dnoi : 12;
u16 maxcpu;
u64 dasm; /* dma address space mask */
u64 msia; /* MSI address */
u64 reserved4;
Expand Down
74 changes: 63 additions & 11 deletions arch/s390/include/asm/pci_insn.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
#define ZPCI_MOD_FC_RESET_ERROR 7
#define ZPCI_MOD_FC_RESET_BLOCK 9
#define ZPCI_MOD_FC_SET_MEASURE 10
#define ZPCI_MOD_FC_REG_INT_D 16
#define ZPCI_MOD_FC_DEREG_INT_D 17

/* FIB function controls */
#define ZPCI_FIB_FC_ENABLED 0x80
Expand All @@ -51,16 +53,7 @@
#define ZPCI_FIB_FC_LS_BLOCKED 0x20
#define ZPCI_FIB_FC_DMAAS_REG 0x10

/* Function Information Block */
struct zpci_fib {
u32 fmt : 8; /* format */
u32 : 24;
u32 : 32;
u8 fc; /* function controls */
u64 : 56;
u64 pba; /* PCI base address */
u64 pal; /* PCI address limit */
u64 iota; /* I/O Translation Anchor */
struct zpci_fib_fmt0 {
u32 : 1;
u32 isc : 3; /* Interrupt subclass */
u32 noi : 12; /* Number of interrupts */
Expand All @@ -72,16 +65,75 @@ struct zpci_fib {
u32 : 32;
u64 aibv; /* Adapter int bit vector address */
u64 aisb; /* Adapter int summary bit address */
};

struct zpci_fib_fmt1 {
u32 : 4;
u32 noi : 12;
u32 : 16;
u32 dibvo : 16;
u32 : 16;
u64 : 64;
u64 : 64;
};

/* Function Information Block */
struct zpci_fib {
u32 fmt : 8; /* format */
u32 : 24;
u32 : 32;
u8 fc; /* function controls */
u64 : 56;
u64 pba; /* PCI base address */
u64 pal; /* PCI address limit */
u64 iota; /* I/O Translation Anchor */
union {
struct zpci_fib_fmt0 fmt0;
struct zpci_fib_fmt1 fmt1;
};
u64 fmb_addr; /* Function measurement block address and key */
u32 : 32;
u32 gd;
} __packed __aligned(8);

/* directed interruption information block */
struct zpci_diib {
u32 : 1;
u32 isc : 3;
u32 : 28;
u16 : 16;
u16 nr_cpus;
u64 disb_addr;
u64 : 64;
u64 : 64;
} __packed __aligned(8);

/* cpu directed interruption information block */
struct zpci_cdiib {
u64 : 64;
u64 dibv_addr;
u64 : 64;
u64 : 64;
u64 : 64;
} __packed __aligned(8);

union zpci_sic_iib {
struct zpci_diib diib;
struct zpci_cdiib cdiib;
};

u8 zpci_mod_fc(u64 req, struct zpci_fib *fib, u8 *status);
int zpci_refresh_trans(u64 fn, u64 addr, u64 range);
int zpci_load(u64 *data, u64 req, u64 offset);
int zpci_store(u64 data, u64 req, u64 offset);
int zpci_store_block(const u64 *data, u64 req, u64 offset);
int zpci_set_irq_ctrl(u16 ctl, char *unused, u8 isc);
int __zpci_set_irq_ctrl(u16 ctl, u8 isc, union zpci_sic_iib *iib);

static inline int zpci_set_irq_ctrl(u16 ctl, u8 isc)
{
union zpci_sic_iib iib = {{0}};

return __zpci_set_irq_ctrl(ctl, isc, &iib);
}

#endif
10 changes: 6 additions & 4 deletions arch/s390/pci/pci_insn.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,15 @@ int zpci_refresh_trans(u64 fn, u64 addr, u64 range)
}

/* Set Interruption Controls */
int zpci_set_irq_ctrl(u16 ctl, char *unused, u8 isc)
int __zpci_set_irq_ctrl(u16 ctl, u8 isc, union zpci_sic_iib *iib)
{
if (!test_facility(72))
return -EIO;
asm volatile (
" .insn rsy,0xeb00000000d1,%[ctl],%[isc],%[u]\n"
: : [ctl] "d" (ctl), [isc] "d" (isc << 27), [u] "Q" (*unused));

asm volatile(
".insn rsy,0xeb00000000d1,%[ctl],%[isc],%[iib]\n"
: : [ctl] "d" (ctl), [isc] "d" (isc << 27), [iib] "Q" (*iib));

return 0;
}

Expand Down
Loading

0 comments on commit e979ce7

Please sign in to comment.