^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);