@@ -304,7 +304,7 @@ static void mvebu_pcie_del_windows(struct mvebu_pcie_port *port,
304
304
* areas each having a power of two size. We start from the largest
305
305
* one (i.e highest order bit set in the size).
306
306
*/
307
- static void mvebu_pcie_add_windows (struct mvebu_pcie_port * port ,
307
+ static int mvebu_pcie_add_windows (struct mvebu_pcie_port * port ,
308
308
unsigned int target , unsigned int attribute ,
309
309
phys_addr_t base , size_t size ,
310
310
phys_addr_t remap )
@@ -325,7 +325,7 @@ static void mvebu_pcie_add_windows(struct mvebu_pcie_port *port,
325
325
& base , & end , ret );
326
326
mvebu_pcie_del_windows (port , base - size_mapped ,
327
327
size_mapped );
328
- return ;
328
+ return ret ;
329
329
}
330
330
331
331
size -= sz ;
@@ -334,16 +334,20 @@ static void mvebu_pcie_add_windows(struct mvebu_pcie_port *port,
334
334
if (remap != MVEBU_MBUS_NO_REMAP )
335
335
remap += sz ;
336
336
}
337
+
338
+ return 0 ;
337
339
}
338
340
339
- static void mvebu_pcie_set_window (struct mvebu_pcie_port * port ,
341
+ static int mvebu_pcie_set_window (struct mvebu_pcie_port * port ,
340
342
unsigned int target , unsigned int attribute ,
341
343
const struct mvebu_pcie_window * desired ,
342
344
struct mvebu_pcie_window * cur )
343
345
{
346
+ int ret ;
347
+
344
348
if (desired -> base == cur -> base && desired -> remap == cur -> remap &&
345
349
desired -> size == cur -> size )
346
- return ;
350
+ return 0 ;
347
351
348
352
if (cur -> size != 0 ) {
349
353
mvebu_pcie_del_windows (port , cur -> base , cur -> size );
@@ -358,30 +362,35 @@ static void mvebu_pcie_set_window(struct mvebu_pcie_port *port,
358
362
}
359
363
360
364
if (desired -> size == 0 )
361
- return ;
365
+ return 0 ;
366
+
367
+ ret = mvebu_pcie_add_windows (port , target , attribute , desired -> base ,
368
+ desired -> size , desired -> remap );
369
+ if (ret ) {
370
+ cur -> size = 0 ;
371
+ cur -> base = 0 ;
372
+ return ret ;
373
+ }
362
374
363
- mvebu_pcie_add_windows (port , target , attribute , desired -> base ,
364
- desired -> size , desired -> remap );
365
375
* cur = * desired ;
376
+ return 0 ;
366
377
}
367
378
368
- static void mvebu_pcie_handle_iobase_change (struct mvebu_pcie_port * port )
379
+ static int mvebu_pcie_handle_iobase_change (struct mvebu_pcie_port * port )
369
380
{
370
381
struct mvebu_pcie_window desired = {};
371
382
struct pci_bridge_emul_conf * conf = & port -> bridge .conf ;
372
383
373
384
/* Are the new iobase/iolimit values invalid? */
374
385
if (conf -> iolimit < conf -> iobase ||
375
- conf -> iolimitupper < conf -> iobaseupper ) {
376
- mvebu_pcie_set_window (port , port -> io_target , port -> io_attr ,
377
- & desired , & port -> iowin );
378
- return ;
379
- }
386
+ conf -> iolimitupper < conf -> iobaseupper )
387
+ return mvebu_pcie_set_window (port , port -> io_target , port -> io_attr ,
388
+ & desired , & port -> iowin );
380
389
381
390
if (!mvebu_has_ioport (port )) {
382
391
dev_WARN (& port -> pcie -> pdev -> dev ,
383
392
"Attempt to set IO when IO is disabled\n" );
384
- return ;
393
+ return - EOPNOTSUPP ;
385
394
}
386
395
387
396
/*
@@ -399,21 +408,19 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
399
408
desired .remap ) +
400
409
1 ;
401
410
402
- mvebu_pcie_set_window (port , port -> io_target , port -> io_attr , & desired ,
403
- & port -> iowin );
411
+ return mvebu_pcie_set_window (port , port -> io_target , port -> io_attr , & desired ,
412
+ & port -> iowin );
404
413
}
405
414
406
- static void mvebu_pcie_handle_membase_change (struct mvebu_pcie_port * port )
415
+ static int mvebu_pcie_handle_membase_change (struct mvebu_pcie_port * port )
407
416
{
408
417
struct mvebu_pcie_window desired = {.remap = MVEBU_MBUS_NO_REMAP };
409
418
struct pci_bridge_emul_conf * conf = & port -> bridge .conf ;
410
419
411
420
/* Are the new membase/memlimit values invalid? */
412
- if (conf -> memlimit < conf -> membase ) {
413
- mvebu_pcie_set_window (port , port -> mem_target , port -> mem_attr ,
414
- & desired , & port -> memwin );
415
- return ;
416
- }
421
+ if (conf -> memlimit < conf -> membase )
422
+ return mvebu_pcie_set_window (port , port -> mem_target , port -> mem_attr ,
423
+ & desired , & port -> memwin );
417
424
418
425
/*
419
426
* We read the PCI-to-PCI bridge emulated registers, and
@@ -425,8 +432,8 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
425
432
desired .size = (((conf -> memlimit & 0xFFF0 ) << 16 ) | 0xFFFFF ) -
426
433
desired .base + 1 ;
427
434
428
- mvebu_pcie_set_window (port , port -> mem_target , port -> mem_attr , & desired ,
429
- & port -> memwin );
435
+ return mvebu_pcie_set_window (port , port -> mem_target , port -> mem_attr , & desired ,
436
+ & port -> memwin );
430
437
}
431
438
432
439
static pci_bridge_emul_read_status_t
@@ -511,15 +518,36 @@ mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge,
511
518
break ;
512
519
513
520
case PCI_IO_BASE :
514
- mvebu_pcie_handle_iobase_change (port );
521
+ if ((mask & 0xffff ) && mvebu_pcie_handle_iobase_change (port )) {
522
+ /* On error disable IO range */
523
+ conf -> iobase &= ~0xf0 ;
524
+ conf -> iolimit &= ~0xf0 ;
525
+ conf -> iobaseupper = cpu_to_le16 (0x0000 );
526
+ conf -> iolimitupper = cpu_to_le16 (0x0000 );
527
+ if (mvebu_has_ioport (port ))
528
+ conf -> iobase |= 0xf0 ;
529
+ }
515
530
break ;
516
531
517
532
case PCI_MEMORY_BASE :
518
- mvebu_pcie_handle_membase_change (port );
533
+ if (mvebu_pcie_handle_membase_change (port )) {
534
+ /* On error disable mem range */
535
+ conf -> membase = cpu_to_le16 (le16_to_cpu (conf -> membase ) & ~0xfff0 );
536
+ conf -> memlimit = cpu_to_le16 (le16_to_cpu (conf -> memlimit ) & ~0xfff0 );
537
+ conf -> membase = cpu_to_le16 (le16_to_cpu (conf -> membase ) | 0xfff0 );
538
+ }
519
539
break ;
520
540
521
541
case PCI_IO_BASE_UPPER16 :
522
- mvebu_pcie_handle_iobase_change (port );
542
+ if (mvebu_pcie_handle_iobase_change (port )) {
543
+ /* On error disable IO range */
544
+ conf -> iobase &= ~0xf0 ;
545
+ conf -> iolimit &= ~0xf0 ;
546
+ conf -> iobaseupper = cpu_to_le16 (0x0000 );
547
+ conf -> iolimitupper = cpu_to_le16 (0x0000 );
548
+ if (mvebu_has_ioport (port ))
549
+ conf -> iobase |= 0xf0 ;
550
+ }
523
551
break ;
524
552
525
553
case PCI_PRIMARY_BUS :
0 commit comments