Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Sysfs entries for PCI Error Recovery for PAPR-compliant platform.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Copyright IBM Corporation 2007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright Linas Vepstas <linas@austin.ibm.com> 2007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Send comments and feedback to Linas Vepstas <linas@austin.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <asm/ppc-pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <asm/pci-bridge.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  * EEH_SHOW_ATTR -- Create sysfs entry for eeh statistic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  * @_name: name of file in sysfs directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  * @_memb: name of member in struct eeh_dev to access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  * @_format: printf format for display
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * All of the attributes look very similar, so just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  * auto-gen a cut-n-paste routine to display them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #define EEH_SHOW_ATTR(_name,_memb,_format)               \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) static ssize_t eeh_show_##_name(struct device *dev,      \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 		struct device_attribute *attr, char *buf)          \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) {                                                        \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	struct pci_dev *pdev = to_pci_dev(dev);               \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	struct eeh_dev *edev = pci_dev_to_eeh_dev(pdev);      \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	                                                      \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	if (!edev)                                            \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 		return 0;                                     \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	                                                      \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	return sprintf(buf, _format "\n", edev->_memb);       \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) }                                                        \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) static DEVICE_ATTR(_name, 0444, eeh_show_##_name, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) EEH_SHOW_ATTR(eeh_mode,            mode,            "0x%x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) EEH_SHOW_ATTR(eeh_pe_config_addr,  pe_config_addr,  "0x%x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) static ssize_t eeh_pe_state_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 				 struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	struct pci_dev *pdev = to_pci_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	struct eeh_dev *edev = pci_dev_to_eeh_dev(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	int state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	if (!edev || !edev->pe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	state = eeh_ops->get_state(edev->pe, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	return sprintf(buf, "0x%08x 0x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 		       state, edev->pe->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) static ssize_t eeh_pe_state_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 				  struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 				  const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	struct pci_dev *pdev = to_pci_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	struct eeh_dev *edev = pci_dev_to_eeh_dev(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	if (!edev || !edev->pe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	/* Nothing to do if it's not frozen */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	if (!(edev->pe->state & EEH_PE_ISOLATED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	if (eeh_unfreeze_pe(edev->pe))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	eeh_pe_state_clear(edev->pe, EEH_PE_ISOLATED, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) static DEVICE_ATTR_RW(eeh_pe_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) #if defined(CONFIG_PCI_IOV) && defined(CONFIG_PPC_PSERIES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) static ssize_t eeh_notify_resume_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 				      struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	struct pci_dev *pdev = to_pci_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	struct eeh_dev *edev = pci_dev_to_eeh_dev(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	struct pci_dn *pdn = pci_get_pdn(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	if (!edev || !edev->pe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	return sprintf(buf, "%d\n", pdn->last_allow_rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) static ssize_t eeh_notify_resume_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 				       struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 				       const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	struct pci_dev *pdev = to_pci_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	struct eeh_dev *edev = pci_dev_to_eeh_dev(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	if (!edev || !edev->pe || !eeh_ops->notify_resume)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	if (eeh_ops->notify_resume(edev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static DEVICE_ATTR_RW(eeh_notify_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static int eeh_notify_resume_add(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	np = pci_device_to_OF_node(pdev->is_physfn ? pdev : pdev->physfn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	if (of_property_read_bool(np, "ibm,is-open-sriov-pf"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		rc = device_create_file(&pdev->dev, &dev_attr_eeh_notify_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static void eeh_notify_resume_remove(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	np = pci_device_to_OF_node(pdev->is_physfn ? pdev : pdev->physfn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	if (of_property_read_bool(np, "ibm,is-open-sriov-pf"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		device_remove_file(&pdev->dev, &dev_attr_eeh_notify_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static inline int eeh_notify_resume_add(struct pci_dev *pdev) { return 0; }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static inline void eeh_notify_resume_remove(struct pci_dev *pdev) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #endif /* CONFIG_PCI_IOV && CONFIG PPC_PSERIES*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) void eeh_sysfs_add_device(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	struct eeh_dev *edev = pci_dev_to_eeh_dev(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	int rc=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	if (!eeh_enabled())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	if (edev && (edev->mode & EEH_DEV_SYSFS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	rc += device_create_file(&pdev->dev, &dev_attr_eeh_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	rc += device_create_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	rc += device_create_file(&pdev->dev, &dev_attr_eeh_pe_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	rc += eeh_notify_resume_add(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		pr_warn("EEH: Unable to create sysfs entries\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	else if (edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		edev->mode |= EEH_DEV_SYSFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) void eeh_sysfs_remove_device(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	struct eeh_dev *edev = pci_dev_to_eeh_dev(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	if (!edev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		WARN_ON(eeh_enabled());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	edev->mode &= ~EEH_DEV_SYSFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	 * The parent directory might have been removed. We needn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	 * continue for that case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	if (!pdev->dev.kobj.sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	device_remove_file(&pdev->dev, &dev_attr_eeh_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	device_remove_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	device_remove_file(&pdev->dev, &dev_attr_eeh_pe_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	eeh_notify_resume_remove(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }