|
26 | 26 | #define FLAG_CFG0 BIT(0) |
27 | 27 | #define FLAG_CFG1 BIT(1) |
28 | 28 | #define FLAG_DEV_FIX BIT(2) |
| 29 | +#define FLAG_DEV_HIDDEN BIT(3) |
29 | 30 |
|
30 | 31 | struct loongson_pci_data { |
31 | 32 | u32 flags; |
@@ -138,18 +139,34 @@ static void __iomem *cfg1_map(struct loongson_pci *priv, struct pci_bus *bus, |
138 | 139 | return priv->cfg1_base + addroff; |
139 | 140 | } |
140 | 141 |
|
| 142 | +static bool pdev_may_exist(struct pci_bus *bus, unsigned int device, |
| 143 | + unsigned int function) |
| 144 | +{ |
| 145 | + return !(pci_is_root_bus(bus) && |
| 146 | + (device >= 9 && device <= 20) && (function > 0)); |
| 147 | +} |
| 148 | + |
141 | 149 | static void __iomem *pci_loongson_map_bus(struct pci_bus *bus, |
142 | 150 | unsigned int devfn, int where) |
143 | 151 | { |
| 152 | + unsigned int device = PCI_SLOT(devfn); |
| 153 | + unsigned int function = PCI_FUNC(devfn); |
144 | 154 | struct loongson_pci *priv = pci_bus_to_loongson_pci(bus); |
145 | 155 |
|
146 | 156 | /* |
147 | 157 | * Do not read more than one device on the bus other than |
148 | 158 | * the host bus. |
149 | 159 | */ |
150 | | - if (priv->data->flags & FLAG_DEV_FIX && |
151 | | - !pci_is_root_bus(bus) && PCI_SLOT(devfn) > 0) |
152 | | - return NULL; |
| 160 | + if ((priv->data->flags & FLAG_DEV_FIX) && bus->self) { |
| 161 | + if (!pci_is_root_bus(bus) && (device > 0)) |
| 162 | + return NULL; |
| 163 | + } |
| 164 | + |
| 165 | + /* Don't access non-existent devices */ |
| 166 | + if (priv->data->flags & FLAG_DEV_HIDDEN) { |
| 167 | + if (!pdev_may_exist(bus, device, function)) |
| 168 | + return NULL; |
| 169 | + } |
153 | 170 |
|
154 | 171 | /* CFG0 can only access standard space */ |
155 | 172 | if (where < PCI_CFG_SPACE_SIZE && priv->cfg0_base) |
@@ -197,12 +214,12 @@ static struct pci_ops loongson_pci_ops32 = { |
197 | 214 | }; |
198 | 215 |
|
199 | 216 | static const struct loongson_pci_data ls2k_pci_data = { |
200 | | - .flags = FLAG_CFG1 | FLAG_DEV_FIX, |
| 217 | + .flags = FLAG_CFG1 | FLAG_DEV_FIX | FLAG_DEV_HIDDEN, |
201 | 218 | .ops = &loongson_pci_ops, |
202 | 219 | }; |
203 | 220 |
|
204 | 221 | static const struct loongson_pci_data ls7a_pci_data = { |
205 | | - .flags = FLAG_CFG1 | FLAG_DEV_FIX, |
| 222 | + .flags = FLAG_CFG1 | FLAG_DEV_FIX | FLAG_DEV_HIDDEN, |
206 | 223 | .ops = &loongson_pci_ops, |
207 | 224 | }; |
208 | 225 |
|
@@ -297,7 +314,7 @@ static int loongson_pci_ecam_init(struct pci_config_window *cfg) |
297 | 314 | return -ENOMEM; |
298 | 315 |
|
299 | 316 | cfg->priv = priv; |
300 | | - data->flags = FLAG_CFG1; |
| 317 | + data->flags = FLAG_CFG1 | FLAG_DEV_HIDDEN; |
301 | 318 | priv->data = data; |
302 | 319 | priv->cfg1_base = cfg->win - (cfg->busr.start << 16); |
303 | 320 |
|
|
0 commit comments