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