xref: /openbmc/linux/arch/s390/pci/pci_clp.c (revision 0d456bad)
1 /*
2  * Copyright IBM Corp. 2012
3  *
4  * Author(s):
5  *   Jan Glauber <jang@linux.vnet.ibm.com>
6  */
7 
8 #define COMPONENT "zPCI"
9 #define pr_fmt(fmt) COMPONENT ": " fmt
10 
11 #include <linux/kernel.h>
12 #include <linux/slab.h>
13 #include <linux/err.h>
14 #include <linux/delay.h>
15 #include <linux/pci.h>
16 #include <asm/pci_clp.h>
17 
18 /*
19  * Call Logical Processor
20  * Retry logic is handled by the caller.
21  */
22 static inline u8 clp_instr(void *req)
23 {
24 	u64 ilpm;
25 	u8 cc;
26 
27 	asm volatile (
28 		"	.insn	rrf,0xb9a00000,%[ilpm],%[req],0x0,0x2\n"
29 		"	ipm	%[cc]\n"
30 		"	srl	%[cc],28\n"
31 		: [cc] "=d" (cc), [ilpm] "=d" (ilpm)
32 		: [req] "a" (req)
33 		: "cc", "memory");
34 	return cc;
35 }
36 
37 static void *clp_alloc_block(void)
38 {
39 	struct page *page = alloc_pages(GFP_KERNEL, get_order(CLP_BLK_SIZE));
40 	return (page) ? page_address(page) : NULL;
41 }
42 
43 static void clp_free_block(void *ptr)
44 {
45 	free_pages((unsigned long) ptr, get_order(CLP_BLK_SIZE));
46 }
47 
48 static void clp_store_query_pci_fngrp(struct zpci_dev *zdev,
49 				      struct clp_rsp_query_pci_grp *response)
50 {
51 	zdev->tlb_refresh = response->refresh;
52 	zdev->dma_mask = response->dasm;
53 	zdev->msi_addr = response->msia;
54 	zdev->fmb_update = response->mui;
55 
56 	pr_debug("Supported number of MSI vectors: %u\n", response->noi);
57 	switch (response->version) {
58 	case 1:
59 		zdev->max_bus_speed = PCIE_SPEED_5_0GT;
60 		break;
61 	default:
62 		zdev->max_bus_speed = PCI_SPEED_UNKNOWN;
63 		break;
64 	}
65 }
66 
67 static int clp_query_pci_fngrp(struct zpci_dev *zdev, u8 pfgid)
68 {
69 	struct clp_req_rsp_query_pci_grp *rrb;
70 	int rc;
71 
72 	rrb = clp_alloc_block();
73 	if (!rrb)
74 		return -ENOMEM;
75 
76 	memset(rrb, 0, sizeof(*rrb));
77 	rrb->request.hdr.len = sizeof(rrb->request);
78 	rrb->request.hdr.cmd = CLP_QUERY_PCI_FNGRP;
79 	rrb->response.hdr.len = sizeof(rrb->response);
80 	rrb->request.pfgid = pfgid;
81 
82 	rc = clp_instr(rrb);
83 	if (!rc && rrb->response.hdr.rsp == CLP_RC_OK)
84 		clp_store_query_pci_fngrp(zdev, &rrb->response);
85 	else {
86 		pr_err("Query PCI FNGRP failed with response: %x  cc: %d\n",
87 			rrb->response.hdr.rsp, rc);
88 		rc = -EIO;
89 	}
90 	clp_free_block(rrb);
91 	return rc;
92 }
93 
94 static int clp_store_query_pci_fn(struct zpci_dev *zdev,
95 				  struct clp_rsp_query_pci *response)
96 {
97 	int i;
98 
99 	for (i = 0; i < PCI_BAR_COUNT; i++) {
100 		zdev->bars[i].val = le32_to_cpu(response->bar[i]);
101 		zdev->bars[i].size = response->bar_size[i];
102 	}
103 	zdev->start_dma = response->sdma;
104 	zdev->end_dma = response->edma;
105 	zdev->pchid = response->pchid;
106 	zdev->pfgid = response->pfgid;
107 	return 0;
108 }
109 
110 static int clp_query_pci_fn(struct zpci_dev *zdev, u32 fh)
111 {
112 	struct clp_req_rsp_query_pci *rrb;
113 	int rc;
114 
115 	rrb = clp_alloc_block();
116 	if (!rrb)
117 		return -ENOMEM;
118 
119 	memset(rrb, 0, sizeof(*rrb));
120 	rrb->request.hdr.len = sizeof(rrb->request);
121 	rrb->request.hdr.cmd = CLP_QUERY_PCI_FN;
122 	rrb->response.hdr.len = sizeof(rrb->response);
123 	rrb->request.fh = fh;
124 
125 	rc = clp_instr(rrb);
126 	if (!rc && rrb->response.hdr.rsp == CLP_RC_OK) {
127 		rc = clp_store_query_pci_fn(zdev, &rrb->response);
128 		if (rc)
129 			goto out;
130 		if (rrb->response.pfgid)
131 			rc = clp_query_pci_fngrp(zdev, rrb->response.pfgid);
132 	} else {
133 		pr_err("Query PCI failed with response: %x  cc: %d\n",
134 			 rrb->response.hdr.rsp, rc);
135 		rc = -EIO;
136 	}
137 out:
138 	clp_free_block(rrb);
139 	return rc;
140 }
141 
142 int clp_add_pci_device(u32 fid, u32 fh, int configured)
143 {
144 	struct zpci_dev *zdev;
145 	int rc;
146 
147 	zdev = zpci_alloc_device();
148 	if (IS_ERR(zdev))
149 		return PTR_ERR(zdev);
150 
151 	zdev->fh = fh;
152 	zdev->fid = fid;
153 
154 	/* Query function properties and update zdev */
155 	rc = clp_query_pci_fn(zdev, fh);
156 	if (rc)
157 		goto error;
158 
159 	if (configured)
160 		zdev->state = ZPCI_FN_STATE_CONFIGURED;
161 	else
162 		zdev->state = ZPCI_FN_STATE_STANDBY;
163 
164 	rc = zpci_create_device(zdev);
165 	if (rc)
166 		goto error;
167 	return 0;
168 
169 error:
170 	zpci_free_device(zdev);
171 	return rc;
172 }
173 
174 /*
175  * Enable/Disable a given PCI function defined by its function handle.
176  */
177 static int clp_set_pci_fn(u32 *fh, u8 nr_dma_as, u8 command)
178 {
179 	struct clp_req_rsp_set_pci *rrb;
180 	int rc, retries = 1000;
181 
182 	rrb = clp_alloc_block();
183 	if (!rrb)
184 		return -ENOMEM;
185 
186 	do {
187 		memset(rrb, 0, sizeof(*rrb));
188 		rrb->request.hdr.len = sizeof(rrb->request);
189 		rrb->request.hdr.cmd = CLP_SET_PCI_FN;
190 		rrb->response.hdr.len = sizeof(rrb->response);
191 		rrb->request.fh = *fh;
192 		rrb->request.oc = command;
193 		rrb->request.ndas = nr_dma_as;
194 
195 		rc = clp_instr(rrb);
196 		if (rrb->response.hdr.rsp == CLP_RC_SETPCIFN_BUSY) {
197 			retries--;
198 			if (retries < 0)
199 				break;
200 			msleep(1);
201 		}
202 	} while (rrb->response.hdr.rsp == CLP_RC_SETPCIFN_BUSY);
203 
204 	if (!rc && rrb->response.hdr.rsp == CLP_RC_OK)
205 		*fh = rrb->response.fh;
206 	else {
207 		pr_err("Set PCI FN failed with response: %x  cc: %d\n",
208 			rrb->response.hdr.rsp, rc);
209 		rc = -EIO;
210 	}
211 	clp_free_block(rrb);
212 	return rc;
213 }
214 
215 int clp_enable_fh(struct zpci_dev *zdev, u8 nr_dma_as)
216 {
217 	u32 fh = zdev->fh;
218 	int rc;
219 
220 	rc = clp_set_pci_fn(&fh, nr_dma_as, CLP_SET_ENABLE_PCI_FN);
221 	if (!rc)
222 		/* Success -> store enabled handle in zdev */
223 		zdev->fh = fh;
224 	return rc;
225 }
226 
227 int clp_disable_fh(struct zpci_dev *zdev)
228 {
229 	u32 fh = zdev->fh;
230 	int rc;
231 
232 	if (!zdev_enabled(zdev))
233 		return 0;
234 
235 	dev_info(&zdev->pdev->dev, "disabling fn handle: 0x%x\n", fh);
236 	rc = clp_set_pci_fn(&fh, 0, CLP_SET_DISABLE_PCI_FN);
237 	if (!rc)
238 		/* Success -> store disabled handle in zdev */
239 		zdev->fh = fh;
240 	else
241 		dev_err(&zdev->pdev->dev,
242 			"Failed to disable fn handle: 0x%x\n", fh);
243 	return rc;
244 }
245 
246 static void clp_check_pcifn_entry(struct clp_fh_list_entry *entry)
247 {
248 	int present, rc;
249 
250 	if (!entry->vendor_id)
251 		return;
252 
253 	/* TODO: be a little bit more scalable */
254 	present = zpci_fid_present(entry->fid);
255 
256 	if (present)
257 		pr_debug("%s: device %x already present\n", __func__, entry->fid);
258 
259 	/* skip already used functions */
260 	if (present && entry->config_state)
261 		return;
262 
263 	/* aev 306: function moved to stand-by state */
264 	if (present && !entry->config_state) {
265 		/*
266 		 * The handle is already disabled, that means no iota/irq freeing via
267 		 * the firmware interfaces anymore. Need to free resources manually
268 		 * (DMA memory, debug, sysfs)...
269 		 */
270 		zpci_stop_device(get_zdev_by_fid(entry->fid));
271 		return;
272 	}
273 
274 	rc = clp_add_pci_device(entry->fid, entry->fh, entry->config_state);
275 	if (rc)
276 		pr_err("Failed to add fid: 0x%x\n", entry->fid);
277 }
278 
279 int clp_find_pci_devices(void)
280 {
281 	struct clp_req_rsp_list_pci *rrb;
282 	u64 resume_token = 0;
283 	int entries, i, rc;
284 
285 	rrb = clp_alloc_block();
286 	if (!rrb)
287 		return -ENOMEM;
288 
289 	do {
290 		memset(rrb, 0, sizeof(*rrb));
291 		rrb->request.hdr.len = sizeof(rrb->request);
292 		rrb->request.hdr.cmd = CLP_LIST_PCI;
293 		/* store as many entries as possible */
294 		rrb->response.hdr.len = CLP_BLK_SIZE - LIST_PCI_HDR_LEN;
295 		rrb->request.resume_token = resume_token;
296 
297 		/* Get PCI function handle list */
298 		rc = clp_instr(rrb);
299 		if (rc || rrb->response.hdr.rsp != CLP_RC_OK) {
300 			pr_err("List PCI failed with response: 0x%x  cc: %d\n",
301 				rrb->response.hdr.rsp, rc);
302 			rc = -EIO;
303 			goto out;
304 		}
305 
306 		WARN_ON_ONCE(rrb->response.entry_size !=
307 			sizeof(struct clp_fh_list_entry));
308 
309 		entries = (rrb->response.hdr.len - LIST_PCI_HDR_LEN) /
310 			rrb->response.entry_size;
311 		pr_info("Detected number of PCI functions: %u\n", entries);
312 
313 		/* Store the returned resume token as input for the next call */
314 		resume_token = rrb->response.resume_token;
315 
316 		for (i = 0; i < entries; i++)
317 			clp_check_pcifn_entry(&rrb->response.fh_list[i]);
318 	} while (resume_token);
319 
320 	pr_debug("Maximum number of supported PCI functions: %u\n",
321 		rrb->response.max_fn);
322 out:
323 	clp_free_block(rrb);
324 	return rc;
325 }
326