drivers/pci/ide.c

Source file repositories/reference/linux-study-clean/drivers/pci/ide.c

File Facts

System
Linux kernel
Corpus path
drivers/pci/ide.c
Extension
.c
Size
23330 bytes
Lines
812
Domain
Representative Device Path
Bucket
PCIe NVMe Storage Path
Inferred role
Representative Device Path: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.

Dependency Surface

Detected Declarations

Annotated Snippet

struct stream_index {
	struct ida *ida;
	u8 stream_index;
};

static void free_stream_index(struct stream_index *stream)
{
	ida_free(stream->ida, stream->stream_index);
}

DEFINE_FREE(free_stream, struct stream_index *, if (_T) free_stream_index(_T))
static struct stream_index *alloc_stream_index(struct ida *ida, u16 max,
					       struct stream_index *stream)
{
	int id;

	if (!max)
		return NULL;

	id = ida_alloc_max(ida, max - 1, GFP_KERNEL);
	if (id < 0)
		return NULL;

	*stream = (struct stream_index) {
		.ida = ida,
		.stream_index = id,
	};
	return stream;
}

/**
 * pci_ide_stream_alloc() - Reserve stream indices and probe for settings
 * @pdev: IDE capable PCIe Endpoint Physical Function
 *
 * Retrieve the Requester ID range of @pdev for programming its Root
 * Port IDE RID Association registers, and conversely retrieve the
 * Requester ID of the Root Port for programming @pdev's IDE RID
 * Association registers.
 *
 * Allocate a Selective IDE Stream Register Block instance per port.
 *
 * Allocate a platform stream resource from the associated host bridge.
 * Retrieve stream association parameters for Requester ID range and
 * address range restrictions for the stream.
 */
struct pci_ide *pci_ide_stream_alloc(struct pci_dev *pdev)
{
	/* EP, RP, + HB Stream allocation */
	struct stream_index __stream[PCI_IDE_HB + 1];
	struct pci_bus_region pref_assoc = { 0, -1 };
	struct pci_bus_region mem_assoc = { 0, -1 };
	struct resource *mem, *pref;
	struct pci_host_bridge *hb;
	struct pci_dev *rp, *br;
	int num_vf, rid_end;

	if (!pci_is_pcie(pdev))
		return NULL;

	if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ENDPOINT)
		return NULL;

	if (!pdev->ide_cap)
		return NULL;

	struct pci_ide *ide __free(kfree) = kzalloc_obj(*ide);
	if (!ide)
		return NULL;

	hb = pci_find_host_bridge(pdev->bus);
	struct stream_index *hb_stream __free(free_stream) = alloc_stream_index(
		&hb->ide_stream_ida, hb->nr_ide_streams, &__stream[PCI_IDE_HB]);
	if (!hb_stream)
		return NULL;

	rp = pcie_find_root_port(pdev);
	struct stream_index *rp_stream __free(free_stream) = alloc_stream_index(
		&rp->ide_stream_ida, rp->nr_sel_ide, &__stream[PCI_IDE_RP]);
	if (!rp_stream)
		return NULL;

	struct stream_index *ep_stream __free(free_stream) = alloc_stream_index(
		&pdev->ide_stream_ida, pdev->nr_sel_ide, &__stream[PCI_IDE_EP]);
	if (!ep_stream)
		return NULL;

	/* for SR-IOV case, cover all VFs */
	num_vf = pci_num_vf(pdev);
	if (num_vf)
		rid_end = PCI_DEVID(pci_iov_virtfn_bus(pdev, num_vf - 1),

Annotation

Implementation Notes