Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/powernv: Capture actag information for the device

In the opencapi protocol, host memory contexts are referenced by a
'actag'. During setup, a driver must tell the device how many actags
it can used, and what values are acceptable.

On POWER9, the NPU can handle 64 actags per link, so they must be
shared between all the PCI functions of the link. To get a global
picture of how many actags are used by each AFU of every function, we
capture some data at the end of PCI enumeration, so that actags can be
shared fairly if needed.

This is not powernv specific per say, but rather a consequence of the
opencapi configuration specification being quite general. The number
of available actags on POWER9 makes it more likely to be hit. This is
somewhat mitigated by the fact that existing AFUs are coded by
requesting a reasonable count of actags and existing devices carry
only one AFU.

Signed-off-by: Frederic Barrat <fbarrat@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

authored by

Frederic Barrat and committed by
Michael Ellerman
2cb3d64b 6914c757

+354
+4
arch/powerpc/include/asm/pnv-ocxl.h
··· 9 9 #define PNV_OCXL_TL_BITS_PER_RATE 4 10 10 #define PNV_OCXL_TL_RATE_BUF_SIZE ((PNV_OCXL_TL_MAX_TEMPLATE+1) * PNV_OCXL_TL_BITS_PER_RATE / 8) 11 11 12 + extern int pnv_ocxl_get_actag(struct pci_dev *dev, u16 *base, u16 *enabled, 13 + u16 *supported); 14 + extern int pnv_ocxl_get_pasid_count(struct pci_dev *dev, int *count); 15 + 12 16 extern int pnv_ocxl_get_tl_cap(struct pci_dev *dev, long *cap, 13 17 char *rate_buf, int rate_buf_size); 14 18 extern int pnv_ocxl_set_tl_conf(struct pci_dev *dev, long cap,
+305
arch/powerpc/platforms/powernv/ocxl.c
··· 2 2 // Copyright 2017 IBM Corp. 3 3 #include <asm/pnv-ocxl.h> 4 4 #include <asm/opal.h> 5 + #include <misc/ocxl-config.h> 5 6 #include "pci.h" 6 7 7 8 #define PNV_OCXL_TL_P9_RECV_CAP 0x000000000000000Full 9 + #define PNV_OCXL_ACTAG_MAX 64 8 10 /* PASIDs are 20-bit, but on P9, NPU can only handle 15 bits */ 9 11 #define PNV_OCXL_PASID_BITS 15 10 12 #define PNV_OCXL_PASID_MAX ((1 << PNV_OCXL_PASID_BITS) - 1) 11 13 14 + #define AFU_PRESENT (1 << 31) 15 + #define AFU_INDEX_MASK 0x3F000000 16 + #define AFU_INDEX_SHIFT 24 17 + #define ACTAG_MASK 0xFFF 18 + 19 + 20 + struct actag_range { 21 + u16 start; 22 + u16 count; 23 + }; 24 + 25 + struct npu_link { 26 + struct list_head list; 27 + int domain; 28 + int bus; 29 + int dev; 30 + u16 fn_desired_actags[8]; 31 + struct actag_range fn_actags[8]; 32 + bool assignment_done; 33 + }; 34 + static struct list_head links_list = LIST_HEAD_INIT(links_list); 35 + static DEFINE_MUTEX(links_list_lock); 36 + 37 + 38 + /* 39 + * opencapi actags handling: 40 + * 41 + * When sending commands, the opencapi device references the memory 42 + * context it's targeting with an 'actag', which is really an alias 43 + * for a (BDF, pasid) combination. When it receives a command, the NPU 44 + * must do a lookup of the actag to identify the memory context. The 45 + * hardware supports a finite number of actags per link (64 for 46 + * POWER9). 47 + * 48 + * The device can carry multiple functions, and each function can have 49 + * multiple AFUs. Each AFU advertises in its config space the number 50 + * of desired actags. The host must configure in the config space of 51 + * the AFU how many actags the AFU is really allowed to use (which can 52 + * be less than what the AFU desires). 53 + * 54 + * When a PCI function is probed by the driver, it has no visibility 55 + * about the other PCI functions and how many actags they'd like, 56 + * which makes it impossible to distribute actags fairly among AFUs. 57 + * 58 + * Unfortunately, the only way to know how many actags a function 59 + * desires is by looking at the data for each AFU in the config space 60 + * and add them up. Similarly, the only way to know how many actags 61 + * all the functions of the physical device desire is by adding the 62 + * previously computed function counts. Then we can match that against 63 + * what the hardware supports. 64 + * 65 + * To get a comprehensive view, we use a 'pci fixup': at the end of 66 + * PCI enumeration, each function counts how many actags its AFUs 67 + * desire and we save it in a 'npu_link' structure, shared between all 68 + * the PCI functions of a same device. Therefore, when the first 69 + * function is probed by the driver, we can get an idea of the total 70 + * count of desired actags for the device, and assign the actags to 71 + * the AFUs, by pro-rating if needed. 72 + */ 73 + 74 + static int find_dvsec_from_pos(struct pci_dev *dev, int dvsec_id, int pos) 75 + { 76 + int vsec = pos; 77 + u16 vendor, id; 78 + 79 + while ((vsec = pci_find_next_ext_capability(dev, vsec, 80 + OCXL_EXT_CAP_ID_DVSEC))) { 81 + pci_read_config_word(dev, vsec + OCXL_DVSEC_VENDOR_OFFSET, 82 + &vendor); 83 + pci_read_config_word(dev, vsec + OCXL_DVSEC_ID_OFFSET, &id); 84 + if (vendor == PCI_VENDOR_ID_IBM && id == dvsec_id) 85 + return vsec; 86 + } 87 + return 0; 88 + } 89 + 90 + static int find_dvsec_afu_ctrl(struct pci_dev *dev, u8 afu_idx) 91 + { 92 + int vsec = 0; 93 + u8 idx; 94 + 95 + while ((vsec = find_dvsec_from_pos(dev, OCXL_DVSEC_AFU_CTRL_ID, 96 + vsec))) { 97 + pci_read_config_byte(dev, vsec + OCXL_DVSEC_AFU_CTRL_AFU_IDX, 98 + &idx); 99 + if (idx == afu_idx) 100 + return vsec; 101 + } 102 + return 0; 103 + } 104 + 105 + static int get_max_afu_index(struct pci_dev *dev, int *afu_idx) 106 + { 107 + int pos; 108 + u32 val; 109 + 110 + pos = find_dvsec_from_pos(dev, OCXL_DVSEC_FUNC_ID, 0); 111 + if (!pos) 112 + return -ESRCH; 113 + 114 + pci_read_config_dword(dev, pos + OCXL_DVSEC_FUNC_OFF_INDEX, &val); 115 + if (val & AFU_PRESENT) 116 + *afu_idx = (val & AFU_INDEX_MASK) >> AFU_INDEX_SHIFT; 117 + else 118 + *afu_idx = -1; 119 + return 0; 120 + } 121 + 122 + static int get_actag_count(struct pci_dev *dev, int afu_idx, int *actag) 123 + { 124 + int pos; 125 + u16 actag_sup; 126 + 127 + pos = find_dvsec_afu_ctrl(dev, afu_idx); 128 + if (!pos) 129 + return -ESRCH; 130 + 131 + pci_read_config_word(dev, pos + OCXL_DVSEC_AFU_CTRL_ACTAG_SUP, 132 + &actag_sup); 133 + *actag = actag_sup & ACTAG_MASK; 134 + return 0; 135 + } 136 + 137 + static struct npu_link *find_link(struct pci_dev *dev) 138 + { 139 + struct npu_link *link; 140 + 141 + list_for_each_entry(link, &links_list, list) { 142 + /* The functions of a device all share the same link */ 143 + if (link->domain == pci_domain_nr(dev->bus) && 144 + link->bus == dev->bus->number && 145 + link->dev == PCI_SLOT(dev->devfn)) { 146 + return link; 147 + } 148 + } 149 + 150 + /* link doesn't exist yet. Allocate one */ 151 + link = kzalloc(sizeof(struct npu_link), GFP_KERNEL); 152 + if (!link) 153 + return NULL; 154 + link->domain = pci_domain_nr(dev->bus); 155 + link->bus = dev->bus->number; 156 + link->dev = PCI_SLOT(dev->devfn); 157 + list_add(&link->list, &links_list); 158 + return link; 159 + } 160 + 161 + static void pnv_ocxl_fixup_actag(struct pci_dev *dev) 162 + { 163 + struct pci_controller *hose = pci_bus_to_host(dev->bus); 164 + struct pnv_phb *phb = hose->private_data; 165 + struct npu_link *link; 166 + int rc, afu_idx = -1, i, actag; 167 + 168 + if (!machine_is(powernv)) 169 + return; 170 + 171 + if (phb->type != PNV_PHB_NPU_OCAPI) 172 + return; 173 + 174 + mutex_lock(&links_list_lock); 175 + 176 + link = find_link(dev); 177 + if (!link) { 178 + dev_warn(&dev->dev, "couldn't update actag information\n"); 179 + mutex_unlock(&links_list_lock); 180 + return; 181 + } 182 + 183 + /* 184 + * Check how many actags are desired for the AFUs under that 185 + * function and add it to the count for the link 186 + */ 187 + rc = get_max_afu_index(dev, &afu_idx); 188 + if (rc) { 189 + /* Most likely an invalid config space */ 190 + dev_dbg(&dev->dev, "couldn't find AFU information\n"); 191 + afu_idx = -1; 192 + } 193 + 194 + link->fn_desired_actags[PCI_FUNC(dev->devfn)] = 0; 195 + for (i = 0; i <= afu_idx; i++) { 196 + /* 197 + * AFU index 'holes' are allowed. So don't fail if we 198 + * can't read the actag info for an index 199 + */ 200 + rc = get_actag_count(dev, i, &actag); 201 + if (rc) 202 + continue; 203 + link->fn_desired_actags[PCI_FUNC(dev->devfn)] += actag; 204 + } 205 + dev_dbg(&dev->dev, "total actags for function: %d\n", 206 + link->fn_desired_actags[PCI_FUNC(dev->devfn)]); 207 + 208 + mutex_unlock(&links_list_lock); 209 + } 210 + DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pnv_ocxl_fixup_actag); 211 + 212 + static u16 assign_fn_actags(u16 desired, u16 total) 213 + { 214 + u16 count; 215 + 216 + if (total <= PNV_OCXL_ACTAG_MAX) 217 + count = desired; 218 + else 219 + count = PNV_OCXL_ACTAG_MAX * desired / total; 220 + 221 + return count; 222 + } 223 + 224 + static void assign_actags(struct npu_link *link) 225 + { 226 + u16 actag_count, range_start = 0, total_desired = 0; 227 + int i; 228 + 229 + for (i = 0; i < 8; i++) 230 + total_desired += link->fn_desired_actags[i]; 231 + 232 + for (i = 0; i < 8; i++) { 233 + if (link->fn_desired_actags[i]) { 234 + actag_count = assign_fn_actags( 235 + link->fn_desired_actags[i], 236 + total_desired); 237 + link->fn_actags[i].start = range_start; 238 + link->fn_actags[i].count = actag_count; 239 + range_start += actag_count; 240 + WARN_ON(range_start >= PNV_OCXL_ACTAG_MAX); 241 + } 242 + pr_debug("link %x:%x:%x fct %d actags: start=%d count=%d (desired=%d)\n", 243 + link->domain, link->bus, link->dev, i, 244 + link->fn_actags[i].start, link->fn_actags[i].count, 245 + link->fn_desired_actags[i]); 246 + } 247 + link->assignment_done = true; 248 + } 249 + 250 + int pnv_ocxl_get_actag(struct pci_dev *dev, u16 *base, u16 *enabled, 251 + u16 *supported) 252 + { 253 + struct npu_link *link; 254 + 255 + mutex_lock(&links_list_lock); 256 + 257 + link = find_link(dev); 258 + if (!link) { 259 + dev_err(&dev->dev, "actag information not found\n"); 260 + mutex_unlock(&links_list_lock); 261 + return -ENODEV; 262 + } 263 + /* 264 + * On p9, we only have 64 actags per link, so they must be 265 + * shared by all the functions of the same adapter. We counted 266 + * the desired actag counts during PCI enumeration, so that we 267 + * can allocate a pro-rated number of actags to each function. 268 + */ 269 + if (!link->assignment_done) 270 + assign_actags(link); 271 + 272 + *base = link->fn_actags[PCI_FUNC(dev->devfn)].start; 273 + *enabled = link->fn_actags[PCI_FUNC(dev->devfn)].count; 274 + *supported = link->fn_desired_actags[PCI_FUNC(dev->devfn)]; 275 + 276 + mutex_unlock(&links_list_lock); 277 + return 0; 278 + } 279 + EXPORT_SYMBOL_GPL(pnv_ocxl_get_actag); 280 + 281 + int pnv_ocxl_get_pasid_count(struct pci_dev *dev, int *count) 282 + { 283 + struct npu_link *link; 284 + int i, rc = -EINVAL; 285 + 286 + /* 287 + * The number of PASIDs (process address space ID) which can 288 + * be used by a function depends on how many functions exist 289 + * on the device. The NPU needs to be configured to know how 290 + * many bits are available to PASIDs and how many are to be 291 + * used by the function BDF indentifier. 292 + * 293 + * We only support one AFU-carrying function for now. 294 + */ 295 + mutex_lock(&links_list_lock); 296 + 297 + link = find_link(dev); 298 + if (!link) { 299 + dev_err(&dev->dev, "actag information not found\n"); 300 + mutex_unlock(&links_list_lock); 301 + return -ENODEV; 302 + } 303 + 304 + for (i = 0; i < 8; i++) 305 + if (link->fn_desired_actags[i] && (i == PCI_FUNC(dev->devfn))) { 306 + *count = PNV_OCXL_PASID_MAX; 307 + rc = 0; 308 + break; 309 + } 310 + 311 + mutex_unlock(&links_list_lock); 312 + dev_dbg(&dev->dev, "%d PASIDs available for function\n", 313 + rc ? 0 : *count); 314 + return rc; 315 + } 316 + EXPORT_SYMBOL_GPL(pnv_ocxl_get_pasid_count); 12 317 13 318 static void set_templ_rate(unsigned int templ, unsigned int rate, char *buf) 14 319 {
+45
include/misc/ocxl-config.h
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + // Copyright 2017 IBM Corp. 3 + #ifndef _OCXL_CONFIG_H_ 4 + #define _OCXL_CONFIG_H_ 5 + 6 + /* 7 + * This file lists the various constants used to read the 8 + * configuration space of an opencapi adapter. 9 + * 10 + * It follows the specification for opencapi 3.0 11 + */ 12 + 13 + #define OCXL_EXT_CAP_ID_DVSEC 0x23 14 + 15 + #define OCXL_DVSEC_VENDOR_OFFSET 0x4 16 + #define OCXL_DVSEC_ID_OFFSET 0x8 17 + #define OCXL_DVSEC_TL_ID 0xF000 18 + #define OCXL_DVSEC_TL_BACKOFF_TIMERS 0x10 19 + #define OCXL_DVSEC_TL_RECV_CAP 0x18 20 + #define OCXL_DVSEC_TL_SEND_CAP 0x20 21 + #define OCXL_DVSEC_TL_RECV_RATE 0x30 22 + #define OCXL_DVSEC_TL_SEND_RATE 0x50 23 + #define OCXL_DVSEC_FUNC_ID 0xF001 24 + #define OCXL_DVSEC_FUNC_OFF_INDEX 0x08 25 + #define OCXL_DVSEC_FUNC_OFF_ACTAG 0x0C 26 + #define OCXL_DVSEC_AFU_INFO_ID 0xF003 27 + #define OCXL_DVSEC_AFU_INFO_AFU_IDX 0x0A 28 + #define OCXL_DVSEC_AFU_INFO_OFF 0x0C 29 + #define OCXL_DVSEC_AFU_INFO_DATA 0x10 30 + #define OCXL_DVSEC_AFU_CTRL_ID 0xF004 31 + #define OCXL_DVSEC_AFU_CTRL_AFU_IDX 0x0A 32 + #define OCXL_DVSEC_AFU_CTRL_TERM_PASID 0x0C 33 + #define OCXL_DVSEC_AFU_CTRL_ENABLE 0x0F 34 + #define OCXL_DVSEC_AFU_CTRL_PASID_SUP 0x10 35 + #define OCXL_DVSEC_AFU_CTRL_PASID_EN 0x11 36 + #define OCXL_DVSEC_AFU_CTRL_PASID_BASE 0x14 37 + #define OCXL_DVSEC_AFU_CTRL_ACTAG_SUP 0x18 38 + #define OCXL_DVSEC_AFU_CTRL_ACTAG_EN 0x1A 39 + #define OCXL_DVSEC_AFU_CTRL_ACTAG_BASE 0x1C 40 + #define OCXL_DVSEC_VENDOR_ID 0xF0F0 41 + #define OCXL_DVSEC_VENDOR_CFG_VERS 0x0C 42 + #define OCXL_DVSEC_VENDOR_TLX_VERS 0x10 43 + #define OCXL_DVSEC_VENDOR_DLX_VERS 0x20 44 + 45 + #endif /* _OCXL_CONFIG_H_ */