LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: Please pull linux-2.6-8xx.git for-paulus branch
From: Kumar Gala @ 2007-12-14  5:47 UTC (permalink / raw)
  To: Vitaly Bordug; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20071209115353.1ae09ee1@kernel.crashing.org>


On Dec 9, 2007, at 2:53 AM, Vitaly Bordug wrote:

> On Sat, 8 Dec 2007 09:17:06 -0600
> Kumar Gala wrote:
>
>>
>> On Dec 8, 2007, at 4:09 AM, Vitaly Bordug wrote:
>>
>>> On Sat, 8 Dec 2007 13:00:25 +0300
>>> Vitaly Bordug wrote:
>>>
>>>> Paul,
>>>>
>>>> please do
>>>> git-pull
>>>> git://git.kernel.org/pub/scm/linux/kernel/git/vitb/ 
>>>> linux-2.6-8xx.git
>>>> for-paulus
>>>>
>>>> to receive the following updates:
>>>>
>>> Forgot to tell that this is .25 material...
>>
>> Vitaly, if you don't mind I'll pull these into my tree for Paul to
>> collect all the FSL stuff in one place.
>>
> I'm ok with either way.

I've pulled this and split the patches between for-2.6.24 (sent pull  
request to paulus) and for-2.6.25

- k

^ permalink raw reply

* Re: [PATCH] Fix rounding bug in emulation for double floatoperating
From: Kumar Gala @ 2007-12-14  5:46 UTC (permalink / raw)
  To: Zang Roy-r61911; +Cc: linuxppc-dev list, Liu Yu, David Gibson
In-Reply-To: <1197448223.29372.12.camel@localhost.localdomain>

>> When I run this on a G5 (w/HW FP) I get:
>>
>> dmul 3fe0000000000000 * 1 = 0 expected 0 (PASS)
>> dmul bfe0000000000000 * 1 = 8000000000000000 expected 0 (PASS)
>> dmul 8000000000000001 * bfe0000000000000 = 0 expected 0 (PASS)
>>
>> ddiv 1 / 4000000000000000 = 0 expected 0 (PASS)
>>
>> and on the 85xx w/FP emu:
>>
>> dmul 3fe0000000000000 * 1 = 0 expected 0 (PASS)
>> dmul bfe0000000000000 * 1 = 8000000000000000 expected 0 (PASS)
>> dmul 8000000000000001 * bfe0000000000000 = 0 expected 0 (PASS)
>>
>> ddiv 1 / 4000000000000000 = 0 expected 0 (PASS)
>>
>> Maybe I'm missing where the error is.
> I am missing ...
> It is supposed to run based on previous IEEE 754 patch.
> http://ozlabs.org/pipermail/linuxppc-dev/2007-February/031351.html

I'd really like to see to see a testcase show the issue with "classic  
FP emu" on a 85xx system.

(seems like it should be pretty straight forward).

- k

^ permalink raw reply

* Re: [PATCH 2/2] powerpc: Add IPIC MSI support
From: Kumar Gala @ 2007-12-14  5:44 UTC (permalink / raw)
  To: Li Li; +Cc: linuxppc-dev, kim phillips
In-Reply-To: <1196764760.2573.10.camel@Guyver>


On Dec 4, 2007, at 4:39 AM, Li Li wrote:

> Modified based on discussion on list.
>
> 1. Adopt virq_to_hw routine
> 2. Correct a legacy bug
>
> Implements the IPIC MSI as two level interrupt controller.
>
> Signed-off-by: Tony Li <tony.li@freescale.com>

Tony, have you looked at the 85xx/86xx PCIe MSI mechanism?  The 2nd  
level PIC handling seems like its pretty similar between IPIC and  
MPIC.  Would like to see if we could somehow make the code common for  
to handle MSIs from both?

- k

^ permalink raw reply

* Re: [PATCH 2/3] mpc82xx: Embedded Planet EP8248E support
From: Kumar Gala @ 2007-12-14  5:19 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <20071211212247.GB3620@loki.buserror.net>


On Dec 11, 2007, at 3:22 PM, Scott Wood wrote:

> This board is also resold by Freescale under the names
> "QUICCStart MPC8248 Evaluation System" and "CWH-PPC-8248N-VE".
>
> Signed-off-by: Scott Wood <scottwood@freescale.com>
> ---
> arch/powerpc/boot/Makefile             |    3 +-
> arch/powerpc/boot/dts/ep8248e.dts      |  193 +++++++
> arch/powerpc/boot/ep8248e.c            |   55 ++
> arch/powerpc/boot/wrapper              |    2 +-
> arch/powerpc/configs/ep8248e_defconfig |  864 +++++++++++++++++++++++ 
> +++++++++
> arch/powerpc/platforms/82xx/Kconfig    |   13 +
> arch/powerpc/platforms/82xx/Makefile   |    1 +
> arch/powerpc/platforms/82xx/ep8248e.c  |  321 ++++++++++++
> include/asm-powerpc/mpc8260.h          |    1 +
> 9 files changed, 1451 insertions(+), 2 deletions(-)
> create mode 100644 arch/powerpc/boot/dts/ep8248e.dts
> create mode 100644 arch/powerpc/boot/ep8248e.c
> create mode 100644 arch/powerpc/configs/ep8248e_defconfig
> create mode 100644 arch/powerpc/platforms/82xx/ep8248e.c


>
> diff --git a/arch/powerpc/boot/dts/ep8248e.dts b/arch/powerpc/boot/ 
> dts/ep8248e.dts
> new file mode 100644
> index 0000000..ee8405d
> --- /dev/null
> +++ b/arch/powerpc/boot/dts/ep8248e.dts
> @@ -0,0 +1,193 @@
> +/*
> + * Device Tree for the Embedded Planet EP8248E board running  
> PlanetCore.
> + *
> + * Copyright 2007 Freescale Semiconductor Inc.
> + *
> + * This program is free software; you can redistribute  it and/or  
> modify it
> + * under  the terms of  the GNU General  Public License as  
> published by the
> + * Free Software Foundation;  either version 2 of the  License, or  
> (at your
> + * option) any later version.
> + */
> +

Can we make this a /dts-v1/; since its new.
>
> +/ {
> +	model = "EP8248E";
> +	compatible = "fsl,ep8248e";
> +	#address-cells = <1>;
> +	#size-cells = <1>;

Add a aliases { } and can we use that instead of linux,network-index  
and linux,planetcore-label.

> +
> +	cpus {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		PowerPC,8248@0 {
> +			device_type = "cpu";
> +			reg = <0>;
> +			d-cache-line-size = <d#32>;
> +			i-cache-line-size = <d#32>;
> +			d-cache-size = <d#16384>;
> +			i-cache-size = <d#16384>;
> +			timebase-frequency = <0>;
> +			clock-frequency = <0>;
> +		};
> +	};
> +
> +	localbus {
> +		compatible = "fsl,ep8248e-localbus",
> +		             "fsl,mpc8248-localbus",
> +		             "fsl,pq2-localbus";
> +		#address-cells = <2>;
> +		#size-cells = <1>;
> +		reg = <f0010100 40>;
> +
> +		ranges = <0 0 fc000000 04000000
> +		          1 0 fa000000 00008000>;
> +
> +		flash@0,3800000 {
> +			compatible = "cfi-flash";
> +			reg = <0 3800000 800000>;
> +			bank-width = <4>;
> +			device-width = <2>;
> +		};
> +
> +		bcsr@1,0 {
> +			#address-cells = <2>;
> +			#size-cells = <1>;
> +			reg = <1 0 10>;
> +			compatible = "fsl,ep8248e-bcsr";
> +			ranges;
> +
> +			mdio {
> +				device_type = "mdio";
> +				compatible = "fsl,ep8248e-mdio-bitbang";
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				reg = <1 8 1>;
> +
> +				PHY0: ethernet-phy@0 {
> +					interrupt-parent = <&PIC>;
> +					reg = <0>;
> +					device_type = "ethernet-phy";
> +				};
> +
> +				PHY1: ethernet-phy@1 {
> +					interrupt-parent = <&PIC>;
> +					reg = <1>;
> +					device_type = "ethernet-phy";
> +				};
> +			};
> +		};
> +	};
> +
> +	memory {
> +		device_type = "memory";
> +		reg = <0 0>;
> +	};
> +
> +	soc@f0000000 {
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +		device_type = "soc";
> +		compatible = "fsl,mpc8248", "fsl,pq2-soc";
> +		ranges = <00000000 f0000000 00053000>;
> +
> +		// Temporary -- will go away once kernel uses ranges for  
> get_immrbase().
> +		reg = <f0000000 00053000>;
> +
> +		cpm@119c0 {
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			#interrupt-cells = <2>;
> +			compatible = "fsl,mpc8248-cpm", "fsl,cpm2";
> +			reg = <119c0 30>;
> +			ranges;
> +
> +			muram {
> +				#address-cells = <1>;
> +				#size-cells = <1>;
> +				ranges = <0 0 10000>;
> +
> +				data@0 {
> +					compatible = "fsl,cpm-muram-data";
> +					reg = <0 1100 1140 ec0 9800 800>;
> +				};
> +			};
> +
> +			brg@119f0 {
> +				compatible = "fsl,mpc8272-brg",
> +				             "fsl,cpm2-brg",
> +				             "fsl,cpm-brg";
> +				reg = <119f0 10 115f0 10>;
> +			};
> +
> +			/* Monitor port/SMC1 */
> +			serial@11a80 {
> +				device_type = "serial";
> +				compatible = "fsl,mpc8248-smc-uart",
> +				             "fsl,cpm2-smc-uart";
> +				reg = <11a80 20 1100 40>;
> +				interrupts = <4 8>;
> +				interrupt-parent = <&PIC>;
> +				fsl,cpm-brg = <7>;
> +				fsl,cpm-command = <1d000000>;
> +				linux,planetcore-label = "SMC1";
> +			};
> +
> +			/* "Serial" port/SCC1 */
> +			serial@11a00 {
> +				device_type = "serial";
> +				compatible = "fsl,mpc8248-scc-uart",
> +				             "fsl,cpm2-scc-uart";
> +				reg = <11a00 20 8000 100>;
> +				interrupts = <28 8>;
> +				interrupt-parent = <&PIC>;
> +				fsl,cpm-brg = <1>;
> +				fsl,cpm-command = <00800000>;
> +				linux,planetcore-label = "SCC1";
> +			};
> +
> +			ethernet@11300 {
> +				device_type = "network";
> +				compatible = "fsl,mpc8248-fcc-enet",
> +				             "fsl,cpm2-fcc-enet";
> +				reg = <11300 20 8400 100 11390 1>;
> +				local-mac-address = [ 00 00 00 00 00 00 ];
> +				interrupts = <20 8>;
> +				interrupt-parent = <&PIC>;
> +				phy-handle = <&PHY0>;
> +				linux,network-index = <0>;
> +				fsl,cpm-command = <12000300>;
> +			};
> +
> +			ethernet@11320 {
> +				device_type = "network";
> +				compatible = "fsl,mpc8248-fcc-enet",
> +				             "fsl,cpm2-fcc-enet";
> +				reg = <11320 20 8500 100 113b0 1>;
> +				local-mac-address = [ 00 00 00 00 00 00 ];
> +				interrupts = <21 8>;
> +				interrupt-parent = <&PIC>;
> +				phy-handle = <&PHY1>;
> +				linux,network-index = <1>;
> +				fsl,cpm-command = <16200300>;
> +			};
> +
> +			usb@11b60 {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				compatible = "fsl,mpc8248-usb",
> +				             "fsl,cpm2-usb";
> +				reg = <11b60 18 8b00 100>;
> +				interrupt-parent = <&PIC>;
> +				interrupts = <b 8>;
> +				fsl,cpm-command = <2e600000>;
> +			};
> +		};
> +
> +		PIC: interrupt-controller@10c00 {
> +			#interrupt-cells = <2>;
> +			interrupt-controller;
> +			reg = <10c00 80>;
> +			compatible = "fsl,mpc8248-pic", "fsl,pq2-pic";
> +		};
> +	};
> +};

- k

^ permalink raw reply

* Re: [PATCH 4/4] MPC8313 enhanced Local Bus Controller NAND support.
From: Kumar Gala @ 2007-12-14  5:14 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, dwmw2, linux-mtd
In-Reply-To: <20071213171554.GC4459@loki.buserror.net>

Patch title should really be someting like FSL enhanced local bus (not  
mpc8313).

On Dec 13, 2007, at 11:15 AM, Scott Wood wrote:

> Signed-off-by: Nick Spence <nick.spence@freescale.com>
> Signed-off-by: Scott Wood <scottwood@freescale.com>
> ---
> drivers/mtd/nand/Kconfig         |    9 +
> drivers/mtd/nand/Makefile        |    1 +
> drivers/mtd/nand/fsl_elbc_nand.c | 1281 +++++++++++++++++++++++++++++ 
> +++++++++
> 3 files changed, 1291 insertions(+), 0 deletions(-)
> create mode 100644 drivers/mtd/nand/fsl_elbc_nand.c
>
> diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
> index 246d451..05d976c 100644
> --- a/drivers/mtd/nand/Kconfig
> +++ b/drivers/mtd/nand/Kconfig
> @@ -306,4 +306,13 @@ config MTD_ALAUDA
> 	  These two (and possibly other) Alauda-based cardreaders for
> 	  SmartMedia and xD allow raw flash access.
>
> +config MTD_NAND_FSL_ELBC
> +	tristate "NAND support for Freescale eLBC controllers"
> +	depends on MTD_NAND && PPC_OF
> +	help
> +	  Various Freescale chips, including the 8313, include a NAND Flash
> +	  Controller Module with built-in hardware ECC capabilities.
> +	  Enabling this option will enable you to use this to control
> +	  external NAND devices.
> +
> endif # MTD_NAND
> diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
> index 3ad6c01..d0d4de2 100644
> --- a/drivers/mtd/nand/Makefile
> +++ b/drivers/mtd/nand/Makefile
> @@ -29,5 +29,6 @@ obj-$(CONFIG_MTD_NAND_CM_X270)		+= cmx270_nand.o
> obj-$(CONFIG_MTD_NAND_BASLER_EXCITE)	+= excite_nandflash.o
> obj-$(CONFIG_MTD_NAND_PLATFORM)		+= plat_nand.o
> obj-$(CONFIG_MTD_ALAUDA)		+= alauda.o
> +obj-$(CONFIG_MTD_NAND_FSL_ELBC)		+= fsl_elbc_nand.o
>
> nand-objs := nand_base.o nand_bbt.o
> diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/ 
> fsl_elbc_nand.c
> new file mode 100644
> index 0000000..ce8b0bf
> --- /dev/null
> +++ b/drivers/mtd/nand/fsl_elbc_nand.c
> @@ -0,0 +1,1281 @@
> +/* Freescale Enhanced Local Bus Controller NAND driver
> + *
> + * Copyright (c) 2006-2007 Freescale Semiconductor
> + *
> + * Authors: Nick Spence <nick.spence@freescale.com>,
> + *          Scott Wood <scottwood@freescale.com>
> + *
> + * This program is free software; you can redistribute it and/or  
> modify
> + * it under the terms of the GNU General Public License as  
> published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA   
> 02111-1307  USA
> + */
> +
> +#include <linux/module.h>
> +#include <linux/types.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/string.h>
> +#include <linux/ioport.h>
> +#include <linux/of_platform.h>
> +#include <linux/slab.h>
> +#include <linux/interrupt.h>
> +
> +#include <linux/mtd/mtd.h>
> +#include <linux/mtd/nand.h>
> +#include <linux/mtd/nand_ecc.h>
> +#include <linux/mtd/partitions.h>
> +
> +#include <asm/io.h>
> +
> +
> +//#define ELBC_NAND_DEBUG_LVL 6

undef or something, not C++ comment.

>
> +
> +#ifdef ELBC_NAND_DEBUG_LVL
> +static int fcm_debug_level = ELBC_NAND_DEBUG_LVL;
> +#define FCM_DEBUG(n, args...)		\
> +	do {					\
> +		if (n <= fcm_debug_level)	\
> +			pr_dbg(args);	\
> +	} while(0)
> +#else
> +#define FCM_DEBUG(n, dev, args...) do { } while(0)
> +#endif
> +
> +#define MAX_BANKS 8
> +#define ERR_BYTE 0xFF /* Value returned for read bytes when read  
> failed */
> +#define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait  
> for FCM */
> +
> +struct elbc_bank {
> +	u32 br;             /**< Base Register  */
> +#define BR_BA           0xFFFF8000
> +#define BR_BA_SHIFT             15
> +#define BR_PS           0x00001800
> +#define BR_PS_SHIFT             11
> +#define BR_PS_8         0x00000800  /* Port Size 8 bit */
> +#define BR_PS_16        0x00001000  /* Port Size 16 bit */
> +#define BR_PS_32        0x00001800  /* Port Size 32 bit */
> +#define BR_DECC         0x00000600
> +#define BR_DECC_SHIFT            9
> +#define BR_DECC_OFF     0x00000000  /* HW ECC checking and  
> generation off */
> +#define BR_DECC_CHK     0x00000200  /* HW ECC checking on,  
> generation off */
> +#define BR_DECC_CHK_GEN 0x00000400  /* HW ECC checking and  
> generation on */
> +#define BR_WP           0x00000100
> +#define BR_WP_SHIFT              8
> +#define BR_MSEL         0x000000E0
> +#define BR_MSEL_SHIFT            5
> +#define BR_MS_GPCM      0x00000000  /* GPCM */
> +#define BR_MS_FCM       0x00000020  /* FCM */
> +#define BR_MS_SDRAM     0x00000060  /* SDRAM */
> +#define BR_MS_UPMA      0x00000080  /* UPMA */
> +#define BR_MS_UPMB      0x000000A0  /* UPMB */
> +#define BR_MS_UPMC      0x000000C0  /* UPMC */
> +#define BR_V            0x00000001
> +#define BR_V_SHIFT               0
> +#define BR_RES          ~(BR_BA|BR_PS|BR_DECC|BR_WP|BR_MSEL|BR_V)
> +
> +	u32 or;             /**< Base Register  */
> +#define OR0 0x5004
> +#define OR1 0x500C
> +#define OR2 0x5014
> +#define OR3 0x501C
> +#define OR4 0x5024
> +#define OR5 0x502C
> +#define OR6 0x5034
> +#define OR7 0x503C
> +
> +#define OR_GPCM_AM              0xFFFF8000
> +#define OR_GPCM_AM_SHIFT                15
> +#define OR_GPCM_BCTLD           0x00001000
> +#define OR_GPCM_BCTLD_SHIFT             12
> +#define OR_GPCM_CSNT            0x00000800
> +#define OR_GPCM_CSNT_SHIFT              11
> +#define OR_GPCM_ACS             0x00000600
> +#define OR_GPCM_ACS_SHIFT                9
> +#define OR_GPCM_ACS_0b10        0x00000400
> +#define OR_GPCM_ACS_0b11        0x00000600
> +#define OR_GPCM_XACS            0x00000100
> +#define OR_GPCM_XACS_SHIFT               8
> +#define OR_GPCM_SCY             0x000000F0
> +#define OR_GPCM_SCY_SHIFT                4
> +#define OR_GPCM_SCY_1           0x00000010
> +#define OR_GPCM_SCY_2           0x00000020
> +#define OR_GPCM_SCY_3           0x00000030
> +#define OR_GPCM_SCY_4           0x00000040
> +#define OR_GPCM_SCY_5           0x00000050
> +#define OR_GPCM_SCY_6           0x00000060
> +#define OR_GPCM_SCY_7           0x00000070
> +#define OR_GPCM_SCY_8           0x00000080
> +#define OR_GPCM_SCY_9           0x00000090
> +#define OR_GPCM_SCY_10          0x000000a0
> +#define OR_GPCM_SCY_11          0x000000b0
> +#define OR_GPCM_SCY_12          0x000000c0
> +#define OR_GPCM_SCY_13          0x000000d0
> +#define OR_GPCM_SCY_14          0x000000e0
> +#define OR_GPCM_SCY_15          0x000000f0
> +#define OR_GPCM_SETA            0x00000008
> +#define OR_GPCM_SETA_SHIFT               3
> +#define OR_GPCM_TRLX            0x00000004
> +#define OR_GPCM_TRLX_SHIFT               2
> +#define OR_GPCM_EHTR            0x00000002
> +#define OR_GPCM_EHTR_SHIFT               1
> +#define OR_GPCM_EAD             0x00000001
> +#define OR_GPCM_EAD_SHIFT                0
> +
> +#define OR_UPM_AM    0xFFFF8000
> +#define OR_UPM_AM_SHIFT      15
> +#define OR_UPM_XAM   0x00006000
> +#define OR_UPM_XAM_SHIFT     13
> +#define OR_UPM_BCTLD 0x00001000
> +#define OR_UPM_BCTLD_SHIFT   12
> +#define OR_UPM_BI    0x00000100
> +#define OR_UPM_BI_SHIFT       8
> +#define OR_UPM_TRLX  0x00000004
> +#define OR_UPM_TRLX_SHIFT     2
> +#define OR_UPM_EHTR  0x00000002
> +#define OR_UPM_EHTR_SHIFT     1
> +#define OR_UPM_EAD   0x00000001
> +#define OR_UPM_EAD_SHIFT      0
> +
> +#define OR_SDRAM_AM    0xFFFF8000
> +#define OR_SDRAM_AM_SHIFT      15
> +#define OR_SDRAM_XAM   0x00006000
> +#define OR_SDRAM_XAM_SHIFT     13
> +#define OR_SDRAM_COLS  0x00001C00
> +#define OR_SDRAM_COLS_SHIFT    10
> +#define OR_SDRAM_ROWS  0x000001C0
> +#define OR_SDRAM_ROWS_SHIFT     6
> +#define OR_SDRAM_PMSEL 0x00000020
> +#define OR_SDRAM_PMSEL_SHIFT    5
> +#define OR_SDRAM_EAD   0x00000001
> +#define OR_SDRAM_EAD_SHIFT      0

remove all OR_GPCM_*, OR_UPM_*, OR_SDRAM_* not used anywhere

[snip]

>
> +struct elbc_regs {
> +	struct elbc_bank bank[8];
> +	u8 res0[0x28];
> +	u32 mar;                /**< UPM Address Register */
> +	u8 res1[0x4];
> +	u32 mamr;               /**< UPMA Mode Register */
> +	u32 mbmr;               /**< UPMB Mode Register */
> +	u32 mcmr;               /**< UPMC Mode Register */
> +	u8 res2[0x8];
> +	u32 mrtpr;              /**< Memory Refresh Timer Prescaler  
> Register */
> +	u32 mdr;                /**< UPM Data Register */
> +	u8 res3[0x4];
> +	u32 lsor;               /**< Special Operation Initiation Register  
> */
> +	u32 lsdmr;              /**< SDRAM Mode Register */
> +	u8 res4[0x8];
> +	u32 lurt;               /**< UPM Refresh Timer */
> +	u32 lsrt;               /**< SDRAM Refresh Timer */
> +	u8 res5[0x8];
> +	u32 ltesr;              /**< Transfer Error Status Register */
> +#define LTESR_BM   0x80000000
> +#define LTESR_FCT  0x40000000
> +#define LTESR_PAR  0x20000000
> +#define LTESR_WP   0x04000000
> +#define LTESR_ATMW 0x00800000
> +#define LTESR_ATMR 0x00400000
> +#define LTESR_CS   0x00080000
> +#define LTESR_CC   0x00000001
> +#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
> +	u32 ltedr;              /**< Transfer Error Disable Register */
> +	u32 lteir;              /**< Transfer Error Interrupt Register */
> +	u32 lteatr;             /**< Transfer Error Attributes Register */
> +	u32 ltear;              /**< Transfer Error Address Register */
> +	u8 res6[0xC];
> +	u32 lbcr;               /**< Configuration Register */
> +#define LBCR_LDIS  0x80000000
> +#define LBCR_LDIS_SHIFT    31
> +#define LBCR_BCTLC 0x00C00000
> +#define LBCR_BCTLC_SHIFT   22
> +#define LBCR_AHD   0x00200000
> +#define LBCR_LPBSE 0x00020000
> +#define LBCR_LPBSE_SHIFT   17
> +#define LBCR_EPAR  0x00010000
> +#define LBCR_EPAR_SHIFT    16
> +#define LBCR_BMT   0x0000FF00
> +#define LBCR_BMT_SHIFT      8
> +#define LBCR_INIT  0x00040000
> +	u32 lcrr;               /**< Clock Ratio Register */
> +#define LCRR_DBYP    0x80000000
> +#define LCRR_DBYP_SHIFT      31
> +#define LCRR_BUFCMDC 0x30000000
> +#define LCRR_BUFCMDC_SHIFT   28
> +#define LCRR_ECL     0x03000000
> +#define LCRR_ECL_SHIFT       24
> +#define LCRR_EADC    0x00030000
> +#define LCRR_EADC_SHIFT      16
> +#define LCRR_CLKDIV  0x0000000F
> +#define LCRR_CLKDIV_SHIFT     0
> +	u8 res7[0x8];
> +	u32 fmr;               /**< Flash Mode Register */
> +#define FMR_CWTO     0x0000F000
> +#define FMR_CWTO_SHIFT       12
> +#define FMR_BOOT     0x00000800
> +#define FMR_ECCM     0x00000100
> +#define FMR_AL       0x00000030
> +#define FMR_AL_SHIFT          4
> +#define FMR_OP       0x00000003
> +#define FMR_OP_SHIFT          0
> +	u32 fir;               /**< Flash Instruction Register */
> +#define FIR_OP0      0xF0000000
> +#define FIR_OP0_SHIFT        28
> +#define FIR_OP1      0x0F000000
> +#define FIR_OP1_SHIFT        24
> +#define FIR_OP2      0x00F00000
> +#define FIR_OP2_SHIFT        20
> +#define FIR_OP3      0x000F0000
> +#define FIR_OP3_SHIFT        16
> +#define FIR_OP4      0x0000F000
> +#define FIR_OP4_SHIFT        12
> +#define FIR_OP5      0x00000F00
> +#define FIR_OP5_SHIFT         8
> +#define FIR_OP6      0x000000F0
> +#define FIR_OP6_SHIFT         4
> +#define FIR_OP7      0x0000000F
> +#define FIR_OP7_SHIFT         0
> +#define FIR_OP_NOP   0x0	/* No operation and end of sequence */
> +#define FIR_OP_CA    0x1        /* Issue current column address */
> +#define FIR_OP_PA    0x2        /* Issue current block+page address  
> */
> +#define FIR_OP_UA    0x3        /* Issue user defined address */
> +#define FIR_OP_CM0   0x4        /* Issue command from FCR[CMD0] */
> +#define FIR_OP_CM1   0x5        /* Issue command from FCR[CMD1] */
> +#define FIR_OP_CM2   0x6        /* Issue command from FCR[CMD2] */
> +#define FIR_OP_CM3   0x7        /* Issue command from FCR[CMD3] */
> +#define FIR_OP_WB    0x8        /* Write FBCR bytes from FCM buffer  
> */
> +#define FIR_OP_WS    0x9        /* Write 1 or 2 bytes from MDR[AS] */
> +#define FIR_OP_RB    0xA        /* Read FBCR bytes to FCM buffer */
> +#define FIR_OP_RS    0xB        /* Read 1 or 2 bytes to MDR[AS] */
> +#define FIR_OP_CW0   0xC        /* Wait then issue FCR[CMD0] */
> +#define FIR_OP_CW1   0xD        /* Wait then issue FCR[CMD1] */
> +#define FIR_OP_RBW   0xE        /* Wait then read FBCR bytes */
> +#define FIR_OP_RSW   0xE        /* Wait then read 1 or 2 bytes */
> +	u32 fcr;               /**< Flash Command Register */
> +#define FCR_CMD0     0xFF000000
> +#define FCR_CMD0_SHIFT       24
> +#define FCR_CMD1     0x00FF0000
> +#define FCR_CMD1_SHIFT       16
> +#define FCR_CMD2     0x0000FF00
> +#define FCR_CMD2_SHIFT        8
> +#define FCR_CMD3     0x000000FF
> +#define FCR_CMD3_SHIFT        0
> +	u32 fbar;              /**< Flash Block Address Register */
> +#define FBAR_BLK     0x00FFFFFF
> +	u32 fpar;              /**< Flash Page Address Register */
> +#define FPAR_SP_PI   0x00007C00
> +#define FPAR_SP_PI_SHIFT     10
> +#define FPAR_SP_MS   0x00000200
> +#define FPAR_SP_CI   0x000001FF
> +#define FPAR_SP_CI_SHIFT      0
> +#define FPAR_LP_PI   0x0003F000
> +#define FPAR_LP_PI_SHIFT     12
> +#define FPAR_LP_MS   0x00000800
> +#define FPAR_LP_CI   0x000007FF
> +#define FPAR_LP_CI_SHIFT      0
> +	u32 fbcr;              /**< Flash Byte Count Register */
> +#define FBCR_BC      0x00000FFF
> +	u8 res11[0x8];
> +	u8 res8[0xF00];

we really should use __be32


- k

^ permalink raw reply

* Re: [PATCH 2/2] ucc_geth: use rx-clock-name and tx-clock-name device tree properties
From: Kumar Gala @ 2007-12-14  5:07 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: netdev, Timur Tabi, linuxppc-dev list
In-Reply-To: <1196716685975-git-send-email-timur@freescale.com>


On Dec 3, 2007, at 3:17 PM, Timur Tabi wrote:

> Updates the ucc_geth device driver to check the new rx-clock-name and
> tx-clock-name properties first.  If present, it uses the new function
> qe_clock_source() to obtain the clock source.  Otherwise, it checks  
> the
> deprecated rx-clock and tx-clock properties.
>
> Update the device trees for 832x, 836x, and 8568 to contain the new  
> property
> names only.
>
> Signed-off-by: Timur Tabi <timur@freescale.com>
> ---
>
> This patch applies to Kumar's for-2.6.25 branch.  ucc_geth will  
> compile but not
> run if my other patch, "qe: add function qe_clock_source" has not  
> also been
> applied.

Jeff, I'll take this patch via powerpc.git if you don't have any issue  
since its just touching probe/setup bits.

- k

> arch/powerpc/boot/dts/mpc832x_mds.dts |    8 ++--
> arch/powerpc/boot/dts/mpc832x_rdb.dts |    8 ++--
> arch/powerpc/boot/dts/mpc836x_mds.dts |    8 ++--
> arch/powerpc/boot/dts/mpc8568mds.dts  |    8 ++--
> drivers/net/ucc_geth.c                |   55 ++++++++++++++++++++++++ 
> ++++++--
> 5 files changed, 67 insertions(+), 20 deletions(-)
>
> diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/ 
> boot/dts/mpc832x_mds.dts
> index c64f303..fe54489 100644
> --- a/arch/powerpc/boot/dts/mpc832x_mds.dts
> +++ b/arch/powerpc/boot/dts/mpc832x_mds.dts
> @@ -223,8 +223,8 @@
> 			 */
> 			mac-address = [ 00 00 00 00 00 00 ];
> 			local-mac-address = [ 00 00 00 00 00 00 ];
> -			rx-clock = <19>;
> -			tx-clock = <1a>;
> +			rx-clock-name = "clk9";
> +			tx-clock-name = "clk10";
> 			phy-handle = < &phy3 >;
> 			pio-handle = < &pio3 >;
> 		};
> @@ -244,8 +244,8 @@
> 			 */
> 			mac-address = [ 00 00 00 00 00 00 ];
> 			local-mac-address = [ 00 00 00 00 00 00 ];
> -			rx-clock = <17>;
> -			tx-clock = <18>;
> +			rx-clock-name = "clk7";
> +			tx-clock-name = "clk8";
> 			phy-handle = < &phy4 >;
> 			pio-handle = < &pio4 >;
> 		};
> diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/ 
> boot/dts/mpc832x_rdb.dts
> index 388c8a7..e68a08b 100644
> --- a/arch/powerpc/boot/dts/mpc832x_rdb.dts
> +++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts
> @@ -202,8 +202,8 @@
> 			 */
> 			mac-address = [ 00 00 00 00 00 00 ];
> 			local-mac-address = [ 00 00 00 00 00 00 ];
> -			rx-clock = <20>;
> -			tx-clock = <13>;
> +			rx-clock-name = "clk16";
> +			tx-clock-name = "clk3";
> 			phy-handle = <&phy00>;
> 			pio-handle = <&ucc2pio>;
> 		};
> @@ -223,8 +223,8 @@
> 			 */
> 			mac-address = [ 00 00 00 00 00 00 ];
> 			local-mac-address = [ 00 00 00 00 00 00 ];
> -			rx-clock = <19>;
> -			tx-clock = <1a>;
> +			rx-clock-name = "clk9";
> +			tx-clock-name = "clk10";
> 			phy-handle = <&phy04>;
> 			pio-handle = <&ucc3pio>;
> 		};
> diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/ 
> boot/dts/mpc836x_mds.dts
> index 0b2d2b5..bfd48d0 100644
> --- a/arch/powerpc/boot/dts/mpc836x_mds.dts
> +++ b/arch/powerpc/boot/dts/mpc836x_mds.dts
> @@ -254,8 +254,8 @@
> 			 */
> 			mac-address = [ 00 00 00 00 00 00 ];
> 			local-mac-address = [ 00 00 00 00 00 00 ];
> -			rx-clock = <0>;
> -			tx-clock = <19>;
> +			rx-clock-name = "none";
> +			tx-clock-name = "clk9";
> 			phy-handle = < &phy0 >;
> 			phy-connection-type = "rgmii-id";
> 			pio-handle = < &pio1 >;
> @@ -276,8 +276,8 @@
> 			 */
> 			mac-address = [ 00 00 00 00 00 00 ];
> 			local-mac-address = [ 00 00 00 00 00 00 ];
> -			rx-clock = <0>;
> -			tx-clock = <14>;
> +			rx-clock-name = "none";
> +			tx-clock-name = "clk4";
> 			phy-handle = < &phy1 >;
> 			phy-connection-type = "rgmii-id";
> 			pio-handle = < &pio2 >;
> diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/ 
> boot/dts/mpc8568mds.dts
> index 5439437..cf45aab 100644
> --- a/arch/powerpc/boot/dts/mpc8568mds.dts
> +++ b/arch/powerpc/boot/dts/mpc8568mds.dts
> @@ -333,8 +333,8 @@
> 			 */
> 			mac-address = [ 00 00 00 00 00 00 ];
> 			local-mac-address = [ 00 00 00 00 00 00 ];
> -			rx-clock = <0>;
> -			tx-clock = <20>;
> +			rx-clock-name = "none";
> +			tx-clock-name = "clk16";
> 			pio-handle = <&pio1>;
> 			phy-handle = <&phy0>;
> 			phy-connection-type = "rgmii-id";
> @@ -355,8 +355,8 @@
> 			 */
> 			mac-address = [ 00 00 00 00 00 00 ];
> 			local-mac-address = [ 00 00 00 00 00 00 ];
> -			rx-clock = <0>;
> -			tx-clock = <20>;
> +			rx-clock-name = "none";
> +			tx-clock-name = "clk16";
> 			pio-handle = <&pio2>;
> 			phy-handle = <&phy1>;
> 			phy-connection-type = "rgmii-id";
> diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
> index a3ff270..a93342e 100644
> --- a/drivers/net/ucc_geth.c
> +++ b/drivers/net/ucc_geth.c
> @@ -3814,6 +3814,7 @@ static int ucc_geth_probe(struct of_device*  
> ofdev, const struct of_device_id *ma
> 	int err, ucc_num, max_speed = 0;
> 	const phandle *ph;
> 	const unsigned int *prop;
> +	const char *sprop;
> 	const void *mac_addr;
> 	phy_interface_t phy_interface;
> 	static const int enet_to_speed[] = {
> @@ -3846,10 +3847,56 @@ static int ucc_geth_probe(struct of_device*  
> ofdev, const struct of_device_id *ma
>
> 	ug_info->uf_info.ucc_num = ucc_num;
>
> -	prop = of_get_property(np, "rx-clock", NULL);
> -	ug_info->uf_info.rx_clock = *prop;
> -	prop = of_get_property(np, "tx-clock", NULL);
> -	ug_info->uf_info.tx_clock = *prop;
> +	sprop = of_get_property(np, "rx-clock-name", NULL);
> +	if (sprop) {
> +		ug_info->uf_info.rx_clock = qe_clock_source(sprop);
> +		if ((ug_info->uf_info.rx_clock < QE_CLK_NONE) ||
> +		    (ug_info->uf_info.rx_clock > QE_CLK24)) {
> +			printk(KERN_ERR
> +				"ucc_geth: invalid rx-clock-name property\n");
> +			return -EINVAL;
> +		}
> +	} else {
> +		prop = of_get_property(np, "rx-clock", NULL);
> +		if (!prop) {
> +			/* If both rx-clock-name and rx-clock are missing,
> +			   we want to tell people to use rx-clock-name. */
> +			printk(KERN_ERR
> +				"ucc_geth: missing rx-clock-name property\n");
> +			return -EINVAL;
> +		}
> +		if ((*prop < QE_CLK_NONE) || (*prop > QE_CLK24)) {
> +			printk(KERN_ERR
> +				"ucc_geth: invalid rx-clock propperty\n");
> +			return -EINVAL;
> +		}
> +		ug_info->uf_info.rx_clock = *prop;
> +	}
> +
> +	sprop = of_get_property(np, "tx-clock-name", NULL);
> +	if (sprop) {
> +		ug_info->uf_info.tx_clock = qe_clock_source(sprop);
> +		if ((ug_info->uf_info.tx_clock < QE_CLK_NONE) ||
> +		    (ug_info->uf_info.tx_clock > QE_CLK24)) {
> +			printk(KERN_ERR
> +				"ucc_geth: invalid tx-clock-name property\n");
> +			return -EINVAL;
> +		}
> +	} else {
> +		prop = of_get_property(np, "rx-clock", NULL);
> +		if (!prop) {
> +			printk(KERN_ERR
> +				"ucc_geth: mising tx-clock-name property\n");
> +			return -EINVAL;
> +		}
> +		if ((*prop < QE_CLK_NONE) || (*prop > QE_CLK24)) {
> +			printk(KERN_ERR
> +				"ucc_geth: invalid tx-clock property\n");
> +			return -EINVAL;
> +		}
> +		ug_info->uf_info.tx_clock = *prop;
> +	}
> +
> 	err = of_address_to_resource(np, 0, &res);
> 	if (err)
> 		return -EINVAL;
> -- 
> 1.5.2.4

^ permalink raw reply

* Please pull from 'for-2.6.24' branch
From: Kumar Gala @ 2007-12-14  5:04 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, Vitaly Bordug

Please pull from 'for-2.6.24' branch of

	master.kernel.org:/pub/scm/linux/kernel/git/galak/powerpc.git for-2.6.24

to receive the following updates:

 arch/powerpc/configs/mpc8272_ads_defconfig |    6 +++---
 arch/powerpc/configs/pq2fads_defconfig     |    6 +++---
 arch/powerpc/kernel/ppc_ksyms.c            |   12 ------------
 arch/powerpc/math-emu/op-2.h               |    3 ++-
 arch/powerpc/sysdev/cpm2_common.c          |    3 +--
 drivers/net/fs_enet/mac-scc.c              |    2 +-
 include/asm-powerpc/commproc.h             |    3 ---
 7 files changed, 10 insertions(+), 25 deletions(-)

Jochen Friedrich (2):
      [POWERPC] Fix typo #ifdef -> #ifndef
      [POWERPC] Kill non-existent symbols from ksyms and commproc.h

Liu Yu (1):
      [POWERPC] Fix rounding bug in emulation for double float operating

Scott Wood (2):
      [POWRPC] CPM2: Eliminate section mismatch warning in cpm2_reset().
      [POWERPC] 82xx: mpc8272ads, pq2fads: Update defconfig with CONFIG_FS_ENET_MDIO_FCC

^ permalink raw reply

* Re: any more patches for 2.6.24?
From: Kumar Gala @ 2007-12-14  5:02 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <18274.3076.467791.719752@cargo.ozlabs.ibm.com>


On Dec 13, 2007, at 10:52 PM, Paul Mackerras wrote:

> Currently I have just this one bugfix queued up to go to Linus for
> 2.6.24:
>
> Stephen Rothwell (1):
>      [POWERPC] iSeries: don't printk with HV spinlock held
>
> Does anyone else have bugfixes that need to go in 2.6.24?

I've got a pull request I'm about to send you.

- k

^ permalink raw reply

* Re: [PATCH] Fix rounding bug in emulation for double float operating
From: Kumar Gala @ 2007-12-14  5:01 UTC (permalink / raw)
  To: Liu Yu; +Cc: linuxppc-dev
In-Reply-To: <11972628522442-git-send-email-b13201@freescale.com>


On Dec 9, 2007, at 11:00 PM, Liu Yu wrote:

>
> This patch fixes rounding bug in emulation for double float  
> operating on PowerPC platform.
>
> When pack double float operand, it need to truncate the tail due to  
> the limited precision.
> If the truncated part is not zero, the last bit of work bit (totally  
> 3 bits) need to '|' 1.
>
> This patch is completed in _FP_FRAC_SRS_2(X,N,sz) (arch/powerpc/math- 
> emu/op-2.h).
> Originally the code leftwards rotates the operand to just keep the  
> truncated part,
> then check whether it is zero. However, the number it rotates is not  
> correct when
> N is not smaller than _FP_W_TYPE_SIZE, and it will cause the work  
> bit '|' 1 in the improper case.
>
> This patch fixes this issue.
>
> Signed-off-by: Liu Yu <b13201@freescale.com>
>
> ---
> arch/powerpc/math-emu/op-2.h |    3 ++-
> 1 files changed, 2 insertions(+), 1 deletions(-)

applied.

- k

^ permalink raw reply

* [PATCH 15/15] [POWERPC] Various fixes to pcibios_enable_device()
From: Benjamin Herrenschmidt @ 2007-12-14  4:56 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1197608163.200976.87755569596.qpush@grosgo>

Our implementation of pcibios_enable_device() has a couple of problems.

One is that it should not check IORESOURCE_UNSET, as this might be
left dangling after resource assignment (shouldn't but there are
bugs), but instead, we make it check resource->parent which should
be a reliable indication that the resource has been successfully
claimed (it's in the resource tree).

Then, we also need to skip ROM resources that haven't been enabled
as x86 does.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

 arch/powerpc/kernel/pci-common.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

--- linux-merge.orig/arch/powerpc/kernel/pci-common.c	2007-12-14 15:49:34.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci-common.c	2007-12-14 15:49:36.000000000 +1100
@@ -1147,7 +1147,10 @@ int pcibios_enable_device(struct pci_dev
 		r = &dev->resource[idx];
 		if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
 			continue;
-		if (r->flags & IORESOURCE_UNSET) {
+		if ((idx == PCI_ROM_RESOURCE) &&
+				(!(r->flags & IORESOURCE_ROM_ENABLE)))
+			continue;
+		if (r->parent == NULL) {
 			printk(KERN_ERR "PCI: Device %s not available because"
 			       " of resource collisions\n", pci_name(dev));
 			return -EINVAL;

^ permalink raw reply

* [PATCH 14/15] [POWERPC] Clear pci_probe_only on 64 bits PowerMac
From: Benjamin Herrenschmidt @ 2007-12-14  4:56 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1197608163.200976.87755569596.qpush@grosgo>

It should now be safe to re-assign unassigned resources on 64 bits PowerMac
machines (G5s). This clears pci_probe_only on those.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

 arch/powerpc/platforms/powermac/pci.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

--- linux-merge.orig/arch/powerpc/platforms/powermac/pci.c	2007-12-14 15:49:34.000000000 +1100
+++ linux-merge/arch/powerpc/platforms/powermac/pci.c	2007-12-14 15:49:35.000000000 +1100
@@ -1041,8 +1041,8 @@ void __init pmac_pci_init(void)
 	}
 	/* pmac_check_ht_link(); */
 
-	/* Tell pci.c to not use the common resource allocation mechanism */
-	pci_probe_only = 1;
+	/* We can allocate missing resources if any */
+	pci_probe_only = 0;
 
 #else /* CONFIG_PPC64 */
 	init_p2pbridge();

^ permalink raw reply

* [PATCH 13/15] [POWERPC] Fixup powermac enable device hook
From: Benjamin Herrenschmidt @ 2007-12-14  4:56 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1197608163.200976.87755569596.qpush@grosgo>

Powermac's use of the pcibios_enable_device_hook() got slightly
broken by the recent PCI merge in that it won't be called for
the "initial" case of assigning resources to a previously
unassigned device. This was an abuse of that hook anyway, so
instead we now use a header quirk.

While at it, we move a #ifdef CONFIG_PPC32 to enclose more code
that is only ever used on 32 bits.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

 arch/powerpc/platforms/powermac/pci.c |   18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

--- linux-merge.orig/arch/powerpc/platforms/powermac/pci.c	2007-12-14 15:49:34.000000000 +1100
+++ linux-merge/arch/powerpc/platforms/powermac/pci.c	2007-12-14 15:49:34.000000000 +1100
@@ -1058,6 +1058,7 @@ void __init pmac_pci_init(void)
 #endif
 }
 
+#ifdef CONFIG_PPC32
 int pmac_pci_enable_device_hook(struct pci_dev *dev)
 {
 	struct device_node* node;
@@ -1106,7 +1107,6 @@ int pmac_pci_enable_device_hook(struct p
 	 * bridge and we must not, for example, enable MWI or set the
 	 * cache line size on them.
 	 */
-#ifdef CONFIG_PPC32
 	if (updatecfg) {
 		u16 cmd;
 
@@ -1118,12 +1118,23 @@ int pmac_pci_enable_device_hook(struct p
 
 		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
 				      L1_CACHE_BYTES >> 2);
-#endif
 	}
 
 	return 0;
 }
 
+void __devinit pmac_pci_fixup_ohci(struct pci_dev *dev)
+{
+	struct device_node *node = pci_device_to_OF_node(dev);
+
+	/* We don't want to assign resources to USB controllers
+	 * absent from the OF tree (iBook second controller)
+	 */
+	if (dev->class == PCI_CLASS_SERIAL_USB_OHCI && !node)
+		dev->resource[0].flags = 0;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_APPLE, PCI_ANY_ID, pmac_pci_fixup_ohci);
+
 /* We power down some devices after they have been probed. They'll
  * be powered back on later on
  */
@@ -1171,7 +1182,6 @@ void __init pmac_pcibios_after_init(void
 	of_node_put(nd);
 }
 
-#ifdef CONFIG_PPC32
 void pmac_pci_fixup_cardbus(struct pci_dev* dev)
 {
 	if (!machine_is(powermac))
@@ -1259,7 +1269,7 @@ void pmac_pci_fixup_pciata(struct pci_de
 	}
 }
 DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, pmac_pci_fixup_pciata);
-#endif
+#endif /* CONFIG_PPC32 */
 
 /*
  * Disable second function on K2-SATA, it's broken

^ permalink raw reply

* [PATCH 12/15] [POWERPC] Merge 32 and 64 bits pcibios_enable_device
From: Benjamin Herrenschmidt @ 2007-12-14  4:56 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1197608163.200976.87755569596.qpush@grosgo>

This merge the two implementations, based on the previously
fixed up 32 bits one. The pcibios_enable_device_hook in ppc_md
is now available for ppc64 use. Also remove the new unused
"initial" parameter from it and fixup users.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

 arch/powerpc/kernel/pci-common.c       |   38 +++++++++++++++++++++++++++++++++
 arch/powerpc/kernel/pci_32.c           |   37 --------------------------------
 arch/powerpc/kernel/pci_64.c           |   30 --------------------------
 arch/powerpc/platforms/powermac/pci.c  |   22 ++++++++-----------
 arch/powerpc/platforms/powermac/pmac.h |    2 -
 include/asm-powerpc/machdep.h          |   10 +++-----
 6 files changed, 53 insertions(+), 86 deletions(-)

--- linux-merge.orig/arch/powerpc/kernel/pci-common.c	2007-12-14 15:49:33.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci-common.c	2007-12-14 15:49:34.000000000 +1100
@@ -1127,3 +1127,41 @@ void __devinit pcibios_claim_one_bus(str
 }
 EXPORT_SYMBOL_GPL(pcibios_claim_one_bus);
 #endif /* CONFIG_HOTPLUG */
+
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+	u16 cmd, old_cmd;
+	int idx;
+	struct resource *r;
+
+	if (ppc_md.pcibios_enable_device_hook)
+		if (ppc_md.pcibios_enable_device_hook(dev))
+			return -EINVAL;
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	old_cmd = cmd;
+	for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
+		/* Only set up the requested stuff */
+		if (!(mask & (1 << idx)))
+			continue;
+		r = &dev->resource[idx];
+		if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
+			continue;
+		if (r->flags & IORESOURCE_UNSET) {
+			printk(KERN_ERR "PCI: Device %s not available because"
+			       " of resource collisions\n", pci_name(dev));
+			return -EINVAL;
+		}
+		if (r->flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+		if (r->flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+	}
+	if (cmd != old_cmd) {
+		printk("PCI: Enabling device %s (%04x -> %04x)\n",
+		       pci_name(dev), old_cmd, cmd);
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+	}
+	return 0;
+}
+
Index: linux-merge/include/asm-powerpc/machdep.h
===================================================================
--- linux-merge.orig/include/asm-powerpc/machdep.h	2007-12-14 15:49:31.000000000 +1100
+++ linux-merge/include/asm-powerpc/machdep.h	2007-12-14 15:49:34.000000000 +1100
@@ -204,12 +204,6 @@ struct machdep_calls {
 	/*
 	 * optional PCI "hooks"
 	 */
-
-	/* Called when pci_enable_device() is called (initial=0) or
-	 * when a device with no assigned resource is found (initial=1).
-	 * Returns 0 to allow assignment/enabling of the device. */
-	int  (*pcibios_enable_device_hook)(struct pci_dev *, int initial);
-
 	/* Called in indirect_* to avoid touching devices */
 	int (*pci_exclude_device)(struct pci_controller *, unsigned char, unsigned char);
 
@@ -225,6 +219,10 @@ struct machdep_calls {
 	/* Called for each PCI bus in the system when it's probed */
 	void (*pcibios_fixup_bus)(struct pci_bus *);
 
+	/* Called when pci_enable_device() is called. Returns 0 to
+	 * allow assignment/enabling of the device. */
+	int  (*pcibios_enable_device_hook)(struct pci_dev *);
+
 	/* Called to shutdown machine specific hardware not already controlled
 	 * by other drivers.
 	 */
Index: linux-merge/arch/powerpc/kernel/pci_32.c
===================================================================
--- linux-merge.orig/arch/powerpc/kernel/pci_32.c	2007-12-14 15:49:33.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci_32.c	2007-12-14 15:49:34.000000000 +1100
@@ -518,43 +518,6 @@ pcibios_update_irq(struct pci_dev *dev, 
 	/* XXX FIXME - update OF device tree node interrupt property */
 }
 
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-	u16 cmd, old_cmd;
-	int idx;
-	struct resource *r;
-
-	if (ppc_md.pcibios_enable_device_hook)
-		if (ppc_md.pcibios_enable_device_hook(dev, 0))
-			return -EINVAL;
-		
-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
-	old_cmd = cmd;
-	for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
-		/* Only set up the requested stuff */
-		if (!(mask & (1 << idx)))
-			continue;
-		r = &dev->resource[idx];
-		if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
-			continue;
-		if (r->flags & IORESOURCE_UNSET) {
-			printk(KERN_ERR "PCI: Device %s not available because"
-			       " of resource collisions\n", pci_name(dev));
-			return -EINVAL;
-		}
-		if (r->flags & IORESOURCE_IO)
-			cmd |= PCI_COMMAND_IO;
-		if (r->flags & IORESOURCE_MEM)
-			cmd |= PCI_COMMAND_MEMORY;
-	}
-	if (cmd != old_cmd) {
-		printk("PCI: Enabling device %s (%04x -> %04x)\n",
-		       pci_name(dev), old_cmd, cmd);
-		pci_write_config_word(dev, PCI_COMMAND, cmd);
-	}
-	return 0;
-}
-
 static struct pci_controller*
 pci_bus_to_hose(int bus)
 {
Index: linux-merge/arch/powerpc/kernel/pci_64.c
===================================================================
--- linux-merge.orig/arch/powerpc/kernel/pci_64.c	2007-12-14 15:49:33.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci_64.c	2007-12-14 15:49:34.000000000 +1100
@@ -420,36 +420,6 @@ static int __init pcibios_init(void)
 
 subsys_initcall(pcibios_init);
 
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-	u16 cmd, oldcmd;
-	int i;
-
-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
-	oldcmd = cmd;
-
-	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-		struct resource *res = &dev->resource[i];
-
-		/* Only set up the requested stuff */
-		if (!(mask & (1<<i)))
-			continue;
-
-		if (res->flags & IORESOURCE_IO)
-			cmd |= PCI_COMMAND_IO;
-		if (res->flags & IORESOURCE_MEM)
-			cmd |= PCI_COMMAND_MEMORY;
-	}
-
-	if (cmd != oldcmd) {
-		printk(KERN_DEBUG "PCI: Enabling device: (%s), cmd %x\n",
-		       pci_name(dev), cmd);
-                /* Enable the appropriate bits in the PCI command register.  */
-		pci_write_config_word(dev, PCI_COMMAND, cmd);
-	}
-	return 0;
-}
-
 #ifdef CONFIG_HOTPLUG
 
 int pcibios_unmap_io_space(struct pci_bus *bus)
Index: linux-merge/arch/powerpc/platforms/powermac/pci.c
===================================================================
--- linux-merge.orig/arch/powerpc/platforms/powermac/pci.c	2007-12-14 15:49:32.000000000 +1100
+++ linux-merge/arch/powerpc/platforms/powermac/pci.c	2007-12-14 15:49:34.000000000 +1100
@@ -1058,8 +1058,7 @@ void __init pmac_pci_init(void)
 #endif
 }
 
-int
-pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
+int pmac_pci_enable_device_hook(struct pci_dev *dev)
 {
 	struct device_node* node;
 	int updatecfg = 0;
@@ -1101,26 +1100,25 @@ pmac_pci_enable_device_hook(struct pci_d
 		updatecfg = 1;
 	}
 
+	/*
+	 * Fixup various header fields on 32 bits. We don't do that on
+	 * 64 bits as some of these have strange values behind the HT
+	 * bridge and we must not, for example, enable MWI or set the
+	 * cache line size on them.
+	 */
+#ifdef CONFIG_PPC32
 	if (updatecfg) {
 		u16 cmd;
 
-		/*
-		 * Make sure PCI is correctly configured
-		 *
-		 * We use old pci_bios versions of the function since, by
-		 * default, gmac is not powered up, and so will be absent
-		 * from the kernel initial PCI lookup.
-		 *
-		 * Should be replaced by 2.4 new PCI mechanisms and really
-		 * register the device.
-		 */
 		pci_read_config_word(dev, PCI_COMMAND, &cmd);
 		cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER
 			| PCI_COMMAND_INVALIDATE;
 		pci_write_config_word(dev, PCI_COMMAND, cmd);
 		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 16);
+
 		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
 				      L1_CACHE_BYTES >> 2);
+#endif
 	}
 
 	return 0;
Index: linux-merge/arch/powerpc/platforms/powermac/pmac.h
===================================================================
--- linux-merge.orig/arch/powerpc/platforms/powermac/pmac.h	2007-12-14 15:48:58.000000000 +1100
+++ linux-merge/arch/powerpc/platforms/powermac/pmac.h	2007-12-14 15:49:34.000000000 +1100
@@ -26,7 +26,7 @@ extern void pmac_pci_init(void);
 extern void pmac_nvram_update(void);
 extern unsigned char pmac_nvram_read_byte(int addr);
 extern void pmac_nvram_write_byte(int addr, unsigned char val);
-extern int pmac_pci_enable_device_hook(struct pci_dev *dev, int initial);
+extern int pmac_pci_enable_device_hook(struct pci_dev *dev);
 extern void pmac_pcibios_after_init(void);
 extern int of_show_percpuinfo(struct seq_file *m, int i);
 

^ permalink raw reply

* [PATCH 11/15] [POWERPC] Updates/fixes to 32 bits pcibios_enable_device()
From: Benjamin Herrenschmidt @ 2007-12-14  4:56 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1197608163.200976.87755569596.qpush@grosgo>

Our implementation of pcibios_enable_device() incorrectly ignores
the mask argument and always checks that all resources have been
allocated which isn't the right thing to do anymore.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

 arch/powerpc/kernel/pci_32.c |   10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

--- linux-merge.orig/arch/powerpc/kernel/pci_32.c	2007-12-14 15:49:32.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci_32.c	2007-12-14 15:49:33.000000000 +1100
@@ -530,10 +530,16 @@ int pcibios_enable_device(struct pci_dev
 		
 	pci_read_config_word(dev, PCI_COMMAND, &cmd);
 	old_cmd = cmd;
-	for (idx=0; idx<6; idx++) {
+	for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
+		/* Only set up the requested stuff */
+		if (!(mask & (1 << idx)))
+			continue;
 		r = &dev->resource[idx];
+		if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
+			continue;
 		if (r->flags & IORESOURCE_UNSET) {
-			printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
+			printk(KERN_ERR "PCI: Device %s not available because"
+			       " of resource collisions\n", pci_name(dev));
 			return -EINVAL;
 		}
 		if (r->flags & IORESOURCE_IO)

^ permalink raw reply

* [PATCH 10/15] [POWERPC] fix iSeries PCI resource management
From: Benjamin Herrenschmidt @ 2007-12-14  4:56 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1197608163.200976.87755569596.qpush@grosgo>

The way iSeries manages PCI IO and Memory resources is a bit strange
and is based on overriding the content of those resources with home
cooked ones afterward.

This changes it a bit to better integrate with the new resource handling
so that the "virtual" tokens that iSeries replaces resources with are
done from the proper per-device fixup hook, and bridge resources are
set to enclose that token space. This fixes various things such as
the output of /proc/iomem & ioports, among others. The patch also fixup
various boot messages as well.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 
 arch/powerpc/kernel/pci-common.c       |   16 ++++
 arch/powerpc/kernel/pci_64.c           |   19 ++++-
 arch/powerpc/platforms/iseries/pci.c   |  123 +++++++++++++++++----------------
 arch/powerpc/platforms/iseries/pci.h   |    4 +
 arch/powerpc/platforms/iseries/setup.c |   37 +++++----
 5 files changed, 121 insertions(+), 78 deletions(-)

--- linux-merge.orig/arch/powerpc/kernel/pci-common.c	2007-12-14 15:49:32.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci-common.c	2007-12-14 15:49:33.000000000 +1100
@@ -190,6 +190,20 @@ int pci_read_irq_line(struct pci_dev *pc
 	struct of_irq oirq;
 	unsigned int virq;
 
+	/* The current device-tree that iSeries generates from the HV
+	 * PCI informations doesn't contain proper interrupt routing,
+	 * and all the fallback would do is print out crap, so we
+	 * don't attempt to resolve the interrupts here at all, some
+	 * iSeries specific fixup does it.
+	 *
+	 * In the long run, we will hopefully fix the generated device-tree
+	 * instead.
+	 */
+#ifdef CONFIG_PPC_ISERIES
+	if (firmware_has_feature(FW_FEATURE_ISERIES))
+		return -1;
+#endif
+
 	DBG("Try to map irq for %s...\n", pci_name(pci_dev));
 
 #ifdef DEBUG
@@ -946,7 +960,7 @@ static void __init pcibios_allocate_bus_
 			    || res->start > res->end)
 				continue;
 			if (bus->parent == NULL)
-				pr = (res->flags & IORESOURCE_IO)?
+				pr = (res->flags & IORESOURCE_IO) ?
 					&ioport_resource : &iomem_resource;
 			else {
 				/* Don't bother with non-root busses when
Index: linux-merge/arch/powerpc/kernel/pci_64.c
===================================================================
--- linux-merge.orig/arch/powerpc/kernel/pci_64.c	2007-12-14 15:49:32.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci_64.c	2007-12-14 15:49:33.000000000 +1100
@@ -343,7 +343,7 @@ void __devinit scan_phb(struct pci_contr
 	int i, mode;
 	struct resource *res;
 
-	DBG("Scanning PHB %s\n", node ? node->full_name : "<NO NAME>");
+	DBG("PCI: Scanning PHB %s\n", node ? node->full_name : "<NO NAME>");
 
 	/* Create an empty bus for the toplevel */
 	bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, node);
@@ -359,9 +359,22 @@ void __devinit scan_phb(struct pci_contr
 	pcibios_map_io_space(bus);
 
 	/* Wire up PHB bus resources */
-	bus->resource[0] = res = &hose->io_resource;
-	for (i = 0; i < 3; ++i)
+	if (hose->io_resource.flags) {
+		DBG("PCI: PHB IO resource    = %016lx-%016lx [%lx]\n",
+		    hose->io_resource.start, hose->io_resource.end,
+		    hose->io_resource.flags);
+		bus->resource[0] = res = &hose->io_resource;
+	}
+	for (i = 0; i < 3; ++i) {
+		DBG("PCI: PHB MEM resource %d = %016lx-%016lx [%lx]\n", i,
+		    hose->mem_resources[i].start,
+		    hose->mem_resources[i].end,
+		    hose->mem_resources[i].flags);
 		bus->resource[i+1] = &hose->mem_resources[i];
+	}
+	DBG("PCI: PHB MEM offset     = %016lx\n", hose->pci_mem_offset);
+	DBG("PCI: PHB IO  offset     = %08lx\n",
+	    (unsigned long)hose->io_base_virt - _IO_BASE);
 
 	/* Get probe mode and perform scan */
 	mode = PCI_PROBE_NORMAL;
Index: linux-merge/arch/powerpc/platforms/iseries/pci.c
===================================================================
--- linux-merge.orig/arch/powerpc/platforms/iseries/pci.c	2007-12-14 15:48:59.000000000 +1100
+++ linux-merge/arch/powerpc/platforms/iseries/pci.c	2007-12-14 15:49:33.000000000 +1100
@@ -20,6 +20,9 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
+
+#undef DEBUG
+
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/string.h>
@@ -58,6 +61,7 @@ static int limit_pci_retries = 1;	/* Set
 #define IOMM_TABLE_MAX_ENTRIES	1024
 #define IOMM_TABLE_ENTRY_SIZE	0x0000000000400000UL
 #define BASE_IO_MEMORY		0xE000000000000000UL
+#define END_IO_MEMORY		0xEFFFFFFFFFFFFFFFUL
 
 static unsigned long max_io_memory = BASE_IO_MEMORY;
 static long current_iomm_table_entry;
@@ -68,7 +72,6 @@ static long current_iomm_table_entry;
 static struct device_node *iomm_table[IOMM_TABLE_MAX_ENTRIES];
 static u8 iobar_table[IOMM_TABLE_MAX_ENTRIES];
 
-static const char pci_io_text[] = "iSeries PCI I/O";
 static DEFINE_SPINLOCK(iomm_table_lock);
 
 /*
@@ -279,8 +282,8 @@ out_free:
  * PCI: Bus  0, Device 26, Vendor 0x12AE  Frame  1, Card  C10  Ethernet
  * controller
  */
-static void __init iseries_device_information(struct pci_dev *pdev, int count,
-		u16 bus, HvSubBusNumber subbus)
+static void __init iseries_device_information(struct pci_dev *pdev,
+					      u16 bus, HvSubBusNumber subbus)
 {
 	u8 frame = 0;
 	char card[4];
@@ -290,10 +293,9 @@ static void __init iseries_device_inform
 			ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus));
 
 	if (iseries_get_location_code(bus, agent, &frame, card)) {
-		printk("%d. PCI: Bus%3d, Device%3d, Vendor %04X Frame%3d, "
-			"Card %4s  0x%04X\n", count, bus,
-			PCI_SLOT(pdev->devfn), pdev->vendor, frame,
-			card, (int)(pdev->class >> 8));
+		printk(KERN_INFO "PCI: %s, Vendor %04X Frame%3d, "
+		       "Card %4s  0x%04X\n", pci_name(pdev), pdev->vendor,
+		       frame, card, (int)(pdev->class >> 8));
 	}
 }
 
@@ -323,7 +325,6 @@ static void __init iomm_table_allocate_e
 	 * Set Resource values.
 	 */
 	spin_lock(&iomm_table_lock);
-	bar_res->name = pci_io_text;
 	bar_res->start = BASE_IO_MEMORY +
 		IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry;
 	bar_res->end = bar_res->start + bar_size - 1;
@@ -393,61 +394,63 @@ static struct device_node *find_device_n
 }
 
 /*
- * iSeries_pci_final_fixup(void)
+ * iSeries_pcibios_fixup_resources
+ *
+ * Fixes up all resources for devices
  */
-void __init iSeries_pci_final_fixup(void)
+void __init iSeries_pcibios_fixup_resources(struct pci_dev *pdev)
 {
-	struct pci_dev *pdev = NULL;
+	const u32 *agent;
+	const u32 *sub_bus;
+	unsigned char bus = pdev->bus->number;
 	struct device_node *node;
-	int num_dev = 0;
-
-	/* Fix up at the device node and pci_dev relationship */
-	mf_display_src(0xC9000100);
+	int i;
 
-	printk("pcibios_final_fixup\n");
-	for_each_pci_dev(pdev) {
-		const u32 *agent;
-		const u32 *sub_bus;
-		unsigned char bus = pdev->bus->number;
-
-		node = find_device_node(bus, pdev->devfn);
-		printk("pci dev %p (%x.%x), node %p\n", pdev, bus,
-			pdev->devfn, node);
-		if (!node) {
-			printk("PCI: Device Tree not found for 0x%016lX\n",
-					(unsigned long)pdev);
-			continue;
-		}
-
-		agent = of_get_property(node, "linux,agent-id", NULL);
-		sub_bus = of_get_property(node, "linux,subbus", NULL);
-		if (agent && sub_bus) {
-			u8 irq = iSeries_allocate_IRQ(bus, 0, *sub_bus);
-			int err;
-
-			err = HvCallXm_connectBusUnit(bus, *sub_bus,
-					*agent, irq);
-			if (err)
-				pci_log_error("Connect Bus Unit",
-					bus, *sub_bus, *agent, err);
-			else {
-				err = HvCallPci_configStore8(bus, *sub_bus,
+	node = find_device_node(bus, pdev->devfn);
+	pr_debug("PCI: iSeries %s, pdev %p, node %p\n",
+		 pci_name(pdev), pdev, node);
+	if (!node) {
+		printk("PCI: %s disabled, device tree entry not found !\n",
+		       pci_name(pdev));
+		for (i = 0; i <= PCI_ROM_RESOURCE; i++)
+			pdev->resource[i].flags = 0;
+		return;
+	}
+	sub_bus = of_get_property(node, "linux,subbus", NULL);
+	agent = of_get_property(node, "linux,agent-id", NULL);
+	if (agent && sub_bus) {
+		u8 irq = iSeries_allocate_IRQ(bus, 0, *sub_bus);
+		int err;
+
+		err = HvCallXm_connectBusUnit(bus, *sub_bus, *agent, irq);
+		if (err)
+			pci_log_error("Connect Bus Unit",
+				      bus, *sub_bus, *agent, err);
+		else {
+			err = HvCallPci_configStore8(bus, *sub_bus,
 					*agent, PCI_INTERRUPT_LINE, irq);
-				if (err)
-					pci_log_error("PciCfgStore Irq Failed!",
+			if (err)
+				pci_log_error("PciCfgStore Irq Failed!",
 						bus, *sub_bus, *agent, err);
-				else
-					pdev->irq = irq;
-			}
+			else
+				pdev->irq = irq;
 		}
-
-		num_dev++;
-		pdev->sysdata = node;
-		PCI_DN(node)->pcidev = pdev;
-		allocate_device_bars(pdev);
-		iseries_device_information(pdev, num_dev, bus, *sub_bus);
-		iommu_devnode_init_iSeries(pdev, node);
 	}
+
+	pdev->sysdata = node;
+	PCI_DN(node)->pcidev = pdev;
+	allocate_device_bars(pdev);
+	iseries_device_information(pdev, bus, *sub_bus);
+	iommu_devnode_init_iSeries(pdev, node);
+}
+
+/*
+ * iSeries_pci_final_fixup(void)
+ */
+void __init iSeries_pci_final_fixup(void)
+{
+	/* Fix up at the device node and pci_dev relationship */
+	mf_display_src(0xC9000100);
 	iSeries_activate_IRQs();
 	mf_display_src(0xC9000200);
 }
@@ -894,10 +897,18 @@ void __init iSeries_pcibios_init(void)
 		/* All legacy iSeries PHBs are in domain zero */
 		phb->global_number = 0;
 
-		phb->pci_mem_offset = bus;
 		phb->first_busno = bus;
 		phb->last_busno = bus;
 		phb->ops = &iSeries_pci_ops;
+		phb->io_base_virt = (void __iomem *)_IO_BASE;
+		phb->io_resource.flags = IORESOURCE_IO;
+		phb->io_resource.start = BASE_IO_MEMORY;
+		phb->io_resource.end = END_IO_MEMORY;
+		phb->io_resource.name = "iSeries PCI IO";
+		phb->mem_resources[0].flags = IORESOURCE_MEM;
+		phb->mem_resources[0].start = BASE_IO_MEMORY;
+		phb->mem_resources[0].end = END_IO_MEMORY;
+		phb->mem_resources[0].name = "Series PCI MEM";
 	}
 
 	of_node_put(root);
Index: linux-merge/arch/powerpc/platforms/iseries/pci.h
===================================================================
--- linux-merge.orig/arch/powerpc/platforms/iseries/pci.h	2007-12-14 15:48:59.000000000 +1100
+++ linux-merge/arch/powerpc/platforms/iseries/pci.h	2007-12-14 15:49:33.000000000 +1100
@@ -43,12 +43,16 @@
 #define ISERIES_GET_DEVICE_FROM_SUBBUS(subbus)		((subbus >> 5) & 0x7)
 #define ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus)	((subbus >> 2) & 0x7)
 
+struct pci_dev;
+
 #ifdef CONFIG_PCI
 extern void	iSeries_pcibios_init(void);
 extern void	iSeries_pci_final_fixup(void);
+extern void 	iSeries_pcibios_fixup_resources(struct pci_dev *dev);
 #else
 static inline void	iSeries_pcibios_init(void) { }
 static inline void	iSeries_pci_final_fixup(void) { }
+static inline void 	iSeries_pcibios_fixup_resources(struct pci_dev *dev) {}
 #endif
 
 #endif /* _PLATFORMS_ISERIES_PCI_H */
Index: linux-merge/arch/powerpc/platforms/iseries/setup.c
===================================================================
--- linux-merge.orig/arch/powerpc/platforms/iseries/setup.c	2007-12-14 15:48:59.000000000 +1100
+++ linux-merge/arch/powerpc/platforms/iseries/setup.c	2007-12-14 15:49:33.000000000 +1100
@@ -639,24 +639,25 @@ static int __init iseries_probe(void)
 }
 
 define_machine(iseries) {
-	.name		= "iSeries",
-	.setup_arch	= iSeries_setup_arch,
-	.show_cpuinfo	= iSeries_show_cpuinfo,
-	.init_IRQ	= iSeries_init_IRQ,
-	.get_irq	= iSeries_get_irq,
-	.init_early	= iSeries_init_early,
-	.pcibios_fixup	= iSeries_pci_final_fixup,
-	.restart	= mf_reboot,
-	.power_off	= mf_power_off,
-	.halt		= mf_power_off,
-	.get_boot_time	= iSeries_get_boot_time,
-	.set_rtc_time	= iSeries_set_rtc_time,
-	.get_rtc_time	= iSeries_get_rtc_time,
-	.calibrate_decr	= generic_calibrate_decr,
-	.progress	= iSeries_progress,
-	.probe		= iseries_probe,
-	.ioremap	= iseries_ioremap,
-	.iounmap	= iseries_iounmap,
+	.name			= "iSeries",
+	.setup_arch		= iSeries_setup_arch,
+	.show_cpuinfo		= iSeries_show_cpuinfo,
+	.init_IRQ		= iSeries_init_IRQ,
+	.get_irq		= iSeries_get_irq,
+	.init_early		= iSeries_init_early,
+	.pcibios_fixup		= iSeries_pci_final_fixup,
+	.pcibios_fixup_resources= iSeries_pcibios_fixup_resources,
+	.restart		= mf_reboot,
+	.power_off		= mf_power_off,
+	.halt			= mf_power_off,
+	.get_boot_time		= iSeries_get_boot_time,
+	.set_rtc_time		= iSeries_set_rtc_time,
+	.get_rtc_time		= iSeries_get_rtc_time,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= iSeries_progress,
+	.probe			= iseries_probe,
+	.ioremap		= iseries_ioremap,
+	.iounmap		= iseries_iounmap,
 	/* XXX Implement enable_pmcs for iSeries */
 };
 

^ permalink raw reply

* [PATCH 9/15] [POWERPC] Merge PCI resource allocation & assignment
From: Benjamin Herrenschmidt @ 2007-12-14  4:56 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1197608163.200976.87755569596.qpush@grosgo>

The 32 bits PCI code now uses the generic code for assigning unassigned
resources and an algorithm similar to x86 for claiming existing ones.

This works far better than the 64 bits code which basically can only
claim existing ones (pci_probe_only=1) or would fall appart completely.

This merges them so that the new 32 bits implementation is used for both.

64 bits now gets the new PCI flags for controlling the behaviour, though
the old pci_probe_only global is still there for now to be cleared if you
want to.

I kept a pcibios_claim_one_bus() function mostly based on the old 64
bits code for use by the DLPAR hotplug. This will have to be cleaned
up, thought I hope it will work in the meantime.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

 arch/powerpc/kernel/pci-common.c      |  292 ++++++++++++++++++++++++++++++++++
 arch/powerpc/kernel/pci_32.c          |  246 ----------------------------
 arch/powerpc/kernel/pci_64.c          |  118 +------------
 arch/powerpc/platforms/powermac/pci.c |    3 
 include/asm-powerpc/pci.h             |    8 
 5 files changed, 311 insertions(+), 356 deletions(-)

--- linux-merge.orig/arch/powerpc/kernel/pci-common.c	2007-12-14 15:49:31.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci-common.c	2007-12-14 15:49:32.000000000 +1100
@@ -53,6 +53,8 @@ static int global_phb_number;		/* Global
 /* ISA Memory physical address */
 resource_size_t isa_mem_base;
 
+/* Default PCI flags is 0 */
+unsigned int ppc_pci_flags;
 
 struct pci_controller *pcibios_alloc_controller(struct device_node *dev)
 {
@@ -821,3 +823,293 @@ void __devinit pcibios_fixup_of_probed_b
 {
 	__pcibios_fixup_bus(bus);
 }
+
+static int skip_isa_ioresource_align(struct pci_dev *dev)
+{
+	if ((ppc_pci_flags & PPC_PCI_CAN_SKIP_ISA_ALIGN) &&
+	    !(dev->bus->bridge_ctl & PCI_BRIDGE_CTL_ISA))
+		return 1;
+	return 0;
+}
+
+/*
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ *
+ * Why? Because some silly external IO cards only decode
+ * the low 10 bits of the IO address. The 0x00-0xff region
+ * is reserved for motherboard devices that decode all 16
+ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
+ * but we want to try to avoid allocating at 0x2900-0x2bff
+ * which might have be mirrored at 0x0100-0x03ff..
+ */
+void pcibios_align_resource(void *data, struct resource *res,
+				resource_size_t size, resource_size_t align)
+{
+	struct pci_dev *dev = data;
+
+	if (res->flags & IORESOURCE_IO) {
+		resource_size_t start = res->start;
+
+		if (skip_isa_ioresource_align(dev))
+			return;
+		if (start & 0x300) {
+			start = (start + 0x3ff) & ~0x3ff;
+			res->start = start;
+		}
+	}
+}
+EXPORT_SYMBOL(pcibios_align_resource);
+
+/*
+ * Reparent resource children of pr that conflict with res
+ * under res, and make res replace those children.
+ */
+static int __init reparent_resources(struct resource *parent,
+				     struct resource *res)
+{
+	struct resource *p, **pp;
+	struct resource **firstpp = NULL;
+
+	for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) {
+		if (p->end < res->start)
+			continue;
+		if (res->end < p->start)
+			break;
+		if (p->start < res->start || p->end > res->end)
+			return -1;	/* not completely contained */
+		if (firstpp == NULL)
+			firstpp = pp;
+	}
+	if (firstpp == NULL)
+		return -1;	/* didn't find any conflicting entries? */
+	res->parent = parent;
+	res->child = *firstpp;
+	res->sibling = *pp;
+	*firstpp = res;
+	*pp = NULL;
+	for (p = res->child; p != NULL; p = p->sibling) {
+		p->parent = res;
+		DBG(KERN_INFO "PCI: reparented %s [%llx..%llx] under %s\n",
+		    p->name,
+		    (unsigned long long)p->start,
+		    (unsigned long long)p->end, res->name);
+	}
+	return 0;
+}
+
+/*
+ *  Handle resources of PCI devices.  If the world were perfect, we could
+ *  just allocate all the resource regions and do nothing more.  It isn't.
+ *  On the other hand, we cannot just re-allocate all devices, as it would
+ *  require us to know lots of host bridge internals.  So we attempt to
+ *  keep as much of the original configuration as possible, but tweak it
+ *  when it's found to be wrong.
+ *
+ *  Known BIOS problems we have to work around:
+ *	- I/O or memory regions not configured
+ *	- regions configured, but not enabled in the command register
+ *	- bogus I/O addresses above 64K used
+ *	- expansion ROMs left enabled (this may sound harmless, but given
+ *	  the fact the PCI specs explicitly allow address decoders to be
+ *	  shared between expansion ROMs and other resource regions, it's
+ *	  at least dangerous)
+ *
+ *  Our solution:
+ *	(1) Allocate resources for all buses behind PCI-to-PCI bridges.
+ *	    This gives us fixed barriers on where we can allocate.
+ *	(2) Allocate resources for all enabled devices.  If there is
+ *	    a collision, just mark the resource as unallocated. Also
+ *	    disable expansion ROMs during this step.
+ *	(3) Try to allocate resources for disabled devices.  If the
+ *	    resources were assigned correctly, everything goes well,
+ *	    if they weren't, they won't disturb allocation of other
+ *	    resources.
+ *	(4) Assign new addresses to resources which were either
+ *	    not configured at all or misconfigured.  If explicitly
+ *	    requested by the user, configure expansion ROM address
+ *	    as well.
+ */
+
+static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
+{
+	struct pci_bus *bus;
+	int i;
+	struct resource *res, *pr;
+
+	/* Depth-First Search on bus tree */
+	list_for_each_entry(bus, bus_list, node) {
+		for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) {
+			if ((res = bus->resource[i]) == NULL || !res->flags
+			    || res->start > res->end)
+				continue;
+			if (bus->parent == NULL)
+				pr = (res->flags & IORESOURCE_IO)?
+					&ioport_resource : &iomem_resource;
+			else {
+				/* Don't bother with non-root busses when
+				 * re-assigning all resources. We clear the
+				 * resource flags as if they were colliding
+				 * and as such ensure proper re-allocation
+				 * later.
+				 */
+				if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC)
+					goto clear_resource;
+				pr = pci_find_parent_resource(bus->self, res);
+				if (pr == res) {
+					/* this happens when the generic PCI
+					 * code (wrongly) decides that this
+					 * bridge is transparent  -- paulus
+					 */
+					continue;
+				}
+			}
+
+			DBG("PCI: %s (bus %d) bridge rsrc %d: %016llx-%016llx "
+			    "[0x%x], parent %p (%s)\n",
+			    bus->self ? pci_name(bus->self) : "PHB",
+			    bus->number, i,
+			    (unsigned long long)res->start,
+			    (unsigned long long)res->end,
+			    (unsigned int)res->flags,
+			    pr, (pr && pr->name) ? pr->name : "nil");
+
+			if (pr && !(pr->flags & IORESOURCE_UNSET)) {
+				if (request_resource(pr, res) == 0)
+					continue;
+				/*
+				 * Must be a conflict with an existing entry.
+				 * Move that entry (or entries) under the
+				 * bridge resource and try again.
+				 */
+				if (reparent_resources(pr, res) == 0)
+					continue;
+			}
+			printk(KERN_WARNING
+			       "PCI: Cannot allocate resource region "
+			       "%d of PCI bridge %d, will remap\n",
+			       i, bus->number);
+clear_resource:
+			res->flags = 0;
+		}
+		pcibios_allocate_bus_resources(&bus->children);
+	}
+}
+
+static inline void __devinit alloc_resource(struct pci_dev *dev, int idx)
+{
+	struct resource *pr, *r = &dev->resource[idx];
+
+	DBG("PCI: Allocating %s: Resource %d: %016llx..%016llx [%x]\n",
+	    pci_name(dev), idx,
+	    (unsigned long long)r->start,
+	    (unsigned long long)r->end,
+	    (unsigned int)r->flags);
+
+	pr = pci_find_parent_resource(dev, r);
+	if (!pr || (pr->flags & IORESOURCE_UNSET) ||
+	    request_resource(pr, r) < 0) {
+		printk(KERN_WARNING "PCI: Cannot allocate resource region %d"
+		       " of device %s, will remap\n", idx, pci_name(dev));
+		if (pr)
+			DBG("PCI:  parent is %p: %016llx-%016llx [%x]\n", pr,
+			    (unsigned long long)pr->start,
+			    (unsigned long long)pr->end,
+			    (unsigned int)pr->flags);
+		/* We'll assign a new address later */
+		r->flags |= IORESOURCE_UNSET;
+		r->end -= r->start;
+		r->start = 0;
+	}
+}
+
+static void __init pcibios_allocate_resources(int pass)
+{
+	struct pci_dev *dev = NULL;
+	int idx, disabled;
+	u16 command;
+	struct resource *r;
+
+	for_each_pci_dev(dev) {
+		pci_read_config_word(dev, PCI_COMMAND, &command);
+		for (idx = 0; idx < 6; idx++) {
+			r = &dev->resource[idx];
+			if (r->parent)		/* Already allocated */
+				continue;
+			if (!r->flags || (r->flags & IORESOURCE_UNSET))
+				continue;	/* Not assigned at all */
+			if (r->flags & IORESOURCE_IO)
+				disabled = !(command & PCI_COMMAND_IO);
+			else
+				disabled = !(command & PCI_COMMAND_MEMORY);
+			if (pass == disabled)
+				alloc_resource(dev, idx);
+		}
+		if (pass)
+			continue;
+		r = &dev->resource[PCI_ROM_RESOURCE];
+		if (r->flags & IORESOURCE_ROM_ENABLE) {
+			/* Turn the ROM off, leave the resource region,
+			 * but keep it unregistered.
+			 */
+			u32 reg;
+			DBG("PCI: Switching off ROM of %s\n", pci_name(dev));
+			r->flags &= ~IORESOURCE_ROM_ENABLE;
+			pci_read_config_dword(dev, dev->rom_base_reg, &reg);
+			pci_write_config_dword(dev, dev->rom_base_reg,
+					       reg & ~PCI_ROM_ADDRESS_ENABLE);
+		}
+	}
+}
+
+void __init pcibios_resource_survey(void)
+{
+	/* Allocate and assign resources. If we re-assign everything, then
+	 * we skip the allocate phase
+	 */
+	pcibios_allocate_bus_resources(&pci_root_buses);
+
+	if (!(ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC)) {
+		pcibios_allocate_resources(0);
+		pcibios_allocate_resources(1);
+	}
+
+	if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) {
+		DBG("PCI: Assigning unassigned resouces...\n");
+		pci_assign_unassigned_resources();
+	}
+
+	/* Call machine dependent fixup */
+	if (ppc_md.pcibios_fixup)
+		ppc_md.pcibios_fixup();
+}
+
+#ifdef CONFIG_HOTPLUG
+/* This is used by the pSeries hotplug driver to allocate resource
+ * of newly plugged busses. We can try to consolidate with the
+ * rest of the code later, for now, keep it as-is
+ */
+void __devinit pcibios_claim_one_bus(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+	struct pci_bus *child_bus;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		int i;
+
+		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+			struct resource *r = &dev->resource[i];
+
+			if (r->parent || !r->start || !r->flags)
+				continue;
+			pci_claim_resource(dev, i);
+		}
+	}
+
+	list_for_each_entry(child_bus, &bus->children, node)
+		pcibios_claim_one_bus(child_bus);
+}
+EXPORT_SYMBOL_GPL(pcibios_claim_one_bus);
+#endif /* CONFIG_HOTPLUG */
Index: linux-merge/arch/powerpc/kernel/pci_32.c
===================================================================
--- linux-merge.orig/arch/powerpc/kernel/pci_32.c	2007-12-14 15:49:31.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci_32.c	2007-12-14 15:49:32.000000000 +1100
@@ -35,13 +35,9 @@ unsigned long isa_io_base     = 0;
 unsigned long pci_dram_offset = 0;
 int pcibios_assign_bus_offset = 1;
 
-/* Default PCI flags is 0 */
-unsigned int ppc_pci_flags;
-
 void pcibios_make_OF_bus_map(void);
 
 static void fixup_broken_pcnet32(struct pci_dev* dev);
-static int reparent_resources(struct resource *parent, struct resource *res);
 static void fixup_cpc710_pci64(struct pci_dev* dev);
 #ifdef CONFIG_PPC_OF
 static u8* pci_to_OF_bus_map;
@@ -97,170 +93,6 @@ fixup_cpc710_pci64(struct pci_dev* dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM,	PCI_DEVICE_ID_IBM_CPC710_PCI64,	fixup_cpc710_pci64);
 
-static int skip_isa_ioresource_align(struct pci_dev *dev)
-{
-	if ((ppc_pci_flags & PPC_PCI_CAN_SKIP_ISA_ALIGN) &&
-	    !(dev->bus->bridge_ctl & PCI_BRIDGE_CTL_ISA))
-		return 1;
-	return 0;
-}
-
-/*
- * We need to avoid collisions with `mirrored' VGA ports
- * and other strange ISA hardware, so we always want the
- * addresses to be allocated in the 0x000-0x0ff region
- * modulo 0x400.
- *
- * Why? Because some silly external IO cards only decode
- * the low 10 bits of the IO address. The 0x00-0xff region
- * is reserved for motherboard devices that decode all 16
- * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
- * but we want to try to avoid allocating at 0x2900-0x2bff
- * which might have be mirrored at 0x0100-0x03ff..
- */
-void pcibios_align_resource(void *data, struct resource *res,
-				resource_size_t size, resource_size_t align)
-{
-	struct pci_dev *dev = data;
-
-	if (res->flags & IORESOURCE_IO) {
-		resource_size_t start = res->start;
-
-		if (skip_isa_ioresource_align(dev))
-			return;
-		if (start & 0x300) {
-			start = (start + 0x3ff) & ~0x3ff;
-			res->start = start;
-		}
-	}
-}
-EXPORT_SYMBOL(pcibios_align_resource);
-
-/*
- *  Handle resources of PCI devices.  If the world were perfect, we could
- *  just allocate all the resource regions and do nothing more.  It isn't.
- *  On the other hand, we cannot just re-allocate all devices, as it would
- *  require us to know lots of host bridge internals.  So we attempt to
- *  keep as much of the original configuration as possible, but tweak it
- *  when it's found to be wrong.
- *
- *  Known BIOS problems we have to work around:
- *	- I/O or memory regions not configured
- *	- regions configured, but not enabled in the command register
- *	- bogus I/O addresses above 64K used
- *	- expansion ROMs left enabled (this may sound harmless, but given
- *	  the fact the PCI specs explicitly allow address decoders to be
- *	  shared between expansion ROMs and other resource regions, it's
- *	  at least dangerous)
- *
- *  Our solution:
- *	(1) Allocate resources for all buses behind PCI-to-PCI bridges.
- *	    This gives us fixed barriers on where we can allocate.
- *	(2) Allocate resources for all enabled devices.  If there is
- *	    a collision, just mark the resource as unallocated. Also
- *	    disable expansion ROMs during this step.
- *	(3) Try to allocate resources for disabled devices.  If the
- *	    resources were assigned correctly, everything goes well,
- *	    if they weren't, they won't disturb allocation of other
- *	    resources.
- *	(4) Assign new addresses to resources which were either
- *	    not configured at all or misconfigured.  If explicitly
- *	    requested by the user, configure expansion ROM address
- *	    as well.
- */
-
-static void __init
-pcibios_allocate_bus_resources(struct list_head *bus_list)
-{
-	struct pci_bus *bus;
-	int i;
-	struct resource *res, *pr;
-
-	/* Depth-First Search on bus tree */
-	list_for_each_entry(bus, bus_list, node) {
-		for (i = 0; i < 4; ++i) {
-			if ((res = bus->resource[i]) == NULL || !res->flags
-			    || res->start > res->end)
-				continue;
-			if (bus->parent == NULL)
-				pr = (res->flags & IORESOURCE_IO)?
-					&ioport_resource : &iomem_resource;
-			else {
-				/* Don't bother with non-root busses when
-				 * re-assigning all resources.
-				 */
-				if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC)
-					continue;
-				pr = pci_find_parent_resource(bus->self, res);
-				if (pr == res) {
-					/* this happens when the generic PCI
-					 * code (wrongly) decides that this
-					 * bridge is transparent  -- paulus
-					 */
-					continue;
-				}
-			}
-
-			DBG("PCI: dev %s (bus 0x%02x) bridge rsrc %d: %016llx..%016llx "
-			    "(f:0x%08lx), parent %p\n",
-			    bus->self ? pci_name(bus->self) : "PHB", bus->number, i,
-			    (u64)res->start, (u64)res->end, res->flags, pr);
-
-			if (pr && !(pr->flags & IORESOURCE_UNSET)) {
-				if (request_resource(pr, res) == 0)
-					continue;
-				/*
-				 * Must be a conflict with an existing entry.
-				 * Move that entry (or entries) under the
-				 * bridge resource and try again.
-				 */
-				if (reparent_resources(pr, res) == 0)
-					continue;
-			}
-			printk(KERN_WARNING
-			       "PCI: Cannot allocate resource region "
-			       "%d of PCI bridge %d, will remap\n",
-			       i, bus->number);
-			res->flags |= IORESOURCE_UNSET;
-		}
-		pcibios_allocate_bus_resources(&bus->children);
-	}
-}
-
-/*
- * Reparent resource children of pr that conflict with res
- * under res, and make res replace those children.
- */
-static int __init
-reparent_resources(struct resource *parent, struct resource *res)
-{
-	struct resource *p, **pp;
-	struct resource **firstpp = NULL;
-
-	for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) {
-		if (p->end < res->start)
-			continue;
-		if (res->end < p->start)
-			break;
-		if (p->start < res->start || p->end > res->end)
-			return -1;	/* not completely contained */
-		if (firstpp == NULL)
-			firstpp = pp;
-	}
-	if (firstpp == NULL)
-		return -1;	/* didn't find any conflicting entries? */
-	res->parent = parent;
-	res->child = *firstpp;
-	res->sibling = *pp;
-	*firstpp = res;
-	*pp = NULL;
-	for (p = res->child; p != NULL; p = p->sibling) {
-		p->parent = res;
-		DBG(KERN_INFO "PCI: reparented %s [%llx..%llx] under %s\n",
-		    p->name, (u64)p->start, (u64)p->end, res->name);
-	}
-	return 0;
-}
 
 void __init
 update_bridge_resource(struct pci_dev *dev, struct resource *res)
@@ -318,63 +150,6 @@ update_bridge_resource(struct pci_dev *d
 	pci_write_config_word(dev, PCI_COMMAND, cmd);
 }
 
-static inline void alloc_resource(struct pci_dev *dev, int idx)
-{
-	struct resource *pr, *r = &dev->resource[idx];
-
-	DBG("PCI: Allocating %s: Resource %d: %016llx..%016llx (f=%lx)\n",
-	    pci_name(dev), idx, (u64)r->start, (u64)r->end, r->flags);
-	pr = pci_find_parent_resource(dev, r);
-	if (!pr || (pr->flags & IORESOURCE_UNSET) ||  request_resource(pr, r) < 0) {
-		printk(KERN_WARNING "PCI: Cannot allocate resource region %d"
-		       " of device %s, will remap\n", idx, pci_name(dev));
-		if (pr)
-			DBG("PCI:  parent is %p: %016llx-%016llx (f=%lx)\n",
-			    pr, (u64)pr->start, (u64)pr->end, pr->flags);
-		/* We'll assign a new address later */
-		r->flags |= IORESOURCE_UNSET;
-		r->end -= r->start;
-		r->start = 0;
-	}
-}
-
-static void __init
-pcibios_allocate_resources(int pass)
-{
-	struct pci_dev *dev = NULL;
-	int idx, disabled;
-	u16 command;
-	struct resource *r;
-
-	for_each_pci_dev(dev) {
-		pci_read_config_word(dev, PCI_COMMAND, &command);
-		for (idx = 0; idx < 6; idx++) {
-			r = &dev->resource[idx];
-			if (r->parent)		/* Already allocated */
-				continue;
-			if (!r->flags || (r->flags & IORESOURCE_UNSET))
-				continue;	/* Not assigned at all */
-			if (r->flags & IORESOURCE_IO)
-				disabled = !(command & PCI_COMMAND_IO);
-			else
-				disabled = !(command & PCI_COMMAND_MEMORY);
-			if (pass == disabled)
-				alloc_resource(dev, idx);
-		}
-		if (pass)
-			continue;
-		r = &dev->resource[PCI_ROM_RESOURCE];
-		if (r->flags & IORESOURCE_ROM_ENABLE) {
-			/* Turn the ROM off, leave the resource region, but keep it unregistered. */
-			u32 reg;
-			DBG("PCI: Switching off ROM of %s\n", pci_name(dev));
-			r->flags &= ~IORESOURCE_ROM_ENABLE;
-			pci_read_config_dword(dev, dev->rom_base_reg, &reg);
-			pci_write_config_dword(dev, dev->rom_base_reg,
-					       reg & ~PCI_ROM_ADDRESS_ENABLE);
-		}
-	}
-}
 
 #ifdef CONFIG_PPC_OF
 /*
@@ -649,8 +424,7 @@ void pcibios_make_OF_bus_map(void)
 }
 #endif /* CONFIG_PPC_OF */
 
-static int __init
-pcibios_init(void)
+static int __init pcibios_init(void)
 {
 	struct pci_controller *hose, *tmp;
 	struct pci_bus *bus;
@@ -683,22 +457,8 @@ pcibios_init(void)
 	if (pci_assign_all_buses && have_of)
 		pcibios_make_OF_bus_map();
 
-	/* Call machine dependent fixup */
-	if (ppc_md.pcibios_fixup)
-		ppc_md.pcibios_fixup();
-
-	/* Allocate and assign resources. If we re-assign everything, then
-	 * we skip the allocate phase
-	 */
-	pcibios_allocate_bus_resources(&pci_root_buses);
-	if (!(ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC)) {
-		pcibios_allocate_resources(0);
-		pcibios_allocate_resources(1);
-	}
-	if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) {
-		DBG("PCI: Assigning unassigned resouces...\n");
-		pci_assign_unassigned_resources();
-	}
+	/* Call common code to handle resource allocation */
+	pcibios_resource_survey();
 
 	/* Call machine dependent post-init code */
 	if (ppc_md.pcibios_after_init)
Index: linux-merge/arch/powerpc/kernel/pci_64.c
===================================================================
--- linux-merge.orig/arch/powerpc/kernel/pci_64.c	2007-12-14 15:49:31.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci_64.c	2007-12-14 15:49:32.000000000 +1100
@@ -75,85 +75,6 @@ static void fixup_broken_pcnet32(struct 
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32);
 
 
-/*
- * We need to avoid collisions with `mirrored' VGA ports
- * and other strange ISA hardware, so we always want the
- * addresses to be allocated in the 0x000-0x0ff region
- * modulo 0x400.
- *
- * Why? Because some silly external IO cards only decode
- * the low 10 bits of the IO address. The 0x00-0xff region
- * is reserved for motherboard devices that decode all 16
- * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
- * but we want to try to avoid allocating at 0x2900-0x2bff
- * which might have be mirrored at 0x0100-0x03ff..
- */
-void pcibios_align_resource(void *data, struct resource *res,
-			    resource_size_t size, resource_size_t align)
-{
-	struct pci_dev *dev = data;
-	struct pci_controller *hose = pci_bus_to_host(dev->bus);
-	resource_size_t start = res->start;
-	unsigned long alignto;
-
-	if (res->flags & IORESOURCE_IO) {
-	        unsigned long offset = (unsigned long)hose->io_base_virt -
-					_IO_BASE;
-		/* Make sure we start at our min on all hoses */
-		if (start - offset < PCIBIOS_MIN_IO)
-			start = PCIBIOS_MIN_IO + offset;
-
-		/*
-		 * Put everything into 0x00-0xff region modulo 0x400
-		 */
-		if (start & 0x300)
-			start = (start + 0x3ff) & ~0x3ff;
-
-	} else if (res->flags & IORESOURCE_MEM) {
-		/* Make sure we start at our min on all hoses */
-		if (start - hose->pci_mem_offset < PCIBIOS_MIN_MEM)
-			start = PCIBIOS_MIN_MEM + hose->pci_mem_offset;
-
-		/* Align to multiple of size of minimum base.  */
-		alignto = max(0x1000UL, align);
-		start = ALIGN(start, alignto);
-	}
-
-	res->start = start;
-}
-
-void __devinit pcibios_claim_one_bus(struct pci_bus *b)
-{
-	struct pci_dev *dev;
-	struct pci_bus *child_bus;
-
-	list_for_each_entry(dev, &b->devices, bus_list) {
-		int i;
-
-		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-			struct resource *r = &dev->resource[i];
-
-			if (r->parent || !r->start || !r->flags)
-				continue;
-			pci_claim_resource(dev, i);
-		}
-	}
-
-	list_for_each_entry(child_bus, &b->children, node)
-		pcibios_claim_one_bus(child_bus);
-}
-#ifdef CONFIG_HOTPLUG
-EXPORT_SYMBOL_GPL(pcibios_claim_one_bus);
-#endif
-
-static void __init pcibios_claim_of_setup(void)
-{
-	struct pci_bus *b;
-
-	list_for_each_entry(b, &pci_root_buses, node)
-		pcibios_claim_one_bus(b);
-}
-
 static u32 get_int_prop(struct device_node *np, const char *name, u32 def)
 {
 	const u32 *prop;
@@ -424,6 +345,7 @@ void __devinit scan_phb(struct pci_contr
 
 	DBG("Scanning PHB %s\n", node ? node->full_name : "<NO NAME>");
 
+	/* Create an empty bus for the toplevel */
 	bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, node);
 	if (bus == NULL) {
 		printk(KERN_ERR "Failed to create bus for PCI domain %04x\n",
@@ -433,26 +355,16 @@ void __devinit scan_phb(struct pci_contr
 	bus->secondary = hose->first_busno;
 	hose->bus = bus;
 
+	/* Get some IO space for the new PHB */
 	pcibios_map_io_space(bus);
 
+	/* Wire up PHB bus resources */
 	bus->resource[0] = res = &hose->io_resource;
-	if (res->flags && request_resource(&ioport_resource, res)) {
-		printk(KERN_ERR "Failed to request PCI IO region "
-		       "on PCI domain %04x\n", hose->global_number);
-		DBG("res->start = 0x%016lx, res->end = 0x%016lx\n",
-		    res->start, res->end);
-	}
-
-	for (i = 0; i < 3; ++i) {
-		res = &hose->mem_resources[i];
-		bus->resource[i+1] = res;
-		if (res->flags && request_resource(&iomem_resource, res))
-			printk(KERN_ERR "Failed to request PCI memory region "
-			       "on PCI domain %04x\n", hose->global_number);
-	}
+	for (i = 0; i < 3; ++i)
+		bus->resource[i+1] = &hose->mem_resources[i];
 
+	/* Get probe mode and perform scan */
 	mode = PCI_PROBE_NORMAL;
-
 	if (node && ppc_md.pci_probe_mode)
 		mode = ppc_md.pci_probe_mode(bus);
 	DBG("    probe mode: %d\n", mode);
@@ -469,12 +381,15 @@ static int __init pcibios_init(void)
 {
 	struct pci_controller *hose, *tmp;
 
+	printk(KERN_INFO "PCI: Probing PCI hardware\n");
+
 	/* For now, override phys_mem_access_prot. If we need it,
 	 * later, we may move that initialization to each ppc_md
 	 */
 	ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
 
-	printk(KERN_DEBUG "PCI: Probing PCI hardware\n");
+	if (pci_probe_only)
+		ppc_pci_flags |= PPC_PCI_PROBE_ONLY;
 
 	/* Scan all of the recorded PCI controllers.  */
 	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
@@ -482,17 +397,8 @@ static int __init pcibios_init(void)
 		pci_bus_add_devices(hose->bus);
 	}
 
-	if (pci_probe_only)
-		pcibios_claim_of_setup();
-	else
-		/* FIXME: `else' will be removed when
-		   pci_assign_unassigned_resources() is able to work
-		   correctly with [partially] allocated PCI tree. */
-		pci_assign_unassigned_resources();
-
-	/* Call machine dependent final fixup */
-	if (ppc_md.pcibios_fixup)
-		ppc_md.pcibios_fixup();
+	/* Call common code to handle resource allocation */
+	pcibios_resource_survey();
 
 	printk(KERN_DEBUG "PCI: Probing PCI hardware done\n");
 
Index: linux-merge/arch/powerpc/platforms/powermac/pci.c
===================================================================
--- linux-merge.orig/arch/powerpc/platforms/powermac/pci.c	2007-12-14 15:49:29.000000000 +1100
+++ linux-merge/arch/powerpc/platforms/powermac/pci.c	2007-12-14 15:49:32.000000000 +1100
@@ -994,9 +994,8 @@ void __init pmac_pci_init(void)
 	struct device_node *np, *root;
 	struct device_node *ht = NULL;
 
-#ifdef CONFIG_PPC32
 	ppc_pci_flags = PPC_PCI_CAN_SKIP_ISA_ALIGN;
-#endif
+
 	root = of_find_node_by_path("/");
 	if (root == NULL) {
 		printk(KERN_CRIT "pmac_pci_init: can't find root "
Index: linux-merge/include/asm-powerpc/pci.h
===================================================================
--- linux-merge.orig/include/asm-powerpc/pci.h	2007-12-14 15:49:31.000000000 +1100
+++ linux-merge/include/asm-powerpc/pci.h	2007-12-14 15:49:32.000000000 +1100
@@ -36,14 +36,10 @@ struct pci_dev;
 
 /*
  * Set this to 1 if you want the kernel to re-assign all PCI
- * bus numbers
+ * bus numbers (don't do that on ppc64 yet !)
  */
-#ifdef CONFIG_PPC64
-#define pcibios_assign_all_busses()	0
-#else
 #define pcibios_assign_all_busses()    	(ppc_pci_flags & \
 					 PPC_PCI_REASSIGN_ALL_BUS)
-#endif
 #define pcibios_scan_all_fns(a, b)	0
 
 static inline void pcibios_set_master(struct pci_dev *dev)
@@ -200,6 +196,8 @@ extern void pcibios_setup_new_device(str
 
 extern void pcibios_claim_one_bus(struct pci_bus *b);
 
+extern void pcibios_resource_survey(void);
+
 extern struct pci_controller *init_phb_dynamic(struct device_node *dn);
 
 extern struct pci_dev *of_create_pci_dev(struct device_node *node,

^ permalink raw reply

* [PATCH 8/15] [POWERPC] Merge PCI resource fixups
From: Benjamin Herrenschmidt @ 2007-12-14  4:56 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1197608163.200976.87755569596.qpush@grosgo>

The PCI code in 32 and 64 bits fixes up resources differently.

32 bits uses a header quirk plus handles bridges in pcibios_fixup_bus()
while 64 bits does things in various places depending on whether you
are using OF probing, using PCI hotplug, etc...

This merges those by basically using the 32 bits approach for both,
with various tweaks to make 64 bits work with the new approach.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

 arch/powerpc/kernel/pci-common.c           |  130 +++++++++++++++++++++++++++++
 arch/powerpc/kernel/pci_32.c               |   83 ------------------
 arch/powerpc/kernel/pci_64.c               |  104 +++--------------------
 arch/powerpc/platforms/pseries/pci_dlpar.c |   14 +--
 drivers/pci/hotplug/rpadlpar_core.c        |    2 
 include/asm-powerpc/machdep.h              |   14 +--
 include/asm-powerpc/pci-bridge.h           |    2 
 include/asm-powerpc/pci.h                  |    6 -
 8 files changed, 167 insertions(+), 188 deletions(-)

--- linux-merge.orig/arch/powerpc/kernel/pci-common.c	2007-12-14 15:49:31.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci-common.c	2007-12-14 15:49:31.000000000 +1100
@@ -691,3 +691,133 @@ void pcibios_bus_to_resource(struct pci_
 	res->end = (region->end + offset) & mask;
 }
 EXPORT_SYMBOL(pcibios_bus_to_resource);
+
+/* Fixup a bus resource into a linux resource */
+static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
+{
+	struct pci_controller *hose = pci_bus_to_host(dev->bus);
+	resource_size_t offset = 0, mask = (resource_size_t)-1;
+
+	if (res->flags & IORESOURCE_IO) {
+		offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+		mask = 0xffffffffu;
+	} else if (res->flags & IORESOURCE_MEM)
+		offset = hose->pci_mem_offset;
+
+	res->start = (res->start + offset) & mask;
+	res->end = (res->end + offset) & mask;
+
+	pr_debug("PCI:%s            %016llx-%016llx\n",
+		 pci_name(dev),
+		 (unsigned long long)res->start,
+		 (unsigned long long)res->end);
+}
+
+
+/* This header fixup will do the resource fixup for all devices as they are
+ * probed, but not for bridge ranges
+ */
+static void __devinit pcibios_fixup_resources(struct pci_dev *dev)
+{
+	struct pci_controller *hose = pci_bus_to_host(dev->bus);
+	int i;
+
+	if (!hose) {
+		printk(KERN_ERR "No host bridge for PCI dev %s !\n",
+		       pci_name(dev));
+		return;
+	}
+	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+		struct resource *res = dev->resource + i;
+		if (!res->flags)
+			continue;
+		if (res->end == 0xffffffff) {
+			pr_debug("PCI:%s Resource %d %016llx-%016llx [%x] is unassigned\n",
+				 pci_name(dev), i,
+				 (unsigned long long)res->start,
+				 (unsigned long long)res->end,
+				 (unsigned int)res->flags);
+			res->end -= res->start;
+			res->start = 0;
+			res->flags |= IORESOURCE_UNSET;
+			continue;
+		}
+
+		pr_debug("PCI:%s Resource %d %016llx-%016llx [%x] fixup...\n",
+			 pci_name(dev), i,
+			 (unsigned long long)res->start,\
+			 (unsigned long long)res->end,
+			 (unsigned int)res->flags);
+
+		fixup_resource(res, dev);
+	}
+
+	/* Call machine specific resource fixup */
+	if (ppc_md.pcibios_fixup_resources)
+		ppc_md.pcibios_fixup_resources(dev);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources);
+
+static void __devinit __pcibios_fixup_bus(struct pci_bus *bus)
+{
+	struct pci_dev *dev = bus->self;
+
+	pr_debug("PCI: Fixup bus %d (%s)\n", bus->number, dev ? pci_name(dev) : "PHB");
+
+	/* Fixup PCI<->PCI bridges. Host bridges are handled separately, for
+	 * now differently between 32 and 64 bits.
+	 */
+	if (dev != NULL) {
+		struct resource *res;
+		int i;
+
+		for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) {
+			if ((res = bus->resource[i]) == NULL)
+				continue;
+			if (!res->flags || bus->self->transparent)
+				continue;
+
+			pr_debug("PCI:%s Bus rsrc %d %016llx-%016llx [%x] fixup...\n",
+				 pci_name(dev), i,
+				 (unsigned long long)res->start,\
+				 (unsigned long long)res->end,
+				 (unsigned int)res->flags);
+
+			fixup_resource(res, dev);
+		}
+	}
+
+	/* Additional setup that is different between 32 and 64 bits for now */
+	pcibios_do_bus_setup(bus);
+
+	/* Platform specific bus fixups */
+	if (ppc_md.pcibios_fixup_bus)
+		ppc_md.pcibios_fixup_bus(bus);
+
+	/* Read default IRQs and fixup if necessary */
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		pci_read_irq_line(dev);
+		if (ppc_md.pci_irq_fixup)
+			ppc_md.pci_irq_fixup(dev);
+	}
+}
+
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+{
+	/* When called from the generic PCI probe, read PCI<->PCI bridge
+	 * bases before proceeding
+	 */
+	if (bus->self != NULL)
+		pci_read_bridge_bases(bus);
+	__pcibios_fixup_bus(bus);
+}
+EXPORT_SYMBOL(pcibios_fixup_bus);
+
+/* When building a bus from the OF tree rather than probing, we need a
+ * slightly different version of the fixup which doesn't read the
+ * bridge bases using config space accesses
+ */
+void __devinit pcibios_fixup_of_probed_bus(struct pci_bus *bus)
+{
+	__pcibios_fixup_bus(bus);
+}
Index: linux-merge/arch/powerpc/kernel/pci_32.c
===================================================================
--- linux-merge.orig/arch/powerpc/kernel/pci_32.c	2007-12-14 15:49:31.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci_32.c	2007-12-14 15:49:31.000000000 +1100
@@ -40,7 +40,6 @@ unsigned int ppc_pci_flags;
 
 void pcibios_make_OF_bus_map(void);
 
-static void pcibios_fixup_resources(struct pci_dev* dev);
 static void fixup_broken_pcnet32(struct pci_dev* dev);
 static int reparent_resources(struct resource *parent, struct resource *res);
 static void fixup_cpc710_pci64(struct pci_dev* dev);
@@ -98,53 +97,6 @@ fixup_cpc710_pci64(struct pci_dev* dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM,	PCI_DEVICE_ID_IBM_CPC710_PCI64,	fixup_cpc710_pci64);
 
-static void
-pcibios_fixup_resources(struct pci_dev *dev)
-{
-	struct pci_controller* hose = (struct pci_controller *)dev->sysdata;
-	int i;
-	resource_size_t offset, mask;
-
-	if (!hose) {
-		printk(KERN_ERR "No hose for PCI dev %s!\n", pci_name(dev));
-		return;
-	}
-	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
-		struct resource *res = dev->resource + i;
-		if (!res->flags)
-			continue;
-		if (res->end == 0xffffffff) {
-			DBG("PCI:%s Resource %d [%016llx-%016llx] is unassigned\n",
-			    pci_name(dev), i, (u64)res->start, (u64)res->end);
-			res->end -= res->start;
-			res->start = 0;
-			res->flags |= IORESOURCE_UNSET;
-			continue;
-		}
-		offset = 0;
-		mask = (resource_size_t)-1;
-		if (res->flags & IORESOURCE_MEM) {
-			offset = hose->pci_mem_offset;
-		} else if (res->flags & IORESOURCE_IO) {
-			offset = (unsigned long) hose->io_base_virt
-				- isa_io_base;
-			mask = 0xffffffffu;
-		}
-		if (offset != 0) {
-			res->start = (res->start + offset) & mask;
-			res->end = (res->end + offset) & mask;
-			DBG("PCI: Fixup res %d (0x%lx) of dev %s: %llx -> %llx\n",
-			    i, res->flags, pci_name(dev),
-			    (u64)res->start - offset, (u64)res->start);
-		}
-	}
-
-	/* Call machine specific resource fixup */
-	if (ppc_md.pcibios_fixup_resources)
-		ppc_md.pcibios_fixup_resources(dev);
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID,		PCI_ANY_ID,			pcibios_fixup_resources);
-
 static int skip_isa_ioresource_align(struct pci_dev *dev)
 {
 	if ((ppc_pci_flags & PPC_PCI_CAN_SKIP_ISA_ALIGN) &&
@@ -757,14 +709,14 @@ pcibios_init(void)
 
 subsys_initcall(pcibios_init);
 
-void pcibios_fixup_bus(struct pci_bus *bus)
+void __devinit pcibios_do_bus_setup(struct pci_bus *bus)
 {
 	struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
 	unsigned long io_offset;
 	struct resource *res;
-	struct pci_dev *dev;
 	int i;
 
+	/* Hookup PHB resources */
 	io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
 	if (bus->parent == NULL) {
 		/* This is a host bridge - fill in its resources */
@@ -795,37 +747,6 @@ void pcibios_fixup_bus(struct pci_bus *b
 			}
 			bus->resource[i+1] = res;
 		}
-	} else {
-		/* This is a subordinate bridge */
-		pci_read_bridge_bases(bus);
-
-		for (i = 0; i < 4; ++i) {
-			if ((res = bus->resource[i]) == NULL)
-				continue;
-			if (!res->flags || bus->self->transparent)
-				continue;
-			if (io_offset && (res->flags & IORESOURCE_IO)) {
-				res->start = (res->start + io_offset) &
-					0xffffffffu;
-				res->end = (res->end + io_offset) &
-					0xffffffffu;
-			} else if (hose->pci_mem_offset
-				   && (res->flags & IORESOURCE_MEM)) {
-				res->start += hose->pci_mem_offset;
-				res->end += hose->pci_mem_offset;
-			}
-		}
-	}
-
-	/* Platform specific bus fixups */
-	if (ppc_md.pcibios_fixup_bus)
-		ppc_md.pcibios_fixup_bus(bus);
-
-	/* Read default IRQs and fixup if necessary */
-	list_for_each_entry(dev, &bus->devices, bus_list) {
-		pci_read_irq_line(dev);
-		if (ppc_md.pci_irq_fixup)
-			ppc_md.pci_irq_fixup(dev);
 	}
 }
 
Index: linux-merge/arch/powerpc/kernel/pci_64.c
===================================================================
--- linux-merge.orig/arch/powerpc/kernel/pci_64.c	2007-12-14 15:49:31.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci_64.c	2007-12-14 15:49:31.000000000 +1100
@@ -41,9 +41,6 @@
 
 unsigned long pci_probe_only = 1;
 
-static void fixup_resource(struct resource *res, struct pci_dev *dev);
-static void do_bus_setup(struct pci_bus *bus);
-
 /* pci_io_base -- the base address from which io bars are offsets.
  * This is the lowest I/O base address (so bar values are always positive),
  * and it *must* be the start of ISA space if an ISA bus exists because
@@ -223,7 +220,6 @@ static void pci_parse_of_addrs(struct de
 		res->end = base + size - 1;
 		res->flags = flags;
 		res->name = pci_name(dev);
-		fixup_resource(res, dev);
 	}
 }
 
@@ -292,7 +288,7 @@ struct pci_dev *of_create_pci_dev(struct
 EXPORT_SYMBOL(of_create_pci_dev);
 
 void __devinit of_scan_bus(struct device_node *node,
-				  struct pci_bus *bus)
+			   struct pci_bus *bus)
 {
 	struct device_node *child = NULL;
 	const u32 *reg;
@@ -301,6 +297,7 @@ void __devinit of_scan_bus(struct device
 
 	DBG("of_scan_bus(%s) bus no %d... \n", node->full_name, bus->number);
 
+	/* Scan direct children */
 	while ((child = of_get_next_child(node, child)) != NULL) {
 		DBG("  * %s\n", child->full_name);
 		reg = of_get_property(child, "reg", &reglen);
@@ -312,19 +309,26 @@ void __devinit of_scan_bus(struct device
 		dev = of_create_pci_dev(child, bus, devfn);
 		if (!dev)
 			continue;
-		DBG("dev header type: %x\n", dev->hdr_type);
+		DBG("    dev header type: %x\n", dev->hdr_type);
+	}
+
+	/* Ally all fixups */
+	pcibios_fixup_of_probed_bus(bus);
 
+	/* Now scan child busses */
+	list_for_each_entry(dev, &bus->devices, bus_list) {
 		if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
-		    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
-			of_scan_pci_bridge(child, dev);
+		    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
+			struct device_node *child = pci_device_to_OF_node(dev);
+			if (dev)
+				of_scan_pci_bridge(child, dev);
+		}
 	}
-
-	do_bus_setup(bus);
 }
 EXPORT_SYMBOL(of_scan_bus);
 
 void __devinit of_scan_pci_bridge(struct device_node *node,
-			 	struct pci_dev *dev)
+				  struct pci_dev *dev)
 {
 	struct pci_bus *bus;
 	const u32 *busrange, *ranges;
@@ -394,7 +398,6 @@ void __devinit of_scan_pci_bridge(struct
 		res->start = of_read_number(&ranges[1], 2);
 		res->end = res->start + size - 1;
 		res->flags = flags;
-		fixup_resource(res, dev);
 	}
 	sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
 		bus->number);
@@ -643,51 +646,13 @@ int __devinit pcibios_map_io_space(struc
 }
 EXPORT_SYMBOL_GPL(pcibios_map_io_space);
 
-static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
-{
-	struct pci_controller *hose = pci_bus_to_host(dev->bus);
-	unsigned long offset;
-
-	if (res->flags & IORESOURCE_IO) {
-		offset = (unsigned long)hose->io_base_virt - _IO_BASE;
-		res->start += offset;
-		res->end += offset;
-	} else if (res->flags & IORESOURCE_MEM) {
-		res->start += hose->pci_mem_offset;
-		res->end += hose->pci_mem_offset;
-	}
-}
-
-void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
-					      struct pci_bus *bus)
-{
-	/* Update device resources.  */
-	int i;
-
-	DBG("%s: Fixup resources:\n", pci_name(dev));
-	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-		struct resource *res = &dev->resource[i];
-		if (!res->flags)
-			continue;
-
-		DBG("  0x%02x < %08lx:0x%016lx...0x%016lx\n",
-		    i, res->flags, res->start, res->end);
-
-		fixup_resource(res, dev);
-
-		DBG("       > %08lx:0x%016lx...0x%016lx\n",
-		    res->flags, res->start, res->end);
-	}
-}
-EXPORT_SYMBOL(pcibios_fixup_device_resources);
-
 void __devinit pcibios_setup_new_device(struct pci_dev *dev)
 {
 	struct dev_archdata *sd = &dev->dev.archdata;
 
 	sd->of_node = pci_device_to_OF_node(dev);
 
-	DBG("PCI device %s OF node: %s\n", pci_name(dev),
+	DBG("PCI: device %s OF node: %s\n", pci_name(dev),
 	    sd->of_node ? sd->of_node->full_name : "<none>");
 
 	sd->dma_ops = pci_dma_ops;
@@ -701,7 +666,7 @@ void __devinit pcibios_setup_new_device(
 }
 EXPORT_SYMBOL(pcibios_setup_new_device);
 
-static void __devinit do_bus_setup(struct pci_bus *bus)
+void __devinit pcibios_do_bus_setup(struct pci_bus *bus)
 {
 	struct pci_dev *dev;
 
@@ -710,42 +675,7 @@ static void __devinit do_bus_setup(struc
 
 	list_for_each_entry(dev, &bus->devices, bus_list)
 		pcibios_setup_new_device(dev);
-
-	/* Read default IRQs and fixup if necessary */
-	list_for_each_entry(dev, &bus->devices, bus_list) {
-		pci_read_irq_line(dev);
-		if (ppc_md.pci_irq_fixup)
-			ppc_md.pci_irq_fixup(dev);
-	}
-}
-
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
-{
-	struct pci_dev *dev = bus->self;
-	struct device_node *np;
-
-	np = pci_bus_to_OF_node(bus);
-
-	DBG("pcibios_fixup_bus(%s)\n", np ? np->full_name : "<???>");
-
-	if (dev && pci_probe_only &&
-	    (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
-		/* This is a subordinate bridge */
-
-		pci_read_bridge_bases(bus);
-		pcibios_fixup_device_resources(dev, bus);
-	}
-
-	do_bus_setup(bus);
-
-	if (!pci_probe_only)
-		return;
-
-	list_for_each_entry(dev, &bus->devices, bus_list)
-		if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
-			pcibios_fixup_device_resources(dev, bus);
 }
-EXPORT_SYMBOL(pcibios_fixup_bus);
 
 unsigned long pci_address_to_pio(phys_addr_t address)
 {
Index: linux-merge/arch/powerpc/platforms/pseries/pci_dlpar.c
===================================================================
--- linux-merge.orig/arch/powerpc/platforms/pseries/pci_dlpar.c	2007-12-14 15:48:59.000000000 +1100
+++ linux-merge/arch/powerpc/platforms/pseries/pci_dlpar.c	2007-12-14 15:49:31.000000000 +1100
@@ -83,7 +83,7 @@ EXPORT_SYMBOL_GPL(pcibios_remove_pci_dev
 
 /* Must be called before pci_bus_add_devices */
 void
-pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
+pcibios_fixup_new_pci_devices(struct pci_bus *bus)
 {
 	struct pci_dev *dev;
 
@@ -98,8 +98,6 @@ pcibios_fixup_new_pci_devices(struct pci
 			/* Fill device archdata and setup iommu table */
 			pcibios_setup_new_device(dev);
 
-			if(fix_bus)
-				pcibios_fixup_device_resources(dev, bus);
 			pci_read_irq_line(dev);
 			for (i = 0; i < PCI_NUM_RESOURCES; i++) {
 				struct resource *r = &dev->resource[i];
@@ -132,8 +130,8 @@ pcibios_pci_config_bridge(struct pci_dev
 
 	pci_scan_child_bus(child_bus);
 
-	/* Fixup new pci devices without touching bus struct */
-	pcibios_fixup_new_pci_devices(child_bus, 0);
+	/* Fixup new pci devices */
+	pcibios_fixup_new_pci_devices(child_bus);
 
 	/* Make the discovered devices available */
 	pci_bus_add_devices(child_bus);
@@ -169,7 +167,7 @@ pcibios_add_pci_devices(struct pci_bus *
 		/* use ofdt-based probe */
 		of_scan_bus(dn, bus);
 		if (!list_empty(&bus->devices)) {
-			pcibios_fixup_new_pci_devices(bus, 0);
+			pcibios_fixup_new_pci_devices(bus);
 			pci_bus_add_devices(bus);
 			eeh_add_device_tree_late(bus);
 		}
@@ -178,7 +176,7 @@ pcibios_add_pci_devices(struct pci_bus *
 		slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
 		num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
 		if (num) {
-			pcibios_fixup_new_pci_devices(bus, 1);
+			pcibios_fixup_new_pci_devices(bus);
 			pci_bus_add_devices(bus);
 			eeh_add_device_tree_late(bus);
 		}
@@ -208,7 +206,7 @@ struct pci_controller * __devinit init_p
 		eeh_add_device_tree_early(dn);
 
 	scan_phb(phb);
-	pcibios_fixup_new_pci_devices(phb->bus, 0);
+	pcibios_fixup_new_pci_devices(phb->bus);
 	pci_bus_add_devices(phb->bus);
 	eeh_add_device_tree_late(phb->bus);
 
Index: linux-merge/drivers/pci/hotplug/rpadlpar_core.c
===================================================================
--- linux-merge.orig/drivers/pci/hotplug/rpadlpar_core.c	2007-12-14 15:48:59.000000000 +1100
+++ linux-merge/drivers/pci/hotplug/rpadlpar_core.c	2007-12-14 15:49:31.000000000 +1100
@@ -155,7 +155,7 @@ static void dlpar_pci_add_bus(struct dev
 	    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
 		of_scan_pci_bridge(dn, dev);
 
-	pcibios_fixup_new_pci_devices(dev->subordinate,0);
+	pcibios_fixup_new_pci_devices(dev->subordinate);
 
 	/* Claim new bus resources */
 	pcibios_claim_one_bus(dev->bus);
Index: linux-merge/include/asm-powerpc/machdep.h
===================================================================
--- linux-merge.orig/include/asm-powerpc/machdep.h	2007-12-14 15:48:59.000000000 +1100
+++ linux-merge/include/asm-powerpc/machdep.h	2007-12-14 15:49:31.000000000 +1100
@@ -205,13 +205,6 @@ struct machdep_calls {
 	 * optional PCI "hooks"
 	 */
 
-	/* Called after PPC generic resource fixup to perform
-	   machine specific fixups */
-	void (*pcibios_fixup_resources)(struct pci_dev *);
-
-	/* Called for each PCI bus in the system when it's probed */
-	void (*pcibios_fixup_bus)(struct pci_bus *);
-
 	/* Called when pci_enable_device() is called (initial=0) or
 	 * when a device with no assigned resource is found (initial=1).
 	 * Returns 0 to allow assignment/enabling of the device. */
@@ -225,6 +218,13 @@ struct machdep_calls {
 
 #endif /* CONFIG_PPC32 */
 
+	/* Called after PPC generic resource fixup to perform
+	   machine specific fixups */
+	void (*pcibios_fixup_resources)(struct pci_dev *);
+
+	/* Called for each PCI bus in the system when it's probed */
+	void (*pcibios_fixup_bus)(struct pci_bus *);
+
 	/* Called to shutdown machine specific hardware not already controlled
 	 * by other drivers.
 	 */
Index: linux-merge/include/asm-powerpc/pci-bridge.h
===================================================================
--- linux-merge.orig/include/asm-powerpc/pci-bridge.h	2007-12-14 15:49:30.000000000 +1100
+++ linux-merge/include/asm-powerpc/pci-bridge.h	2007-12-14 15:49:31.000000000 +1100
@@ -235,7 +235,7 @@ extern void pcibios_remove_pci_devices(s
 
 /** Discover new pci devices under this bus, and add them */
 extern void pcibios_add_pci_devices(struct pci_bus *bus);
-extern void pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus);
+extern void pcibios_fixup_new_pci_devices(struct pci_bus *bus);
 
 extern int pcibios_remove_root_bus(struct pci_controller *phb);
 
Index: linux-merge/include/asm-powerpc/pci.h
===================================================================
--- linux-merge.orig/include/asm-powerpc/pci.h	2007-12-14 15:49:30.000000000 +1100
+++ linux-merge/include/asm-powerpc/pci.h	2007-12-14 15:49:31.000000000 +1100
@@ -196,9 +196,6 @@ static inline struct resource *pcibios_s
 	return root;
 }
 
-extern void pcibios_fixup_device_resources(struct pci_dev *dev,
-			struct pci_bus *bus);
-
 extern void pcibios_setup_new_device(struct pci_dev *dev);
 
 extern void pcibios_claim_one_bus(struct pci_bus *b);
@@ -226,5 +223,8 @@ extern void pci_resource_to_user(const s
 				 const struct resource *rsrc,
 				 resource_size_t *start, resource_size_t *end);
 
+extern void pcibios_do_bus_setup(struct pci_bus *bus);
+extern void pcibios_fixup_of_probed_bus(struct pci_bus *bus);
+
 #endif	/* __KERNEL__ */
 #endif /* __ASM_POWERPC_PCI_H */

^ permalink raw reply

* [PATCH 7/15] [POWERPC] Merge pcibios_resource_to_bus/bus_to_resource
From: Benjamin Herrenschmidt @ 2007-12-14  4:56 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1197608163.200976.87755569596.qpush@grosgo>

This merges the PowerPC 32 and 64 bits version of pcibios_resource_to_bus
and pcibios_bus_to_resource().

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

 arch/powerpc/kernel/pci-common.c |   36 +++++++++++++++++++++++++++++++++
 arch/powerpc/kernel/pci_32.c     |   32 -----------------------------
 arch/powerpc/kernel/pci_64.c     |   42 ---------------------------------------
 3 files changed, 36 insertions(+), 74 deletions(-)

--- linux-merge.orig/arch/powerpc/kernel/pci-common.c	2007-12-14 15:49:30.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci-common.c	2007-12-14 15:49:31.000000000 +1100
@@ -655,3 +655,39 @@ int pci_proc_domain(struct pci_bus *bus)
 #endif
 }
 
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+			     struct resource *res)
+{
+	resource_size_t offset = 0, mask = (resource_size_t)-1;
+	struct pci_controller *hose = pci_bus_to_host(dev->bus);
+
+	if (!hose)
+		return;
+	if (res->flags & IORESOURCE_IO) {
+		offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+		mask = 0xffffffffu;
+	} else if (res->flags & IORESOURCE_MEM)
+		offset = hose->pci_mem_offset;
+
+	region->start = (res->start - offset) & mask;
+	region->end = (res->end - offset) & mask;
+}
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+
+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+			     struct pci_bus_region *region)
+{
+	resource_size_t offset = 0, mask = (resource_size_t)-1;
+	struct pci_controller *hose = pci_bus_to_host(dev->bus);
+
+	if (!hose)
+		return;
+	if (res->flags & IORESOURCE_IO) {
+		offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+		mask = 0xffffffffu;
+	} else if (res->flags & IORESOURCE_MEM)
+		offset = hose->pci_mem_offset;
+	res->start = (region->start + offset) & mask;
+	res->end = (region->end + offset) & mask;
+}
+EXPORT_SYMBOL(pcibios_bus_to_resource);
Index: linux-merge/arch/powerpc/kernel/pci_32.c
===================================================================
--- linux-merge.orig/arch/powerpc/kernel/pci_32.c	2007-12-14 15:49:29.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci_32.c	2007-12-14 15:49:31.000000000 +1100
@@ -145,38 +145,6 @@ pcibios_fixup_resources(struct pci_dev *
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID,		PCI_ANY_ID,			pcibios_fixup_resources);
 
-void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
-			struct resource *res)
-{
-	resource_size_t offset = 0, mask = (resource_size_t)-1;
-	struct pci_controller *hose = dev->sysdata;
-
-	if (hose && res->flags & IORESOURCE_IO) {
-		offset = (unsigned long)hose->io_base_virt - isa_io_base;
-		mask = 0xffffffffu;
-	} else if (hose && res->flags & IORESOURCE_MEM)
-		offset = hose->pci_mem_offset;
-	region->start = (res->start - offset) & mask;
-	region->end = (res->end - offset) & mask;
-}
-EXPORT_SYMBOL(pcibios_resource_to_bus);
-
-void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
-			     struct pci_bus_region *region)
-{
-	resource_size_t offset = 0, mask = (resource_size_t)-1;
-	struct pci_controller *hose = dev->sysdata;
-
-	if (hose && res->flags & IORESOURCE_IO) {
-		offset = (unsigned long)hose->io_base_virt - isa_io_base;
-		mask = 0xffffffffu;
-	} else if (hose && res->flags & IORESOURCE_MEM)
-		offset = hose->pci_mem_offset;
-	res->start = (region->start + offset) & mask;
-	res->end = (region->end + offset) & mask;
-}
-EXPORT_SYMBOL(pcibios_bus_to_resource);
-
 static int skip_isa_ioresource_align(struct pci_dev *dev)
 {
 	if ((ppc_pci_flags & PPC_PCI_CAN_SKIP_ISA_ALIGN) &&
Index: linux-merge/arch/powerpc/kernel/pci_64.c
===================================================================
--- linux-merge.orig/arch/powerpc/kernel/pci_64.c	2007-12-14 15:49:30.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci_64.c	2007-12-14 15:49:31.000000000 +1100
@@ -77,48 +77,6 @@ static void fixup_broken_pcnet32(struct 
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32);
 
-void  pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
-			      struct resource *res)
-{
-	unsigned long offset = 0;
-	struct pci_controller *hose = pci_bus_to_host(dev->bus);
-
-	if (!hose)
-		return;
-
-	if (res->flags & IORESOURCE_IO)
-	        offset = (unsigned long)hose->io_base_virt - _IO_BASE;
-
-	if (res->flags & IORESOURCE_MEM)
-		offset = hose->pci_mem_offset;
-
-	region->start = res->start - offset;
-	region->end = res->end - offset;
-}
-
-void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
-			      struct pci_bus_region *region)
-{
-	unsigned long offset = 0;
-	struct pci_controller *hose = pci_bus_to_host(dev->bus);
-
-	if (!hose)
-		return;
-
-	if (res->flags & IORESOURCE_IO)
-	        offset = (unsigned long)hose->io_base_virt - _IO_BASE;
-
-	if (res->flags & IORESOURCE_MEM)
-		offset = hose->pci_mem_offset;
-
-	res->start = region->start + offset;
-	res->end = region->end + offset;
-}
-
-#ifdef CONFIG_HOTPLUG
-EXPORT_SYMBOL(pcibios_resource_to_bus);
-EXPORT_SYMBOL(pcibios_bus_to_resource);
-#endif
 
 /*
  * We need to avoid collisions with `mirrored' VGA ports

^ permalink raw reply

* [PATCH 6/15] [POWERPC] pci32: Add platform option to enable /proc PCI domains
From: Benjamin Herrenschmidt @ 2007-12-14  4:56 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1197608163.200976.87755569596.qpush@grosgo>

This adds flags the platforms can use to enable domain numbers
in /proc/bus/pci.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

 arch/powerpc/kernel/pci-common.c |   16 ++++++++++++++++
 arch/powerpc/kernel/pci_64.c     |    8 --------
 include/asm-powerpc/pci-bridge.h |    5 +++++
 include/asm-powerpc/pci.h        |   14 ++++----------
 4 files changed, 25 insertions(+), 18 deletions(-)

--- linux-merge.orig/arch/powerpc/kernel/pci-common.c	2007-12-14 15:49:00.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci-common.c	2007-12-14 15:49:30.000000000 +1100
@@ -639,3 +639,19 @@ void __devinit pci_process_bridge_OF_ran
 		hose->mem_resources[memno-1] = tmp;
 	}
 }
+
+/* Decide whether to display the domain number in /proc */
+int pci_proc_domain(struct pci_bus *bus)
+{
+	struct pci_controller *hose = pci_bus_to_host(bus);
+#ifdef CONFIG_PPC64
+	return hose->buid != 0;
+#else
+	if (!(ppc_pci_flags & PPC_PCI_ENABLE_PROC_DOMAINS))
+		return 0;
+	if (ppc_pci_flags & PPC_PCI_COMPAT_DOMAIN_0)
+		return hose->global_number != 0;
+	return 1;
+#endif
+}
+
Index: linux-merge/arch/powerpc/kernel/pci_64.c
===================================================================
--- linux-merge.orig/arch/powerpc/kernel/pci_64.c	2007-12-14 15:49:29.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci_64.c	2007-12-14 15:49:30.000000000 +1100
@@ -570,14 +570,6 @@ int pcibios_enable_device(struct pci_dev
 	return 0;
 }
 
-/* Decide whether to display the domain number in /proc */
-int pci_proc_domain(struct pci_bus *bus)
-{
-	struct pci_controller *hose = pci_bus_to_host(bus);
-	return hose->buid != 0;
-}
-
-
 #ifdef CONFIG_HOTPLUG
 
 int pcibios_unmap_io_space(struct pci_bus *bus)
Index: linux-merge/include/asm-powerpc/pci-bridge.h
===================================================================
--- linux-merge.orig/include/asm-powerpc/pci-bridge.h	2007-12-14 15:49:29.000000000 +1100
+++ linux-merge/include/asm-powerpc/pci-bridge.h	2007-12-14 15:49:30.000000000 +1100
@@ -30,6 +30,11 @@ enum {
 	 * ISA forwarding enabled
 	 */
 	PPC_PCI_CAN_SKIP_ISA_ALIGN	= 0x00000008,
+
+	/* Enable domain numbers in /proc */
+	PPC_PCI_ENABLE_PROC_DOMAINS	= 0x00000010,
+	/* ... except for domain 0 */
+	PPC_PCI_COMPAT_DOMAIN_0		= 0x00000020,
 };
 
 
Index: linux-merge/include/asm-powerpc/pci.h
===================================================================
--- linux-merge.orig/include/asm-powerpc/pci.h	2007-12-14 15:49:29.000000000 +1100
+++ linux-merge/include/asm-powerpc/pci.h	2007-12-14 15:49:30.000000000 +1100
@@ -98,9 +98,6 @@ static inline void pci_dma_burst_advice(
 #define get_pci_dma_ops()	NULL
 #endif
 
-/* Decide whether to display the domain number in /proc */
-extern int pci_proc_domain(struct pci_bus *bus);
-
 #else /* 32-bit */
 
 #ifdef CONFIG_PCI
@@ -112,17 +109,14 @@ static inline void pci_dma_burst_advice(
 	*strategy_parameter = ~0UL;
 }
 #endif
-
-/* Set the name of the bus as it appears in /proc/bus/pci */
-static inline int pci_proc_domain(struct pci_bus *bus)
-{
-	return 0;
-}
-
 #endif /* CONFIG_PPC64 */
 
 extern int pci_domain_nr(struct pci_bus *bus);
 
+/* Decide whether to display the domain number in /proc */
+extern int pci_proc_domain(struct pci_bus *bus);
+
+
 struct vm_area_struct;
 /* Map a range of PCI memory or I/O space for a device into user space */
 int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,

^ permalink raw reply

* [PATCH 5/15] [POWERPC] pci32: Remove obsolete PowerMac bus number hack
From: Benjamin Herrenschmidt @ 2007-12-14  4:56 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1197608163.200976.87755569596.qpush@grosgo>

The 32 bits PCI code carries an old hack that was only useful for G5
machines. Nowdays, the 32 bits kernel doesn't support any of those
machines anymore so the hack is basically never used, remove it.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

 arch/powerpc/kernel/pci_32.c |   11 -----------
 1 file changed, 11 deletions(-)

--- linux-merge.orig/arch/powerpc/kernel/pci_32.c	2007-12-14 15:49:29.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci_32.c	2007-12-14 15:49:29.000000000 +1100
@@ -922,17 +922,6 @@ long sys_pciconfig_iobase(long which, un
 	struct pci_controller* hose;
 	long result = -EOPNOTSUPP;
 
-	/* Argh ! Please forgive me for that hack, but that's the
-	 * simplest way to get existing XFree to not lockup on some
-	 * G5 machines... So when something asks for bus 0 io base
-	 * (bus 0 is HT root), we return the AGP one instead.
-	 */
-#ifdef CONFIG_PPC_PMAC
-	if (machine_is(powermac) && machine_is_compatible("MacRISC4"))
-		if (bus == 0)
-			bus = 0xf0;
-#endif /* CONFIG_PPC_PMAC */
-
 	hose = pci_bus_to_hose(bus);
 	if (!hose)
 		return -ENODEV;

^ permalink raw reply

* [PATCH 4/15] [POWERPC] pci32: Add flags modifying the PCI code behaviour
From: Benjamin Herrenschmidt @ 2007-12-14  4:56 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1197608163.200976.87755569596.qpush@grosgo>

This adds to the 32 bits PCI code some flags, replacing the old
pci_assign_all_busses global, that allow to control various
aspects of the PCI probing, such as whether to re-assign all
resources or not, or to not try to assign anything at all.

This also adds the flag x86 already has to avoid ISA alignment
on bridges that don't have ISA forwarding enabled (no legacy
devices on the top level bus) and sets it for PowerMacs.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

 arch/powerpc/kernel/pci_32.c              |   42 ++++++++++++++++++++++++------
 arch/powerpc/kernel/pci_64.c              |    1 
 arch/powerpc/kernel/rtas_pci.c            |    6 ++--
 arch/powerpc/platforms/52xx/mpc52xx_pci.c |    2 -
 arch/powerpc/platforms/82xx/pq2.c         |    2 -
 arch/powerpc/platforms/83xx/pci.c         |    2 -
 arch/powerpc/platforms/chrp/pci.c         |    2 -
 arch/powerpc/platforms/powermac/pci.c     |    7 +++--
 arch/powerpc/sysdev/fsl_pci.c             |    2 -
 arch/powerpc/sysdev/grackle.c             |    2 -
 include/asm-powerpc/pci-bridge.h          |   20 ++++++++++++++
 include/asm-powerpc/pci.h                 |    9 ++++--
 12 files changed, 75 insertions(+), 22 deletions(-)

--- linux-merge.orig/arch/powerpc/kernel/pci_32.c	2007-12-14 15:49:28.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci_32.c	2007-12-14 15:49:29.000000000 +1100
@@ -35,6 +35,9 @@ unsigned long isa_io_base     = 0;
 unsigned long pci_dram_offset = 0;
 int pcibios_assign_bus_offset = 1;
 
+/* Default PCI flags is 0 */
+unsigned int ppc_pci_flags;
+
 void pcibios_make_OF_bus_map(void);
 
 static void pcibios_fixup_resources(struct pci_dev* dev);
@@ -48,7 +51,7 @@ static u8* pci_to_OF_bus_map;
 /* By default, we don't re-assign bus numbers. We do this only on
  * some pmacs
  */
-int pci_assign_all_buses;
+static int pci_assign_all_buses;
 
 LIST_HEAD(hose_list);
 
@@ -174,6 +177,14 @@ void pcibios_bus_to_resource(struct pci_
 }
 EXPORT_SYMBOL(pcibios_bus_to_resource);
 
+static int skip_isa_ioresource_align(struct pci_dev *dev)
+{
+	if ((ppc_pci_flags & PPC_PCI_CAN_SKIP_ISA_ALIGN) &&
+	    !(dev->bus->bridge_ctl & PCI_BRIDGE_CTL_ISA))
+		return 1;
+	return 0;
+}
+
 /*
  * We need to avoid collisions with `mirrored' VGA ports
  * and other strange ISA hardware, so we always want the
@@ -195,6 +206,8 @@ void pcibios_align_resource(void *data, 
 	if (res->flags & IORESOURCE_IO) {
 		resource_size_t start = res->start;
 
+		if (skip_isa_ioresource_align(dev))
+			return;
 		if (start & 0x300) {
 			start = (start + 0x3ff) & ~0x3ff;
 			res->start = start;
@@ -251,8 +264,13 @@ pcibios_allocate_bus_resources(struct li
 				continue;
 			if (bus->parent == NULL)
 				pr = (res->flags & IORESOURCE_IO)?
-					&ioport_resource: &iomem_resource;
+					&ioport_resource : &iomem_resource;
 			else {
+				/* Don't bother with non-root busses when
+				 * re-assigning all resources.
+				 */
+				if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC)
+					continue;
 				pr = pci_find_parent_resource(bus->self, res);
 				if (pr == res) {
 					/* this happens when the generic PCI
@@ -720,6 +738,9 @@ pcibios_init(void)
 
 	printk(KERN_INFO "PCI: Probing PCI hardware\n");
 
+	if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_BUS)
+		pci_assign_all_buses = 1;
+
 	/* Scan all of the recorded PCI controllers.  */
 	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
 		if (pci_assign_all_buses)
@@ -746,13 +767,18 @@ pcibios_init(void)
 	if (ppc_md.pcibios_fixup)
 		ppc_md.pcibios_fixup();
 
-	/* Allocate and assign resources */
+	/* Allocate and assign resources. If we re-assign everything, then
+	 * we skip the allocate phase
+	 */
 	pcibios_allocate_bus_resources(&pci_root_buses);
-	pcibios_allocate_resources(0);
-	pcibios_allocate_resources(1);
-
-	DBG("PCI: Assigning unassigned resouces...\n");
-	pci_assign_unassigned_resources();
+	if (!(ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC)) {
+		pcibios_allocate_resources(0);
+		pcibios_allocate_resources(1);
+	}
+	if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) {
+		DBG("PCI: Assigning unassigned resouces...\n");
+		pci_assign_unassigned_resources();
+	}
 
 	/* Call machine dependent post-init code */
 	if (ppc_md.pcibios_after_init)
Index: linux-merge/arch/powerpc/kernel/pci_64.c
===================================================================
--- linux-merge.orig/arch/powerpc/kernel/pci_64.c	2007-12-14 15:49:00.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci_64.c	2007-12-14 15:49:29.000000000 +1100
@@ -40,7 +40,6 @@
 #endif
 
 unsigned long pci_probe_only = 1;
-int pci_assign_all_buses = 0;
 
 static void fixup_resource(struct resource *res, struct pci_dev *dev);
 static void do_bus_setup(struct pci_bus *bus);
Index: linux-merge/arch/powerpc/kernel/rtas_pci.c
===================================================================
--- linux-merge.orig/arch/powerpc/kernel/rtas_pci.c	2007-12-14 15:49:00.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/rtas_pci.c	2007-12-14 15:49:29.000000000 +1100
@@ -311,10 +311,12 @@ void __init find_and_init_phbs(void)
 		if (prop)
 			pci_probe_only = *prop;
 
+#ifdef CONFIG_PPC32 /* Will be made generic soon */
 		prop = of_get_property(of_chosen,
 				"linux,pci-assign-all-buses", NULL);
-		if (prop)
-			pci_assign_all_buses = *prop;
+		if (prop && *prop)
+			ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
+#endif /* CONFIG_PPC32 */
 	}
 }
 
Index: linux-merge/arch/powerpc/platforms/52xx/mpc52xx_pci.c
===================================================================
--- linux-merge.orig/arch/powerpc/platforms/52xx/mpc52xx_pci.c	2007-12-14 15:49:00.000000000 +1100
+++ linux-merge/arch/powerpc/platforms/52xx/mpc52xx_pci.c	2007-12-14 15:49:29.000000000 +1100
@@ -363,7 +363,7 @@ mpc52xx_add_bridge(struct device_node *n
 
 	pr_debug("Adding MPC52xx PCI host bridge %s\n", node->full_name);
 
-	pci_assign_all_buses = 1;
+	ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
 
 	if (of_address_to_resource(node, 0, &rsrc) != 0) {
 		printk(KERN_ERR "Can't get %s resources\n", node->full_name);
Index: linux-merge/arch/powerpc/platforms/82xx/pq2.c
===================================================================
--- linux-merge.orig/arch/powerpc/platforms/82xx/pq2.c	2007-12-14 15:49:00.000000000 +1100
+++ linux-merge/arch/powerpc/platforms/82xx/pq2.c	2007-12-14 15:49:29.000000000 +1100
@@ -53,7 +53,7 @@ static void __init pq2_pci_add_bridge(st
 	if (of_address_to_resource(np, 0, &r) || r.end - r.start < 0x10b)
 		goto err;
 
-	pci_assign_all_buses = 1;
+	ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
 
 	hose = pcibios_alloc_controller(np);
 	if (!hose)
Index: linux-merge/arch/powerpc/platforms/83xx/pci.c
===================================================================
--- linux-merge.orig/arch/powerpc/platforms/83xx/pci.c	2007-12-14 15:49:00.000000000 +1100
+++ linux-merge/arch/powerpc/platforms/83xx/pci.c	2007-12-14 15:49:29.000000000 +1100
@@ -54,7 +54,7 @@ int __init mpc83xx_add_bridge(struct dev
 		       " bus 0\n", dev->full_name);
 	}
 
-	pci_assign_all_buses = 1;
+	ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
 	hose = pcibios_alloc_controller(dev);
 	if (!hose)
 		return -ENOMEM;
Index: linux-merge/arch/powerpc/platforms/chrp/pci.c
===================================================================
--- linux-merge.orig/arch/powerpc/platforms/chrp/pci.c	2007-12-14 15:49:00.000000000 +1100
+++ linux-merge/arch/powerpc/platforms/chrp/pci.c	2007-12-14 15:49:29.000000000 +1100
@@ -198,7 +198,7 @@ static void __init setup_peg2(struct pci
 		printk ("RTAS supporting Pegasos OF not found, please upgrade"
 			" your firmware\n");
 	}
-	pci_assign_all_buses = 1;
+	ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
 	/* keep the reference to the root node */
 }
 
Index: linux-merge/arch/powerpc/platforms/powermac/pci.c
===================================================================
--- linux-merge.orig/arch/powerpc/platforms/powermac/pci.c	2007-12-14 15:49:00.000000000 +1100
+++ linux-merge/arch/powerpc/platforms/powermac/pci.c	2007-12-14 15:49:29.000000000 +1100
@@ -725,7 +725,7 @@ static void __init setup_bandit(struct p
 static int __init setup_uninorth(struct pci_controller *hose,
 				 struct resource *addr)
 {
-	pci_assign_all_buses = 1;
+	ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
 	has_uninorth = 1;
 	hose->ops = &macrisc_pci_ops;
 	hose->cfg_addr = ioremap(addr->start + 0x800000, 0x1000);
@@ -994,6 +994,9 @@ void __init pmac_pci_init(void)
 	struct device_node *np, *root;
 	struct device_node *ht = NULL;
 
+#ifdef CONFIG_PPC32
+	ppc_pci_flags = PPC_PCI_CAN_SKIP_ISA_ALIGN;
+#endif
 	root = of_find_node_by_path("/");
 	if (root == NULL) {
 		printk(KERN_CRIT "pmac_pci_init: can't find root "
@@ -1051,7 +1054,7 @@ void __init pmac_pci_init(void)
 	 * some offset between bus number and domains for now when we
 	 * assign all busses should help for now
 	 */
-	if (pci_assign_all_buses)
+	if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_BUS)
 		pcibios_assign_bus_offset = 0x10;
 #endif
 }
Index: linux-merge/arch/powerpc/sysdev/fsl_pci.c
===================================================================
--- linux-merge.orig/arch/powerpc/sysdev/fsl_pci.c	2007-12-14 15:49:00.000000000 +1100
+++ linux-merge/arch/powerpc/sysdev/fsl_pci.c	2007-12-14 15:49:29.000000000 +1100
@@ -202,7 +202,7 @@ int __init fsl_add_bridge(struct device_
 		printk(KERN_WARNING "Can't get bus-range for %s, assume"
 			" bus 0\n", dev->full_name);
 
-	pci_assign_all_buses = 1;
+	ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
 	hose = pcibios_alloc_controller(dev);
 	if (!hose)
 		return -ENOMEM;
Index: linux-merge/arch/powerpc/sysdev/grackle.c
===================================================================
--- linux-merge.orig/arch/powerpc/sysdev/grackle.c	2007-12-14 15:49:00.000000000 +1100
+++ linux-merge/arch/powerpc/sysdev/grackle.c	2007-12-14 15:49:29.000000000 +1100
@@ -57,7 +57,7 @@ void __init setup_grackle(struct pci_con
 {
 	setup_indirect_pci(hose, 0xfec00000, 0xfee00000, 0);
 	if (machine_is_compatible("PowerMac1,1"))
-		pci_assign_all_buses = 1;
+		ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
 	if (machine_is_compatible("AAPL,PowerBook1998"))
 		grackle_set_loop_snoop(hose, 1);
 #if 0	/* Disabled for now, HW problems ??? */
Index: linux-merge/include/asm-powerpc/pci-bridge.h
===================================================================
--- linux-merge.orig/include/asm-powerpc/pci-bridge.h	2007-12-14 15:49:01.000000000 +1100
+++ linux-merge/include/asm-powerpc/pci-bridge.h	2007-12-14 15:49:29.000000000 +1100
@@ -13,6 +13,26 @@
 
 struct device_node;
 
+extern unsigned int ppc_pci_flags;
+enum {
+	/* Force re-assigning all resources (ignore firmware
+	 * setup completely)
+	 */
+	PPC_PCI_REASSIGN_ALL_RSRC	= 0x00000001,
+
+	/* Re-assign all bus numbers */
+	PPC_PCI_REASSIGN_ALL_BUS	= 0x00000002,
+
+	/* Do not try to assign, just use existing setup */
+	PPC_PCI_PROBE_ONLY		= 0x00000004,
+
+	/* Don't bother with ISA alignment unless the bridge has
+	 * ISA forwarding enabled
+	 */
+	PPC_PCI_CAN_SKIP_ISA_ALIGN	= 0x00000008,
+};
+
+
 /*
  * Structure of a PCI controller (host bridge)
  */
Index: linux-merge/include/asm-powerpc/pci.h
===================================================================
--- linux-merge.orig/include/asm-powerpc/pci.h	2007-12-14 15:49:01.000000000 +1100
+++ linux-merge/include/asm-powerpc/pci.h	2007-12-14 15:49:29.000000000 +1100
@@ -38,9 +38,12 @@ struct pci_dev;
  * Set this to 1 if you want the kernel to re-assign all PCI
  * bus numbers
  */
-extern int pci_assign_all_buses;
-#define pcibios_assign_all_busses()	(pci_assign_all_buses)
-
+#ifdef CONFIG_PPC64
+#define pcibios_assign_all_busses()	0
+#else
+#define pcibios_assign_all_busses()    	(ppc_pci_flags & \
+					 PPC_PCI_REASSIGN_ALL_BUS)
+#endif
 #define pcibios_scan_all_fns(a, b)	0
 
 static inline void pcibios_set_master(struct pci_dev *dev)

^ permalink raw reply

* [PATCH 3/15] [POWERPC] pci32: Remove PowerMac P2P bridge IO hack
From: Benjamin Herrenschmidt @ 2007-12-14  4:56 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1197608163.200976.87755569596.qpush@grosgo>

The 32 bits PowerPC PCI code has a hack for use by some PowerMacs
to try to re-open PCI<->PCI bridge IO resources that were closed
by the firmware. This is no longer necessary as the generic code
will now do that for us.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

 arch/powerpc/kernel/pci_32.c |  215 -------------------------------------------
 1 file changed, 1 insertion(+), 214 deletions(-)

--- linux-merge.orig/arch/powerpc/kernel/pci_32.c	2007-12-14 15:49:27.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci_32.c	2007-12-14 15:49:28.000000000 +1100
@@ -711,217 +711,6 @@ void pcibios_make_OF_bus_map(void)
 }
 #endif /* CONFIG_PPC_OF */
 
-#ifdef CONFIG_PPC_PMAC
-/*
- * This set of routines checks for PCI<->PCI bridges that have closed
- * IO resources and have child devices. It tries to re-open an IO
- * window on them.
- *
- * This is a _temporary_ fix to workaround a problem with Apple's OF
- * closing IO windows on P2P bridges when the OF drivers of cards
- * below this bridge don't claim any IO range (typically ATI or
- * Adaptec).
- *
- * A more complete fix would be to use drivers/pci/setup-bus.c, which
- * involves a working pcibios_fixup_pbus_ranges(), some more care about
- * ordering when creating the host bus resources, and maybe a few more
- * minor tweaks
- */
-
-/* Initialize bridges with base/limit values we have collected */
-static void __init
-do_update_p2p_io_resource(struct pci_bus *bus, int enable_vga)
-{
-	struct pci_dev *bridge = bus->self;
-	struct pci_controller* hose = (struct pci_controller *)bridge->sysdata;
-	u32 l;
-	u16 w;
-	struct resource res;
-
-	if (bus->resource[0] == NULL)
-		return;
- 	res = *(bus->resource[0]);
-
-	DBG("Remapping Bus %d, bridge: %s\n", bus->number, pci_name(bridge));
-	res.start -= ((unsigned long) hose->io_base_virt - isa_io_base);
-	res.end -= ((unsigned long) hose->io_base_virt - isa_io_base);
-	DBG("  IO window: %016llx-%016llx\n", res.start, res.end);
-
-	/* Set up the top and bottom of the PCI I/O segment for this bus. */
-	pci_read_config_dword(bridge, PCI_IO_BASE, &l);
-	l &= 0xffff000f;
-	l |= (res.start >> 8) & 0x00f0;
-	l |= res.end & 0xf000;
-	pci_write_config_dword(bridge, PCI_IO_BASE, l);
-
-	if ((l & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
-		l = (res.start >> 16) | (res.end & 0xffff0000);
-		pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, l);
-	}
-
-	pci_read_config_word(bridge, PCI_COMMAND, &w);
-	w |= PCI_COMMAND_IO;
-	pci_write_config_word(bridge, PCI_COMMAND, w);
-
-#if 0 /* Enabling this causes XFree 4.2.0 to hang during PCI probe */
-	if (enable_vga) {
-		pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &w);
-		w |= PCI_BRIDGE_CTL_VGA;
-		pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, w);
-	}
-#endif
-}
-
-/* This function is pretty basic and actually quite broken for the
- * general case, it's enough for us right now though. It's supposed
- * to tell us if we need to open an IO range at all or not and what
- * size.
- */
-static int __init
-check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga)
-{
-	struct pci_dev *dev;
-	int	i;
-	int	rc = 0;
-
-#define push_end(res, mask) do {		\
-	BUG_ON((mask+1) & mask);		\
-	res->end = (res->end + mask) | mask;	\
-} while (0)
-
-	list_for_each_entry(dev, &bus->devices, bus_list) {
-		u16 class = dev->class >> 8;
-
-		if (class == PCI_CLASS_DISPLAY_VGA ||
-		    class == PCI_CLASS_NOT_DEFINED_VGA)
-			*found_vga = 1;
-		if (class >> 8 == PCI_BASE_CLASS_BRIDGE && dev->subordinate)
-			rc |= check_for_io_childs(dev->subordinate, res, found_vga);
-		if (class == PCI_CLASS_BRIDGE_CARDBUS)
-			push_end(res, 0xfff);
-
-		for (i=0; i<PCI_NUM_RESOURCES; i++) {
-			struct resource *r;
-			unsigned long r_size;
-
-			if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI
-			    && i >= PCI_BRIDGE_RESOURCES)
-				continue;
-			r = &dev->resource[i];
-			r_size = r->end - r->start;
-			if (r_size < 0xfff)
-				r_size = 0xfff;
-			if (r->flags & IORESOURCE_IO && (r_size) != 0) {
-				rc = 1;
-				push_end(res, r_size);
-			}
-		}
-	}
-
-	return rc;
-}
-
-/* Here we scan all P2P bridges of a given level that have a closed
- * IO window. Note that the test for the presence of a VGA card should
- * be improved to take into account already configured P2P bridges,
- * currently, we don't see them and might end up configuring 2 bridges
- * with VGA pass through enabled
- */
-static void __init
-do_fixup_p2p_level(struct pci_bus *bus)
-{
-	struct pci_bus *b;
-	int i, parent_io;
-	int has_vga = 0;
-
-	for (parent_io=0; parent_io<4; parent_io++)
-		if (bus->resource[parent_io]
-		    && bus->resource[parent_io]->flags & IORESOURCE_IO)
-			break;
-	if (parent_io >= 4)
-		return;
-
-	list_for_each_entry(b, &bus->children, node) {
-		struct pci_dev *d = b->self;
-		struct pci_controller* hose = (struct pci_controller *)d->sysdata;
-		struct resource *res = b->resource[0];
-		struct resource tmp_res;
-		unsigned long max;
-		int found_vga = 0;
-
-		memset(&tmp_res, 0, sizeof(tmp_res));
-		tmp_res.start = bus->resource[parent_io]->start;
-
-		/* We don't let low addresses go through that closed P2P bridge, well,
-		 * that may not be necessary but I feel safer that way
-		 */
-		if (tmp_res.start == 0)
-			tmp_res.start = 0x1000;
-	
-		if (!list_empty(&b->devices) && res && res->flags == 0 &&
-		    res != bus->resource[parent_io] &&
-		    (d->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
-		    check_for_io_childs(b, &tmp_res, &found_vga)) {
-			u8 io_base_lo;
-
-			printk(KERN_INFO "Fixing up IO bus %s\n", b->name);
-
-			if (found_vga) {
-				if (has_vga) {
-					printk(KERN_WARNING "Skipping VGA, already active"
-					    " on bus segment\n");
-					found_vga = 0;
-				} else
-					has_vga = 1;
-			}
-			pci_read_config_byte(d, PCI_IO_BASE, &io_base_lo);
-
-			if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32)
-				max = ((unsigned long) hose->io_base_virt
-					- isa_io_base) + 0xffffffff;
-			else
-				max = ((unsigned long) hose->io_base_virt
-					- isa_io_base) + 0xffff;
-
-			*res = tmp_res;
-			res->flags = IORESOURCE_IO;
-			res->name = b->name;
-		
-			/* Find a resource in the parent where we can allocate */
-			for (i = 0 ; i < 4; i++) {
-				struct resource *r = bus->resource[i];
-				if (!r)
-					continue;
-				if ((r->flags & IORESOURCE_IO) == 0)
-					continue;
-				DBG("Trying to allocate from %016llx, size %016llx from parent"
-				    " res %d: %016llx -> %016llx\n",
-					res->start, res->end, i, r->start, r->end);
-			
-				if (allocate_resource(r, res, res->end + 1, res->start, max,
-				    res->end + 1, NULL, NULL) < 0) {
-					DBG("Failed !\n");
-					continue;
-				}
-				do_update_p2p_io_resource(b, found_vga);
-				break;
-			}
-		}
-		do_fixup_p2p_level(b);
-	}
-}
-
-static void
-pcibios_fixup_p2p_bridges(void)
-{
-	struct pci_bus *b;
-
-	list_for_each_entry(b, &pci_root_buses, node)
-		do_fixup_p2p_level(b);
-}
-
-#endif /* CONFIG_PPC_PMAC */
-
 static int __init
 pcibios_init(void)
 {
@@ -961,9 +750,7 @@ pcibios_init(void)
 	pcibios_allocate_bus_resources(&pci_root_buses);
 	pcibios_allocate_resources(0);
 	pcibios_allocate_resources(1);
-#ifdef CONFIG_PPC_PMAC
-	pcibios_fixup_p2p_bridges();
-#endif /* CONFIG_PPC_PMAC */
+
 	DBG("PCI: Assigning unassigned resouces...\n");
 	pci_assign_unassigned_resources();
 

^ permalink raw reply

* [PATCH 2/15] [POWERPC] pci32: use generic pci_assign_unassign_resources
From: Benjamin Herrenschmidt @ 2007-12-14  4:56 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1197608163.200976.87755569596.qpush@grosgo>

This makes the 32 bits PowerPC PCI code use the generic code to assign
resources to devices that had unassigned or conflicting resources.

This allow to remove the local implementation that was incomplete and
could not assign for example a PCI<->PCI bridge from scratch, which is
needed on various embedded platforms.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

 arch/powerpc/kernel/pci_32.c |  191 +++----------------------------------------
 1 file changed, 17 insertions(+), 174 deletions(-)

--- linux-merge.orig/arch/powerpc/kernel/pci_32.c	2007-12-14 15:49:27.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci_32.c	2007-12-14 15:49:27.000000000 +1100
@@ -37,10 +37,6 @@ int pcibios_assign_bus_offset = 1;
 
 void pcibios_make_OF_bus_map(void);
 
-static int pci_relocate_bridge_resource(struct pci_bus *bus, int i);
-static int probe_resource(struct pci_bus *parent, struct resource *pr,
-			  struct resource *res, struct resource **conflict);
-static void update_bridge_base(struct pci_bus *bus, int i);
 static void pcibios_fixup_resources(struct pci_dev* dev);
 static void fixup_broken_pcnet32(struct pci_dev* dev);
 static int reparent_resources(struct resource *parent, struct resource *res);
@@ -134,7 +130,7 @@ pcibios_fixup_resources(struct pci_dev *
 		if (offset != 0) {
 			res->start = (res->start + offset) & mask;
 			res->end = (res->end + offset) & mask;
-			DBG("Fixup res %d (%lx) of dev %s: %llx -> %llx\n",
+			DBG("PCI: Fixup res %d (0x%lx) of dev %s: %llx -> %llx\n",
 			    i, res->flags, pci_name(dev),
 			    (u64)res->start - offset, (u64)res->start);
 		}
@@ -267,9 +263,12 @@ pcibios_allocate_bus_resources(struct li
 				}
 			}
 
-			DBG("PCI: bridge rsrc %llx..%llx (%lx), parent %p\n",
+			DBG("PCI: dev %s (bus 0x%02x) bridge rsrc %d: %016llx..%016llx "
+			    "(f:0x%08lx), parent %p\n",
+			    bus->self ? pci_name(bus->self) : "PHB", bus->number, i,
 			    (u64)res->start, (u64)res->end, res->flags, pr);
-			if (pr) {
+
+			if (pr && !(pr->flags & IORESOURCE_UNSET)) {
 				if (request_resource(pr, res) == 0)
 					continue;
 				/*
@@ -280,10 +279,11 @@ pcibios_allocate_bus_resources(struct li
 				if (reparent_resources(pr, res) == 0)
 					continue;
 			}
-			printk(KERN_ERR "PCI: Cannot allocate resource region "
-			       "%d of PCI bridge %d\n", i, bus->number);
-			if (pci_relocate_bridge_resource(bus, i))
-				bus->resource[i] = NULL;
+			printk(KERN_WARNING
+			       "PCI: Cannot allocate resource region "
+			       "%d of PCI bridge %d, will remap\n",
+			       i, bus->number);
+			res->flags |= IORESOURCE_UNSET;
 		}
 		pcibios_allocate_bus_resources(&bus->children);
 	}
@@ -324,112 +324,6 @@ reparent_resources(struct resource *pare
 	return 0;
 }
 
-/*
- * A bridge has been allocated a range which is outside the range
- * of its parent bridge, so it needs to be moved.
- */
-static int __init
-pci_relocate_bridge_resource(struct pci_bus *bus, int i)
-{
-	struct resource *res, *pr, *conflict;
-	resource_size_t try, size;
-	struct pci_bus *parent = bus->parent;
-	int j;
-
-	if (parent == NULL) {
-		/* shouldn't ever happen */
-		printk(KERN_ERR "PCI: can't move host bridge resource\n");
-		return -1;
-	}
-	res = bus->resource[i];
-	if (res == NULL)
-		return -1;
-	pr = NULL;
-	for (j = 0; j < 4; j++) {
-		struct resource *r = parent->resource[j];
-		if (!r)
-			continue;
-		if ((res->flags ^ r->flags) & (IORESOURCE_IO | IORESOURCE_MEM))
-			continue;
-		if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH)) {
-			pr = r;
-			break;
-		}
-		if (res->flags & IORESOURCE_PREFETCH)
-			pr = r;
-	}
-	if (pr == NULL)
-		return -1;
-	size = res->end - res->start;
-	if (pr->start > pr->end || size > pr->end - pr->start)
-		return -1;
-	try = pr->end;
-	for (;;) {
-		res->start = try - size;
-		res->end = try;
-		if (probe_resource(bus->parent, pr, res, &conflict) == 0)
-			break;
-		if (conflict->start <= pr->start + size)
-			return -1;
-		try = conflict->start - 1;
-	}
-	if (request_resource(pr, res)) {
-		DBG(KERN_ERR "PCI: huh? couldn't move to %llx..%llx\n",
-		    (u64)res->start, (u64)res->end);
-		return -1;		/* "can't happen" */
-	}
-	update_bridge_base(bus, i);
-	printk(KERN_INFO "PCI: bridge %d resource %d moved to %llx..%llx\n",
-	       bus->number, i, (unsigned long long)res->start,
-	       (unsigned long long)res->end);
-	return 0;
-}
-
-static int __init
-probe_resource(struct pci_bus *parent, struct resource *pr,
-	       struct resource *res, struct resource **conflict)
-{
-	struct pci_bus *bus;
-	struct pci_dev *dev;
-	struct resource *r;
-	int i;
-
-	for (r = pr->child; r != NULL; r = r->sibling) {
-		if (r->end >= res->start && res->end >= r->start) {
-			*conflict = r;
-			return 1;
-		}
-	}
-	list_for_each_entry(bus, &parent->children, node) {
-		for (i = 0; i < 4; ++i) {
-			if ((r = bus->resource[i]) == NULL)
-				continue;
-			if (!r->flags || r->start > r->end || r == res)
-				continue;
-			if (pci_find_parent_resource(bus->self, r) != pr)
-				continue;
-			if (r->end >= res->start && res->end >= r->start) {
-				*conflict = r;
-				return 1;
-			}
-		}
-	}
-	list_for_each_entry(dev, &parent->devices, bus_list) {
-		for (i = 0; i < 6; ++i) {
-			r = &dev->resource[i];
-			if (!r->flags || (r->flags & IORESOURCE_UNSET))
-				continue;
-			if (pci_find_parent_resource(dev, r) != pr)
-				continue;
-			if (r->end >= res->start && res->end >= r->start) {
-				*conflict = r;
-				return 1;
-			}
-		}
-	}
-	return 0;
-}
-
 void __init
 update_bridge_resource(struct pci_dev *dev, struct resource *res)
 {
@@ -486,24 +380,16 @@ update_bridge_resource(struct pci_dev *d
 	pci_write_config_word(dev, PCI_COMMAND, cmd);
 }
 
-static void __init
-update_bridge_base(struct pci_bus *bus, int i)
-{
-	struct resource *res = bus->resource[i];
-	struct pci_dev *dev = bus->self;
-	update_bridge_resource(dev, res);
-}
-
 static inline void alloc_resource(struct pci_dev *dev, int idx)
 {
 	struct resource *pr, *r = &dev->resource[idx];
 
-	DBG("PCI:%s: Resource %d: %016llx-%016llx (f=%lx)\n",
+	DBG("PCI: Allocating %s: Resource %d: %016llx..%016llx (f=%lx)\n",
 	    pci_name(dev), idx, (u64)r->start, (u64)r->end, r->flags);
 	pr = pci_find_parent_resource(dev, r);
-	if (!pr || request_resource(pr, r) < 0) {
-		printk(KERN_WARNING "PCI: Remapping resource region %d"
-		       " of device %s\n", idx, pci_name(dev));
+	if (!pr || (pr->flags & IORESOURCE_UNSET) ||  request_resource(pr, r) < 0) {
+		printk(KERN_WARNING "PCI: Cannot allocate resource region %d"
+		       " of device %s, will remap\n", idx, pci_name(dev));
 		if (pr)
 			DBG("PCI:  parent is %p: %016llx-%016llx (f=%lx)\n",
 			    pr, (u64)pr->start, (u64)pr->end, pr->flags);
@@ -552,50 +438,6 @@ pcibios_allocate_resources(int pass)
 	}
 }
 
-static void __init
-pcibios_assign_resources(void)
-{
-	struct pci_dev *dev = NULL;
-	int idx;
-	struct resource *r;
-
-	for_each_pci_dev(dev) {
-		int class = dev->class >> 8;
-
-		/* Don't touch classless devices and host bridges */
-		if (!class || class == PCI_CLASS_BRIDGE_HOST)
-			continue;
-
-		for (idx = 0; idx < 6; idx++) {
-			r = &dev->resource[idx];
-
-			/*
-			 * We shall assign a new address to this resource,
-			 * either because the BIOS (sic) forgot to do so
-			 * or because we have decided the old address was
-			 * unusable for some reason.
-			 */
-			if ((r->flags & IORESOURCE_UNSET) && r->end &&
-			    (!ppc_md.pcibios_enable_device_hook ||
-			     !ppc_md.pcibios_enable_device_hook(dev, 1))) {
-				int rc;
-
-				r->flags &= ~IORESOURCE_UNSET;
-				rc = pci_assign_resource(dev, idx);
-				BUG_ON(rc);
-			}
-		}
-
-#if 0 /* don't assign ROMs */
-		r = &dev->resource[PCI_ROM_RESOURCE];
-		r->end -= r->start;
-		r->start = 0;
-		if (r->end)
-			pci_assign_resource(dev, PCI_ROM_RESOURCE);
-#endif
-	}
-}
-
 #ifdef CONFIG_PPC_OF
 /*
  * Functions below are used on OpenFirmware machines.
@@ -1122,7 +964,8 @@ pcibios_init(void)
 #ifdef CONFIG_PPC_PMAC
 	pcibios_fixup_p2p_bridges();
 #endif /* CONFIG_PPC_PMAC */
-	pcibios_assign_resources();
+	DBG("PCI: Assigning unassigned resouces...\n");
+	pci_assign_unassigned_resources();
 
 	/* Call machine dependent post-init code */
 	if (ppc_md.pcibios_after_init)

^ permalink raw reply

* [PATCH 1/15] [POWERPC] pci32: remove bogus alignment message
From: Benjamin Herrenschmidt @ 2007-12-14  4:56 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1197608163.200976.87755569596.qpush@grosgo>

There's a stale & bogus piece of code in 32 bits PCI code that
complains about ISA related alignment issues. Just remove it.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

 arch/powerpc/kernel/pci_32.c |    6 ------
 1 file changed, 6 deletions(-)

--- linux-merge.orig/arch/powerpc/kernel/pci_32.c	2007-12-14 15:49:01.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/pci_32.c	2007-12-14 15:49:27.000000000 +1100
@@ -199,12 +199,6 @@ void pcibios_align_resource(void *data, 
 	if (res->flags & IORESOURCE_IO) {
 		resource_size_t start = res->start;
 
-		if (size > 0x100) {
-			printk(KERN_ERR "PCI: I/O Region %s/%d too large"
-			       " (%lld bytes)\n", pci_name(dev),
-			       dev->resource - res, (unsigned long long)size);
-		}
-
 		if (start & 0x300) {
 			start = (start + 0x3ff) & ~0x3ff;
 			res->start = start;

^ permalink raw reply

* [PATCH 0/15] [POWERPC] PCI updates & merges
From: Benjamin Herrenschmidt @ 2007-12-14  4:56 UTC (permalink / raw)
  To: linuxppc-dev

(THIS SERIES STILL NEEDS MORE TESTING)

(This version is rebased on top of current for-2.6.25, my remaining
 4xx patches will apply on top of this)

This serie of patches converts the 32 bits PCI code to use the generic
pci_assign_unassigned_resources() instead of its own assignment code
which was unable to deal with unassigned PCI<->PCI bridges among
other issues.

It then merges the resource fixup and allocation code between 32 and
64 bits (mostly making 64 bits use the 32 bits code with a few fixups),
hopefully fixing the longstanding issue that not setting pci_probe_only
on ppc64 would generally not work.

We also add flags to control the behaviour of the PCI code, such as
letting some platforms force a full re-assignment (similar to what
pci-auto used to provide in arch/ppc) and remove a whole bunch of
hackish code that is made obsolete by that change.

32 bits platforms with 64 bits resources support will also need my
separate patch to fix the generic setup-bus.c for that situation.

Finally, I also merge the implementations of pcibios_enable_device()
and fixup the PowerMac code that used hooks in that area in ways
that don't work anymore.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox