@@ -304,7 +304,7 @@ static void mvebu_pcie_del_windows(struct mvebu_pcie_port *port,
304304 * areas each having a power of two size. We start from the largest
305305 * one (i.e highest order bit set in the size).
306306 */
307- static void mvebu_pcie_add_windows (struct mvebu_pcie_port * port ,
307+ static int mvebu_pcie_add_windows (struct mvebu_pcie_port * port ,
308308 unsigned int target , unsigned int attribute ,
309309 phys_addr_t base , size_t size ,
310310 phys_addr_t remap )
@@ -325,7 +325,7 @@ static void mvebu_pcie_add_windows(struct mvebu_pcie_port *port,
325325 & base , & end , ret );
326326 mvebu_pcie_del_windows (port , base - size_mapped ,
327327 size_mapped );
328- return ;
328+ return ret ;
329329 }
330330
331331 size -= sz ;
@@ -334,16 +334,20 @@ static void mvebu_pcie_add_windows(struct mvebu_pcie_port *port,
334334 if (remap != MVEBU_MBUS_NO_REMAP )
335335 remap += sz ;
336336 }
337+
338+ return 0 ;
337339}
338340
339- static void mvebu_pcie_set_window (struct mvebu_pcie_port * port ,
341+ static int mvebu_pcie_set_window (struct mvebu_pcie_port * port ,
340342 unsigned int target , unsigned int attribute ,
341343 const struct mvebu_pcie_window * desired ,
342344 struct mvebu_pcie_window * cur )
343345{
346+ int ret ;
347+
344348 if (desired -> base == cur -> base && desired -> remap == cur -> remap &&
345349 desired -> size == cur -> size )
346- return ;
350+ return 0 ;
347351
348352 if (cur -> size != 0 ) {
349353 mvebu_pcie_del_windows (port , cur -> base , cur -> size );
@@ -358,30 +362,35 @@ static void mvebu_pcie_set_window(struct mvebu_pcie_port *port,
358362 }
359363
360364 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+ }
362374
363- mvebu_pcie_add_windows (port , target , attribute , desired -> base ,
364- desired -> size , desired -> remap );
365375 * cur = * desired ;
376+ return 0 ;
366377}
367378
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 )
369380{
370381 struct mvebu_pcie_window desired = {};
371382 struct pci_bridge_emul_conf * conf = & port -> bridge .conf ;
372383
373384 /* Are the new iobase/iolimit values invalid? */
374385 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 );
380389
381390 if (!mvebu_has_ioport (port )) {
382391 dev_WARN (& port -> pcie -> pdev -> dev ,
383392 "Attempt to set IO when IO is disabled\n" );
384- return ;
393+ return - EOPNOTSUPP ;
385394 }
386395
387396 /*
@@ -399,21 +408,19 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
399408 desired .remap ) +
400409 1 ;
401410
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 );
404413}
405414
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 )
407416{
408417 struct mvebu_pcie_window desired = {.remap = MVEBU_MBUS_NO_REMAP };
409418 struct pci_bridge_emul_conf * conf = & port -> bridge .conf ;
410419
411420 /* 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 );
417424
418425 /*
419426 * 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)
425432 desired .size = (((conf -> memlimit & 0xFFF0 ) << 16 ) | 0xFFFFF ) -
426433 desired .base + 1 ;
427434
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 );
430437}
431438
432439static pci_bridge_emul_read_status_t
@@ -511,15 +518,36 @@ mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge,
511518 break ;
512519
513520 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+ }
515530 break ;
516531
517532 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+ }
519539 break ;
520540
521541 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+ }
523551 break ;
524552
525553 case PCI_PRIMARY_BUS :
0 commit comments