lkml.org 
[lkml]   [2022]   [Jul]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.4 09/87] PCI: hv: Fix interrupt mapping for multi-MSI
    Date
    From: Jeffrey Hugo <quic_jhugo@quicinc.com>

    commit a2bad844a67b1c7740bda63e87453baf63c3a7f7 upstream.

    According to Dexuan, the hypervisor folks beleive that multi-msi
    allocations are not correct. compose_msi_msg() will allocate multi-msi
    one by one. However, multi-msi is a block of related MSIs, with alignment
    requirements. In order for the hypervisor to allocate properly aligned
    and consecutive entries in the IOMMU Interrupt Remapping Table, there
    should be a single mapping request that requests all of the multi-msi
    vectors in one shot.

    Dexuan suggests detecting the multi-msi case and composing a single
    request related to the first MSI. Then for the other MSIs in the same
    block, use the cached information. This appears to be viable, so do it.

    5.4 backport - add hv_msi_get_int_vector helper function. Fixed merge
    conflict due to delivery_mode name change (APIC_DELIVERY_MODE_FIXED
    is the value given to dest_Fixed). Removed unused variable in
    hv_compose_msi_msg. Fixed reference to msi_desc->pci to point to
    the same is_msix variable. Removed changes to compose_msi_req_v3 since
    it doesn't exist yet.

    Suggested-by: Dexuan Cui <decui@microsoft.com>
    Signed-off-by: Jeffrey Hugo <quic_jhugo@quicinc.com>
    Reviewed-by: Dexuan Cui <decui@microsoft.com>
    Tested-by: Michael Kelley <mikelley@microsoft.com>
    Link: https://lore.kernel.org/r/1652282599-21643-1-git-send-email-quic_jhugo@quicinc.com
    Signed-off-by: Wei Liu <wei.liu@kernel.org>
    Signed-off-by: Carl Vanderlip <quic_carlv@quicinc.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/pci/controller/pci-hyperv.c | 61 +++++++++++++++++++++++++++++++-----
    1 file changed, 53 insertions(+), 8 deletions(-)

    --- a/drivers/pci/controller/pci-hyperv.c
    +++ b/drivers/pci/controller/pci-hyperv.c
    @@ -1110,6 +1110,10 @@ static void hv_int_desc_free(struct hv_p
    u8 buffer[sizeof(struct pci_delete_interrupt)];
    } ctxt;

    + if (!int_desc->vector_count) {
    + kfree(int_desc);
    + return;
    + }
    memset(&ctxt, 0, sizeof(ctxt));
    int_pkt = (struct pci_delete_interrupt *)&ctxt.pkt.message;
    int_pkt->message_type.type =
    @@ -1172,6 +1176,13 @@ static void hv_irq_mask(struct irq_data
    pci_msi_mask_irq(data);
    }

    +static unsigned int hv_msi_get_int_vector(struct irq_data *data)
    +{
    + struct irq_cfg *cfg = irqd_cfg(data);
    +
    + return cfg->vector;
    +}
    +
    static int hv_msi_prepare(struct irq_domain *domain, struct device *dev,
    int nvec, msi_alloc_info_t *info)
    {
    @@ -1313,12 +1324,12 @@ static void hv_pci_compose_compl(void *c

    static u32 hv_compose_msi_req_v1(
    struct pci_create_interrupt *int_pkt, struct cpumask *affinity,
    - u32 slot, u8 vector)
    + u32 slot, u8 vector, u8 vector_count)
    {
    int_pkt->message_type.type = PCI_CREATE_INTERRUPT_MESSAGE;
    int_pkt->wslot.slot = slot;
    int_pkt->int_desc.vector = vector;
    - int_pkt->int_desc.vector_count = 1;
    + int_pkt->int_desc.vector_count = vector_count;
    int_pkt->int_desc.delivery_mode = dest_Fixed;

    /*
    @@ -1332,14 +1343,14 @@ static u32 hv_compose_msi_req_v1(

    static u32 hv_compose_msi_req_v2(
    struct pci_create_interrupt2 *int_pkt, struct cpumask *affinity,
    - u32 slot, u8 vector)
    + u32 slot, u8 vector, u8 vector_count)
    {
    int cpu;

    int_pkt->message_type.type = PCI_CREATE_INTERRUPT_MESSAGE2;
    int_pkt->wslot.slot = slot;
    int_pkt->int_desc.vector = vector;
    - int_pkt->int_desc.vector_count = 1;
    + int_pkt->int_desc.vector_count = vector_count;
    int_pkt->int_desc.delivery_mode = dest_Fixed;

    /*
    @@ -1367,7 +1378,6 @@ static u32 hv_compose_msi_req_v2(
    */
    static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
    {
    - struct irq_cfg *cfg = irqd_cfg(data);
    struct hv_pcibus_device *hbus;
    struct hv_pci_dev *hpdev;
    struct pci_bus *pbus;
    @@ -1376,6 +1386,8 @@ static void hv_compose_msi_msg(struct ir
    unsigned long flags;
    struct compose_comp_ctxt comp;
    struct tran_int_desc *int_desc;
    + struct msi_desc *msi_desc;
    + u8 vector, vector_count;
    struct {
    struct pci_packet pci_pkt;
    union {
    @@ -1396,7 +1408,8 @@ static void hv_compose_msi_msg(struct ir
    return;
    }

    - pdev = msi_desc_to_pci_dev(irq_data_get_msi_desc(data));
    + msi_desc = irq_data_get_msi_desc(data);
    + pdev = msi_desc_to_pci_dev(msi_desc);
    dest = irq_data_get_effective_affinity_mask(data);
    pbus = pdev->bus;
    hbus = container_of(pbus->sysdata, struct hv_pcibus_device, sysdata);
    @@ -1408,6 +1421,36 @@ static void hv_compose_msi_msg(struct ir
    if (!int_desc)
    goto drop_reference;

    + if (!msi_desc->msi_attrib.is_msix && msi_desc->nvec_used > 1) {
    + /*
    + * If this is not the first MSI of Multi MSI, we already have
    + * a mapping. Can exit early.
    + */
    + if (msi_desc->irq != data->irq) {
    + data->chip_data = int_desc;
    + int_desc->address = msi_desc->msg.address_lo |
    + (u64)msi_desc->msg.address_hi << 32;
    + int_desc->data = msi_desc->msg.data +
    + (data->irq - msi_desc->irq);
    + msg->address_hi = msi_desc->msg.address_hi;
    + msg->address_lo = msi_desc->msg.address_lo;
    + msg->data = int_desc->data;
    + put_pcichild(hpdev);
    + return;
    + }
    + /*
    + * The vector we select here is a dummy value. The correct
    + * value gets sent to the hypervisor in unmask(). This needs
    + * to be aligned with the count, and also not zero. Multi-msi
    + * is powers of 2 up to 32, so 32 will always work here.
    + */
    + vector = 32;
    + vector_count = msi_desc->nvec_used;
    + } else {
    + vector = hv_msi_get_int_vector(data);
    + vector_count = 1;
    + }
    +
    memset(&ctxt, 0, sizeof(ctxt));
    init_completion(&comp.comp_pkt.host_event);
    ctxt.pci_pkt.completion_func = hv_pci_compose_compl;
    @@ -1418,14 +1461,16 @@ static void hv_compose_msi_msg(struct ir
    size = hv_compose_msi_req_v1(&ctxt.int_pkts.v1,
    dest,
    hpdev->desc.win_slot.slot,
    - cfg->vector);
    + vector,
    + vector_count);
    break;

    case PCI_PROTOCOL_VERSION_1_2:
    size = hv_compose_msi_req_v2(&ctxt.int_pkts.v2,
    dest,
    hpdev->desc.win_slot.slot,
    - cfg->vector);
    + vector,
    + vector_count);
    break;

    default:

    \
     
     \ /
      Last update: 2022-07-27 18:39    [W:2.076 / U:0.136 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site