Skip to content

Commit b5dab9b

Browse files
floatiousMani-Sadhasivam
authored andcommitted
PCI: dwc: Clean up iATU index usage in dw_pcie_iatu_setup()
The current iATU index usage in dw_pcie_iatu_setup() is a mess. For outbound address translation the index is incremented before usage. For inbound address translation the index is incremented after usage. Incrementing the index after usage make much more sense, and make the index usage consistent for both outbound and inbound address translation. Most likely, the overly complicated logic for the outbound address translation is because the iATU at index 0 is reserved for CFG IOs (dw_pcie_other_conf_map_bus()), however, we should be able to use the exact same logic for the indexing of the outbound and inbound iATUs. (Only the starting index should be different.) Create two new variables ob_iatu_index and ib_iatu_index, which makes it more clear from the name itself that it is a zeroes based index, and only increment the index if the iATU configuration call succeeded. Since we always check if there is an index available immediately before programming the iATU, we can remove the useless "ranges exceed outbound iATU size" warnings, as the code is already unreachable. For the same reason, we can also remove the useless breaks outside of the while loops. No functional changes intended. Signed-off-by: Niklas Cassel <cassel@kernel.org> Signed-off-by: Manivannan Sadhasivam <mani@kernel.org> Tested-by: Maciej W. Rozycki <macro@orcam.me.uk> Reviewed-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Hans Zhang <zhanghuabing@ecosda.com> Reviewed-by: Frank Li <Frank.Li@nxp.com> Link: https://patch.msgid.link/20260127151038.1484881-7-cassel@kernel.org
1 parent 58fbf08 commit b5dab9b

1 file changed

Lines changed: 31 additions & 28 deletions

File tree

drivers/pci/controller/dwc/pcie-designware-host.c

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -892,9 +892,10 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
892892
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
893893
struct dw_pcie_ob_atu_cfg atu = { 0 };
894894
struct resource_entry *entry;
895+
int ob_iatu_index;
896+
int ib_iatu_index;
895897
int i, ret;
896898

897-
/* Note the very first outbound ATU is used for CFG IOs */
898899
if (!pci->num_ob_windows) {
899900
dev_err(pci->dev, "No outbound iATU found\n");
900901
return -EINVAL;
@@ -910,16 +911,18 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
910911
for (i = 0; i < pci->num_ib_windows; i++)
911912
dw_pcie_disable_atu(pci, PCIE_ATU_REGION_DIR_IB, i);
912913

913-
i = 0;
914+
/*
915+
* NOTE: For outbound address translation, outbound iATU at index 0 is
916+
* reserved for CFG IOs (dw_pcie_other_conf_map_bus()), thus start at
917+
* index 1.
918+
*/
919+
ob_iatu_index = 1;
914920
resource_list_for_each_entry(entry, &pp->bridge->windows) {
915921
resource_size_t res_size;
916922

917923
if (resource_type(entry->res) != IORESOURCE_MEM)
918924
continue;
919925

920-
if (pci->num_ob_windows <= i + 1)
921-
break;
922-
923926
atu.type = PCIE_ATU_TYPE_MEM;
924927
atu.parent_bus_addr = entry->res->start - pci->parent_bus_offset;
925928
atu.pci_addr = entry->res->start - entry->offset;
@@ -937,13 +940,13 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
937940
* middle. Otherwise, we would end up only partially
938941
* mapping a single resource.
939942
*/
940-
if (pci->num_ob_windows <= ++i) {
941-
dev_err(pci->dev, "Exhausted outbound windows for region: %pr\n",
943+
if (ob_iatu_index >= pci->num_ob_windows) {
944+
dev_err(pci->dev, "Cannot add outbound window for region: %pr\n",
942945
entry->res);
943946
return -ENOMEM;
944947
}
945948

946-
atu.index = i;
949+
atu.index = ob_iatu_index;
947950
atu.size = MIN(pci->region_limit + 1, res_size);
948951

949952
ret = dw_pcie_prog_outbound_atu(pci, &atu);
@@ -953,15 +956,16 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
953956
return ret;
954957
}
955958

959+
ob_iatu_index++;
956960
atu.parent_bus_addr += atu.size;
957961
atu.pci_addr += atu.size;
958962
res_size -= atu.size;
959963
}
960964
}
961965

962966
if (pp->io_size) {
963-
if (pci->num_ob_windows > ++i) {
964-
atu.index = i;
967+
if (ob_iatu_index < pci->num_ob_windows) {
968+
atu.index = ob_iatu_index;
965969
atu.type = PCIE_ATU_TYPE_IO;
966970
atu.parent_bus_addr = pp->io_base - pci->parent_bus_offset;
967971
atu.pci_addr = pp->io_bus_addr;
@@ -973,34 +977,35 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
973977
entry->res);
974978
return ret;
975979
}
980+
ob_iatu_index++;
976981
} else {
982+
/*
983+
* If there are not enough outbound windows to give I/O
984+
* space its own iATU, the outbound iATU at index 0 will
985+
* be shared between I/O space and CFG IOs, by
986+
* temporarily reconfiguring the iATU to CFG space, in
987+
* order to do a CFG IO, and then immediately restoring
988+
* it to I/O space.
989+
*/
977990
pp->cfg0_io_shared = true;
978991
}
979992
}
980993

981-
if (pci->num_ob_windows <= i)
982-
dev_warn(pci->dev, "Ranges exceed outbound iATU size (%d)\n",
983-
pci->num_ob_windows);
984-
985994
if (pp->use_atu_msg) {
986-
if (pci->num_ob_windows > ++i) {
987-
pp->msg_atu_index = i;
988-
} else {
995+
if (ob_iatu_index >= pci->num_ob_windows) {
989996
dev_err(pci->dev, "Cannot add outbound window for MSG TLP\n");
990997
return -ENOMEM;
991998
}
999+
pp->msg_atu_index = ob_iatu_index++;
9921000
}
9931001

994-
i = 0;
1002+
ib_iatu_index = 0;
9951003
resource_list_for_each_entry(entry, &pp->bridge->dma_ranges) {
9961004
resource_size_t res_start, res_size, window_size;
9971005

9981006
if (resource_type(entry->res) != IORESOURCE_MEM)
9991007
continue;
10001008

1001-
if (pci->num_ib_windows <= i)
1002-
break;
1003-
10041009
res_size = resource_size(entry->res);
10051010
res_start = entry->res->start;
10061011
while (res_size > 0) {
@@ -1009,30 +1014,28 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
10091014
* middle. Otherwise, we would end up only partially
10101015
* mapping a single resource.
10111016
*/
1012-
if (pci->num_ib_windows <= i) {
1013-
dev_err(pci->dev, "Exhausted inbound windows for region: %pr\n",
1017+
if (ib_iatu_index >= pci->num_ib_windows) {
1018+
dev_err(pci->dev, "Cannot add inbound window for region: %pr\n",
10141019
entry->res);
10151020
return -ENOMEM;
10161021
}
10171022

10181023
window_size = MIN(pci->region_limit + 1, res_size);
1019-
ret = dw_pcie_prog_inbound_atu(pci, i++, PCIE_ATU_TYPE_MEM, res_start,
1024+
ret = dw_pcie_prog_inbound_atu(pci, ib_iatu_index,
1025+
PCIE_ATU_TYPE_MEM, res_start,
10201026
res_start - entry->offset, window_size);
10211027
if (ret) {
10221028
dev_err(pci->dev, "Failed to set DMA range %pr\n",
10231029
entry->res);
10241030
return ret;
10251031
}
10261032

1033+
ib_iatu_index++;
10271034
res_start += window_size;
10281035
res_size -= window_size;
10291036
}
10301037
}
10311038

1032-
if (pci->num_ib_windows <= i)
1033-
dev_warn(pci->dev, "Dma-ranges exceed inbound iATU size (%u)\n",
1034-
pci->num_ib_windows);
1035-
10361039
return 0;
10371040
}
10381041

0 commit comments

Comments
 (0)