Linux Audio

Check our new training course

Linux BSP upgrade and security maintenance

Need help to get security updates for your Linux BSP?
Loading...
v5.4
  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/* Content Code Description for PCI Function Error */
 18struct zpci_ccdf_err {
 19	u32 reserved1;
 20	u32 fh;				/* function handle */
 21	u32 fid;			/* function id */
 22	u32 ett		:  4;		/* expected table type */
 23	u32 mvn		: 12;		/* MSI vector number */
 24	u32 dmaas	:  8;		/* DMA address space */
 25	u32		:  6;
 26	u32 q		:  1;		/* event qualifier */
 27	u32 rw		:  1;		/* read/write */
 28	u64 faddr;			/* failing address */
 29	u32 reserved3;
 30	u16 reserved4;
 31	u16 pec;			/* PCI event code */
 32} __packed;
 33
 34/* Content Code Description for PCI Function Availability */
 35struct zpci_ccdf_avail {
 36	u32 reserved1;
 37	u32 fh;				/* function handle */
 38	u32 fid;			/* function id */
 39	u32 reserved2;
 40	u32 reserved3;
 41	u32 reserved4;
 42	u32 reserved5;
 43	u16 reserved6;
 44	u16 pec;			/* PCI event code */
 45} __packed;
 46
 47static void __zpci_event_error(struct zpci_ccdf_err *ccdf)
 48{
 49	struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
 50	struct pci_dev *pdev = NULL;
 51
 52	zpci_err("error CCDF:\n");
 53	zpci_err_hex(ccdf, sizeof(*ccdf));
 54
 55	if (zdev)
 56		pdev = pci_get_slot(zdev->bus, ZPCI_DEVFN);
 57
 58	pr_err("%s: Event 0x%x reports an error for PCI function 0x%x\n",
 59	       pdev ? pci_name(pdev) : "n/a", ccdf->pec, ccdf->fid);
 60
 61	if (!pdev)
 62		return;
 63
 64	pdev->error_state = pci_channel_io_perm_failure;
 65	pci_dev_put(pdev);
 66}
 67
 68void zpci_event_error(void *data)
 69{
 70	if (zpci_is_enabled())
 71		__zpci_event_error(data);
 72}
 73
 74static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
 75{
 76	struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
 77	struct pci_dev *pdev = NULL;
 78	enum zpci_state state;
 79	int ret;
 80
 81	if (zdev)
 82		pdev = pci_get_slot(zdev->bus, ZPCI_DEVFN);
 83
 84	pr_info("%s: Event 0x%x reconfigured PCI function 0x%x\n",
 85		pdev ? pci_name(pdev) : "n/a", ccdf->pec, ccdf->fid);
 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			ret = clp_add_pci_device(ccdf->fid, ccdf->fh, 0);
 93			if (ret)
 94				break;
 95			zdev = get_zdev_by_fid(ccdf->fid);
 96		}
 97		if (!zdev || zdev->state != ZPCI_FN_STATE_STANDBY)
 
 98			break;
 99		zdev->state = ZPCI_FN_STATE_CONFIGURED;
100		zdev->fh = ccdf->fh;
 
101		ret = zpci_enable_device(zdev);
102		if (ret)
103			break;
 
 
 
 
 
 
104		pci_lock_rescan_remove();
105		pci_rescan_bus(zdev->bus);
106		pci_unlock_rescan_remove();
107		break;
108	case 0x0302: /* Reserved -> Standby */
109		if (!zdev)
110			clp_add_pci_device(ccdf->fid, ccdf->fh, 0);
 
 
 
111		break;
112	case 0x0303: /* Deconfiguration requested */
113		if (!zdev)
114			break;
115		if (pdev)
116			pci_stop_and_remove_bus_device_locked(pdev);
117
118		ret = zpci_disable_device(zdev);
119		if (ret)
120			break;
121
122		ret = sclp_pci_deconfigure(zdev->fid);
123		zpci_dbg(3, "deconf fid:%x, rc:%d\n", zdev->fid, ret);
124		if (!ret)
125			zdev->state = ZPCI_FN_STATE_STANDBY;
126
127		break;
128	case 0x0304: /* Configured -> Standby|Reserved */
129		if (!zdev)
130			break;
131		if (pdev) {
132			/* Give the driver a hint that the function is
133			 * already unusable. */
134			pdev->error_state = pci_channel_io_perm_failure;
135			pci_stop_and_remove_bus_device_locked(pdev);
136		}
137
138		zdev->fh = ccdf->fh;
139		zpci_disable_device(zdev);
140		zdev->state = ZPCI_FN_STATE_STANDBY;
141		if (!clp_get_state(ccdf->fid, &state) &&
142		    state == ZPCI_FN_STATE_RESERVED) {
143			zpci_remove_device(zdev);
144		}
145		break;
146	case 0x0306: /* 0x308 or 0x302 for multiple devices */
147		clp_rescan_pci_devices();
148		break;
149	case 0x0308: /* Standby -> Reserved */
150		if (!zdev)
151			break;
152		zpci_remove_device(zdev);
153		break;
154	default:
155		break;
156	}
157	pci_dev_put(pdev);
158}
159
160void zpci_event_availability(void *data)
161{
162	if (zpci_is_enabled())
163		__zpci_event_availability(data);
164}
v5.9
  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		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: /* Reserved|Standby -> Configured */
 91		if (!zdev) {
 92			ret = clp_add_pci_device(ccdf->fid, ccdf->fh, 1);
 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		pdev = pci_scan_single_device(zdev->zbus->bus, zdev->devfn);
105		if (!pdev)
106			break;
107
108		pci_bus_add_device(pdev);
109		pci_lock_rescan_remove();
110		pci_bus_add_devices(zdev->zbus->bus);
111		pci_unlock_rescan_remove();
112		break;
113	case 0x0302: /* Reserved -> Standby */
114		if (!zdev) {
115			clp_add_pci_device(ccdf->fid, ccdf->fh, 0);
116			break;
117		}
118		zdev->fh = ccdf->fh;
119		break;
120	case 0x0303: /* Deconfiguration requested */
121		if (!zdev)
122			break;
123		if (pdev)
124			zpci_remove_device(zdev);
125
126		ret = zpci_disable_device(zdev);
127		if (ret)
128			break;
129
130		ret = sclp_pci_deconfigure(zdev->fid);
131		zpci_dbg(3, "deconf fid:%x, rc:%d\n", zdev->fid, ret);
132		if (!ret)
133			zdev->state = ZPCI_FN_STATE_STANDBY;
134
135		break;
136	case 0x0304: /* Configured -> Standby|Reserved */
137		if (!zdev)
138			break;
139		if (pdev) {
140			/* Give the driver a hint that the function is
141			 * already unusable. */
142			pdev->error_state = pci_channel_io_perm_failure;
143			zpci_remove_device(zdev);
144		}
145
146		zdev->fh = ccdf->fh;
147		zpci_disable_device(zdev);
148		zdev->state = ZPCI_FN_STATE_STANDBY;
149		if (!clp_get_state(ccdf->fid, &state) &&
150		    state == ZPCI_FN_STATE_RESERVED) {
151			zpci_zdev_put(zdev);
152		}
153		break;
154	case 0x0306: /* 0x308 or 0x302 for multiple devices */
155		clp_rescan_pci_devices();
156		break;
157	case 0x0308: /* Standby -> Reserved */
158		if (!zdev)
159			break;
160		zpci_zdev_put(zdev);
161		break;
162	default:
163		break;
164	}
 
165}
166
167void zpci_event_availability(void *data)
168{
169	if (zpci_is_enabled())
170		__zpci_event_availability(data);
171}