1/*
2 *  Copyright IBM Corp. 2012
3 *
4 *  Author(s):
5 *    Jan Glauber <jang@linux.vnet.ibm.com>
6 */
7
8#define KMSG_COMPONENT "zpci"
9#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
10
11#include <linux/kernel.h>
12#include <linux/pci.h>
13#include <asm/pci_debug.h>
14#include <asm/sclp.h>
15
16/* Content Code Description for PCI Function Error */
17struct zpci_ccdf_err {
18	u32 reserved1;
19	u32 fh;				/* function handle */
20	u32 fid;			/* function id */
21	u32 ett		:  4;		/* expected table type */
22	u32 mvn		: 12;		/* MSI vector number */
23	u32 dmaas	:  8;		/* DMA address space */
24	u32		:  6;
25	u32 q		:  1;		/* event qualifier */
26	u32 rw		:  1;		/* read/write */
27	u64 faddr;			/* failing address */
28	u32 reserved3;
29	u16 reserved4;
30	u16 pec;			/* PCI event code */
31} __packed;
32
33/* Content Code Description for PCI Function Availability */
34struct zpci_ccdf_avail {
35	u32 reserved1;
36	u32 fh;				/* function handle */
37	u32 fid;			/* function id */
38	u32 reserved2;
39	u32 reserved3;
40	u32 reserved4;
41	u32 reserved5;
42	u16 reserved6;
43	u16 pec;			/* PCI event code */
44} __packed;
45
46static void __zpci_event_error(struct zpci_ccdf_err *ccdf)
47{
48	struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
49
50	zpci_err("error CCDF:\n");
51	zpci_err_hex(ccdf, sizeof(*ccdf));
52
53	if (!zdev)
54		return;
55
56	pr_err("%s: Event 0x%x reports an error for PCI function 0x%x\n",
57	       pci_name(zdev->pdev), ccdf->pec, ccdf->fid);
58}
59
60void zpci_event_error(void *data)
61{
62	if (zpci_is_enabled())
63		__zpci_event_error(data);
64}
65
66static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
67{
68	struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
69	struct pci_dev *pdev = zdev ? zdev->pdev : NULL;
70	int ret;
71
72	pr_info("%s: Event 0x%x reconfigured PCI function 0x%x\n",
73		pdev ? pci_name(pdev) : "n/a", ccdf->pec, ccdf->fid);
74	zpci_err("avail CCDF:\n");
75	zpci_err_hex(ccdf, sizeof(*ccdf));
76
77	switch (ccdf->pec) {
78	case 0x0301: /* Standby -> Configured */
79		if (!zdev || zdev->state != ZPCI_FN_STATE_STANDBY)
80			break;
81		zdev->state = ZPCI_FN_STATE_CONFIGURED;
82		zdev->fh = ccdf->fh;
83		ret = zpci_enable_device(zdev);
84		if (ret)
85			break;
86		pci_rescan_bus(zdev->bus);
87		break;
88	case 0x0302: /* Reserved -> Standby */
89		if (!zdev)
90			clp_add_pci_device(ccdf->fid, ccdf->fh, 0);
91		break;
92	case 0x0303: /* Deconfiguration requested */
93		if (pdev)
94			pci_stop_and_remove_bus_device(pdev);
95
96		ret = zpci_disable_device(zdev);
97		if (ret)
98			break;
99
100		ret = sclp_pci_deconfigure(zdev->fid);
101		zpci_dbg(3, "deconf fid:%x, rc:%d\n", zdev->fid, ret);
102		if (!ret)
103			zdev->state = ZPCI_FN_STATE_STANDBY;
104
105		break;
106	case 0x0304: /* Configured -> Standby */
107		if (pdev) {
108			/* Give the driver a hint that the function is
109			 * already unusable. */
110			pdev->error_state = pci_channel_io_perm_failure;
111			pci_stop_and_remove_bus_device(pdev);
112		}
113
114		zdev->fh = ccdf->fh;
115		zpci_disable_device(zdev);
116		zdev->state = ZPCI_FN_STATE_STANDBY;
117		break;
118	case 0x0306: /* 0x308 or 0x302 for multiple devices */
119		clp_rescan_pci_devices();
120		break;
121	case 0x0308: /* Standby -> Reserved */
122		if (!zdev)
123			break;
124		pci_stop_root_bus(zdev->bus);
125		pci_remove_root_bus(zdev->bus);
126		break;
127	default:
128		break;
129	}
130}
131
132void zpci_event_availability(void *data)
133{
134	if (zpci_is_enabled())
135		__zpci_event_availability(data);
136}
137