1f456834aSIan Munsie /* 2f456834aSIan Munsie * Copyright 2014-2016 IBM Corp. 3f456834aSIan Munsie * 4f456834aSIan Munsie * This program is free software; you can redistribute it and/or 5f456834aSIan Munsie * modify it under the terms of the GNU General Public License 6f456834aSIan Munsie * as published by the Free Software Foundation; either version 7f456834aSIan Munsie * 2 of the License, or (at your option) any later version. 8f456834aSIan Munsie */ 9f456834aSIan Munsie 104361b034SIan Munsie #include <linux/module.h> 114361b034SIan Munsie #include <asm/pci-bridge.h> 12f456834aSIan Munsie #include <asm/pnv-pci.h> 13f456834aSIan Munsie #include <asm/opal.h> 144361b034SIan Munsie #include <misc/cxl.h> 15f456834aSIan Munsie 16f456834aSIan Munsie #include "pci.h" 17f456834aSIan Munsie 18f456834aSIan Munsie struct device_node *pnv_pci_get_phb_node(struct pci_dev *dev) 19f456834aSIan Munsie { 20f456834aSIan Munsie struct pci_controller *hose = pci_bus_to_host(dev->bus); 21f456834aSIan Munsie 22f456834aSIan Munsie return of_node_get(hose->dn); 23f456834aSIan Munsie } 24f456834aSIan Munsie EXPORT_SYMBOL(pnv_pci_get_phb_node); 25f456834aSIan Munsie 26f456834aSIan Munsie int pnv_phb_to_cxl_mode(struct pci_dev *dev, uint64_t mode) 27f456834aSIan Munsie { 28f456834aSIan Munsie struct pci_controller *hose = pci_bus_to_host(dev->bus); 29f456834aSIan Munsie struct pnv_phb *phb = hose->private_data; 30f456834aSIan Munsie struct pnv_ioda_pe *pe; 31f456834aSIan Munsie int rc; 32f456834aSIan Munsie 33f456834aSIan Munsie pe = pnv_ioda_get_pe(dev); 34f456834aSIan Munsie if (!pe) 35f456834aSIan Munsie return -ENODEV; 36f456834aSIan Munsie 37f456834aSIan Munsie pe_info(pe, "Switching PHB to CXL\n"); 38f456834aSIan Munsie 39f456834aSIan Munsie rc = opal_pci_set_phb_cxl_mode(phb->opal_id, mode, pe->pe_number); 40f456834aSIan Munsie if (rc == OPAL_UNSUPPORTED) 41f456834aSIan Munsie dev_err(&dev->dev, "Required cxl mode not supported by firmware - update skiboot\n"); 42f456834aSIan Munsie else if (rc) 43f456834aSIan Munsie dev_err(&dev->dev, "opal_pci_set_phb_cxl_mode failed: %i\n", rc); 44f456834aSIan Munsie 45f456834aSIan Munsie return rc; 46f456834aSIan Munsie } 47f456834aSIan Munsie EXPORT_SYMBOL(pnv_phb_to_cxl_mode); 48f456834aSIan Munsie 49f456834aSIan Munsie /* Find PHB for cxl dev and allocate MSI hwirqs? 50f456834aSIan Munsie * Returns the absolute hardware IRQ number 51f456834aSIan Munsie */ 52f456834aSIan Munsie int pnv_cxl_alloc_hwirqs(struct pci_dev *dev, int num) 53f456834aSIan Munsie { 54f456834aSIan Munsie struct pci_controller *hose = pci_bus_to_host(dev->bus); 55f456834aSIan Munsie struct pnv_phb *phb = hose->private_data; 56f456834aSIan Munsie int hwirq = msi_bitmap_alloc_hwirqs(&phb->msi_bmp, num); 57f456834aSIan Munsie 58f456834aSIan Munsie if (hwirq < 0) { 59f456834aSIan Munsie dev_warn(&dev->dev, "Failed to find a free MSI\n"); 60f456834aSIan Munsie return -ENOSPC; 61f456834aSIan Munsie } 62f456834aSIan Munsie 63f456834aSIan Munsie return phb->msi_base + hwirq; 64f456834aSIan Munsie } 65f456834aSIan Munsie EXPORT_SYMBOL(pnv_cxl_alloc_hwirqs); 66f456834aSIan Munsie 67f456834aSIan Munsie void pnv_cxl_release_hwirqs(struct pci_dev *dev, int hwirq, int num) 68f456834aSIan Munsie { 69f456834aSIan Munsie struct pci_controller *hose = pci_bus_to_host(dev->bus); 70f456834aSIan Munsie struct pnv_phb *phb = hose->private_data; 71f456834aSIan Munsie 72f456834aSIan Munsie msi_bitmap_free_hwirqs(&phb->msi_bmp, hwirq - phb->msi_base, num); 73f456834aSIan Munsie } 74f456834aSIan Munsie EXPORT_SYMBOL(pnv_cxl_release_hwirqs); 75f456834aSIan Munsie 76f456834aSIan Munsie void pnv_cxl_release_hwirq_ranges(struct cxl_irq_ranges *irqs, 77f456834aSIan Munsie struct pci_dev *dev) 78f456834aSIan Munsie { 79f456834aSIan Munsie struct pci_controller *hose = pci_bus_to_host(dev->bus); 80f456834aSIan Munsie struct pnv_phb *phb = hose->private_data; 81f456834aSIan Munsie int i, hwirq; 82f456834aSIan Munsie 83f456834aSIan Munsie for (i = 1; i < CXL_IRQ_RANGES; i++) { 84f456834aSIan Munsie if (!irqs->range[i]) 85f456834aSIan Munsie continue; 86f456834aSIan Munsie pr_devel("cxl release irq range 0x%x: offset: 0x%lx limit: %ld\n", 87f456834aSIan Munsie i, irqs->offset[i], 88f456834aSIan Munsie irqs->range[i]); 89f456834aSIan Munsie hwirq = irqs->offset[i] - phb->msi_base; 90f456834aSIan Munsie msi_bitmap_free_hwirqs(&phb->msi_bmp, hwirq, 91f456834aSIan Munsie irqs->range[i]); 92f456834aSIan Munsie } 93f456834aSIan Munsie } 94f456834aSIan Munsie EXPORT_SYMBOL(pnv_cxl_release_hwirq_ranges); 95f456834aSIan Munsie 96f456834aSIan Munsie int pnv_cxl_alloc_hwirq_ranges(struct cxl_irq_ranges *irqs, 97f456834aSIan Munsie struct pci_dev *dev, int num) 98f456834aSIan Munsie { 99f456834aSIan Munsie struct pci_controller *hose = pci_bus_to_host(dev->bus); 100f456834aSIan Munsie struct pnv_phb *phb = hose->private_data; 101f456834aSIan Munsie int i, hwirq, try; 102f456834aSIan Munsie 103f456834aSIan Munsie memset(irqs, 0, sizeof(struct cxl_irq_ranges)); 104f456834aSIan Munsie 105f456834aSIan Munsie /* 0 is reserved for the multiplexed PSL DSI interrupt */ 106f456834aSIan Munsie for (i = 1; i < CXL_IRQ_RANGES && num; i++) { 107f456834aSIan Munsie try = num; 108f456834aSIan Munsie while (try) { 109f456834aSIan Munsie hwirq = msi_bitmap_alloc_hwirqs(&phb->msi_bmp, try); 110f456834aSIan Munsie if (hwirq >= 0) 111f456834aSIan Munsie break; 112f456834aSIan Munsie try /= 2; 113f456834aSIan Munsie } 114f456834aSIan Munsie if (!try) 115f456834aSIan Munsie goto fail; 116f456834aSIan Munsie 117f456834aSIan Munsie irqs->offset[i] = phb->msi_base + hwirq; 118f456834aSIan Munsie irqs->range[i] = try; 119f456834aSIan Munsie pr_devel("cxl alloc irq range 0x%x: offset: 0x%lx limit: %li\n", 120f456834aSIan Munsie i, irqs->offset[i], irqs->range[i]); 121f456834aSIan Munsie num -= try; 122f456834aSIan Munsie } 123f456834aSIan Munsie if (num) 124f456834aSIan Munsie goto fail; 125f456834aSIan Munsie 126f456834aSIan Munsie return 0; 127f456834aSIan Munsie fail: 128f456834aSIan Munsie pnv_cxl_release_hwirq_ranges(irqs, dev); 129f456834aSIan Munsie return -ENOSPC; 130f456834aSIan Munsie } 131f456834aSIan Munsie EXPORT_SYMBOL(pnv_cxl_alloc_hwirq_ranges); 132f456834aSIan Munsie 133f456834aSIan Munsie int pnv_cxl_get_irq_count(struct pci_dev *dev) 134f456834aSIan Munsie { 135f456834aSIan Munsie struct pci_controller *hose = pci_bus_to_host(dev->bus); 136f456834aSIan Munsie struct pnv_phb *phb = hose->private_data; 137f456834aSIan Munsie 138f456834aSIan Munsie return phb->msi_bmp.irq_count; 139f456834aSIan Munsie } 140f456834aSIan Munsie EXPORT_SYMBOL(pnv_cxl_get_irq_count); 141f456834aSIan Munsie 142f456834aSIan Munsie int pnv_cxl_ioda_msi_setup(struct pci_dev *dev, unsigned int hwirq, 143f456834aSIan Munsie unsigned int virq) 144f456834aSIan Munsie { 145f456834aSIan Munsie struct pci_controller *hose = pci_bus_to_host(dev->bus); 146f456834aSIan Munsie struct pnv_phb *phb = hose->private_data; 147f456834aSIan Munsie unsigned int xive_num = hwirq - phb->msi_base; 148f456834aSIan Munsie struct pnv_ioda_pe *pe; 149f456834aSIan Munsie int rc; 150f456834aSIan Munsie 151f456834aSIan Munsie if (!(pe = pnv_ioda_get_pe(dev))) 152f456834aSIan Munsie return -ENODEV; 153f456834aSIan Munsie 154f456834aSIan Munsie /* Assign XIVE to PE */ 155f456834aSIan Munsie rc = opal_pci_set_xive_pe(phb->opal_id, pe->pe_number, xive_num); 156f456834aSIan Munsie if (rc) { 157f456834aSIan Munsie pe_warn(pe, "%s: OPAL error %d setting msi_base 0x%x " 158f456834aSIan Munsie "hwirq 0x%x XIVE 0x%x PE\n", 159f456834aSIan Munsie pci_name(dev), rc, phb->msi_base, hwirq, xive_num); 160f456834aSIan Munsie return -EIO; 161f456834aSIan Munsie } 162f456834aSIan Munsie pnv_set_msi_irq_chip(phb, virq); 163f456834aSIan Munsie 164f456834aSIan Munsie return 0; 165f456834aSIan Munsie } 166f456834aSIan Munsie EXPORT_SYMBOL(pnv_cxl_ioda_msi_setup); 1674361b034SIan Munsie 1684361b034SIan Munsie /* 1694361b034SIan Munsie * Sets flags and switches the controller ops to enable the cxl kernel api. 1704361b034SIan Munsie * Originally the cxl kernel API operated on a virtual PHB, but certain cards 1714361b034SIan Munsie * such as the Mellanox CX4 use a peer model instead and for these cards the 1724361b034SIan Munsie * cxl kernel api will operate on the real PHB. 1734361b034SIan Munsie */ 1744361b034SIan Munsie int pnv_cxl_enable_phb_kernel_api(struct pci_controller *hose, bool enable) 1754361b034SIan Munsie { 1764361b034SIan Munsie struct pnv_phb *phb = hose->private_data; 1774361b034SIan Munsie struct module *cxl_module; 1784361b034SIan Munsie 1794361b034SIan Munsie if (!enable) { 1804361b034SIan Munsie /* 1814361b034SIan Munsie * Once cxl mode is enabled on the PHB, there is currently no 1824361b034SIan Munsie * known safe method to disable it again, and trying risks a 1834361b034SIan Munsie * checkstop. If we can find a way to safely disable cxl mode 1844361b034SIan Munsie * in the future we can revisit this, but for now the only sane 1854361b034SIan Munsie * thing to do is to refuse to disable cxl mode: 1864361b034SIan Munsie */ 1874361b034SIan Munsie return -EPERM; 1884361b034SIan Munsie } 1894361b034SIan Munsie 1904361b034SIan Munsie /* 1914361b034SIan Munsie * Hold a reference to the cxl module since several PHB operations now 1924361b034SIan Munsie * depend on it, and it would be insane to allow it to be removed so 1934361b034SIan Munsie * long as we are in this mode (and since we can't safely disable this 1944361b034SIan Munsie * mode once enabled...). 1954361b034SIan Munsie */ 1964361b034SIan Munsie mutex_lock(&module_mutex); 1974361b034SIan Munsie cxl_module = find_module("cxl"); 1984361b034SIan Munsie if (cxl_module) 1994361b034SIan Munsie __module_get(cxl_module); 2004361b034SIan Munsie mutex_unlock(&module_mutex); 2014361b034SIan Munsie if (!cxl_module) 2024361b034SIan Munsie return -ENODEV; 2034361b034SIan Munsie 2044361b034SIan Munsie phb->flags |= PNV_PHB_FLAG_CXL; 2054361b034SIan Munsie hose->controller_ops = pnv_cxl_cx4_ioda_controller_ops; 2064361b034SIan Munsie 2074361b034SIan Munsie return 0; 2084361b034SIan Munsie } 2094361b034SIan Munsie EXPORT_SYMBOL_GPL(pnv_cxl_enable_phb_kernel_api); 2104361b034SIan Munsie 2114361b034SIan Munsie bool pnv_pci_on_cxl_phb(struct pci_dev *dev) 2124361b034SIan Munsie { 2134361b034SIan Munsie struct pci_controller *hose = pci_bus_to_host(dev->bus); 2144361b034SIan Munsie struct pnv_phb *phb = hose->private_data; 2154361b034SIan Munsie 2164361b034SIan Munsie return !!(phb->flags & PNV_PHB_FLAG_CXL); 2174361b034SIan Munsie } 2184361b034SIan Munsie EXPORT_SYMBOL_GPL(pnv_pci_on_cxl_phb); 2194361b034SIan Munsie 2204361b034SIan Munsie struct cxl_afu *pnv_cxl_phb_to_afu(struct pci_controller *hose) 2214361b034SIan Munsie { 2224361b034SIan Munsie struct pnv_phb *phb = hose->private_data; 2234361b034SIan Munsie 2244361b034SIan Munsie return (struct cxl_afu *)phb->cxl_afu; 2254361b034SIan Munsie } 2264361b034SIan Munsie EXPORT_SYMBOL_GPL(pnv_cxl_phb_to_afu); 2274361b034SIan Munsie 2284361b034SIan Munsie void pnv_cxl_phb_set_peer_afu(struct pci_dev *dev, struct cxl_afu *afu) 2294361b034SIan Munsie { 2304361b034SIan Munsie struct pci_controller *hose = pci_bus_to_host(dev->bus); 2314361b034SIan Munsie struct pnv_phb *phb = hose->private_data; 2324361b034SIan Munsie 2334361b034SIan Munsie phb->cxl_afu = afu; 2344361b034SIan Munsie } 2354361b034SIan Munsie EXPORT_SYMBOL_GPL(pnv_cxl_phb_set_peer_afu); 2364361b034SIan Munsie 2374361b034SIan Munsie /* 2384361b034SIan Munsie * In the peer cxl model, the XSL/PSL is physical function 0, and will be used 2394361b034SIan Munsie * by other functions on the device for memory access and interrupts. When the 2404361b034SIan Munsie * other functions are enabled we explicitly take a reference on the cxl 2414361b034SIan Munsie * function since they will use it, and allocate a default context associated 2424361b034SIan Munsie * with that function just like the vPHB model of the cxl kernel API. 2434361b034SIan Munsie */ 2444361b034SIan Munsie bool pnv_cxl_enable_device_hook(struct pci_dev *dev) 2454361b034SIan Munsie { 2464361b034SIan Munsie struct pci_controller *hose = pci_bus_to_host(dev->bus); 2474361b034SIan Munsie struct pnv_phb *phb = hose->private_data; 2484361b034SIan Munsie struct cxl_afu *afu = phb->cxl_afu; 2494361b034SIan Munsie 2504361b034SIan Munsie if (!pnv_pci_enable_device_hook(dev)) 2514361b034SIan Munsie return false; 2524361b034SIan Munsie 2534361b034SIan Munsie 2544361b034SIan Munsie /* No special handling for the cxl function, which is always PF 0 */ 2554361b034SIan Munsie if (PCI_FUNC(dev->devfn) == 0) 2564361b034SIan Munsie return true; 2574361b034SIan Munsie 2584361b034SIan Munsie if (!afu) { 2594361b034SIan Munsie dev_WARN(&dev->dev, "Attempted to enable function > 0 on CXL PHB without a peer AFU\n"); 2604361b034SIan Munsie return false; 2614361b034SIan Munsie } 2624361b034SIan Munsie 2634361b034SIan Munsie dev_info(&dev->dev, "Enabling function on CXL enabled PHB with peer AFU\n"); 2644361b034SIan Munsie 2654361b034SIan Munsie /* Make sure the peer AFU can't go away while this device is active */ 2664361b034SIan Munsie cxl_afu_get(afu); 2674361b034SIan Munsie 2684361b034SIan Munsie return cxl_pci_associate_default_context(dev, afu); 2694361b034SIan Munsie } 2704361b034SIan Munsie 2714361b034SIan Munsie void pnv_cxl_disable_device(struct pci_dev *dev) 2724361b034SIan Munsie { 2734361b034SIan Munsie struct pci_controller *hose = pci_bus_to_host(dev->bus); 2744361b034SIan Munsie struct pnv_phb *phb = hose->private_data; 2754361b034SIan Munsie struct cxl_afu *afu = phb->cxl_afu; 2764361b034SIan Munsie 2774361b034SIan Munsie /* No special handling for cxl function: */ 2784361b034SIan Munsie if (PCI_FUNC(dev->devfn) == 0) 2794361b034SIan Munsie return; 2804361b034SIan Munsie 2814361b034SIan Munsie cxl_pci_disable_device(dev); 2824361b034SIan Munsie cxl_afu_put(afu); 2834361b034SIan Munsie } 284