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

Configure Feed

Select the types of activity you want to include in your feed.

PCI/IDE: Add Address Association Register setup for downstream MMIO

The address ranges for downstream Address Association Registers need to
cover memory addresses for all functions (PFs/VFs/downstream devices)
managed by a Device Security Manager (DSM). The proposed solution is get
the memory (32-bit only) range and prefetchable-memory (64-bit capable)
range from the immediate ancestor downstream port (either the direct-attach
RP or deepest switch port when switch attached).

Similar to RID association, address associations will be set by default if
hardware sets 'Number of Address Association Register Blocks' in the
'Selective IDE Stream Capability Register' to a non-zero value. TSM drivers
can opt-out of the settings by zero'ing out unwanted / unsupported address
ranges. E.g. TDX Connect only supports prefetachable (64-bit capable)
memory ranges for the Address Association setting.

If the immediate downstream port provides both a memory range and
prefetchable-memory range, but the IDE partner port only provides 1 Address
Association Register block then the TSM driver can pick which range to
associate, or let the PCI core prioritize memory.

Note, the Address Association Register setup for upstream requests is still
uncertain so is not included.

Co-developed-by: Aneesh Kumar K.V <aneesh.kumar@kernel.org>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@kernel.org>
Co-developed-by: Arto Merilainen <amerilainen@nvidia.com>
Signed-off-by: Arto Merilainen <amerilainen@nvidia.com>
Signed-off-by: Xu Yilun <yilun.xu@linux.intel.com>
Co-developed-by: Dan Williams <dan.j.williams@intel.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Link: https://patch.msgid.link/20251114010227.567693-1-dan.j.williams@intel.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>

authored by

Xu Yilun and committed by
Dan Williams
f86e5139 c16af019

+145 -9
+108 -9
drivers/pci/ide.c
··· 155 155 { 156 156 /* EP, RP, + HB Stream allocation */ 157 157 struct stream_index __stream[PCI_IDE_HB + 1]; 158 + struct pci_bus_region pref_assoc = { 0, -1 }; 159 + struct pci_bus_region mem_assoc = { 0, -1 }; 160 + struct resource *mem, *pref; 158 161 struct pci_host_bridge *hb; 159 - struct pci_dev *rp; 162 + struct pci_dev *rp, *br; 160 163 int num_vf, rid_end; 161 164 162 165 if (!pci_is_pcie(pdev)) ··· 200 197 else 201 198 rid_end = pci_dev_id(pdev); 202 199 200 + br = pci_upstream_bridge(pdev); 201 + if (!br) 202 + return NULL; 203 + 204 + /* 205 + * Check if the device consumes memory and/or prefetch-memory. Setup 206 + * downstream address association ranges for each. 207 + */ 208 + mem = pci_resource_n(br, PCI_BRIDGE_MEM_WINDOW); 209 + pref = pci_resource_n(br, PCI_BRIDGE_PREF_MEM_WINDOW); 210 + if (resource_assigned(mem)) 211 + pcibios_resource_to_bus(br->bus, &mem_assoc, mem); 212 + if (resource_assigned(pref)) 213 + pcibios_resource_to_bus(br->bus, &pref_assoc, pref); 214 + 203 215 *ide = (struct pci_ide) { 204 216 .pdev = pdev, 205 217 .partner = { ··· 222 204 .rid_start = pci_dev_id(rp), 223 205 .rid_end = pci_dev_id(rp), 224 206 .stream_index = no_free_ptr(ep_stream)->stream_index, 207 + /* Disable upstream address association */ 208 + .mem_assoc = { 0, -1 }, 209 + .pref_assoc = { 0, -1 }, 225 210 }, 226 211 [PCI_IDE_RP] = { 227 212 .rid_start = pci_dev_id(pdev), 228 213 .rid_end = rid_end, 229 214 .stream_index = no_free_ptr(rp_stream)->stream_index, 215 + .mem_assoc = mem_assoc, 216 + .pref_assoc = pref_assoc, 230 217 }, 231 218 }, 232 219 .host_bridge_stream = no_free_ptr(hb_stream)->stream_index, ··· 408 385 pci_write_config_dword(pdev, pos + PCI_IDE_SEL_CTL, val); 409 386 } 410 387 388 + #define SEL_ADDR1_LOWER GENMASK(31, 20) 389 + #define SEL_ADDR_UPPER GENMASK_ULL(63, 32) 390 + #define PREP_PCI_IDE_SEL_ADDR1(base, limit) \ 391 + (FIELD_PREP(PCI_IDE_SEL_ADDR_1_VALID, 1) | \ 392 + FIELD_PREP(PCI_IDE_SEL_ADDR_1_BASE_LOW, \ 393 + FIELD_GET(SEL_ADDR1_LOWER, (base))) | \ 394 + FIELD_PREP(PCI_IDE_SEL_ADDR_1_LIMIT_LOW, \ 395 + FIELD_GET(SEL_ADDR1_LOWER, (limit)))) 396 + 397 + static void mem_assoc_to_regs(struct pci_bus_region *region, 398 + struct pci_ide_regs *regs, int idx) 399 + { 400 + /* convert to u64 range for bitfield size checks */ 401 + struct range r = { region->start, region->end }; 402 + 403 + regs->addr[idx].assoc1 = PREP_PCI_IDE_SEL_ADDR1(r.start, r.end); 404 + regs->addr[idx].assoc2 = FIELD_GET(SEL_ADDR_UPPER, r.end); 405 + regs->addr[idx].assoc3 = FIELD_GET(SEL_ADDR_UPPER, r.start); 406 + } 407 + 408 + /** 409 + * pci_ide_stream_to_regs() - convert IDE settings to association register values 410 + * @pdev: PCIe device object for either a Root Port or Endpoint Partner Port 411 + * @ide: registered IDE settings descriptor 412 + * @regs: output register values 413 + */ 414 + static void pci_ide_stream_to_regs(struct pci_dev *pdev, struct pci_ide *ide, 415 + struct pci_ide_regs *regs) 416 + { 417 + struct pci_ide_partner *settings = pci_ide_to_settings(pdev, ide); 418 + int assoc_idx = 0; 419 + 420 + memset(regs, 0, sizeof(*regs)); 421 + 422 + if (!settings) 423 + return; 424 + 425 + regs->rid1 = FIELD_PREP(PCI_IDE_SEL_RID_1_LIMIT, settings->rid_end); 426 + 427 + regs->rid2 = FIELD_PREP(PCI_IDE_SEL_RID_2_VALID, 1) | 428 + FIELD_PREP(PCI_IDE_SEL_RID_2_BASE, settings->rid_start) | 429 + FIELD_PREP(PCI_IDE_SEL_RID_2_SEG, pci_ide_domain(pdev)); 430 + 431 + if (pdev->nr_ide_mem && pci_bus_region_size(&settings->mem_assoc)) { 432 + mem_assoc_to_regs(&settings->mem_assoc, regs, assoc_idx); 433 + assoc_idx++; 434 + } 435 + 436 + if (pdev->nr_ide_mem > assoc_idx && 437 + pci_bus_region_size(&settings->pref_assoc)) { 438 + mem_assoc_to_regs(&settings->pref_assoc, regs, assoc_idx); 439 + assoc_idx++; 440 + } 441 + 442 + regs->nr_addr = assoc_idx; 443 + } 444 + 411 445 /** 412 446 * pci_ide_stream_setup() - program settings to Selective IDE Stream registers 413 447 * @pdev: PCIe device object for either a Root Port or Endpoint Partner Port ··· 478 398 void pci_ide_stream_setup(struct pci_dev *pdev, struct pci_ide *ide) 479 399 { 480 400 struct pci_ide_partner *settings = pci_ide_to_settings(pdev, ide); 401 + struct pci_ide_regs regs; 481 402 int pos; 482 - u32 val; 483 403 484 404 if (!settings) 485 405 return; 486 406 407 + pci_ide_stream_to_regs(pdev, ide, &regs); 408 + 487 409 pos = sel_ide_offset(pdev, settings); 488 410 489 - val = FIELD_PREP(PCI_IDE_SEL_RID_1_LIMIT, settings->rid_end); 490 - pci_write_config_dword(pdev, pos + PCI_IDE_SEL_RID_1, val); 411 + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_RID_1, regs.rid1); 412 + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_RID_2, regs.rid2); 491 413 492 - val = FIELD_PREP(PCI_IDE_SEL_RID_2_VALID, 1) | 493 - FIELD_PREP(PCI_IDE_SEL_RID_2_BASE, settings->rid_start) | 494 - FIELD_PREP(PCI_IDE_SEL_RID_2_SEG, pci_ide_domain(pdev)); 414 + for (int i = 0; i < regs.nr_addr; i++) { 415 + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_1(i), 416 + regs.addr[i].assoc1); 417 + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_2(i), 418 + regs.addr[i].assoc2); 419 + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_3(i), 420 + regs.addr[i].assoc3); 421 + } 495 422 496 - pci_write_config_dword(pdev, pos + PCI_IDE_SEL_RID_2, val); 423 + /* clear extra unused address association blocks */ 424 + for (int i = regs.nr_addr; i < pdev->nr_ide_mem; i++) { 425 + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_1(i), 0); 426 + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_2(i), 0); 427 + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_3(i), 0); 428 + } 497 429 498 430 /* 499 431 * Setup control register early for devices that expect ··· 528 436 void pci_ide_stream_teardown(struct pci_dev *pdev, struct pci_ide *ide) 529 437 { 530 438 struct pci_ide_partner *settings = pci_ide_to_settings(pdev, ide); 531 - int pos; 439 + int pos, i; 532 440 533 441 if (!settings) 534 442 return; ··· 536 444 pos = sel_ide_offset(pdev, settings); 537 445 538 446 pci_write_config_dword(pdev, pos + PCI_IDE_SEL_CTL, 0); 447 + 448 + for (i = 0; i < pdev->nr_ide_mem; i++) { 449 + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_1(i), 0); 450 + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_2(i), 0); 451 + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_3(i), 0); 452 + } 453 + 539 454 pci_write_config_dword(pdev, pos + PCI_IDE_SEL_RID_2, 0); 540 455 pci_write_config_dword(pdev, pos + PCI_IDE_SEL_RID_1, 0); 541 456 settings->setup = 0;
+32
include/linux/pci-ide.h
··· 28 28 * @rid_start: Partner Port Requester ID range start 29 29 * @rid_end: Partner Port Requester ID range end 30 30 * @stream_index: Selective IDE Stream Register Block selection 31 + * @mem_assoc: PCI bus memory address association for targeting peer partner 32 + * @pref_assoc: PCI bus prefetchable memory address association for 33 + * targeting peer partner 31 34 * @default_stream: Endpoint uses this stream for all upstream TLPs regardless of 32 35 * address and RID association registers 33 36 * @setup: flag to track whether to run pci_ide_stream_teardown() for this 34 37 * partner slot 35 38 * @enable: flag whether to run pci_ide_stream_disable() for this partner slot 39 + * 40 + * By default, pci_ide_stream_alloc() initializes @mem_assoc and @pref_assoc 41 + * with the immediate ancestor downstream port memory ranges (i.e. Type 1 42 + * Configuration Space Header values). Caller may zero size ({0, -1}) the range 43 + * to drop it from consideration at pci_ide_stream_setup() time. 36 44 */ 37 45 struct pci_ide_partner { 38 46 u16 rid_start; 39 47 u16 rid_end; 40 48 u8 stream_index; 49 + struct pci_bus_region mem_assoc; 50 + struct pci_bus_region pref_assoc; 41 51 unsigned int default_stream:1; 42 52 unsigned int setup:1; 43 53 unsigned int enable:1; 54 + }; 55 + 56 + /** 57 + * struct pci_ide_regs - Hardware register association settings for Selective 58 + * IDE Streams 59 + * @rid1: IDE RID Association Register 1 60 + * @rid2: IDE RID Association Register 2 61 + * @addr: Up to two address association blocks (IDE Address Association Register 62 + * 1 through 3) for MMIO and prefetchable MMIO 63 + * @nr_addr: Number of address association blocks initialized 64 + * 65 + * See pci_ide_stream_to_regs() 66 + */ 67 + struct pci_ide_regs { 68 + u32 rid1; 69 + u32 rid2; 70 + struct { 71 + u32 assoc1; 72 + u32 assoc2; 73 + u32 assoc3; 74 + } addr[2]; 75 + int nr_addr; 44 76 }; 45 77 46 78 /**
+5
include/linux/pci.h
··· 870 870 pci_bus_addr_t end; 871 871 }; 872 872 873 + static inline pci_bus_addr_t pci_bus_region_size(const struct pci_bus_region *region) 874 + { 875 + return region->end - region->start + 1; 876 + } 877 + 873 878 struct pci_dynids { 874 879 spinlock_t lock; /* Protects list, index */ 875 880 struct list_head list; /* For IDs added at runtime */