1
2
3
4
5
6
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
20struct zpci_ccdf_err {
21 u32 reserved1;
22 u32 fh;
23 u32 fid;
24 u32 ett : 4;
25 u32 mvn : 12;
26 u32 dmaas : 8;
27 u32 : 6;
28 u32 q : 1;
29 u32 rw : 1;
30 u64 faddr;
31 u32 reserved3;
32 u16 reserved4;
33 u16 pec;
34} __packed;
35
36
37struct zpci_ccdf_avail {
38 u32 reserved1;
39 u32 fh;
40 u32 fid;
41 u32 reserved2;
42 u32 reserved3;
43 u32 reserved4;
44 u32 reserved5;
45 u16 reserved6;
46 u16 pec;
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 return;
65
66 pdev->error_state = pci_channel_io_perm_failure;
67 pci_dev_put(pdev);
68}
69
70void zpci_event_error(void *data)
71{
72 if (zpci_is_enabled())
73 __zpci_event_error(data);
74}
75
76static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
77{
78 struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
79 struct pci_dev *pdev = NULL;
80 enum zpci_state state;
81 int ret;
82
83 if (zdev && zdev->zbus && zdev->zbus->bus)
84 pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn);
85
86 zpci_err("avail CCDF:\n");
87 zpci_err_hex(ccdf, sizeof(*ccdf));
88
89 switch (ccdf->pec) {
90 case 0x0301:
91 if (!zdev) {
92 ret = clp_add_pci_device(ccdf->fid, ccdf->fh, 1);
93 break;
94 }
95 zdev->fh = ccdf->fh;
96 zdev->state = ZPCI_FN_STATE_CONFIGURED;
97 ret = zpci_enable_device(zdev);
98 if (ret)
99 break;
100
101 pdev = pci_scan_single_device(zdev->zbus->bus, zdev->devfn);
102 if (!pdev)
103 break;
104
105 pci_bus_add_device(pdev);
106 pci_lock_rescan_remove();
107 pci_bus_add_devices(zdev->zbus->bus);
108 pci_unlock_rescan_remove();
109 break;
110 case 0x0302:
111 if (!zdev) {
112 clp_add_pci_device(ccdf->fid, ccdf->fh, 0);
113 break;
114 }
115 zdev->fh = ccdf->fh;
116 break;
117 case 0x0303:
118 if (!zdev)
119 break;
120 if (pdev)
121 pci_stop_and_remove_bus_device_locked(pdev);
122
123 ret = zpci_disable_device(zdev);
124 if (ret)
125 break;
126
127 ret = sclp_pci_deconfigure(zdev->fid);
128 zpci_dbg(3, "deconf fid:%x, rc:%d\n", zdev->fid, ret);
129 if (!ret)
130 zdev->state = ZPCI_FN_STATE_STANDBY;
131
132 break;
133 case 0x0304:
134 if (!zdev)
135 break;
136 if (pdev) {
137
138
139 pdev->error_state = pci_channel_io_perm_failure;
140 pci_stop_and_remove_bus_device_locked(pdev);
141 }
142
143 zdev->state = ZPCI_FN_STATE_STANDBY;
144 if (!clp_get_state(ccdf->fid, &state) &&
145 state == ZPCI_FN_STATE_RESERVED) {
146 zpci_zdev_put(zdev);
147 }
148 break;
149 case 0x0306:
150 clp_rescan_pci_devices();
151 break;
152 case 0x0308:
153 if (!zdev)
154 break;
155 zpci_zdev_put(zdev);
156 break;
157 default:
158 break;
159 }
160}
161
162void zpci_event_availability(void *data)
163{
164 if (zpci_is_enabled())
165 __zpci_event_availability(data);
166}
167