// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2024-2025 Intel Corporation. All rights reserved. */

/* PCIe r7.0 section 6.33 Integrity & Data Encryption (IDE) */

#define dev_fmt(fmt) "PCI/IDE: " fmt
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/pci.h>
#include <linux/pci-ide.h>
#include <linux/pci_regs.h>
#include <linux/slab.h>
#include <linux/sysfs.h>

#include "pci.h"

static int __sel_ide_offset(u16 ide_cap, u8 nr_link_ide, u8 stream_index,
			    u8 nr_ide_mem)
{
	u32 offset = ide_cap + PCI_IDE_LINK_STREAM_0 +
		     nr_link_ide * PCI_IDE_LINK_BLOCK_SIZE;

	/*
	 * Assume a constant number of address association resources per stream
	 * index
	 */
	return offset + stream_index * PCI_IDE_SEL_BLOCK_SIZE(nr_ide_mem);
}

static int sel_ide_offset(struct pci_dev *pdev,
			  struct pci_ide_partner *settings)
{
	return __sel_ide_offset(pdev->ide_cap, pdev->nr_link_ide,
				settings->stream_index, pdev->nr_ide_mem);
}

static bool reserve_stream_index(struct pci_dev *pdev, u8 idx)
{
	int ret;

	ret = ida_alloc_range(&pdev->ide_stream_ida, idx, idx, GFP_KERNEL);
	return ret >= 0;
}

static bool reserve_stream_id(struct pci_host_bridge *hb, u8 id)
{
	int ret;

	ret = ida_alloc_range(&hb->ide_stream_ids_ida, id, id, GFP_KERNEL);
	return ret >= 0;
}

static bool claim_stream(struct pci_host_bridge *hb, u8 stream_id,
			 struct pci_dev *pdev, u8 stream_idx)
{
	dev_info(&hb->dev, "Stream ID %d active at init\n", stream_id);
	if (!reserve_stream_id(hb, stream_id)) {
		dev_info(&hb->dev, "Failed to claim %s Stream ID %d\n",
			 stream_id == PCI_IDE_RESERVED_STREAM_ID ? "reserved" :
								   "active",
			 stream_id);
		return false;
	}

	/* No stream index to reserve in the Link IDE case */
	if (!pdev)
		return true;

	if (!reserve_stream_index(pdev, stream_idx)) {
		pci_info(pdev, "Failed to claim active Selective Stream %d\n",
			 stream_idx);
		return false;
	}

	return true;
}

void pci_ide_init(struct pci_dev *pdev)
{
	struct pci_host_bridge *hb = pci_find_host_bridge(pdev->bus);
	u16 nr_link_ide, nr_ide_mem, nr_streams;
	u16 ide_cap;
	u32 val;

	/*
	 * Unconditionally init so that ida idle state is consistent with
	 * pdev->ide_cap.
	 */
	ida_init(&pdev->ide_stream_ida);

	if (!pci_is_pcie(pdev))
		return;

	ide_cap = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_IDE);
	if (!ide_cap)
		return;

	pci_read_config_dword(pdev, ide_cap + PCI_IDE_CAP, &val);
	if ((val & PCI_IDE_CAP_SELECTIVE) == 0)
		return;

	/*
	 * Require endpoint IDE capability to be paired with IDE Root Port IDE
	 * capability.
	 */
	if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ENDPOINT) {
		struct pci_dev *rp = pcie_find_root_port(pdev);

		if (!rp->ide_cap)
			return;
	}

	pdev->ide_cfg = FIELD_GET(PCI_IDE_CAP_SEL_CFG, val);
	pdev->ide_tee_limit = FIELD_GET(PCI_IDE_CAP_TEE_LIMITED, val);

	if (val & PCI_IDE_CAP_LINK)
		nr_link_ide = 1 + FIELD_GET(PCI_IDE_CAP_LINK_TC_NUM, val);
	else
		nr_link_ide = 0;

	nr_ide_mem = 0;
	nr_streams = 1 + FIELD_GET(PCI_IDE_CAP_SEL_NUM, val);
	for (u16 i = 0; i < nr_streams; i++) {
		int pos = __sel_ide_offset(ide_cap, nr_link_ide, i, nr_ide_mem);
		int nr_assoc;
		u32 val;
		u8 id;

		pci_read_config_dword(pdev, pos + PCI_IDE_SEL_CAP, &val);

		/*
		 * Let's not entertain streams that do not have a constant
		 * number of address association blocks
		 */
		nr_assoc = FIELD_GET(PCI_IDE_SEL_CAP_ASSOC_NUM, val);
		if (i && (nr_assoc != nr_ide_mem)) {
			pci_info(pdev, "Unsupported Selective Stream %d capability, SKIP the rest\n", i);
			nr_streams = i;
			break;
		}

		nr_ide_mem = nr_assoc;

		/*
		 * Claim Stream IDs and Selective Stream blocks that are already
		 * active on the device
		 */
		pci_read_config_dword(pdev, pos + PCI_IDE_SEL_CTL, &val);
		id = FIELD_GET(PCI_IDE_SEL_CTL_ID, val);
		if ((val & PCI_IDE_SEL_CTL_EN) &&
		    !claim_stream(hb, id, pdev, i))
			return;
	}

	/* Reserve link stream-ids that are already active on the device */
	for (u16 i = 0; i < nr_link_ide; ++i) {
		int pos = ide_cap + PCI_IDE_LINK_STREAM_0 + i * PCI_IDE_LINK_BLOCK_SIZE;
		u8 id;

		pci_read_config_dword(pdev, pos + PCI_IDE_LINK_CTL_0, &val);
		id = FIELD_GET(PCI_IDE_LINK_CTL_ID, val);
		if ((val & PCI_IDE_LINK_CTL_EN) &&
		    !claim_stream(hb, id, NULL, -1))
			return;
	}

	for (u16 i = 0; i < nr_streams; i++) {
		int pos = __sel_ide_offset(ide_cap, nr_link_ide, i, nr_ide_mem);

		pci_read_config_dword(pdev, pos + PCI_IDE_SEL_CTL, &val);
		if (val & PCI_IDE_SEL_CTL_EN)
			continue;
		FIELD_MODIFY(PCI_IDE_SEL_CTL_ID, &val, PCI_IDE_RESERVED_STREAM_ID);
		pci_write_config_dword(pdev, pos + PCI_IDE_SEL_CTL, val);
	}

	for (u16 i = 0; i < nr_link_ide; ++i) {
		int pos = ide_cap + PCI_IDE_LINK_STREAM_0 +
			  i * PCI_IDE_LINK_BLOCK_SIZE;

		pci_read_config_dword(pdev, pos, &val);
		if (val & PCI_IDE_LINK_CTL_EN)
			continue;
		FIELD_MODIFY(PCI_IDE_LINK_CTL_ID, &val, PCI_IDE_RESERVED_STREAM_ID);
		pci_write_config_dword(pdev, pos, val);
	}

	pdev->ide_cap = ide_cap;
	pdev->nr_link_ide = nr_link_ide;
	pdev->nr_sel_ide = nr_streams;
	pdev->nr_ide_mem = nr_ide_mem;
}

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),
				    pci_iov_virtfn_devfn(pdev, num_vf - 1));
	else
		rid_end = pci_dev_id(pdev);

	br = pci_upstream_bridge(pdev);
	if (!br)
		return NULL;

	/*
	 * Check if the device consumes memory and/or prefetch-memory. Setup
	 * downstream address association ranges for each.
	 */
	mem = pci_resource_n(br, PCI_BRIDGE_MEM_WINDOW);
	pref = pci_resource_n(br, PCI_BRIDGE_PREF_MEM_WINDOW);
	if (resource_assigned(mem))
		pcibios_resource_to_bus(br->bus, &mem_assoc, mem);
	if (resource_assigned(pref))
		pcibios_resource_to_bus(br->bus, &pref_assoc, pref);

	*ide = (struct pci_ide) {
		.pdev = pdev,
		.partner = {
			[PCI_IDE_EP] = {
				.rid_start = pci_dev_id(rp),
				.rid_end = pci_dev_id(rp),
				.stream_index = no_free_ptr(ep_stream)->stream_index,
				/* Disable upstream address association */
				.mem_assoc = { 0, -1 },
				.pref_assoc = { 0, -1 },
			},
			[PCI_IDE_RP] = {
				.rid_start = pci_dev_id(pdev),
				.rid_end = rid_end,
				.stream_index = no_free_ptr(rp_stream)->stream_index,
				.mem_assoc = mem_assoc,
				.pref_assoc = pref_assoc,
			},
		},
		.host_bridge_stream = no_free_ptr(hb_stream)->stream_index,
		.stream_id = -1,
	};

	return_ptr(ide);
}
EXPORT_SYMBOL_GPL(pci_ide_stream_alloc);

/**
 * pci_ide_stream_free() - unwind pci_ide_stream_alloc()
 * @ide: idle IDE settings descriptor
 *
 * Free all of the stream index (register block) allocations acquired by
 * pci_ide_stream_alloc(). The stream represented by @ide is assumed to
 * be unregistered and not instantiated in any device.
 */
void pci_ide_stream_free(struct pci_ide *ide)
{
	struct pci_dev *pdev = ide->pdev;
	struct pci_dev *rp = pcie_find_root_port(pdev);
	struct pci_host_bridge *hb = pci_find_host_bridge(pdev->bus);

	ida_free(&pdev->ide_stream_ida, ide->partner[PCI_IDE_EP].stream_index);
	ida_free(&rp->ide_stream_ida, ide->partner[PCI_IDE_RP].stream_index);
	ida_free(&hb->ide_stream_ida, ide->host_bridge_stream);
	kfree(ide);
}
EXPORT_SYMBOL_GPL(pci_ide_stream_free);

/**
 * pci_ide_stream_release() - unwind and release an @ide context
 * @ide: partially or fully registered IDE settings descriptor
 *
 * In support of automatic cleanup of IDE setup routines perform IDE
 * teardown in expected reverse order of setup and with respect to which
 * aspects of IDE setup have successfully completed.
 *
 * Be careful that setup order mirrors this shutdown order. Otherwise,
 * open code releasing the IDE context.
 */
void pci_ide_stream_release(struct pci_ide *ide)
{
	struct pci_dev *pdev = ide->pdev;
	struct pci_dev *rp = pcie_find_root_port(pdev);

	if (ide->partner[PCI_IDE_RP].enable)
		pci_ide_stream_disable(rp, ide);

	if (ide->partner[PCI_IDE_EP].enable)
		pci_ide_stream_disable(pdev, ide);

	if (ide->partner[PCI_IDE_RP].setup)
		pci_ide_stream_teardown(rp, ide);

	if (ide->partner[PCI_IDE_EP].setup)
		pci_ide_stream_teardown(pdev, ide);

	if (ide->name)
		pci_ide_stream_unregister(ide);

	pci_ide_stream_free(ide);
}
EXPORT_SYMBOL_GPL(pci_ide_stream_release);

struct pci_ide_stream_id {
	struct pci_host_bridge *hb;
	u8 stream_id;
};

static struct pci_ide_stream_id *
request_stream_id(struct pci_host_bridge *hb, u8 stream_id,
		  struct pci_ide_stream_id *sid)
{
	if (!reserve_stream_id(hb, stream_id))
		return NULL;

	*sid = (struct pci_ide_stream_id) {
		.hb = hb,
		.stream_id = stream_id,
	};

	return sid;
}
DEFINE_FREE(free_stream_id, struct pci_ide_stream_id *,
	    if (_T) ida_free(&_T->hb->ide_stream_ids_ida, _T->stream_id))

/**
 * pci_ide_stream_register() - Prepare to activate an IDE Stream
 * @ide: IDE settings descriptor
 *
 * After a Stream ID has been acquired for @ide, record the presence of
 * the stream in sysfs. The expectation is that @ide is immutable while
 * registered.
 */
int pci_ide_stream_register(struct pci_ide *ide)
{
	struct pci_dev *pdev = ide->pdev;
	struct pci_host_bridge *hb = pci_find_host_bridge(pdev->bus);
	struct pci_ide_stream_id __sid;
	u8 ep_stream, rp_stream;
	int rc;

	if (ide->stream_id < 0 || ide->stream_id > U8_MAX) {
		pci_err(pdev, "Setup fail: Invalid Stream ID: %d\n", ide->stream_id);
		return -ENXIO;
	}

	struct pci_ide_stream_id *sid __free(free_stream_id) =
		request_stream_id(hb, ide->stream_id, &__sid);
	if (!sid) {
		pci_err(pdev, "Setup fail: Stream ID %d in use\n", ide->stream_id);
		return -EBUSY;
	}

	ep_stream = ide->partner[PCI_IDE_EP].stream_index;
	rp_stream = ide->partner[PCI_IDE_RP].stream_index;
	const char *name __free(kfree) = kasprintf(GFP_KERNEL, "stream%d.%d.%d",
						   ide->host_bridge_stream,
						   rp_stream, ep_stream);
	if (!name)
		return -ENOMEM;

	rc = sysfs_create_link(&hb->dev.kobj, &pdev->dev.kobj, name);
	if (rc)
		return rc;

	ide->name = no_free_ptr(name);

	/* Stream ID reservation recorded in @ide is now successfully registered */
	retain_and_null_ptr(sid);

	return 0;
}
EXPORT_SYMBOL_GPL(pci_ide_stream_register);

/**
 * pci_ide_stream_unregister() - unwind pci_ide_stream_register()
 * @ide: idle IDE settings descriptor
 *
 * In preparation for freeing @ide, remove sysfs enumeration for the
 * stream.
 */
void pci_ide_stream_unregister(struct pci_ide *ide)
{
	struct pci_dev *pdev = ide->pdev;
	struct pci_host_bridge *hb = pci_find_host_bridge(pdev->bus);

	sysfs_remove_link(&hb->dev.kobj, ide->name);
	kfree(ide->name);
	ida_free(&hb->ide_stream_ids_ida, ide->stream_id);
	ide->name = NULL;
}
EXPORT_SYMBOL_GPL(pci_ide_stream_unregister);

static int pci_ide_domain(struct pci_dev *pdev)
{
	if (pdev->fm_enabled)
		return pci_domain_nr(pdev->bus);
	return 0;
}

struct pci_ide_partner *pci_ide_to_settings(struct pci_dev *pdev, struct pci_ide *ide)
{
	if (!pci_is_pcie(pdev)) {
		pci_warn_once(pdev, "not a PCIe device\n");
		return NULL;
	}

	switch (pci_pcie_type(pdev)) {
	case PCI_EXP_TYPE_ENDPOINT:
		if (pdev != ide->pdev) {
			pci_warn_once(pdev, "setup expected Endpoint: %s\n", pci_name(ide->pdev));
			return NULL;
		}
		return &ide->partner[PCI_IDE_EP];
	case PCI_EXP_TYPE_ROOT_PORT: {
		struct pci_dev *rp = pcie_find_root_port(ide->pdev);

		if (pdev != rp) {
			pci_warn_once(pdev, "setup expected Root Port: %s\n",
				      pci_name(rp));
			return NULL;
		}
		return &ide->partner[PCI_IDE_RP];
	}
	default:
		pci_warn_once(pdev, "invalid device type\n");
		return NULL;
	}
}
EXPORT_SYMBOL_GPL(pci_ide_to_settings);

static void set_ide_sel_ctl(struct pci_dev *pdev, struct pci_ide *ide,
			    struct pci_ide_partner *settings, int pos,
			    bool enable)
{
	u32 val = FIELD_PREP(PCI_IDE_SEL_CTL_ID, ide->stream_id) |
		  FIELD_PREP(PCI_IDE_SEL_CTL_DEFAULT, settings->default_stream) |
		  FIELD_PREP(PCI_IDE_SEL_CTL_CFG_EN, pdev->ide_cfg) |
		  FIELD_PREP(PCI_IDE_SEL_CTL_TEE_LIMITED, pdev->ide_tee_limit) |
		  FIELD_PREP(PCI_IDE_SEL_CTL_EN, enable);

	pci_write_config_dword(pdev, pos + PCI_IDE_SEL_CTL, val);
}

#define SEL_ADDR1_LOWER GENMASK(31, 20)
#define SEL_ADDR_UPPER GENMASK_ULL(63, 32)
#define PREP_PCI_IDE_SEL_ADDR1(base, limit)			\
	(FIELD_PREP(PCI_IDE_SEL_ADDR_1_VALID, 1) |		\
	 FIELD_PREP(PCI_IDE_SEL_ADDR_1_BASE_LOW,		\
		    FIELD_GET(SEL_ADDR1_LOWER, (base))) |	\
	 FIELD_PREP(PCI_IDE_SEL_ADDR_1_LIMIT_LOW,		\
		    FIELD_GET(SEL_ADDR1_LOWER, (limit))))

static void mem_assoc_to_regs(struct pci_bus_region *region,
			      struct pci_ide_regs *regs, int idx)
{
	/* convert to u64 range for bitfield size checks */
	struct range r = { region->start, region->end };

	regs->addr[idx].assoc1 = PREP_PCI_IDE_SEL_ADDR1(r.start, r.end);
	regs->addr[idx].assoc2 = FIELD_GET(SEL_ADDR_UPPER, r.end);
	regs->addr[idx].assoc3 = FIELD_GET(SEL_ADDR_UPPER, r.start);
}

/**
 * pci_ide_stream_to_regs() - convert IDE settings to association register values
 * @pdev: PCIe device object for either a Root Port or Endpoint Partner Port
 * @ide: registered IDE settings descriptor
 * @regs: output register values
 */
static void pci_ide_stream_to_regs(struct pci_dev *pdev, struct pci_ide *ide,
				   struct pci_ide_regs *regs)
{
	struct pci_ide_partner *settings = pci_ide_to_settings(pdev, ide);
	int assoc_idx = 0;

	memset(regs, 0, sizeof(*regs));

	if (!settings)
		return;

	regs->rid1 = FIELD_PREP(PCI_IDE_SEL_RID_1_LIMIT, settings->rid_end);

	regs->rid2 = FIELD_PREP(PCI_IDE_SEL_RID_2_VALID, 1) |
		     FIELD_PREP(PCI_IDE_SEL_RID_2_BASE, settings->rid_start) |
		     FIELD_PREP(PCI_IDE_SEL_RID_2_SEG, pci_ide_domain(pdev));

	if (pdev->nr_ide_mem && pci_bus_region_size(&settings->mem_assoc)) {
		mem_assoc_to_regs(&settings->mem_assoc, regs, assoc_idx);
		assoc_idx++;
	}

	if (pdev->nr_ide_mem > assoc_idx &&
	    pci_bus_region_size(&settings->pref_assoc)) {
		mem_assoc_to_regs(&settings->pref_assoc, regs, assoc_idx);
		assoc_idx++;
	}

	regs->nr_addr = assoc_idx;
}

/**
 * pci_ide_stream_setup() - program settings to Selective IDE Stream registers
 * @pdev: PCIe device object for either a Root Port or Endpoint Partner Port
 * @ide: registered IDE settings descriptor
 *
 * When @pdev is a PCI_EXP_TYPE_ENDPOINT then the PCI_IDE_EP partner
 * settings are written to @pdev's Selective IDE Stream register block,
 * and when @pdev is a PCI_EXP_TYPE_ROOT_PORT, the PCI_IDE_RP settings
 * are selected.
 */
void pci_ide_stream_setup(struct pci_dev *pdev, struct pci_ide *ide)
{
	struct pci_ide_partner *settings = pci_ide_to_settings(pdev, ide);
	struct pci_ide_regs regs;
	int pos;

	if (!settings)
		return;

	pci_ide_stream_to_regs(pdev, ide, &regs);

	pos = sel_ide_offset(pdev, settings);

	pci_write_config_dword(pdev, pos + PCI_IDE_SEL_RID_1, regs.rid1);
	pci_write_config_dword(pdev, pos + PCI_IDE_SEL_RID_2, regs.rid2);

	for (int i = 0; i < regs.nr_addr; i++) {
		pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_1(i),
				       regs.addr[i].assoc1);
		pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_2(i),
				       regs.addr[i].assoc2);
		pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_3(i),
				       regs.addr[i].assoc3);
	}

	/* clear extra unused address association blocks */
	for (int i = regs.nr_addr; i < pdev->nr_ide_mem; i++) {
		pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_1(i), 0);
		pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_2(i), 0);
		pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_3(i), 0);
	}

	/*
	 * Setup control register early for devices that expect
	 * stream_id is set during key programming.
	 */
	set_ide_sel_ctl(pdev, ide, settings, pos, false);
	settings->setup = 1;
}
EXPORT_SYMBOL_GPL(pci_ide_stream_setup);

/**
 * pci_ide_stream_teardown() - disable the stream and clear all settings
 * @pdev: PCIe device object for either a Root Port or Endpoint Partner Port
 * @ide: registered IDE settings descriptor
 *
 * For stream destruction, zero all registers that may have been written
 * by pci_ide_stream_setup(). Consider pci_ide_stream_disable() to leave
 * settings in place while temporarily disabling the stream.
 */
void pci_ide_stream_teardown(struct pci_dev *pdev, struct pci_ide *ide)
{
	struct pci_ide_partner *settings = pci_ide_to_settings(pdev, ide);
	int pos, i;

	if (!settings)
		return;

	pos = sel_ide_offset(pdev, settings);

	pci_write_config_dword(pdev, pos + PCI_IDE_SEL_CTL, 0);

	for (i = 0; i < pdev->nr_ide_mem; i++) {
		pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_1(i), 0);
		pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_2(i), 0);
		pci_write_config_dword(pdev, pos + PCI_IDE_SEL_ADDR_3(i), 0);
	}

	pci_write_config_dword(pdev, pos + PCI_IDE_SEL_RID_2, 0);
	pci_write_config_dword(pdev, pos + PCI_IDE_SEL_RID_1, 0);
	settings->setup = 0;
}
EXPORT_SYMBOL_GPL(pci_ide_stream_teardown);

/**
 * pci_ide_stream_enable() - enable a Selective IDE Stream
 * @pdev: PCIe device object for either a Root Port or Endpoint Partner Port
 * @ide: registered and setup IDE settings descriptor
 *
 * Activate the stream by writing to the Selective IDE Stream Control
 * Register.
 *
 * Return: 0 if the stream successfully entered the "secure" state, and -EINVAL
 * if @ide is invalid, and -ENXIO if the stream fails to enter the secure state.
 *
 * Note that the state may go "insecure" at any point after returning 0, but
 * those events are equivalent to a "link down" event and handled via
 * asynchronous error reporting.
 *
 * Caller is responsible to clear the enable bit in the -ENXIO case.
 */
int pci_ide_stream_enable(struct pci_dev *pdev, struct pci_ide *ide)
{
	struct pci_ide_partner *settings = pci_ide_to_settings(pdev, ide);
	int pos;
	u32 val;

	if (!settings)
		return -EINVAL;

	pos = sel_ide_offset(pdev, settings);

	set_ide_sel_ctl(pdev, ide, settings, pos, true);
	settings->enable = 1;

	pci_read_config_dword(pdev, pos + PCI_IDE_SEL_STS, &val);
	if (FIELD_GET(PCI_IDE_SEL_STS_STATE, val) !=
	    PCI_IDE_SEL_STS_STATE_SECURE)
		return -ENXIO;

	return 0;
}
EXPORT_SYMBOL_GPL(pci_ide_stream_enable);

/**
 * pci_ide_stream_disable() - disable a Selective IDE Stream
 * @pdev: PCIe device object for either a Root Port or Endpoint Partner Port
 * @ide: registered and setup IDE settings descriptor
 *
 * Clear the Selective IDE Stream Control Register, but leave all other
 * registers untouched.
 */
void pci_ide_stream_disable(struct pci_dev *pdev, struct pci_ide *ide)
{
	struct pci_ide_partner *settings = pci_ide_to_settings(pdev, ide);
	int pos;

	if (!settings)
		return;

	pos = sel_ide_offset(pdev, settings);

	pci_write_config_dword(pdev, pos + PCI_IDE_SEL_CTL, 0);
	settings->enable = 0;
}
EXPORT_SYMBOL_GPL(pci_ide_stream_disable);

void pci_ide_init_host_bridge(struct pci_host_bridge *hb)
{
	hb->nr_ide_streams = 256;
	ida_init(&hb->ide_stream_ida);
	ida_init(&hb->ide_stream_ids_ida);
	reserve_stream_id(hb, PCI_IDE_RESERVED_STREAM_ID);
}

static ssize_t available_secure_streams_show(struct device *dev,
					     struct device_attribute *attr,
					     char *buf)
{
	struct pci_host_bridge *hb = to_pci_host_bridge(dev);
	int nr = READ_ONCE(hb->nr_ide_streams);
	int avail = nr;

	if (!nr)
		return -ENXIO;

	/*
	 * Yes, this is inefficient and racy, but it is only for occasional
	 * platform resource surveys. Worst case is bounded to 256 streams.
	 */
	for (int i = 0; i < nr; i++)
		if (ida_exists(&hb->ide_stream_ida, i))
			avail--;
	return sysfs_emit(buf, "%d\n", avail);
}
static DEVICE_ATTR_RO(available_secure_streams);

static struct attribute *pci_ide_attrs[] = {
	&dev_attr_available_secure_streams.attr,
	NULL
};

static umode_t pci_ide_attr_visible(struct kobject *kobj, struct attribute *a, int n)
{
	struct device *dev = kobj_to_dev(kobj);
	struct pci_host_bridge *hb = to_pci_host_bridge(dev);

	if (a == &dev_attr_available_secure_streams.attr)
		if (!hb->nr_ide_streams)
			return 0;

	return a->mode;
}

const struct attribute_group pci_ide_attr_group = {
	.attrs = pci_ide_attrs,
	.is_visible = pci_ide_attr_visible,
};

/**
 * pci_ide_set_nr_streams() - sets size of the pool of IDE Stream resources
 * @hb: host bridge boundary for the stream pool
 * @nr: number of streams
 *
 * Platform PCI init and/or expert test module use only. Limit IDE
 * Stream establishment by setting the number of stream resources
 * available at the host bridge. Platform init code must set this before
 * the first pci_ide_stream_alloc() call if the platform has less than the
 * default of 256 streams per host-bridge.
 *
 * The "PCI_IDE" symbol namespace is required because this is typically
 * a detail that is settled in early PCI init. I.e. this export is not
 * for endpoint drivers.
 */
void pci_ide_set_nr_streams(struct pci_host_bridge *hb, u16 nr)
{
	hb->nr_ide_streams = min(nr, 256);
	WARN_ON_ONCE(!ida_is_empty(&hb->ide_stream_ida));
	sysfs_update_group(&hb->dev.kobj, &pci_ide_attr_group);
}
EXPORT_SYMBOL_NS_GPL(pci_ide_set_nr_streams, "PCI_IDE");

void pci_ide_destroy(struct pci_dev *pdev)
{
	ida_destroy(&pdev->ide_stream_ida);
}
