mirror of
https://github.com/torvalds/linux.git
synced 2026-01-25 15:03:52 +08:00
Merge branch 'pci/pci-sysfs'
- Move reset related sysfs code from pci.c to pci-sysfs.c where other similar code lives (Ilpo Järvinen) - Simplify reset_method_store() memory management by using __free() instead of explicit kfree() cleanup (Ilpo Järvinen) - Drop unnecessary zero initializer (Ilpo Järvinen) * pci/pci-sysfs: PCI/sysfs: Remove unnecessary zero in initializer PCI/sysfs: Use __free() in reset_method_store() PCI/sysfs: Move reset related sysfs code to correct file
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/pci.h>
|
||||
@@ -1421,6 +1422,113 @@ static const struct attribute_group pci_dev_reset_attr_group = {
|
||||
.is_visible = pci_dev_reset_attr_is_visible,
|
||||
};
|
||||
|
||||
static ssize_t reset_method_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
ssize_t len = 0;
|
||||
int i, m;
|
||||
|
||||
for (i = 0; i < PCI_NUM_RESET_METHODS; i++) {
|
||||
m = pdev->reset_methods[i];
|
||||
if (!m)
|
||||
break;
|
||||
|
||||
len += sysfs_emit_at(buf, len, "%s%s", len ? " " : "",
|
||||
pci_reset_fn_methods[m].name);
|
||||
}
|
||||
|
||||
if (len)
|
||||
len += sysfs_emit_at(buf, len, "\n");
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int reset_method_lookup(const char *name)
|
||||
{
|
||||
int m;
|
||||
|
||||
for (m = 1; m < PCI_NUM_RESET_METHODS; m++) {
|
||||
if (sysfs_streq(name, pci_reset_fn_methods[m].name))
|
||||
return m;
|
||||
}
|
||||
|
||||
return 0; /* not found */
|
||||
}
|
||||
|
||||
static ssize_t reset_method_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
char *tmp_options, *name;
|
||||
int m, n;
|
||||
u8 reset_methods[PCI_NUM_RESET_METHODS] = {};
|
||||
|
||||
if (sysfs_streq(buf, "")) {
|
||||
pdev->reset_methods[0] = 0;
|
||||
pci_warn(pdev, "All device reset methods disabled by user");
|
||||
return count;
|
||||
}
|
||||
|
||||
if (sysfs_streq(buf, "default")) {
|
||||
pci_init_reset_methods(pdev);
|
||||
return count;
|
||||
}
|
||||
|
||||
char *options __free(kfree) = kstrndup(buf, count, GFP_KERNEL);
|
||||
if (!options)
|
||||
return -ENOMEM;
|
||||
|
||||
n = 0;
|
||||
tmp_options = options;
|
||||
while ((name = strsep(&tmp_options, " ")) != NULL) {
|
||||
if (sysfs_streq(name, ""))
|
||||
continue;
|
||||
|
||||
name = strim(name);
|
||||
|
||||
/* Leave previous methods unchanged if input is invalid */
|
||||
m = reset_method_lookup(name);
|
||||
if (!m) {
|
||||
pci_err(pdev, "Invalid reset method '%s'", name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (pci_reset_fn_methods[m].reset_fn(pdev, PCI_RESET_PROBE)) {
|
||||
pci_err(pdev, "Unsupported reset method '%s'", name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (n == PCI_NUM_RESET_METHODS - 1) {
|
||||
pci_err(pdev, "Too many reset methods\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
reset_methods[n++] = m;
|
||||
}
|
||||
|
||||
reset_methods[n] = 0;
|
||||
|
||||
/* Warn if dev-specific supported but not highest priority */
|
||||
if (pci_reset_fn_methods[1].reset_fn(pdev, PCI_RESET_PROBE) == 0 &&
|
||||
reset_methods[0] != 1)
|
||||
pci_warn(pdev, "Device-specific reset disabled/de-prioritized by user");
|
||||
memcpy(pdev->reset_methods, reset_methods, sizeof(pdev->reset_methods));
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(reset_method);
|
||||
|
||||
static struct attribute *pci_dev_reset_method_attrs[] = {
|
||||
&dev_attr_reset_method.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group pci_dev_reset_method_attr_group = {
|
||||
.attrs = pci_dev_reset_method_attrs,
|
||||
.is_visible = pci_dev_reset_attr_is_visible,
|
||||
};
|
||||
|
||||
static ssize_t __resource_resize_show(struct device *dev, int n, char *buf)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
|
||||
@@ -5163,7 +5163,7 @@ static void pci_dev_restore(struct pci_dev *dev)
|
||||
}
|
||||
|
||||
/* dev->reset_methods[] is a 0-terminated list of indices into this array */
|
||||
static const struct pci_reset_fn_method pci_reset_fn_methods[] = {
|
||||
const struct pci_reset_fn_method pci_reset_fn_methods[] = {
|
||||
{ },
|
||||
{ pci_dev_specific_reset, .name = "device_specific" },
|
||||
{ pci_dev_acpi_reset, .name = "acpi" },
|
||||
@@ -5174,129 +5174,6 @@ static const struct pci_reset_fn_method pci_reset_fn_methods[] = {
|
||||
{ cxl_reset_bus_function, .name = "cxl_bus" },
|
||||
};
|
||||
|
||||
static ssize_t reset_method_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
ssize_t len = 0;
|
||||
int i, m;
|
||||
|
||||
for (i = 0; i < PCI_NUM_RESET_METHODS; i++) {
|
||||
m = pdev->reset_methods[i];
|
||||
if (!m)
|
||||
break;
|
||||
|
||||
len += sysfs_emit_at(buf, len, "%s%s", len ? " " : "",
|
||||
pci_reset_fn_methods[m].name);
|
||||
}
|
||||
|
||||
if (len)
|
||||
len += sysfs_emit_at(buf, len, "\n");
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int reset_method_lookup(const char *name)
|
||||
{
|
||||
int m;
|
||||
|
||||
for (m = 1; m < PCI_NUM_RESET_METHODS; m++) {
|
||||
if (sysfs_streq(name, pci_reset_fn_methods[m].name))
|
||||
return m;
|
||||
}
|
||||
|
||||
return 0; /* not found */
|
||||
}
|
||||
|
||||
static ssize_t reset_method_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
char *options, *tmp_options, *name;
|
||||
int m, n;
|
||||
u8 reset_methods[PCI_NUM_RESET_METHODS] = { 0 };
|
||||
|
||||
if (sysfs_streq(buf, "")) {
|
||||
pdev->reset_methods[0] = 0;
|
||||
pci_warn(pdev, "All device reset methods disabled by user");
|
||||
return count;
|
||||
}
|
||||
|
||||
if (sysfs_streq(buf, "default")) {
|
||||
pci_init_reset_methods(pdev);
|
||||
return count;
|
||||
}
|
||||
|
||||
options = kstrndup(buf, count, GFP_KERNEL);
|
||||
if (!options)
|
||||
return -ENOMEM;
|
||||
|
||||
n = 0;
|
||||
tmp_options = options;
|
||||
while ((name = strsep(&tmp_options, " ")) != NULL) {
|
||||
if (sysfs_streq(name, ""))
|
||||
continue;
|
||||
|
||||
name = strim(name);
|
||||
|
||||
m = reset_method_lookup(name);
|
||||
if (!m) {
|
||||
pci_err(pdev, "Invalid reset method '%s'", name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (pci_reset_fn_methods[m].reset_fn(pdev, PCI_RESET_PROBE)) {
|
||||
pci_err(pdev, "Unsupported reset method '%s'", name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (n == PCI_NUM_RESET_METHODS - 1) {
|
||||
pci_err(pdev, "Too many reset methods\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
reset_methods[n++] = m;
|
||||
}
|
||||
|
||||
reset_methods[n] = 0;
|
||||
|
||||
/* Warn if dev-specific supported but not highest priority */
|
||||
if (pci_reset_fn_methods[1].reset_fn(pdev, PCI_RESET_PROBE) == 0 &&
|
||||
reset_methods[0] != 1)
|
||||
pci_warn(pdev, "Device-specific reset disabled/de-prioritized by user");
|
||||
memcpy(pdev->reset_methods, reset_methods, sizeof(pdev->reset_methods));
|
||||
kfree(options);
|
||||
return count;
|
||||
|
||||
error:
|
||||
/* Leave previous methods unchanged */
|
||||
kfree(options);
|
||||
return -EINVAL;
|
||||
}
|
||||
static DEVICE_ATTR_RW(reset_method);
|
||||
|
||||
static struct attribute *pci_dev_reset_method_attrs[] = {
|
||||
&dev_attr_reset_method.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static umode_t pci_dev_reset_method_attr_is_visible(struct kobject *kobj,
|
||||
struct attribute *a, int n)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
|
||||
|
||||
if (!pci_reset_supported(pdev))
|
||||
return 0;
|
||||
|
||||
return a->mode;
|
||||
}
|
||||
|
||||
const struct attribute_group pci_dev_reset_method_attr_group = {
|
||||
.attrs = pci_dev_reset_method_attrs,
|
||||
.is_visible = pci_dev_reset_method_attr_is_visible,
|
||||
};
|
||||
|
||||
/**
|
||||
* __pci_reset_function_locked - reset a PCI device function while holding
|
||||
* the @dev mutex lock.
|
||||
|
||||
@@ -777,6 +777,7 @@ struct pci_reset_fn_method {
|
||||
int (*reset_fn)(struct pci_dev *pdev, bool probe);
|
||||
char *name;
|
||||
};
|
||||
extern const struct pci_reset_fn_method pci_reset_fn_methods[];
|
||||
|
||||
#ifdef CONFIG_PCI_QUIRKS
|
||||
int pci_dev_specific_reset(struct pci_dev *dev, bool probe);
|
||||
@@ -964,8 +965,6 @@ static inline pci_power_t acpi_pci_choose_state(struct pci_dev *pdev)
|
||||
extern const struct attribute_group aspm_ctrl_attr_group;
|
||||
#endif
|
||||
|
||||
extern const struct attribute_group pci_dev_reset_method_attr_group;
|
||||
|
||||
#ifdef CONFIG_X86_INTEL_MID
|
||||
bool pci_use_mid_pm(void);
|
||||
int mid_pci_set_power_state(struct pci_dev *pdev, pci_power_t state);
|
||||
|
||||
Reference in New Issue
Block a user