ia64/linux-2.6.18-xen.hg

changeset 702:8fbf8e2fd087

dom0 linux: Fix issue on reassigning resources to PCI-PCI bridge.

This patch fixes the issue on reassigning resources to PCI-PCI bridge,
which was found by Zhao, Yu.

Current "quirk_align_mem_resources" updates Base/Limit register of
PCI-PCI bridge, if IORESOURCE_MEM is set in "dev->resource[i].flags".
But, when "quirk_align_mem_resources" is called,
dev->resource[i].flags
is not initialized, because "quirk_align_mem_resources" is called
before "pci_read_bridge_bases". As a result, current code does not
update Base/Limit register.

This patch sets All F to Base register and sets 0 to Limit register,
regardless of "dev->resource[i].flags". After that,
"pci_assign_unassigned_resources" calculates resource window size and
assigns resource to PCI-PCI bridge.

Signed-off-by: Yuji Shimada <shimada-yxb@necst.nec.co.jp>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Oct 17 12:01:56 2008 +0100 (2008-10-17)
parents 16c549b3ba59
children a29df0e2bfe2
files drivers/pci/pci.h drivers/pci/quirks.c drivers/pci/setup-res.c
line diff
     1.1 --- a/drivers/pci/pci.h	Tue Oct 14 14:58:08 2008 +0100
     1.2 +++ b/drivers/pci/pci.h	Fri Oct 17 12:01:56 2008 +0100
     1.3 @@ -102,7 +102,7 @@ pci_match_one_device(const struct pci_de
     1.4  #ifdef CONFIG_PCI_REASSIGN
     1.5  extern int reassign_resources;
     1.6  extern int is_reassigndev(struct pci_dev *dev);
     1.7 -extern void pci_update_bridge(struct pci_dev *dev, int resno);
     1.8 +extern void pci_disable_bridge_window(struct pci_dev *dev);
     1.9  #else
    1.10  #define reassign_resources 0
    1.11  #define is_reassigndev(dev) 0
     2.1 --- a/drivers/pci/quirks.c	Tue Oct 14 14:58:08 2008 +0100
     2.2 +++ b/drivers/pci/quirks.c	Fri Oct 17 12:01:56 2008 +0100
     2.3 @@ -69,8 +69,7 @@ static void __devinit quirk_align_mem_re
     2.4  
     2.5  			for (i=0; i < PCI_NUM_RESOURCES; i++) {
     2.6  				r = &dev->resource[i];
     2.7 -				if ((r == NULL) || 
     2.8 -				   !(r->flags & IORESOURCE_MEM))
     2.9 +				if (!(r->flags & IORESOURCE_MEM))
    2.10  					continue;
    2.11  
    2.12  				r->end = r->end - r->start;
    2.13 @@ -78,15 +77,16 @@ static void __devinit quirk_align_mem_re
    2.14  
    2.15  				if (i < PCI_BRIDGE_RESOURCES) {
    2.16  					pci_update_resource(dev, r, i);
    2.17 -				} else if (i == 8 || i == 9) {
    2.18 -					/* need to update(clear) the Base/Limit
    2.19 -					 * register also, because PCI bridge is
    2.20 -					 * disabled and the resource is 
    2.21 -					 * released.
    2.22 -					 */
    2.23 -					pci_update_bridge(dev, i);
    2.24  				}
    2.25  			}
    2.26 +			/* need to disable bridge's resource window,
    2.27 +			 * to make kernel enable to reassign new resource
    2.28 +			 * window later on.
    2.29 +			 */
    2.30 +			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
    2.31 +			    (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
    2.32 +				pci_disable_bridge_window(dev);
    2.33 +			}
    2.34  		}
    2.35  		return;
    2.36  	}
     3.1 --- a/drivers/pci/setup-res.c	Tue Oct 14 14:58:08 2008 +0100
     3.2 +++ b/drivers/pci/setup-res.c	Fri Oct 17 12:01:56 2008 +0100
     3.3 @@ -118,72 +118,17 @@ pci_claim_resource(struct pci_dev *dev, 
     3.4  EXPORT_SYMBOL_GPL(pci_claim_resource);
     3.5  
     3.6  #ifdef CONFIG_PCI_REASSIGN
     3.7 -void
     3.8 -pci_update_bridge(struct pci_dev *dev, int resno)
     3.9 +void pci_disable_bridge_window(struct pci_dev *dev)
    3.10  {
    3.11 -	struct resource *res = &dev->resource[resno]; 
    3.12 -	struct pci_bus_region region;
    3.13 -	u32 l, dw, base_up32, limit_up32;
    3.14 -
    3.15 -	if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE ||
    3.16 -	    (dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) {
    3.17 -		return;
    3.18 -	}
    3.19 -
    3.20 -	if (!res->flags)
    3.21 -		return;
    3.22 -
    3.23 -	switch (resno) {
    3.24 -	case 8 :	/* MMIO Base/Limit */
    3.25 -		pcibios_resource_to_bus(dev, &region, res);
    3.26 -		if (res->flags & IORESOURCE_MEM &&
    3.27 -		    !(res->flags & IORESOURCE_PREFETCH)) {
    3.28 -			l = (region.start >> 16) & 0xfff0;
    3.29 -			l |= region.end & 0xfff00000;
    3.30 -		} else {
    3.31 -			l = 0x0000fff0;
    3.32 -		}
    3.33 -		pci_write_config_dword(dev, PCI_MEMORY_BASE, l);
    3.34 -
    3.35 -		break;
    3.36 -
    3.37 -	case 9 :	/* Prefetchable MMIO Base/Limit */
    3.38 -		/* Clear out the upper 32 bits of PREF limit.
    3.39 -		 * If PCI_PREF_BASE_UPPER32 was non-zero, this temporarily
    3.40 -		 * disables PREF range, which is ok.
    3.41 -		 */
    3.42 -		pci_write_config_dword(dev, PCI_PREF_LIMIT_UPPER32, 0);
    3.43 -
    3.44 -		/* Get PREF 32/64 bits Addressing mode */
    3.45 -		pci_read_config_dword(dev, PCI_PREF_MEMORY_BASE, &dw);
    3.46 -
    3.47 -		pcibios_resource_to_bus(dev, &region, res);
    3.48 -		if (res->flags & IORESOURCE_MEM &&
    3.49 -		    res->flags & IORESOURCE_PREFETCH) {
    3.50 -			l = (region.start >> 16) & 0xfff0;
    3.51 -			l |= region.end & 0xfff00000;
    3.52 -
    3.53 -			if (dw & PCI_PREF_RANGE_TYPE_64) {
    3.54 -				base_up32 = (region.start >> 32) & 0xffffffff;
    3.55 -				limit_up32 = (region.end >> 32) & 0xffffffff;
    3.56 -			} else {
    3.57 -				base_up32 = 0;
    3.58 -				limit_up32 = 0;
    3.59 -			}
    3.60 -		} else {
    3.61 -			l = 0x0000fff0;
    3.62 -			base_up32 = 0xffffffff;
    3.63 -			limit_up32 = 0;
    3.64 -		}
    3.65 -		pci_write_config_dword(dev, PCI_PREF_MEMORY_BASE, l);
    3.66 -		/* Set up the upper 32 bits of PREF base/limit. */
    3.67 -		pci_write_config_dword(dev, PCI_PREF_BASE_UPPER32, base_up32);
    3.68 -		pci_write_config_dword(dev, PCI_PREF_LIMIT_UPPER32, limit_up32);
    3.69 -		break;
    3.70 -	default :
    3.71 -		BUG();
    3.72 -		break;
    3.73 -	}
    3.74 +	printk(KERN_DEBUG "PCI: Disable bridge window on %s\n", pci_name(dev));
    3.75 +  
    3.76 + 	/* MMIO Base/Limit */
    3.77 + 	pci_write_config_dword(dev, PCI_MEMORY_BASE, 0x0000fff0);
    3.78 +  
    3.79 + 	/* Prefetchable MMIO Base/Limit */
    3.80 + 	pci_write_config_dword(dev, PCI_PREF_LIMIT_UPPER32, 0);
    3.81 + 	pci_write_config_dword(dev, PCI_PREF_MEMORY_BASE, 0x0000fff0);
    3.82 + 	pci_write_config_dword(dev, PCI_PREF_BASE_UPPER32, 0xffffffff);
    3.83  }
    3.84  #endif
    3.85