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
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright IBM Corp. 2012
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Author(s):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *   Jan Glauber <jang@linux.vnet.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #define KMSG_COMPONENT "zpci"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/compat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/miscdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <asm/pci_debug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <asm/pci_clp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <asm/clp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <uapi/asm/clp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) bool zpci_unique_uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) void update_uid_checking(bool new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	if (zpci_unique_uid != new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 		zpci_dbg(1, "uid checking:%d\n", new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	zpci_unique_uid = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) static inline void zpci_err_clp(unsigned int rsp, int rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 		unsigned int rsp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 		int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	} __packed data = {rsp, rc};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	zpci_err_hex(&data, sizeof(data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46)  * Call Logical Processor with c=1, lps=0 and command 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47)  * to get the bit mask of installed logical processors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) static inline int clp_get_ilp(unsigned long *ilp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	unsigned long mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	int cc = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	asm volatile (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 		"	.insn	rrf,0xb9a00000,%[mask],%[cmd],8,0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		"0:	ipm	%[cc]\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		"	srl	%[cc],28\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		"1:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 		EX_TABLE(0b, 1b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		: [cc] "+d" (cc), [mask] "=d" (mask) : [cmd] "a" (1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 		: "cc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	*ilp = mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	return cc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)  * Call Logical Processor with c=0, the give constant lps and an lpcb request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) static __always_inline int clp_req(void *data, unsigned int lps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	struct { u8 _[CLP_BLK_SIZE]; } *req = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	u64 ignored;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	int cc = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	asm volatile (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 		"	.insn	rrf,0xb9a00000,%[ign],%[req],0,%[lps]\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		"0:	ipm	%[cc]\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		"	srl	%[cc],28\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		"1:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		EX_TABLE(0b, 1b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		: [cc] "+d" (cc), [ign] "=d" (ignored), "+m" (*req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		: [req] "a" (req), [lps] "i" (lps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		: "cc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	return cc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) static void *clp_alloc_block(gfp_t gfp_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	return (void *) __get_free_pages(gfp_mask, get_order(CLP_BLK_SIZE));
^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 void clp_free_block(void *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	free_pages((unsigned long) ptr, get_order(CLP_BLK_SIZE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) static void clp_store_query_pci_fngrp(struct zpci_dev *zdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 				      struct clp_rsp_query_pci_grp *response)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	zdev->tlb_refresh = response->refresh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	zdev->dma_mask = response->dasm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	zdev->msi_addr = response->msia;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	zdev->max_msi = response->noi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	zdev->fmb_update = response->mui;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	zdev->version = response->version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	switch (response->version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		zdev->max_bus_speed = PCIE_SPEED_5_0GT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		zdev->max_bus_speed = PCI_SPEED_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static int clp_query_pci_fngrp(struct zpci_dev *zdev, u8 pfgid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	struct clp_req_rsp_query_pci_grp *rrb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	rrb = clp_alloc_block(GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	if (!rrb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	memset(rrb, 0, sizeof(*rrb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	rrb->request.hdr.len = sizeof(rrb->request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	rrb->request.hdr.cmd = CLP_QUERY_PCI_FNGRP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	rrb->response.hdr.len = sizeof(rrb->response);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	rrb->request.pfgid = pfgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	rc = clp_req(rrb, CLP_LPS_PCI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	if (!rc && rrb->response.hdr.rsp == CLP_RC_OK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		clp_store_query_pci_fngrp(zdev, &rrb->response);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		zpci_err("Q PCI FGRP:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		zpci_err_clp(rrb->response.hdr.rsp, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	clp_free_block(rrb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static int clp_store_query_pci_fn(struct zpci_dev *zdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 				  struct clp_rsp_query_pci *response)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		zdev->bars[i].val = le32_to_cpu(response->bar[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		zdev->bars[i].size = response->bar_size[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	zdev->start_dma = response->sdma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	zdev->end_dma = response->edma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	zdev->pchid = response->pchid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	zdev->pfgid = response->pfgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	zdev->pft = response->pft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	zdev->vfn = response->vfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	zdev->port = response->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	zdev->uid = response->uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	zdev->fmb_length = sizeof(u32) * response->fmb_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	zdev->rid_available = response->rid_avail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	zdev->is_physfn = response->is_physfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	if (!s390_pci_no_rid && zdev->rid_available)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		zdev->devfn = response->rid & ZPCI_RID_MASK_DEVFN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	memcpy(zdev->pfip, response->pfip, sizeof(zdev->pfip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	if (response->util_str_avail) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		memcpy(zdev->util_str, response->util_str,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		       sizeof(zdev->util_str));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		zdev->util_str_avail = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	zdev->mio_capable = response->mio_addr_avail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		if (!(response->mio.valid & (1 << (PCI_STD_NUM_BARS - i - 1))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		zdev->bars[i].mio_wb = (void __iomem *) response->mio.addr[i].wb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		zdev->bars[i].mio_wt = (void __iomem *) response->mio.addr[i].wt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) int clp_query_pci_fn(struct zpci_dev *zdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	struct clp_req_rsp_query_pci *rrb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	rrb = clp_alloc_block(GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	if (!rrb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	memset(rrb, 0, sizeof(*rrb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	rrb->request.hdr.len = sizeof(rrb->request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	rrb->request.hdr.cmd = CLP_QUERY_PCI_FN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	rrb->response.hdr.len = sizeof(rrb->response);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	rrb->request.fh = zdev->fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	rc = clp_req(rrb, CLP_LPS_PCI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	if (!rc && rrb->response.hdr.rsp == CLP_RC_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		rc = clp_store_query_pci_fn(zdev, &rrb->response);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		rc = clp_query_pci_fngrp(zdev, rrb->response.pfgid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		zpci_err("Q PCI FN:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		zpci_err_clp(rrb->response.hdr.rsp, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 		rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	clp_free_block(rrb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static int clp_refresh_fh(u32 fid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)  * clp_set_pci_fn() - Execute a command on a PCI function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)  * @zdev: Function that will be affected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)  * @nr_dma_as: DMA address space number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)  * @command: The command code to execute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)  * Returns: 0 on success, < 0 for Linux errors (e.g. -ENOMEM), and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)  * > 0 for non-success platform responses
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static int clp_set_pci_fn(struct zpci_dev *zdev, u8 nr_dma_as, u8 command)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	struct clp_req_rsp_set_pci *rrb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	int rc, retries = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	rrb = clp_alloc_block(GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	if (!rrb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 		memset(rrb, 0, sizeof(*rrb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 		rrb->request.hdr.len = sizeof(rrb->request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 		rrb->request.hdr.cmd = CLP_SET_PCI_FN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		rrb->response.hdr.len = sizeof(rrb->response);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		rrb->request.fh = zdev->fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		rrb->request.oc = command;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		rrb->request.ndas = nr_dma_as;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 		rc = clp_req(rrb, CLP_LPS_PCI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		if (rrb->response.hdr.rsp == CLP_RC_SETPCIFN_BUSY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 			retries--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 			if (retries < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 			msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	} while (rrb->response.hdr.rsp == CLP_RC_SETPCIFN_BUSY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	if (!rc && rrb->response.hdr.rsp == CLP_RC_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		zdev->fh = rrb->response.fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	} else if (!rc && rrb->response.hdr.rsp == CLP_RC_SETPCIFN_ALRDY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		/* Function is already in desired state - update handle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		rc = clp_refresh_fh(zdev->fid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		zpci_err("Set PCI FN:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 		zpci_err_clp(rrb->response.hdr.rsp, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 			rc = rrb->response.hdr.rsp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	clp_free_block(rrb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) int clp_setup_writeback_mio(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	struct clp_req_rsp_slpc_pci *rrb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	u8  wb_bit_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	rrb = clp_alloc_block(GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	if (!rrb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	memset(rrb, 0, sizeof(*rrb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	rrb->request.hdr.len = sizeof(rrb->request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	rrb->request.hdr.cmd = CLP_SLPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	rrb->response.hdr.len = sizeof(rrb->response);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	rc = clp_req(rrb, CLP_LPS_PCI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	if (!rc && rrb->response.hdr.rsp == CLP_RC_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		if (rrb->response.vwb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 			wb_bit_pos = rrb->response.mio_wb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 			set_bit_inv(wb_bit_pos, &mio_wb_bit_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 			zpci_dbg(3, "wb bit: %d\n", wb_bit_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 			zpci_dbg(3, "wb bit: n.a.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 		zpci_err("SLPC PCI:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		zpci_err_clp(rrb->response.hdr.rsp, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	clp_free_block(rrb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) int clp_enable_fh(struct zpci_dev *zdev, u8 nr_dma_as)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	rc = clp_set_pci_fn(zdev, nr_dma_as, CLP_SET_ENABLE_PCI_FN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	zpci_dbg(3, "ena fid:%x, fh:%x, rc:%d\n", zdev->fid, zdev->fh, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	if (!rc && zpci_use_mio(zdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		rc = clp_set_pci_fn(zdev, nr_dma_as, CLP_SET_ENABLE_MIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		zpci_dbg(3, "ena mio fid:%x, fh:%x, rc:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 				zdev->fid, zdev->fh, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 			clp_disable_fh(zdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) int clp_disable_fh(struct zpci_dev *zdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	if (!zdev_enabled(zdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	rc = clp_set_pci_fn(zdev, 0, CLP_SET_DISABLE_PCI_FN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	zpci_dbg(3, "dis fid:%x, fh:%x, rc:%d\n", zdev->fid, zdev->fh, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) static int clp_list_pci(struct clp_req_rsp_list_pci *rrb, void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 			void (*cb)(struct clp_fh_list_entry *, void *))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	u64 resume_token = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	int entries, i, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 		memset(rrb, 0, sizeof(*rrb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 		rrb->request.hdr.len = sizeof(rrb->request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		rrb->request.hdr.cmd = CLP_LIST_PCI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		/* store as many entries as possible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		rrb->response.hdr.len = CLP_BLK_SIZE - LIST_PCI_HDR_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		rrb->request.resume_token = resume_token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 		/* Get PCI function handle list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 		rc = clp_req(rrb, CLP_LPS_PCI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 		if (rc || rrb->response.hdr.rsp != CLP_RC_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 			zpci_err("List PCI FN:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 			zpci_err_clp(rrb->response.hdr.rsp, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 			rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		update_uid_checking(rrb->response.uid_checking);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		WARN_ON_ONCE(rrb->response.entry_size !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 			sizeof(struct clp_fh_list_entry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 		entries = (rrb->response.hdr.len - LIST_PCI_HDR_LEN) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 			rrb->response.entry_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 		resume_token = rrb->response.resume_token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 		for (i = 0; i < entries; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 			cb(&rrb->response.fh_list[i], data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	} while (resume_token);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) static void __clp_add(struct clp_fh_list_entry *entry, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	struct zpci_dev *zdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	if (!entry->vendor_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	zdev = get_zdev_by_fid(entry->fid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	if (!zdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 		zpci_create_device(entry->fid, entry->fh, entry->config_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) int clp_scan_pci_devices(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	struct clp_req_rsp_list_pci *rrb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	rrb = clp_alloc_block(GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	if (!rrb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	rc = clp_list_pci(rrb, NULL, __clp_add);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	clp_free_block(rrb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) static void __clp_refresh_fh(struct clp_fh_list_entry *entry, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	struct zpci_dev *zdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	u32 fid = *((u32 *)data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	if (!entry->vendor_id || fid != entry->fid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	zdev = get_zdev_by_fid(fid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	if (!zdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	zdev->fh = entry->fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)  * Refresh the function handle of the function matching @fid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) static int clp_refresh_fh(u32 fid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	struct clp_req_rsp_list_pci *rrb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	rrb = clp_alloc_block(GFP_NOWAIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	if (!rrb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	rc = clp_list_pci(rrb, &fid, __clp_refresh_fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	clp_free_block(rrb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) struct clp_state_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	u32 fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	enum zpci_state state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) static void __clp_get_state(struct clp_fh_list_entry *entry, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	struct clp_state_data *sd = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 	if (entry->fid != sd->fid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	sd->state = entry->config_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) int clp_get_state(u32 fid, enum zpci_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	struct clp_req_rsp_list_pci *rrb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	struct clp_state_data sd = {fid, ZPCI_FN_STATE_RESERVED};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	rrb = clp_alloc_block(GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	if (!rrb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	rc = clp_list_pci(rrb, &sd, __clp_get_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 		*state = sd.state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	clp_free_block(rrb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static int clp_base_slpc(struct clp_req *req, struct clp_req_rsp_slpc *lpcb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	unsigned long limit = PAGE_SIZE - sizeof(lpcb->request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	if (lpcb->request.hdr.len != sizeof(lpcb->request) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	    lpcb->response.hdr.len > limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	return clp_req(lpcb, CLP_LPS_BASE) ? -EOPNOTSUPP : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) static int clp_base_command(struct clp_req *req, struct clp_req_hdr *lpcb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 	switch (lpcb->cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 	case 0x0001: /* store logical-processor characteristics */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 		return clp_base_slpc(req, (void *) lpcb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) static int clp_pci_slpc(struct clp_req *req, struct clp_req_rsp_slpc_pci *lpcb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	unsigned long limit = PAGE_SIZE - sizeof(lpcb->request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	if (lpcb->request.hdr.len != sizeof(lpcb->request) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	    lpcb->response.hdr.len > limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	return clp_req(lpcb, CLP_LPS_PCI) ? -EOPNOTSUPP : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) static int clp_pci_list(struct clp_req *req, struct clp_req_rsp_list_pci *lpcb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	unsigned long limit = PAGE_SIZE - sizeof(lpcb->request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	if (lpcb->request.hdr.len != sizeof(lpcb->request) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	    lpcb->response.hdr.len > limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	if (lpcb->request.reserved2 != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	return clp_req(lpcb, CLP_LPS_PCI) ? -EOPNOTSUPP : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) static int clp_pci_query(struct clp_req *req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 			 struct clp_req_rsp_query_pci *lpcb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 	unsigned long limit = PAGE_SIZE - sizeof(lpcb->request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	if (lpcb->request.hdr.len != sizeof(lpcb->request) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	    lpcb->response.hdr.len > limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	if (lpcb->request.reserved2 != 0 || lpcb->request.reserved3 != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 	return clp_req(lpcb, CLP_LPS_PCI) ? -EOPNOTSUPP : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) static int clp_pci_query_grp(struct clp_req *req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 			     struct clp_req_rsp_query_pci_grp *lpcb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 	unsigned long limit = PAGE_SIZE - sizeof(lpcb->request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	if (lpcb->request.hdr.len != sizeof(lpcb->request) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 	    lpcb->response.hdr.len > limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 	if (lpcb->request.reserved2 != 0 || lpcb->request.reserved3 != 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 	    lpcb->request.reserved4 != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	return clp_req(lpcb, CLP_LPS_PCI) ? -EOPNOTSUPP : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) static int clp_pci_command(struct clp_req *req, struct clp_req_hdr *lpcb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	switch (lpcb->cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 	case 0x0001: /* store logical-processor characteristics */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 		return clp_pci_slpc(req, (void *) lpcb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 	case 0x0002: /* list PCI functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 		return clp_pci_list(req, (void *) lpcb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	case 0x0003: /* query PCI function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 		return clp_pci_query(req, (void *) lpcb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	case 0x0004: /* query PCI function group */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 		return clp_pci_query_grp(req, (void *) lpcb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) static int clp_normal_command(struct clp_req *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	struct clp_req_hdr *lpcb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	void __user *uptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	if (req->lps != 0 && req->lps != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 	rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	lpcb = clp_alloc_block(GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 	if (!lpcb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 	uptr = (void __force __user *)(unsigned long) req->data_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	if (copy_from_user(lpcb, uptr, PAGE_SIZE) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 		goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 	rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 	if (lpcb->fmt != 0 || lpcb->reserved1 != 0 || lpcb->reserved2 != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 		goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 	switch (req->lps) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 	case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 		rc = clp_base_command(req, lpcb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 	case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 		rc = clp_pci_command(req, lpcb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 		goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 	rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 	if (copy_to_user(uptr, lpcb, PAGE_SIZE) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 		goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 	rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	clp_free_block(lpcb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) static int clp_immediate_command(struct clp_req *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	void __user *uptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 	unsigned long ilp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	int exists;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	if (req->cmd > 1 || clp_get_ilp(&ilp) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 	uptr = (void __force __user *)(unsigned long) req->data_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 	if (req->cmd == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 		/* Command code 0: test for a specific processor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 		exists = test_bit_inv(req->lps, &ilp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 		return put_user(exists, (int __user *) uptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 	/* Command code 1: return bit mask of installed processors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 	return put_user(ilp, (unsigned long __user *) uptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) static long clp_misc_ioctl(struct file *filp, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 			   unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 	struct clp_req req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 	void __user *argp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 	if (cmd != CLP_SYNC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	argp = is_compat_task() ? compat_ptr(arg) : (void __user *) arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 	if (copy_from_user(&req, argp, sizeof(req)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 		return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	if (req.r != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 	return req.c ? clp_immediate_command(&req) : clp_normal_command(&req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) static int clp_misc_release(struct inode *inode, struct file *filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) static const struct file_operations clp_misc_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 	.owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 	.open = nonseekable_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 	.release = clp_misc_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 	.unlocked_ioctl = clp_misc_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 	.compat_ioctl = clp_misc_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	.llseek = no_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) static struct miscdevice clp_misc_device = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 	.minor = MISC_DYNAMIC_MINOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 	.name = "clp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	.fops = &clp_misc_fops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) static int __init clp_misc_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 	return misc_register(&clp_misc_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) device_initcall(clp_misc_init);