arch/s390/pci/pci_insn.c

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

File Facts

System
Linux kernel
Corpus path
arch/s390/pci/pci_insn.c
Extension
.c
Size
10448 bytes
Lines
454
Domain
Architecture Layer
Bucket
arch/s390
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration 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

struct zpci_err_insn_data {
	u8 insn;
	u8 cc;
	u8 status;
	union {
		struct {
			u64 req;
			u64 offset;
		};
		struct {
			u64 addr;
			u64 len;
		};
	};
} __packed;

static inline void zpci_err_insn_req(int lvl, u8 insn, u8 cc, u8 status,
				     u64 req, u64 offset)
{
	struct zpci_err_insn_data data = {
		.insn = insn, .cc = cc, .status = status,
		.req = req, .offset = offset};

	zpci_err_hex_level(lvl, &data, sizeof(data));
}

static inline void zpci_err_insn_addr(int lvl, u8 insn, u8 cc, u8 status,
				      u64 addr, u64 len)
{
	struct zpci_err_insn_data data = {
		.insn = insn, .cc = cc, .status = status,
		.addr = addr, .len = len};

	zpci_err_hex_level(lvl, &data, sizeof(data));
}

/* Modify PCI Function Controls */
static inline u8 __mpcifc(u64 req, struct zpci_fib *fib, u8 *status)
{
	int cc;

	asm volatile (
		"	.insn	rxy,0xe300000000d0,%[req],%[fib]\n"
		CC_IPM(cc)
		: CC_OUT(cc, cc), [req] "+d" (req), [fib] "+Q" (*fib)
		:
		: CC_CLOBBER);
	*status = req >> 24 & 0xff;
	return CC_TRANSFORM(cc);
}

u8 zpci_mod_fc(u64 req, struct zpci_fib *fib, u8 *status)
{
	bool retried = false;
	u8 cc;

	do {
		cc = __mpcifc(req, fib, status);
		if (cc == 2) {
			msleep(ZPCI_INSN_BUSY_DELAY);
			if (!retried) {
				zpci_err_insn_req(1, 'M', cc, *status, req, 0);
				retried = true;
			}
		}
	} while (cc == 2);

	if (cc)
		zpci_err_insn_req(0, 'M', cc, *status, req, 0);
	else if (retried)
		zpci_err_insn_req(1, 'M', cc, *status, req, 0);

	return cc;
}
EXPORT_SYMBOL_GPL(zpci_mod_fc);

/* Refresh PCI Translations */
static inline u8 __rpcit(u64 fn, u64 addr, u64 range, u8 *status)
{
	union register_pair addr_range = {.even = addr, .odd = range};
	int cc;

	asm volatile (
		"	.insn	rre,0xb9d30000,%[fn],%[addr_range]\n"
		CC_IPM(cc)
		: CC_OUT(cc, cc), [fn] "+d" (fn)
		: [addr_range] "d" (addr_range.pair)
		: CC_CLOBBER);
	*status = fn >> 24 & 0xff;
	return CC_TRANSFORM(cc);

Annotation

Implementation Notes