arch/s390/pci/pci_sysfs.c

Source file repositories/reference/linux-study-clean/arch/s390/pci/pci_sysfs.c

File Facts

System
Linux kernel
Corpus path
arch/s390/pci/pci_sysfs.c
Extension
.c
Size
7228 bytes
Lines
280
Domain
Architecture Layer
Bucket
arch/s390
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright IBM Corp. 2012
 *
 * Author(s):
 *   Jan Glauber <jang@linux.vnet.ibm.com>
 */

#define pr_fmt(fmt) "zpci: " fmt

#include <linux/kernel.h>
#include <linux/stat.h>
#include <linux/pci.h>

#include "../../../drivers/pci/pci.h"

#include <asm/sclp.h>

#define zpci_attr(name, fmt, member)					\
static ssize_t name##_show(struct device *dev,				\
			   struct device_attribute *attr, char *buf)	\
{									\
	struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));		\
									\
	return sysfs_emit(buf, fmt, zdev->member);				\
}									\
static DEVICE_ATTR_RO(name)

zpci_attr(function_id, "0x%08x\n", fid);
zpci_attr(function_handle, "0x%08x\n", fh);
zpci_attr(pchid, "0x%04x\n", pchid);
zpci_attr(pfgid, "0x%02x\n", pfgid);
zpci_attr(vfn, "0x%04x\n", vfn);
zpci_attr(pft, "0x%02x\n", pft);
zpci_attr(port, "%d\n", port);
zpci_attr(fidparm, "0x%02x\n", fidparm);
zpci_attr(uid, "0x%x\n", uid);
zpci_attr(segment0, "0x%02x\n", pfip[0]);
zpci_attr(segment1, "0x%02x\n", pfip[1]);
zpci_attr(segment2, "0x%02x\n", pfip[2]);
zpci_attr(segment3, "0x%02x\n", pfip[3]);

#define ZPCI_FW_ATTR_RO(_name)						\
	static struct kobj_attribute _name##_attr = __ATTR_RO(_name)

static ssize_t mio_enabled_show(struct device *dev,
				struct device_attribute *attr, char *buf)
{
	struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));

	return sysfs_emit(buf, zpci_use_mio(zdev) ? "1\n" : "0\n");
}
static DEVICE_ATTR_RO(mio_enabled);

static int _do_recover(struct pci_dev *pdev, struct zpci_dev *zdev)
{
	int ret;

	pci_stop_and_remove_bus_device(pdev);
	if (zdev_enabled(zdev)) {
		ret = zpci_disable_device(zdev);
		/*
		 * Due to a z/VM vs LPAR inconsistency in the error
		 * state the FH may indicate an enabled device but
		 * disable says the device is already disabled don't
		 * treat it as an error here.
		 */
		if (ret == -EINVAL)
			ret = 0;
		if (ret)
			return ret;
	}

	ret = zpci_reenable_device(zdev);

	return ret;
}

static ssize_t recover_store(struct device *dev, struct device_attribute *attr,
			     const char *buf, size_t count)
{
	struct kernfs_node *kn;
	struct pci_dev *pdev = to_pci_dev(dev);
	struct zpci_dev *zdev = to_zpci(pdev);
	int ret = 0;

	/* Can't use device_remove_self() here as that would lead us to lock
	 * the pci_rescan_remove_lock while holding the device' kernfs lock.
	 * This would create a possible deadlock with disable_slot() which is
	 * not directly protected by the device' kernfs lock but takes it

Annotation

Implementation Notes