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 IDE establishment helpers

There are two components to establishing an encrypted link, provisioning
the stream in Partner Port config-space, and programming the keys into
the link layer via IDE_KM (IDE Key Management). This new library,
drivers/pci/ide.c, enables the former. IDE_KM, via a TSM low-level
driver, is saved for later.

With the platform TSM implementations of SEV-TIO and TDX Connect in mind
this library abstracts small differences in those implementations. For
example, TDX Connect handles Root Port register setup while SEV-TIO
expects System Software to update the Root Port registers. This is the
rationale for fine-grained 'setup' + 'enable' verbs.

The other design detail for TSM-coordinated IDE establishment is that
the TSM may manage allocation of Stream IDs, this is why the Stream ID
value is passed in to pci_ide_stream_setup().

The flow is:

pci_ide_stream_alloc():
Allocate a Selective IDE Stream Register Block in each Partner Port
(Endpoint + Root Port), and reserve a host bridge / platform stream
slot. Gather Partner Port specific stream settings like Requester ID.

pci_ide_stream_register():
Publish the stream in sysfs after allocating a Stream ID. In the TSM
case the TSM allocates the Stream ID for the Partner Port pair.

pci_ide_stream_setup():
Program the stream settings to a Partner Port. Caller is responsible
for optionally calling this for the Root Port as well if the TSM
implementation requires it.

pci_ide_stream_enable():
Enable the stream after IDE_KM.

In support of system administrators auditing where platform, Root Port,
and Endpoint IDE stream resources are being spent, the allocated stream
is reflected as a symlink from the host bridge to the endpoint with the
name:

stream%d.%d.%d

Where the tuple of integers reflects the allocated platform, Root Port,
and Endpoint stream index (Selective IDE Stream Register Block) values.

Thanks to Wu Hao for a draft implementation of this infrastructure.

Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Lukas Wunner <lukas@wunner.de>
Cc: Samuel Ortiz <sameo@rivosinc.com>
Co-developed-by: Alexey Kardashevskiy <aik@amd.com>
Signed-off-by: Alexey Kardashevskiy <aik@amd.com>
Co-developed-by: Xu Yilun <yilun.xu@linux.intel.com>
Signed-off-by: Xu Yilun <yilun.xu@linux.intel.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Link: https://patch.msgid.link/20251031212902.2256310-8-dan.j.williams@intel.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>

+529
+14
Documentation/ABI/testing/sysfs-devices-pci-host-bridge
··· 17 17 PNP0A08 (/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00). See 18 18 /sys/devices/pciDDDD:BB entry for details about the DDDD:BB 19 19 format. 20 + 21 + What: pciDDDD:BB/streamH.R.E 22 + Contact: linux-pci@vger.kernel.org 23 + Description: 24 + (RO) When a platform has established a secure connection, PCIe 25 + IDE, between two Partner Ports, this symlink appears. A stream 26 + consumes a Stream ID slot in each of the Host bridge (H), Root 27 + Port (R) and Endpoint (E). The link points to the Endpoint PCI 28 + device in the Selective IDE Stream pairing. Specifically, "R" 29 + and "E" represent the assigned Selective IDE Stream Register 30 + Block in the Root Port and Endpoint, and "H" represents a 31 + platform specific pool of stream resources shared by the Root 32 + Ports in a host bridge. See /sys/devices/pciDDDD:BB entry for 33 + details about the DDDD:BB format.
+428
drivers/pci/ide.c
··· 5 5 6 6 #define dev_fmt(fmt) "PCI/IDE: " fmt 7 7 #include <linux/bitfield.h> 8 + #include <linux/bitops.h> 8 9 #include <linux/pci.h> 10 + #include <linux/pci-ide.h> 9 11 #include <linux/pci_regs.h> 12 + #include <linux/slab.h> 13 + #include <linux/sysfs.h> 10 14 11 15 #include "pci.h" 12 16 ··· 27 23 return offset + stream_index * PCI_IDE_SEL_BLOCK_SIZE(nr_ide_mem); 28 24 } 29 25 26 + static int sel_ide_offset(struct pci_dev *pdev, 27 + struct pci_ide_partner *settings) 28 + { 29 + return __sel_ide_offset(pdev->ide_cap, pdev->nr_link_ide, 30 + settings->stream_index, pdev->nr_ide_mem); 31 + } 32 + 30 33 void pci_ide_init(struct pci_dev *pdev) 31 34 { 32 35 u16 nr_link_ide, nr_ide_mem, nr_streams; 33 36 u16 ide_cap; 34 37 u32 val; 38 + 39 + /* 40 + * Unconditionally init so that ida idle state is consistent with 41 + * pdev->ide_cap. 42 + */ 43 + ida_init(&pdev->ide_stream_ida); 35 44 36 45 if (!pci_is_pcie(pdev)) 37 46 return; ··· 101 84 102 85 pdev->ide_cap = ide_cap; 103 86 pdev->nr_link_ide = nr_link_ide; 87 + pdev->nr_sel_ide = nr_streams; 104 88 pdev->nr_ide_mem = nr_ide_mem; 89 + } 90 + 91 + struct stream_index { 92 + struct ida *ida; 93 + u8 stream_index; 94 + }; 95 + 96 + static void free_stream_index(struct stream_index *stream) 97 + { 98 + ida_free(stream->ida, stream->stream_index); 99 + } 100 + 101 + DEFINE_FREE(free_stream, struct stream_index *, if (_T) free_stream_index(_T)) 102 + static struct stream_index *alloc_stream_index(struct ida *ida, u16 max, 103 + struct stream_index *stream) 104 + { 105 + int id; 106 + 107 + if (!max) 108 + return NULL; 109 + 110 + id = ida_alloc_max(ida, max - 1, GFP_KERNEL); 111 + if (id < 0) 112 + return NULL; 113 + 114 + *stream = (struct stream_index) { 115 + .ida = ida, 116 + .stream_index = id, 117 + }; 118 + return stream; 119 + } 120 + 121 + /** 122 + * pci_ide_stream_alloc() - Reserve stream indices and probe for settings 123 + * @pdev: IDE capable PCIe Endpoint Physical Function 124 + * 125 + * Retrieve the Requester ID range of @pdev for programming its Root 126 + * Port IDE RID Association registers, and conversely retrieve the 127 + * Requester ID of the Root Port for programming @pdev's IDE RID 128 + * Association registers. 129 + * 130 + * Allocate a Selective IDE Stream Register Block instance per port. 131 + * 132 + * Allocate a platform stream resource from the associated host bridge. 133 + * Retrieve stream association parameters for Requester ID range and 134 + * address range restrictions for the stream. 135 + */ 136 + struct pci_ide *pci_ide_stream_alloc(struct pci_dev *pdev) 137 + { 138 + /* EP, RP, + HB Stream allocation */ 139 + struct stream_index __stream[PCI_IDE_HB + 1]; 140 + struct pci_host_bridge *hb; 141 + struct pci_dev *rp; 142 + int num_vf, rid_end; 143 + 144 + if (!pci_is_pcie(pdev)) 145 + return NULL; 146 + 147 + if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ENDPOINT) 148 + return NULL; 149 + 150 + if (!pdev->ide_cap) 151 + return NULL; 152 + 153 + struct pci_ide *ide __free(kfree) = kzalloc(sizeof(*ide), GFP_KERNEL); 154 + if (!ide) 155 + return NULL; 156 + 157 + hb = pci_find_host_bridge(pdev->bus); 158 + struct stream_index *hb_stream __free(free_stream) = alloc_stream_index( 159 + &hb->ide_stream_ida, hb->nr_ide_streams, &__stream[PCI_IDE_HB]); 160 + if (!hb_stream) 161 + return NULL; 162 + 163 + rp = pcie_find_root_port(pdev); 164 + struct stream_index *rp_stream __free(free_stream) = alloc_stream_index( 165 + &rp->ide_stream_ida, rp->nr_sel_ide, &__stream[PCI_IDE_RP]); 166 + if (!rp_stream) 167 + return NULL; 168 + 169 + struct stream_index *ep_stream __free(free_stream) = alloc_stream_index( 170 + &pdev->ide_stream_ida, pdev->nr_sel_ide, &__stream[PCI_IDE_EP]); 171 + if (!ep_stream) 172 + return NULL; 173 + 174 + /* for SR-IOV case, cover all VFs */ 175 + num_vf = pci_num_vf(pdev); 176 + if (num_vf) 177 + rid_end = PCI_DEVID(pci_iov_virtfn_bus(pdev, num_vf), 178 + pci_iov_virtfn_devfn(pdev, num_vf)); 179 + else 180 + rid_end = pci_dev_id(pdev); 181 + 182 + *ide = (struct pci_ide) { 183 + .pdev = pdev, 184 + .partner = { 185 + [PCI_IDE_EP] = { 186 + .rid_start = pci_dev_id(rp), 187 + .rid_end = pci_dev_id(rp), 188 + .stream_index = no_free_ptr(ep_stream)->stream_index, 189 + }, 190 + [PCI_IDE_RP] = { 191 + .rid_start = pci_dev_id(pdev), 192 + .rid_end = rid_end, 193 + .stream_index = no_free_ptr(rp_stream)->stream_index, 194 + }, 195 + }, 196 + .host_bridge_stream = no_free_ptr(hb_stream)->stream_index, 197 + .stream_id = -1, 198 + }; 199 + 200 + return_ptr(ide); 201 + } 202 + EXPORT_SYMBOL_GPL(pci_ide_stream_alloc); 203 + 204 + /** 205 + * pci_ide_stream_free() - unwind pci_ide_stream_alloc() 206 + * @ide: idle IDE settings descriptor 207 + * 208 + * Free all of the stream index (register block) allocations acquired by 209 + * pci_ide_stream_alloc(). The stream represented by @ide is assumed to 210 + * be unregistered and not instantiated in any device. 211 + */ 212 + void pci_ide_stream_free(struct pci_ide *ide) 213 + { 214 + struct pci_dev *pdev = ide->pdev; 215 + struct pci_dev *rp = pcie_find_root_port(pdev); 216 + struct pci_host_bridge *hb = pci_find_host_bridge(pdev->bus); 217 + 218 + ida_free(&pdev->ide_stream_ida, ide->partner[PCI_IDE_EP].stream_index); 219 + ida_free(&rp->ide_stream_ida, ide->partner[PCI_IDE_RP].stream_index); 220 + ida_free(&hb->ide_stream_ida, ide->host_bridge_stream); 221 + kfree(ide); 222 + } 223 + EXPORT_SYMBOL_GPL(pci_ide_stream_free); 224 + 225 + /** 226 + * pci_ide_stream_release() - unwind and release an @ide context 227 + * @ide: partially or fully registered IDE settings descriptor 228 + * 229 + * In support of automatic cleanup of IDE setup routines perform IDE 230 + * teardown in expected reverse order of setup and with respect to which 231 + * aspects of IDE setup have successfully completed. 232 + * 233 + * Be careful that setup order mirrors this shutdown order. Otherwise, 234 + * open code releasing the IDE context. 235 + */ 236 + void pci_ide_stream_release(struct pci_ide *ide) 237 + { 238 + struct pci_dev *pdev = ide->pdev; 239 + struct pci_dev *rp = pcie_find_root_port(pdev); 240 + 241 + if (ide->partner[PCI_IDE_RP].enable) 242 + pci_ide_stream_disable(rp, ide); 243 + 244 + if (ide->partner[PCI_IDE_EP].enable) 245 + pci_ide_stream_disable(pdev, ide); 246 + 247 + if (ide->partner[PCI_IDE_RP].setup) 248 + pci_ide_stream_teardown(rp, ide); 249 + 250 + if (ide->partner[PCI_IDE_EP].setup) 251 + pci_ide_stream_teardown(pdev, ide); 252 + 253 + if (ide->name) 254 + pci_ide_stream_unregister(ide); 255 + 256 + pci_ide_stream_free(ide); 257 + } 258 + EXPORT_SYMBOL_GPL(pci_ide_stream_release); 259 + 260 + /** 261 + * pci_ide_stream_register() - Prepare to activate an IDE Stream 262 + * @ide: IDE settings descriptor 263 + * 264 + * After a Stream ID has been acquired for @ide, record the presence of 265 + * the stream in sysfs. The expectation is that @ide is immutable while 266 + * registered. 267 + */ 268 + int pci_ide_stream_register(struct pci_ide *ide) 269 + { 270 + struct pci_dev *pdev = ide->pdev; 271 + struct pci_host_bridge *hb = pci_find_host_bridge(pdev->bus); 272 + u8 ep_stream, rp_stream; 273 + int rc; 274 + 275 + if (ide->stream_id < 0 || ide->stream_id > U8_MAX) { 276 + pci_err(pdev, "Setup fail: Invalid Stream ID: %d\n", ide->stream_id); 277 + return -ENXIO; 278 + } 279 + 280 + ep_stream = ide->partner[PCI_IDE_EP].stream_index; 281 + rp_stream = ide->partner[PCI_IDE_RP].stream_index; 282 + const char *name __free(kfree) = kasprintf(GFP_KERNEL, "stream%d.%d.%d", 283 + ide->host_bridge_stream, 284 + rp_stream, ep_stream); 285 + if (!name) 286 + return -ENOMEM; 287 + 288 + rc = sysfs_create_link(&hb->dev.kobj, &pdev->dev.kobj, name); 289 + if (rc) 290 + return rc; 291 + 292 + ide->name = no_free_ptr(name); 293 + 294 + return 0; 295 + } 296 + EXPORT_SYMBOL_GPL(pci_ide_stream_register); 297 + 298 + /** 299 + * pci_ide_stream_unregister() - unwind pci_ide_stream_register() 300 + * @ide: idle IDE settings descriptor 301 + * 302 + * In preparation for freeing @ide, remove sysfs enumeration for the 303 + * stream. 304 + */ 305 + void pci_ide_stream_unregister(struct pci_ide *ide) 306 + { 307 + struct pci_dev *pdev = ide->pdev; 308 + struct pci_host_bridge *hb = pci_find_host_bridge(pdev->bus); 309 + 310 + sysfs_remove_link(&hb->dev.kobj, ide->name); 311 + kfree(ide->name); 312 + ide->name = NULL; 313 + } 314 + EXPORT_SYMBOL_GPL(pci_ide_stream_unregister); 315 + 316 + static int pci_ide_domain(struct pci_dev *pdev) 317 + { 318 + if (pdev->fm_enabled) 319 + return pci_domain_nr(pdev->bus); 320 + return 0; 321 + } 322 + 323 + struct pci_ide_partner *pci_ide_to_settings(struct pci_dev *pdev, struct pci_ide *ide) 324 + { 325 + if (!pci_is_pcie(pdev)) { 326 + pci_warn_once(pdev, "not a PCIe device\n"); 327 + return NULL; 328 + } 329 + 330 + switch (pci_pcie_type(pdev)) { 331 + case PCI_EXP_TYPE_ENDPOINT: 332 + if (pdev != ide->pdev) { 333 + pci_warn_once(pdev, "setup expected Endpoint: %s\n", pci_name(ide->pdev)); 334 + return NULL; 335 + } 336 + return &ide->partner[PCI_IDE_EP]; 337 + case PCI_EXP_TYPE_ROOT_PORT: { 338 + struct pci_dev *rp = pcie_find_root_port(ide->pdev); 339 + 340 + if (pdev != rp) { 341 + pci_warn_once(pdev, "setup expected Root Port: %s\n", 342 + pci_name(rp)); 343 + return NULL; 344 + } 345 + return &ide->partner[PCI_IDE_RP]; 346 + } 347 + default: 348 + pci_warn_once(pdev, "invalid device type\n"); 349 + return NULL; 350 + } 351 + } 352 + EXPORT_SYMBOL_GPL(pci_ide_to_settings); 353 + 354 + static void set_ide_sel_ctl(struct pci_dev *pdev, struct pci_ide *ide, 355 + struct pci_ide_partner *settings, int pos, 356 + bool enable) 357 + { 358 + u32 val = FIELD_PREP(PCI_IDE_SEL_CTL_ID, ide->stream_id) | 359 + FIELD_PREP(PCI_IDE_SEL_CTL_DEFAULT, settings->default_stream) | 360 + FIELD_PREP(PCI_IDE_SEL_CTL_CFG_EN, pdev->ide_cfg) | 361 + FIELD_PREP(PCI_IDE_SEL_CTL_TEE_LIMITED, pdev->ide_tee_limit) | 362 + FIELD_PREP(PCI_IDE_SEL_CTL_EN, enable); 363 + 364 + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_CTL, val); 365 + } 366 + 367 + /** 368 + * pci_ide_stream_setup() - program settings to Selective IDE Stream registers 369 + * @pdev: PCIe device object for either a Root Port or Endpoint Partner Port 370 + * @ide: registered IDE settings descriptor 371 + * 372 + * When @pdev is a PCI_EXP_TYPE_ENDPOINT then the PCI_IDE_EP partner 373 + * settings are written to @pdev's Selective IDE Stream register block, 374 + * and when @pdev is a PCI_EXP_TYPE_ROOT_PORT, the PCI_IDE_RP settings 375 + * are selected. 376 + */ 377 + void pci_ide_stream_setup(struct pci_dev *pdev, struct pci_ide *ide) 378 + { 379 + struct pci_ide_partner *settings = pci_ide_to_settings(pdev, ide); 380 + int pos; 381 + u32 val; 382 + 383 + if (!settings) 384 + return; 385 + 386 + pos = sel_ide_offset(pdev, settings); 387 + 388 + val = FIELD_PREP(PCI_IDE_SEL_RID_1_LIMIT, settings->rid_end); 389 + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_RID_1, val); 390 + 391 + val = FIELD_PREP(PCI_IDE_SEL_RID_2_VALID, 1) | 392 + FIELD_PREP(PCI_IDE_SEL_RID_2_BASE, settings->rid_start) | 393 + FIELD_PREP(PCI_IDE_SEL_RID_2_SEG, pci_ide_domain(pdev)); 394 + 395 + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_RID_2, val); 396 + 397 + /* 398 + * Setup control register early for devices that expect 399 + * stream_id is set during key programming. 400 + */ 401 + set_ide_sel_ctl(pdev, ide, settings, pos, false); 402 + settings->setup = 1; 403 + } 404 + EXPORT_SYMBOL_GPL(pci_ide_stream_setup); 405 + 406 + /** 407 + * pci_ide_stream_teardown() - disable the stream and clear all settings 408 + * @pdev: PCIe device object for either a Root Port or Endpoint Partner Port 409 + * @ide: registered IDE settings descriptor 410 + * 411 + * For stream destruction, zero all registers that may have been written 412 + * by pci_ide_stream_setup(). Consider pci_ide_stream_disable() to leave 413 + * settings in place while temporarily disabling the stream. 414 + */ 415 + void pci_ide_stream_teardown(struct pci_dev *pdev, struct pci_ide *ide) 416 + { 417 + struct pci_ide_partner *settings = pci_ide_to_settings(pdev, ide); 418 + int pos; 419 + 420 + if (!settings) 421 + return; 422 + 423 + pos = sel_ide_offset(pdev, settings); 424 + 425 + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_CTL, 0); 426 + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_RID_2, 0); 427 + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_RID_1, 0); 428 + settings->setup = 0; 429 + } 430 + EXPORT_SYMBOL_GPL(pci_ide_stream_teardown); 431 + 432 + /** 433 + * pci_ide_stream_enable() - enable a Selective IDE Stream 434 + * @pdev: PCIe device object for either a Root Port or Endpoint Partner Port 435 + * @ide: registered and setup IDE settings descriptor 436 + * 437 + * Activate the stream by writing to the Selective IDE Stream Control 438 + * Register. 439 + * 440 + * Return: 0 if the stream successfully entered the "secure" state, and -EINVAL 441 + * if @ide is invalid, and -ENXIO if the stream fails to enter the secure state. 442 + * 443 + * Note that the state may go "insecure" at any point after returning 0, but 444 + * those events are equivalent to a "link down" event and handled via 445 + * asynchronous error reporting. 446 + * 447 + * Caller is responsible to clear the enable bit in the -ENXIO case. 448 + */ 449 + int pci_ide_stream_enable(struct pci_dev *pdev, struct pci_ide *ide) 450 + { 451 + struct pci_ide_partner *settings = pci_ide_to_settings(pdev, ide); 452 + int pos; 453 + u32 val; 454 + 455 + if (!settings) 456 + return -EINVAL; 457 + 458 + pos = sel_ide_offset(pdev, settings); 459 + 460 + set_ide_sel_ctl(pdev, ide, settings, pos, true); 461 + settings->enable = 1; 462 + 463 + pci_read_config_dword(pdev, pos + PCI_IDE_SEL_STS, &val); 464 + if (FIELD_GET(PCI_IDE_SEL_STS_STATE, val) != 465 + PCI_IDE_SEL_STS_STATE_SECURE) 466 + return -ENXIO; 467 + 468 + return 0; 469 + } 470 + EXPORT_SYMBOL_GPL(pci_ide_stream_enable); 471 + 472 + /** 473 + * pci_ide_stream_disable() - disable a Selective IDE Stream 474 + * @pdev: PCIe device object for either a Root Port or Endpoint Partner Port 475 + * @ide: registered and setup IDE settings descriptor 476 + * 477 + * Clear the Selective IDE Stream Control Register, but leave all other 478 + * registers untouched. 479 + */ 480 + void pci_ide_stream_disable(struct pci_dev *pdev, struct pci_ide *ide) 481 + { 482 + struct pci_ide_partner *settings = pci_ide_to_settings(pdev, ide); 483 + int pos; 484 + 485 + if (!settings) 486 + return; 487 + 488 + pos = sel_ide_offset(pdev, settings); 489 + 490 + pci_write_config_dword(pdev, pos + PCI_IDE_SEL_CTL, 0); 491 + settings->enable = 0; 492 + } 493 + EXPORT_SYMBOL_GPL(pci_ide_stream_disable); 494 + 495 + void pci_ide_init_host_bridge(struct pci_host_bridge *hb) 496 + { 497 + hb->nr_ide_streams = 256; 498 + ida_init(&hb->ide_stream_ida); 105 499 }
+2
drivers/pci/pci.h
··· 615 615 616 616 #ifdef CONFIG_PCI_IDE 617 617 void pci_ide_init(struct pci_dev *dev); 618 + void pci_ide_init_host_bridge(struct pci_host_bridge *hb); 618 619 #else 619 620 static inline void pci_ide_init(struct pci_dev *dev) { } 621 + static inline void pci_ide_init_host_bridge(struct pci_host_bridge *hb) { } 620 622 #endif 621 623 622 624 #ifdef CONFIG_PCI_TSM
+1
drivers/pci/probe.c
··· 672 672 bridge->native_dpc = 1; 673 673 bridge->domain_nr = PCI_DOMAIN_NR_NOT_SET; 674 674 bridge->native_cxl_error = 1; 675 + pci_ide_init_host_bridge(bridge); 675 676 676 677 device_initialize(&bridge->dev); 677 678 }
+78
include/linux/pci-ide.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Common helpers for drivers (e.g. low-level PCI/TSM drivers) implementing the 4 + * IDE key management protocol (IDE_KM) as defined by: 5 + * PCIe r7.0 section 6.33 Integrity & Data Encryption (IDE) 6 + * 7 + * Copyright(c) 2024-2025 Intel Corporation. All rights reserved. 8 + */ 9 + 10 + #ifndef __PCI_IDE_H__ 11 + #define __PCI_IDE_H__ 12 + 13 + enum pci_ide_partner_select { 14 + PCI_IDE_EP, 15 + PCI_IDE_RP, 16 + PCI_IDE_PARTNER_MAX, 17 + /* 18 + * In addition to the resources in each partner port the 19 + * platform / host-bridge additionally has a Stream ID pool that 20 + * it shares across root ports. Let pci_ide_stream_alloc() use 21 + * the alloc_stream_index() helper as endpoints and root ports. 22 + */ 23 + PCI_IDE_HB = PCI_IDE_PARTNER_MAX, 24 + }; 25 + 26 + /** 27 + * struct pci_ide_partner - Per port pair Selective IDE Stream settings 28 + * @rid_start: Partner Port Requester ID range start 29 + * @rid_end: Partner Port Requester ID range end 30 + * @stream_index: Selective IDE Stream Register Block selection 31 + * @default_stream: Endpoint uses this stream for all upstream TLPs regardless of 32 + * address and RID association registers 33 + * @setup: flag to track whether to run pci_ide_stream_teardown() for this 34 + * partner slot 35 + * @enable: flag whether to run pci_ide_stream_disable() for this partner slot 36 + */ 37 + struct pci_ide_partner { 38 + u16 rid_start; 39 + u16 rid_end; 40 + u8 stream_index; 41 + unsigned int default_stream:1; 42 + unsigned int setup:1; 43 + unsigned int enable:1; 44 + }; 45 + 46 + /** 47 + * struct pci_ide - PCIe Selective IDE Stream descriptor 48 + * @pdev: PCIe Endpoint in the pci_ide_partner pair 49 + * @partner: per-partner settings 50 + * @host_bridge_stream: allocated from host bridge @ide_stream_ida pool 51 + * @stream_id: unique Stream ID (within Partner Port pairing) 52 + * @name: name of the established Selective IDE Stream in sysfs 53 + * 54 + * Negative @stream_id values indicate "uninitialized" on the 55 + * expectation that with TSM established IDE the TSM owns the stream_id 56 + * allocation. 57 + */ 58 + struct pci_ide { 59 + struct pci_dev *pdev; 60 + struct pci_ide_partner partner[PCI_IDE_PARTNER_MAX]; 61 + u8 host_bridge_stream; 62 + int stream_id; 63 + const char *name; 64 + }; 65 + 66 + struct pci_ide_partner *pci_ide_to_settings(struct pci_dev *pdev, 67 + struct pci_ide *ide); 68 + struct pci_ide *pci_ide_stream_alloc(struct pci_dev *pdev); 69 + void pci_ide_stream_free(struct pci_ide *ide); 70 + int pci_ide_stream_register(struct pci_ide *ide); 71 + void pci_ide_stream_unregister(struct pci_ide *ide); 72 + void pci_ide_stream_setup(struct pci_dev *pdev, struct pci_ide *ide); 73 + void pci_ide_stream_teardown(struct pci_dev *pdev, struct pci_ide *ide); 74 + int pci_ide_stream_enable(struct pci_dev *pdev, struct pci_ide *ide); 75 + void pci_ide_stream_disable(struct pci_dev *pdev, struct pci_ide *ide); 76 + void pci_ide_stream_release(struct pci_ide *ide); 77 + DEFINE_FREE(pci_ide_stream_release, struct pci_ide *, if (_T) pci_ide_stream_release(_T)) 78 + #endif /* __PCI_IDE_H__ */
+6
include/linux/pci.h
··· 545 545 u16 ide_cap; /* Link Integrity & Data Encryption */ 546 546 u8 nr_ide_mem; /* Address association resources for streams */ 547 547 u8 nr_link_ide; /* Link Stream count (Selective Stream offset) */ 548 + u16 nr_sel_ide; /* Selective Stream count (register block allocator) */ 549 + struct ida ide_stream_ida; 548 550 unsigned int ide_cfg:1; /* Config cycles over IDE */ 549 551 unsigned int ide_tee_limit:1; /* Disallow T=0 traffic over IDE */ 550 552 #endif ··· 616 614 int domain_nr; 617 615 struct list_head windows; /* resource_entry */ 618 616 struct list_head dma_ranges; /* dma ranges resource list */ 617 + #ifdef CONFIG_PCI_IDE 618 + u16 nr_ide_streams; /* Max streams possibly active in @ide_stream_ida */ 619 + struct ida ide_stream_ida; 620 + #endif 619 621 u8 (*swizzle_irq)(struct pci_dev *, u8 *); /* Platform IRQ swizzler */ 620 622 int (*map_irq)(const struct pci_dev *, u8, u8); 621 623 void (*release_fn)(struct pci_host_bridge *);