Revision 93d2175d3d31f11ba04fcfa0e9a496a1b4bc8b34 authored by Yinghai Lu on 14 May 2011, 01:06:17 UTC, committed by Linus Torvalds on 17 May 2011, 01:33:35 UTC
During pci remove/rescan testing found:

  pci 0000:c0:03.0: PCI bridge to [bus c4-c9]
  pci 0000:c0:03.0:   bridge window [io  0x1000-0x0fff]
  pci 0000:c0:03.0:   bridge window [mem 0xf0000000-0xf00fffff]
  pci 0000:c0:03.0:   bridge window [mem 0xfc180000000-0xfc197ffffff 64bit pref]
  pci 0000:c0:03.0: device not available (can't reserve [io  0x1000-0x0fff])
  pci 0000:c0:03.0: Error enabling bridge (-22), continuing
  pci 0000:c0:03.0: enabling bus mastering
  pci 0000:c0:03.0: setting latency timer to 64
  pcieport 0000:c0:03.0: device not available (can't reserve [io  0x1000-0x0fff])
  pcieport: probe of 0000:c0:03.0 failed with error -22

This bug was caused by commit c8adf9a3e873 ("PCI: pre-allocate
additional resources to devices only after successful allocation of
essential resources.")

After that commit, pci_hotplug_io_size is changed to additional_io_size
from minium size.  So it will not go through resource_size(res) != 0
path, and will not be reset.

The root cause is: pci_bridge_check_ranges will set RESOURCE_IO flag for
pci bridge, and later if children do not need IO resource.  those bridge
resources will not need to be allocated.  but flags is still there.
that will confuse the the pci_enable_bridges later.

related code:

   static void assign_requested_resources_sorted(struct resource_list *head,
                                    struct resource_list_x *fail_head)
   {
           struct resource *res;
           struct resource_list *list;
           int idx;

           for (list = head->next; list; list = list->next) {
                   res = list->res;
                   idx = res - &list->dev->resource[0];
                   if (resource_size(res) && pci_assign_resource(list->dev, idx)) {
   ...
                           reset_resource(res);
                   }
           }
   }

At last, We have to clear the flags in pbus_size_mem/io when requested
size == 0 and !add_head.  becasue this case it will not go through
adjust_resources_sorted().

Just make size1 = size0 when !add_head. it will make flags get cleared.

At the same time when requested size == 0, add_size != 0, will still
have in head and add_list.  because we do not clear the flags for it.

After this, we will get right result:

  pci 0000:c0:03.0: PCI bridge to [bus c4-c9]
  pci 0000:c0:03.0:   bridge window [io  disabled]
  pci 0000:c0:03.0:   bridge window [mem 0xf0000000-0xf00fffff]
  pci 0000:c0:03.0:   bridge window [mem 0xfc180000000-0xfc197ffffff 64bit pref]
  pci 0000:c0:03.0: enabling bus mastering
  pci 0000:c0:03.0: setting latency timer to 64
  pcieport 0000:c0:03.0: setting latency timer to 64
  pcieport 0000:c0:03.0: irq 160 for MSI/MSI-X
  pcieport 0000:c0:03.0: Signaling PME through PCIe PME interrupt
  pci 0000:c4:00.0: Signaling PME through PCIe PME interrupt
  pcie_pme 0000:c0:03.0:pcie01: service driver pcie_pme loaded
  aer 0000:c0:03.0:pcie02: service driver aer loaded
  pciehp 0000:c0:03.0:pcie04: Hotplug Controller:

v3: more simple fix. also fix one typo in pbus_size_mem

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Reviewed-by: Ram Pai <linuxram@us.ibm.com>
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent df8d06a
Raw File
mn10300-serial.h
/* MN10300 On-chip serial port driver definitions
 *
 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
 * Written by David Howells (dhowells@redhat.com)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public Licence
 * as published by the Free Software Foundation; either version
 * 2 of the Licence, or (at your option) any later version.
 */
#ifndef _MN10300_SERIAL_H
#define _MN10300_SERIAL_H

#ifndef __ASSEMBLY__
#include <linux/serial_core.h>
#include <linux/termios.h>
#endif

#include <asm/page.h>
#include <asm/serial-regs.h>

#define NR_PORTS		3		/* should be set 3 or 9 or 16 */

#define MNSC_BUFFER_SIZE	+(PAGE_SIZE / 2)

/* intr_flags bits */
#define MNSCx_RX_AVAIL		0x01
#define MNSCx_RX_OVERF		0x02
#define MNSCx_TX_SPACE		0x04
#define MNSCx_TX_EMPTY		0x08

#ifndef __ASSEMBLY__

struct mn10300_serial_port {
	char			*rx_buffer;	/* reception buffer base */
	unsigned		rx_inp;		/* pointer to rx input offset */
	unsigned		rx_outp;	/* pointer to rx output offset */
	u8			tx_xchar;	/* high-priority XON/XOFF buffer */
	u8			tx_break;	/* transmit break request */
	u8			intr_flags;	/* interrupt flags */
	volatile u16		*rx_icr;	/* Rx interrupt control register */
	volatile u16		*tx_icr;	/* Tx interrupt control register */
	int			rx_irq;		/* reception IRQ */
	int			tx_irq;		/* transmission IRQ */
	int			tm_irq;		/* timer IRQ */

	const char		*name;		/* name of serial port */
	const char		*rx_name;	/* Rx interrupt handler name of serial port */
	const char		*tx_name;	/* Tx interrupt handler name of serial port */
	const char		*tm_name;	/* Timer interrupt handler name */
	unsigned short		type;		/* type of serial port */
	unsigned char		isconsole;	/* T if it's a console */
	volatile void		*_iobase;	/* pointer to base of I/O control regs */
	volatile u16		*_control;	/* control register pointer */
	volatile u8		*_status;	/* status register pointer */
	volatile u8		*_intr;		/* interrupt register pointer */
	volatile void		*_rxb;		/* receive buffer register pointer */
	volatile void		*_txb;		/* transmit buffer register pointer */
	volatile u16		*_tmicr;	/* timer interrupt control register */
	volatile u8		*_tmxmd;	/* baud rate timer mode register */
	volatile u16		*_tmxbr;	/* baud rate timer base register */

	/* this must come down here so that assembly can use BSET to access the
	 * above fields */
	struct uart_port	uart;

	unsigned short		rx_brk;		/* current break reception status */
	u16			tx_cts;		/* current CTS status */
	int			gdbstub;	/* preemptively stolen by GDB stub */

	u8			clock_src;	/* clock source */
#define MNSCx_CLOCK_SRC_IOCLK	0
#define MNSCx_CLOCK_SRC_IOBCLK	1

	u8			div_timer;	/* timer used as divisor */
#define MNSCx_DIV_TIMER_16BIT	0
#define MNSCx_DIV_TIMER_8BIT	1

	u16			options;	/* options */
#define MNSCx_OPT_CTS		0x0001

	unsigned long		ioclk;		/* base clock rate */
};

#ifdef CONFIG_MN10300_TTYSM0
extern struct mn10300_serial_port mn10300_serial_port_sif0;
#endif

#ifdef CONFIG_MN10300_TTYSM1
extern struct mn10300_serial_port mn10300_serial_port_sif1;
#endif

#ifdef CONFIG_MN10300_TTYSM2
extern struct mn10300_serial_port mn10300_serial_port_sif2;
#endif

extern struct mn10300_serial_port *mn10300_serial_ports[];

struct mn10300_serial_int {
	struct mn10300_serial_port *port;
	asmlinkage void (*vdma)(void);
};

extern struct mn10300_serial_int mn10300_serial_int_tbl[];

extern asmlinkage void mn10300_serial_vdma_interrupt(void);
extern asmlinkage void mn10300_serial_vdma_rx_handler(void);
extern asmlinkage void mn10300_serial_vdma_tx_handler(void);

#endif /* __ASSEMBLY__ */

#if defined(CONFIG_GDBSTUB_ON_TTYSM0)
#define SCgSTR SC0STR
#define SCgRXB SC0RXB
#define SCgRXIRQ SC0RXIRQ
#elif defined(CONFIG_GDBSTUB_ON_TTYSM1)
#define SCgSTR SC1STR
#define SCgRXB SC1RXB
#define SCgRXIRQ SC1RXIRQ
#elif defined(CONFIG_GDBSTUB_ON_TTYSM2)
#define SCgSTR SC2STR
#define SCgRXB SC2RXB
#define SCgRXIRQ SC2RXIRQ
#endif

#endif /* _MN10300_SERIAL_H */
back to top