diff options
author | Gavin Shan <shangw@linux.vnet.ibm.com> | 2012-08-19 23:49:16 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2012-09-17 02:35:14 -0400 |
commit | 11685becbf1a962759ae94a0fdb5b0b7521778a5 (patch) | |
tree | 0457f8d2993242ed933b623b22344076a6aaf551 | |
parent | 7ebdf956df7961ae6b57b0328e03d33f95f1346f (diff) |
powerpc/powernv: I/O and MMIO resource assignment for PEs
There're 2 types of PCI bus sensitive PEs: (A) The PE includes
single PCI bus. (B) The PE includes the PCI bus and all the subordinate
PCI buses, and the patch tries to assign I/O and MMIO resources
based on created PEs. Fortunately, we figured out unified scheme
to do resource assignment for all types of PCI bus based PEs according
to Ben's idea:
- Resource assignment based on PE from top to bottom.
- The soureces, either I/O or MMIO, of the PE are figured out
from the assigned PCI bus.
- The occupied resource by parent PE could possibilly be overrided
by children PEs.
Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
Reviewed-by: Ram Pai <linuxram@us.ibm.com>
Reviewed-by: Richard Yang <weiyang@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r-- | arch/powerpc/platforms/powernv/pci-ioda.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 7999da1e0b11..9e34f4614b64 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c | |||
@@ -1153,9 +1153,98 @@ static void __devinit pnv_pci_ioda_fixup_phb(struct pci_controller *hose) | |||
1153 | } | 1153 | } |
1154 | } | 1154 | } |
1155 | 1155 | ||
1156 | /* | ||
1157 | * This function is supposed to be called on basis of PE from top | ||
1158 | * to bottom style. So the the I/O or MMIO segment assigned to | ||
1159 | * parent PE could be overrided by its child PEs if necessary. | ||
1160 | */ | ||
1161 | static void __devinit pnv_ioda_setup_pe_seg(struct pci_controller *hose, | ||
1162 | struct pnv_ioda_pe *pe) | ||
1163 | { | ||
1164 | struct pnv_phb *phb = hose->private_data; | ||
1165 | struct pci_bus_region region; | ||
1166 | struct resource *res; | ||
1167 | int i, index; | ||
1168 | int rc; | ||
1169 | |||
1170 | /* | ||
1171 | * NOTE: We only care PCI bus based PE for now. For PCI | ||
1172 | * device based PE, for example SRIOV sensitive VF should | ||
1173 | * be figured out later. | ||
1174 | */ | ||
1175 | BUG_ON(!(pe->flags & (PNV_IODA_PE_BUS | PNV_IODA_PE_BUS_ALL))); | ||
1176 | |||
1177 | pci_bus_for_each_resource(pe->pbus, res, i) { | ||
1178 | if (!res || !res->flags || | ||
1179 | res->start > res->end) | ||
1180 | continue; | ||
1181 | |||
1182 | if (res->flags & IORESOURCE_IO) { | ||
1183 | region.start = res->start - phb->ioda.io_pci_base; | ||
1184 | region.end = res->end - phb->ioda.io_pci_base; | ||
1185 | index = region.start / phb->ioda.io_segsize; | ||
1186 | |||
1187 | while (index < phb->ioda.total_pe && | ||
1188 | region.start <= region.end) { | ||
1189 | phb->ioda.io_segmap[index] = pe->pe_number; | ||
1190 | rc = opal_pci_map_pe_mmio_window(phb->opal_id, | ||
1191 | pe->pe_number, OPAL_IO_WINDOW_TYPE, 0, index); | ||
1192 | if (rc != OPAL_SUCCESS) { | ||
1193 | pr_err("%s: OPAL error %d when mapping IO " | ||
1194 | "segment #%d to PE#%d\n", | ||
1195 | __func__, rc, index, pe->pe_number); | ||
1196 | break; | ||
1197 | } | ||
1198 | |||
1199 | region.start += phb->ioda.io_segsize; | ||
1200 | index++; | ||
1201 | } | ||
1202 | } else if (res->flags & IORESOURCE_MEM) { | ||
1203 | region.start = res->start - | ||
1204 | hose->pci_mem_offset - | ||
1205 | phb->ioda.m32_pci_base; | ||
1206 | region.end = res->end - | ||
1207 | hose->pci_mem_offset - | ||
1208 | phb->ioda.m32_pci_base; | ||
1209 | index = region.start / phb->ioda.m32_segsize; | ||
1210 | |||
1211 | while (index < phb->ioda.total_pe && | ||
1212 | region.start <= region.end) { | ||
1213 | phb->ioda.m32_segmap[index] = pe->pe_number; | ||
1214 | rc = opal_pci_map_pe_mmio_window(phb->opal_id, | ||
1215 | pe->pe_number, OPAL_M32_WINDOW_TYPE, 0, index); | ||
1216 | if (rc != OPAL_SUCCESS) { | ||
1217 | pr_err("%s: OPAL error %d when mapping M32 " | ||
1218 | "segment#%d to PE#%d", | ||
1219 | __func__, rc, index, pe->pe_number); | ||
1220 | break; | ||
1221 | } | ||
1222 | |||
1223 | region.start += phb->ioda.m32_segsize; | ||
1224 | index++; | ||
1225 | } | ||
1226 | } | ||
1227 | } | ||
1228 | } | ||
1229 | |||
1230 | static void __devinit pnv_pci_ioda_setup_seg(void) | ||
1231 | { | ||
1232 | struct pci_controller *tmp, *hose; | ||
1233 | struct pnv_phb *phb; | ||
1234 | struct pnv_ioda_pe *pe; | ||
1235 | |||
1236 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { | ||
1237 | phb = hose->private_data; | ||
1238 | list_for_each_entry(pe, &phb->ioda.pe_list, list) { | ||
1239 | pnv_ioda_setup_pe_seg(hose, pe); | ||
1240 | } | ||
1241 | } | ||
1242 | } | ||
1243 | |||
1156 | static void __devinit pnv_pci_ioda_fixup(void) | 1244 | static void __devinit pnv_pci_ioda_fixup(void) |
1157 | { | 1245 | { |
1158 | pnv_pci_ioda_setup_PEs(); | 1246 | pnv_pci_ioda_setup_PEs(); |
1247 | pnv_pci_ioda_setup_seg(); | ||
1159 | } | 1248 | } |
1160 | 1249 | ||
1161 | /* | 1250 | /* |