Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f7ea3d7f authored by Kenji Kaneshige's avatar Kenji Kaneshige Committed by Jesse Barnes
Browse files

PCI ASPM: cleanup __pcie_aspm_check_state_one



Clean up and simplify __pcie_aspm_check_state_one().

Acked-by: default avatarShaohua Li <shaohua.li@intel.com>
Signed-off-by: default avatarKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent 8d349ace
Loading
Loading
Loading
Loading
+25 −42
Original line number Diff line number Diff line
@@ -370,56 +370,39 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
	}
}

static unsigned int __pcie_aspm_check_state_one(struct pci_dev *pdev,
	unsigned int state)
/**
 * __pcie_aspm_check_state_one - check latency for endpoint device.
 * @endpoint: pointer to the struct pci_dev of endpoint device
 *
 * TBD: The latency from the endpoint to root complex vary per switch's
 * upstream link state above the device. Here we just do a simple check
 * which assumes all links above the device can be in L1 state, that
 * is we just consider the worst case. If switch's upstream link can't
 * be put into L0S/L1, then our check is too strictly.
 */
static u32 __pcie_aspm_check_state_one(struct pci_dev *endpoint, u32 state)
{
	struct pci_dev *parent_dev, *tmp_dev;
	unsigned int l1_latency = 0;
	struct pcie_link_state *link_state;
	u32 l1_switch_latency = 0;
	struct aspm_latency *acceptable;
	struct pcie_link_state *link;

	parent_dev = pdev->bus->self;
	link_state = parent_dev->link_state;
	state &= link_state->aspm_support;
	if (state == 0)
		return 0;
	acceptable = &link_state->acceptable[PCI_FUNC(pdev->devfn)];
	link = endpoint->bus->self->link_state;
	state &= link->aspm_support;
	acceptable = &link->acceptable[PCI_FUNC(endpoint->devfn)];

	/*
	 * Check latency for endpoint device.
	 * TBD: The latency from the endpoint to root complex vary per
	 * switch's upstream link state above the device. Here we just do a
	 * simple check which assumes all links above the device can be in L1
	 * state, that is we just consider the worst case. If switch's upstream
	 * link can't be put into L0S/L1, then our check is too strictly.
	 */
	tmp_dev = pdev;
	while (state & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
		parent_dev = tmp_dev->bus->self;
		link_state = parent_dev->link_state;
	while (link && state) {
		if ((state & PCIE_LINK_STATE_L0S) &&
		    (link_state->latency.l0s > acceptable->l0s))
		    (link->latency.l0s > acceptable->l0s))
			state &= ~PCIE_LINK_STATE_L0S;

		if ((state & PCIE_LINK_STATE_L1) &&
		    (link_state->latency.l1 + l1_latency > acceptable->l1))
		    (link->latency.l1 + l1_switch_latency > acceptable->l1))
			state &= ~PCIE_LINK_STATE_L1;

		if (!parent_dev->bus->self) /* parent_dev is a root port */
			break;
		else {
		link = link->parent;
		/*
			 * parent_dev is the downstream port of a switch, make
			 * tmp_dev the upstream port of the switch
		 * Every switch on the path to root complex need 1
		 * more microsecond for L1. Spec doesn't mention L0s.
		 */
			tmp_dev = parent_dev->bus->self;
			/*
			 * every switch on the path to root complex need 1 more
			 * microsecond for L1. Spec doesn't mention L0S.
			 */
			if (state & PCIE_LINK_STATE_L1)
				l1_latency += 1000;
		}
		l1_switch_latency += 1000;
	}
	return state;
}