Skip to content

Commit 0d20750

Browse files
allenpaistyhicks
authored andcommitted
Hyper-V: pci: Generify irq/msi set-up and handling
Currently, operations related to irq/msi in Hyper-V vPCI are x86-specific code. In order to support virtual PCI on Hyper-V for other architectures, introduce generic interfaces to replace the x86-specific ones in Hyper-v vPCI. Signed-off-by: Sunil Muthuswamy <sunilmut@microsoft.com> Signed-off-by: Boqun Feng (Microsoft) <boqun.feng@gmail.com> Signed-off-by: Allen Pais <apais@microsoft.com>
1 parent dbcb218 commit 0d20750

2 files changed

Lines changed: 53 additions & 11 deletions

File tree

arch/x86/include/asm/mshyperv.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <asm/hyperv-tlfs.h>
1010
#include <asm/nospec-branch.h>
1111
#include <asm/paravirt.h>
12+
#include <asm/msi.h>
1213

1314
typedef int (*hyperv_fill_flush_list_func)(
1415
struct hv_guest_mapping_flush_list *flush,
@@ -194,6 +195,38 @@ int hyperv_fill_flush_guest_mapping_list(
194195
struct hv_guest_mapping_flush_list *flush,
195196
u64 start_gfn, u64 end_gfn);
196197

198+
#define hv_msi_handler handle_edge_irq
199+
#define hv_msi_handler_name "edge"
200+
#define hv_msi_prepare pci_msi_prepare
201+
202+
/* Returns the Hyper-V PCI parent MSI vector domain. */
203+
static inline struct irq_domain *hv_msi_parent_vector_domain(void)
204+
{
205+
return x86_vector_domain;
206+
}
207+
208+
/* Returns the interrupt vector mapped to the given IRQ. */
209+
static inline unsigned int hv_msi_get_int_vector(struct irq_data *data)
210+
{
211+
struct irq_cfg *cfg = irqd_cfg(data);
212+
213+
return cfg->vector;
214+
}
215+
216+
/* Return the H/W interrupt vector mapped to the given MSI. */
217+
static inline irq_hw_number_t
218+
hv_msi_domain_ops_get_hwirq(struct msi_domain_info *info,
219+
msi_alloc_info_t *arg)
220+
{
221+
return arg->hwirq;
222+
}
223+
224+
/* Get the IRQ delivery mode .*/
225+
static inline u8 hv_msi_irq_delivery_mode(void)
226+
{
227+
return dest_Fixed;
228+
}
229+
197230
#ifdef CONFIG_X86_64
198231
void hv_apic_init(void);
199232
void __init hv_init_spinlocks(void);

drivers/pci/controller/pci-hyperv.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include <linux/msi.h>
5050
#include <linux/hyperv.h>
5151
#include <linux/refcount.h>
52+
#include <linux/pci.h>
5253
#include <asm/mshyperv.h>
5354

5455
/*
@@ -1193,7 +1194,6 @@ static void hv_irq_mask(struct irq_data *data)
11931194
static void hv_irq_unmask(struct irq_data *data)
11941195
{
11951196
struct msi_desc *msi_desc = irq_data_get_msi_desc(data);
1196-
struct irq_cfg *cfg = irqd_cfg(data);
11971197
struct hv_retarget_device_interrupt *params;
11981198
struct hv_pcibus_device *hbus;
11991199
struct cpumask *dest;
@@ -1222,7 +1222,7 @@ static void hv_irq_unmask(struct irq_data *data)
12221222
(hbus->hdev->dev_instance.b[7] << 8) |
12231223
(hbus->hdev->dev_instance.b[6] & 0xf8) |
12241224
PCI_FUNC(pdev->devfn);
1225-
params->int_target.vector = cfg->vector;
1225+
params->int_target.vector = hv_msi_get_int_vector(data);
12261226

12271227
/*
12281228
* Honoring apic->irq_delivery_mode set to dest_Fixed by
@@ -1323,7 +1323,7 @@ static u32 hv_compose_msi_req_v1(
13231323
int_pkt->wslot.slot = slot;
13241324
int_pkt->int_desc.vector = vector;
13251325
int_pkt->int_desc.vector_count = 1;
1326-
int_pkt->int_desc.delivery_mode = dest_Fixed;
1326+
int_pkt->int_desc.delivery_mode = hv_msi_irq_delivery_mode();
13271327

13281328
/*
13291329
* Create MSI w/ dummy vCPU set, overwritten by subsequent retarget in
@@ -1344,7 +1344,7 @@ static u32 hv_compose_msi_req_v2(
13441344
int_pkt->wslot.slot = slot;
13451345
int_pkt->int_desc.vector = vector;
13461346
int_pkt->int_desc.vector_count = 1;
1347-
int_pkt->int_desc.delivery_mode = dest_Fixed;
1347+
int_pkt->int_desc.delivery_mode = hv_msi_irq_delivery_mode();
13481348

13491349
/*
13501350
* Create MSI w/ dummy vCPU set targeting just one vCPU, overwritten
@@ -1371,7 +1371,6 @@ static u32 hv_compose_msi_req_v2(
13711371
*/
13721372
static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
13731373
{
1374-
struct irq_cfg *cfg = irqd_cfg(data);
13751374
struct hv_pcibus_device *hbus;
13761375
struct vmbus_channel *channel;
13771376
struct hv_pci_dev *hpdev;
@@ -1421,15 +1420,15 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
14211420
size = hv_compose_msi_req_v1(&ctxt.int_pkts.v1,
14221421
dest,
14231422
hpdev->desc.win_slot.slot,
1424-
cfg->vector);
1423+
hv_msi_get_int_vector(data));
14251424
break;
14261425

14271426
case PCI_PROTOCOL_VERSION_1_2:
14281427
case PCI_PROTOCOL_VERSION_1_3:
14291428
size = hv_compose_msi_req_v2(&ctxt.int_pkts.v2,
14301429
dest,
14311430
hpdev->desc.win_slot.slot,
1432-
cfg->vector);
1431+
hv_msi_get_int_vector(data));
14331432
break;
14341433

14351434
default:
@@ -1540,12 +1539,13 @@ static struct irq_chip hv_msi_irq_chip = {
15401539
.irq_compose_msi_msg = hv_compose_msi_msg,
15411540
.irq_set_affinity = hv_set_affinity,
15421541
.irq_ack = irq_chip_ack_parent,
1542+
.irq_eoi = irq_chip_eoi_parent,
15431543
.irq_mask = hv_irq_mask,
15441544
.irq_unmask = hv_irq_unmask,
15451545
};
15461546

15471547
static struct msi_domain_ops hv_msi_ops = {
1548-
.msi_prepare = pci_msi_prepare,
1548+
.msi_prepare = hv_msi_prepare,
15491549
.msi_free = hv_msi_free,
15501550
};
15511551

@@ -1564,17 +1564,26 @@ static struct msi_domain_ops hv_msi_ops = {
15641564
*/
15651565
static int hv_pcie_init_irq_domain(struct hv_pcibus_device *hbus)
15661566
{
1567+
struct irq_domain *parent_domain;
1568+
1569+
parent_domain = hv_msi_parent_vector_domain();
1570+
if (!parent_domain) {
1571+
dev_err(&hbus->hdev->device,
1572+
"Failed to get parent MSI domain\n");
1573+
return -ENODEV;
1574+
}
1575+
15671576
hbus->msi_info.chip = &hv_msi_irq_chip;
15681577
hbus->msi_info.ops = &hv_msi_ops;
15691578
hbus->msi_info.flags = (MSI_FLAG_USE_DEF_DOM_OPS |
15701579
MSI_FLAG_USE_DEF_CHIP_OPS | MSI_FLAG_MULTI_PCI_MSI |
15711580
MSI_FLAG_PCI_MSIX);
1572-
hbus->msi_info.handler = handle_edge_irq;
1573-
hbus->msi_info.handler_name = "edge";
1581+
hbus->msi_info.handler = hv_msi_handler;
1582+
hbus->msi_info.handler_name = hv_msi_handler_name;
15741583
hbus->msi_info.data = hbus;
15751584
hbus->irq_domain = pci_msi_create_irq_domain(hbus->sysdata.fwnode,
15761585
&hbus->msi_info,
1577-
x86_vector_domain);
1586+
parent_domain);
15781587
if (!hbus->irq_domain) {
15791588
dev_err(&hbus->hdev->device,
15801589
"Failed to build an MSI IRQ domain\n");

0 commit comments

Comments
 (0)