@@ -128,16 +128,16 @@ void pci_disable_bridge_window(struct pci_dev *dev)
128
128
}
129
129
#endif /* CONFIG_PCI_QUIRKS */
130
130
131
+
132
+
131
133
static int __pci_assign_resource (struct pci_bus * bus , struct pci_dev * dev ,
132
- int resno )
134
+ int resno , resource_size_t size , resource_size_t align )
133
135
{
134
136
struct resource * res = dev -> resource + resno ;
135
- resource_size_t size , min , align ;
137
+ resource_size_t min ;
136
138
int ret ;
137
139
138
- size = resource_size (res );
139
140
min = (res -> flags & IORESOURCE_IO ) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM ;
140
- align = pci_resource_alignment (dev , res );
141
141
142
142
/* First, try exact prefetching match.. */
143
143
ret = pci_bus_alloc_resource (bus , res , size , align , min ,
@@ -154,56 +154,101 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
154
154
ret = pci_bus_alloc_resource (bus , res , size , align , min , 0 ,
155
155
pcibios_align_resource , dev );
156
156
}
157
+ return ret ;
158
+ }
157
159
158
- if (ret < 0 && dev -> fw_addr [resno ]) {
159
- struct resource * root , * conflict ;
160
- resource_size_t start , end ;
160
+ static int pci_revert_fw_address (struct resource * res , struct pci_dev * dev ,
161
+ int resno , resource_size_t size )
162
+ {
163
+ struct resource * root , * conflict ;
164
+ resource_size_t start , end ;
165
+ int ret = 0 ;
161
166
162
- /*
163
- * If we failed to assign anything, let's try the address
164
- * where firmware left it. That at least has a chance of
165
- * working, which is better than just leaving it disabled.
166
- */
167
+ if (res -> flags & IORESOURCE_IO )
168
+ root = & ioport_resource ;
169
+ else
170
+ root = & iomem_resource ;
171
+
172
+ start = res -> start ;
173
+ end = res -> end ;
174
+ res -> start = dev -> fw_addr [resno ];
175
+ res -> end = res -> start + size - 1 ;
176
+ dev_info (& dev -> dev , "BAR %d: trying firmware assignment %pR\n" ,
177
+ resno , res );
178
+ conflict = request_resource_conflict (root , res );
179
+ if (conflict ) {
180
+ dev_info (& dev -> dev ,
181
+ "BAR %d: %pR conflicts with %s %pR\n" , resno ,
182
+ res , conflict -> name , conflict );
183
+ res -> start = start ;
184
+ res -> end = end ;
185
+ ret = 1 ;
186
+ }
187
+ return ret ;
188
+ }
189
+
190
+ static int _pci_assign_resource (struct pci_dev * dev , int resno , int size , resource_size_t min_align )
191
+ {
192
+ struct resource * res = dev -> resource + resno ;
193
+ struct pci_bus * bus ;
194
+ int ret ;
195
+ char * type ;
167
196
168
- if (res -> flags & IORESOURCE_IO )
169
- root = & ioport_resource ;
197
+ bus = dev -> bus ;
198
+ while ((ret = __pci_assign_resource (bus , dev , resno , size , min_align ))) {
199
+ if (!bus -> parent || !bus -> self -> transparent )
200
+ break ;
201
+ bus = bus -> parent ;
202
+ }
203
+
204
+ if (ret ) {
205
+ if (res -> flags & IORESOURCE_MEM )
206
+ if (res -> flags & IORESOURCE_PREFETCH )
207
+ type = "mem pref" ;
208
+ else
209
+ type = "mem" ;
210
+ else if (res -> flags & IORESOURCE_IO )
211
+ type = "io" ;
170
212
else
171
- root = & iomem_resource ;
172
-
173
- start = res -> start ;
174
- end = res -> end ;
175
- res -> start = dev -> fw_addr [resno ];
176
- res -> end = res -> start + size - 1 ;
177
- dev_info (& dev -> dev , "BAR %d: trying firmware assignment %pR\n" ,
178
- resno , res );
179
- conflict = request_resource_conflict (root , res );
180
- if (conflict ) {
181
- dev_info (& dev -> dev ,
182
- "BAR %d: %pR conflicts with %s %pR\n" , resno ,
183
- res , conflict -> name , conflict );
184
- res -> start = start ;
185
- res -> end = end ;
186
- } else
187
- ret = 0 ;
213
+ type = "unknown" ;
214
+ dev_info (& dev -> dev ,
215
+ "BAR %d: can't assign %s (size %#llx)\n" ,
216
+ resno , type , (unsigned long long ) resource_size (res ));
188
217
}
189
218
219
+ return ret ;
220
+ }
221
+
222
+ int pci_reassign_resource (struct pci_dev * dev , int resno , resource_size_t addsize ,
223
+ resource_size_t min_align )
224
+ {
225
+ struct resource * res = dev -> resource + resno ;
226
+ resource_size_t new_size ;
227
+ int ret ;
228
+
229
+ if (!res -> parent ) {
230
+ dev_info (& dev -> dev , "BAR %d: can't reassign an unassigned resouce %pR "
231
+ "\n" , resno , res );
232
+ return - EINVAL ;
233
+ }
234
+
235
+ new_size = resource_size (res ) + addsize + min_align ;
236
+ ret = _pci_assign_resource (dev , resno , new_size , min_align );
190
237
if (!ret ) {
191
238
res -> flags &= ~IORESOURCE_STARTALIGN ;
192
239
dev_info (& dev -> dev , "BAR %d: assigned %pR\n" , resno , res );
193
240
if (resno < PCI_BRIDGE_RESOURCES )
194
241
pci_update_resource (dev , resno );
195
242
}
196
-
197
243
return ret ;
198
244
}
199
245
200
246
int pci_assign_resource (struct pci_dev * dev , int resno )
201
247
{
202
248
struct resource * res = dev -> resource + resno ;
203
- resource_size_t align ;
249
+ resource_size_t align , size ;
204
250
struct pci_bus * bus ;
205
251
int ret ;
206
- char * type ;
207
252
208
253
align = pci_resource_alignment (dev , res );
209
254
if (!align ) {
@@ -213,34 +258,27 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
213
258
}
214
259
215
260
bus = dev -> bus ;
216
- while ((ret = __pci_assign_resource (bus , dev , resno ))) {
217
- if (bus -> parent && bus -> self -> transparent )
218
- bus = bus -> parent ;
219
- else
220
- bus = NULL ;
221
- if (bus )
222
- continue ;
223
- break ;
224
- }
261
+ size = resource_size (res );
262
+ ret = _pci_assign_resource (dev , resno , size , align );
225
263
226
- if (ret ) {
227
- if (res -> flags & IORESOURCE_MEM )
228
- if (res -> flags & IORESOURCE_PREFETCH )
229
- type = "mem pref" ;
230
- else
231
- type = "mem" ;
232
- else if (res -> flags & IORESOURCE_IO )
233
- type = "io" ;
234
- else
235
- type = "unknown" ;
236
- dev_info (& dev -> dev ,
237
- "BAR %d: can't assign %s (size %#llx)\n" ,
238
- resno , type , (unsigned long long ) resource_size (res ));
239
- }
264
+ /*
265
+ * If we failed to assign anything, let's try the address
266
+ * where firmware left it. That at least has a chance of
267
+ * working, which is better than just leaving it disabled.
268
+ */
269
+ if (ret < 0 && dev -> fw_addr [resno ])
270
+ ret = pci_revert_fw_address (res , dev , resno , size );
240
271
272
+ if (!ret ) {
273
+ res -> flags &= ~IORESOURCE_STARTALIGN ;
274
+ dev_info (& dev -> dev , "BAR %d: assigned %pR\n" , resno , res );
275
+ if (resno < PCI_BRIDGE_RESOURCES )
276
+ pci_update_resource (dev , resno );
277
+ }
241
278
return ret ;
242
279
}
243
280
281
+
244
282
/* Sort resources by alignment */
245
283
void pdev_sort_resources (struct pci_dev * dev , struct resource_list * head )
246
284
{
0 commit comments