1// SPDX-License-Identifier: GPL-2.0
2/*
3 *  Copyright IBM Corp. 2012
4 *
5 *  Author(s):
6 *    Jan Glauber <jang@linux.vnet.ibm.com>
7 */
8
9#define KMSG_COMPONENT "zpci"
10#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
11
12#include <linux/kernel.h>
13#include <linux/pci.h>
14#include <asm/pci_debug.h>
15#include <asm/sclp.h>
16
17#include "pci_bus.h"
18
19/* Content Code Description for PCI Function Error */
20struct zpci_ccdf_err {
21	u32 reserved1;
22	u32 fh;				/* function handle */
23	u32 fid;			/* function id */
24	u32 ett		:  4;		/* expected table type */
25	u32 mvn		: 12;		/* MSI vector number */
26	u32 dmaas	:  8;		/* DMA address space */
27	u32		:  6;
28	u32 q		:  1;		/* event qualifier */
29	u32 rw		:  1;		/* read/write */
30	u64 faddr;			/* failing address */
31	u32 reserved3;
32	u16 reserved4;
33	u16 pec;			/* PCI event code */
34} __packed;
35
36/* Content Code Description for PCI Function Availability */
37struct zpci_ccdf_avail {
38	u32 reserved1;
39	u32 fh;				/* function handle */
40	u32 fid;			/* function id */
41	u32 reserved2;
42	u32 reserved3;
43	u32 reserved4;
44	u32 reserved5;
45	u16 reserved6;
46	u16 pec;			/* PCI event code */
47} __packed;
48
49static void __zpci_event_error(struct zpci_ccdf_err *ccdf)
50{
51	struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
52	struct pci_dev *pdev = NULL;
53
54	zpci_err("error CCDF:\n");
55	zpci_err_hex(ccdf, sizeof(*ccdf));
56
57	if (zdev)
58		pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn);
59
60	pr_err("%s: Event 0x%x reports an error for PCI function 0x%x\n",
61	       pdev ? pci_name(pdev) : "n/a", ccdf->pec, ccdf->fid);
62
63	if (!pdev)
64		goto no_pdev;
65
66	pdev->error_state = pci_channel_io_perm_failure;
67	pci_dev_put(pdev);
68no_pdev:
69	zpci_zdev_put(zdev);
70}
71
72void zpci_event_error(void *data)
73{
74	if (zpci_is_enabled())
75		__zpci_event_error(data);
76}
77
78static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
79{
80	struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
81	bool existing_zdev = !!zdev;
82	enum zpci_state state;
83	struct pci_dev *pdev;
84	int ret;
85
86	zpci_err("avail CCDF:\n");
87	zpci_err_hex(ccdf, sizeof(*ccdf));
88
89	switch (ccdf->pec) {
90	case 0x0301: /* Reserved|Standby -> Configured */
91		if (!zdev) {
92			zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_CONFIGURED);
93			break;
94		}
95		/* the configuration request may be stale */
96		if (zdev->state != ZPCI_FN_STATE_STANDBY)
97			break;
98		zdev->fh = ccdf->fh;
99		zdev->state = ZPCI_FN_STATE_CONFIGURED;
100		ret = zpci_enable_device(zdev);
101		if (ret)
102			break;
103
104		/* the PCI function will be scanned once function 0 appears */
105		if (!zdev->zbus->bus)
106			break;
107
108		pdev = pci_scan_single_device(zdev->zbus->bus, zdev->devfn);
109		if (!pdev)
110			break;
111
112		pci_bus_add_device(pdev);
113		pci_lock_rescan_remove();
114		pci_bus_add_devices(zdev->zbus->bus);
115		pci_unlock_rescan_remove();
116		break;
117	case 0x0302: /* Reserved -> Standby */
118		if (!zdev) {
119			zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_STANDBY);
120			break;
121		}
122		zdev->fh = ccdf->fh;
123		break;
124	case 0x0303: /* Deconfiguration requested */
125		if (!zdev)
126			break;
127		zpci_remove_device(zdev, false);
128
129		ret = zpci_disable_device(zdev);
130		if (ret)
131			break;
132
133		ret = sclp_pci_deconfigure(zdev->fid);
134		zpci_dbg(3, "deconf fid:%x, rc:%d\n", zdev->fid, ret);
135		if (!ret)
136			zdev->state = ZPCI_FN_STATE_STANDBY;
137
138		break;
139	case 0x0304: /* Configured -> Standby|Reserved */
140		if (!zdev)
141			break;
142		/* Give the driver a hint that the function is
143		 * already unusable.
144		 */
145		zpci_remove_device(zdev, true);
146
147		zdev->fh = ccdf->fh;
148		zpci_disable_device(zdev);
149		zdev->state = ZPCI_FN_STATE_STANDBY;
150		if (!clp_get_state(ccdf->fid, &state) &&
151		    state == ZPCI_FN_STATE_RESERVED) {
152			zpci_device_reserved(zdev);
153		}
154		break;
155	case 0x0306: /* 0x308 or 0x302 for multiple devices */
156		zpci_remove_reserved_devices();
157		clp_scan_pci_devices();
158		break;
159	case 0x0308: /* Standby -> Reserved */
160		if (!zdev)
161			break;
162		zpci_device_reserved(zdev);
163		break;
164	default:
165		break;
166	}
167	if (existing_zdev)
168		zpci_zdev_put(zdev);
169}
170
171void zpci_event_availability(void *data)
172{
173	if (zpci_is_enabled())
174		__zpci_event_availability(data);
175}
176