From 514604c6d1779c55d3e97dc4e9a71c117c1ccbcd Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Thu, 7 Jul 2005 16:59:00 -0700 Subject: [PATCH 1/6] [IA64] pcibus_to_node implementation for IA64 pcibus_to_node provides a way for the Linux kernel to identify to which node a certain pcibus connects to. Allocations of control structures for devices can then be made on the node where the pci bus is located to allow local access during interrupt and other device manipulation. This patch provides a new "node" field in the the pci_controller structure. The node field will be set based on ACPI information (thanks to Alex Williamson Signed-off-by: Tony Luck --- arch/ia64/pci/pci.c | 12 ++++++++++-- include/asm-ia64/pci.h | 1 + include/asm-ia64/topology.h | 5 +++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 720a861f88be..54d9ed444e4a 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -157,6 +157,7 @@ alloc_pci_controller (int seg) memset(controller, 0, sizeof(*controller)); controller->segment = seg; + controller->node = -1; return controller; } @@ -288,6 +289,7 @@ pci_acpi_scan_root(struct acpi_device *device, int domain, int bus) unsigned int windows = 0; struct pci_bus *pbus; char *name; + int pxm; controller = alloc_pci_controller(domain); if (!controller) @@ -295,10 +297,16 @@ pci_acpi_scan_root(struct acpi_device *device, int domain, int bus) controller->acpi_handle = device->handle; + pxm = acpi_get_pxm(controller->acpi_handle); +#ifdef CONFIG_NUMA + if (pxm >= 0) + controller->node = pxm_to_nid_map[pxm]; +#endif + acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window, &windows); - controller->window = kmalloc(sizeof(*controller->window) * windows, - GFP_KERNEL); + controller->window = kmalloc_node(sizeof(*controller->window) * windows, + GFP_KERNEL, controller->node); if (!controller->window) goto out2; diff --git a/include/asm-ia64/pci.h b/include/asm-ia64/pci.h index 0c4c5d801d3f..8b7237cc84c1 100644 --- a/include/asm-ia64/pci.h +++ b/include/asm-ia64/pci.h @@ -128,6 +128,7 @@ struct pci_controller { void *acpi_handle; void *iommu; int segment; + int node; /* nearest node with memory or -1 for global allocation */ unsigned int windows; struct pci_window *window; diff --git a/include/asm-ia64/topology.h b/include/asm-ia64/topology.h index 4e64c2a6b369..399bc29729fd 100644 --- a/include/asm-ia64/topology.h +++ b/include/asm-ia64/topology.h @@ -40,6 +40,11 @@ */ #define node_to_first_cpu(node) (__ffs(node_to_cpumask(node))) +/* + * Determines the node for a given pci bus + */ +#define pcibus_to_node(bus) PCI_CONTROLLER(bus)->node + void build_cpu_to_node_map(void); #define SD_CPU_INIT (struct sched_domain) { \ From 60a762b6a6dec17cc4339b60154902fd04c2f9f2 Mon Sep 17 00:00:00 2001 From: Greg Edwards Date: Tue, 28 Jun 2005 11:13:00 -0700 Subject: [PATCH 2/6] [IA64] remove CONFIG_IA64_SGI_SN_SIM This patch removes the CONFIG_IA64_SGI_SN_SIM option entirely, allowing any kernel bootable on sn2 to also be booted in the simulator. Boot tested on Altix and HP rx2600. Signed-off-by: Greg Edwards Signed-off-by: Tony Luck --- arch/ia64/Kconfig | 7 ------- arch/ia64/configs/sn2_defconfig | 1 - include/asm-ia64/sn/simulator.h | 9 +-------- 3 files changed, 1 insertion(+), 16 deletions(-) diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 01b78e7f992e..bfdd062dd827 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -220,13 +220,6 @@ config IOSAPIC depends on !IA64_HP_SIM default y -config IA64_SGI_SN_SIM - bool "SGI Medusa Simulator Support" - depends on IA64_SGI_SN2 || IA64_GENERIC - help - If you are compiling a kernel that will run under SGI's IA-64 - simulator (Medusa) then say Y, otherwise say N. - config IA64_SGI_SN_XP tristate "Support communication between SGI SSIs" select IA64_UNCACHED_ALLOCATOR diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig index c05613980300..04d0b00a2b8c 100644 --- a/arch/ia64/configs/sn2_defconfig +++ b/arch/ia64/configs/sn2_defconfig @@ -81,7 +81,6 @@ CONFIG_HOLES_IN_ZONE=y CONFIG_ARCH_DISCONTIGMEM_ENABLE=y # CONFIG_IA64_CYCLONE is not set CONFIG_IOSAPIC=y -CONFIG_IA64_SGI_SN_SIM=y CONFIG_FORCE_MAX_ZONEORDER=18 CONFIG_SMP=y CONFIG_NR_CPUS=512 diff --git a/include/asm-ia64/sn/simulator.h b/include/asm-ia64/sn/simulator.h index cf770e246af5..16a48b5a039c 100644 --- a/include/asm-ia64/sn/simulator.h +++ b/include/asm-ia64/sn/simulator.h @@ -13,16 +13,9 @@ #define SNMAGIC 0xaeeeeeee8badbeefL #define IS_MEDUSA() ({long sn; asm("mov %0=cpuid[%1]" : "=r"(sn) : "r"(2)); sn == SNMAGIC;}) -#ifdef CONFIG_IA64_SGI_SN_SIM #define SIMULATOR_SLEEP() asm("nop.i 0x8beef") -#define IS_RUNNING_ON_SIMULATOR() (sn_prom_type) +#define IS_RUNNING_ON_SIMULATOR() (sn_prom_type) #define IS_RUNNING_ON_FAKE_PROM() (sn_prom_type == 2) extern int sn_prom_type; /* 0=hardware, 1=medusa/realprom, 2=medusa/fakeprom */ -#else -#define IS_RUNNING_ON_SIMULATOR() (0) -#define IS_RUNNING_ON_FAKE_PROM() (0) -#define SIMULATOR_SLEEP() - -#endif #endif /* _ASM_IA64_SN_SIMULATOR_H */ From 08357f82d4decc48bbfd39ae30d5fe0754f7f576 Mon Sep 17 00:00:00 2001 From: Zoltan Menyhart Date: Fri, 3 Jun 2005 05:36:00 -0700 Subject: [PATCH 3/6] [IA64] improve flush_icache_range() Check with PAL to see what the i-cache line size is for each level of the cache, and so use the correct stride when flushing the cache. Acked-by: David Mosberger Signed-off-by: Tony Luck --- arch/ia64/kernel/setup.c | 37 ++++++++++++++++++++++++++++++-- arch/ia64/lib/flush.S | 46 +++++++++++++++++++++++++++++----------- 2 files changed, 69 insertions(+), 14 deletions(-) diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 2693e1522d7c..7fc891aca446 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -20,6 +20,7 @@ * 02/01/00 R.Seth fixed get_cpuinfo for SMP * 01/07/99 S.Eranian added the support for command line argument * 06/24/99 W.Drummond added boot_cpu_data. + * 05/28/05 Z. Menyhart Dynamic stride size for "flush_icache_range()" */ #include #include @@ -82,6 +83,13 @@ struct io_space io_space[MAX_IO_SPACES]; EXPORT_SYMBOL(io_space); unsigned int num_io_spaces; +/* + * "flush_icache_range()" needs to know what processor dependent stride size to use + * when it makes i-cache(s) coherent with d-caches. + */ +#define I_CACHE_STRIDE_SHIFT 5 /* Safest way to go: 32 bytes by 32 bytes */ +unsigned long ia64_i_cache_stride_shift = ~0; + /* * The merge_mask variable needs to be set to (max(iommu_page_size(iommu)) - 1). This * mask specifies a mask of address bits that must be 0 in order for two buffers to be @@ -626,6 +634,12 @@ setup_per_cpu_areas (void) /* start_kernel() requires this... */ } +/* + * Calculate the max. cache line size. + * + * In addition, the minimum of the i-cache stride sizes is calculated for + * "flush_icache_range()". + */ static void get_max_cacheline_size (void) { @@ -639,6 +653,8 @@ get_max_cacheline_size (void) printk(KERN_ERR "%s: ia64_pal_cache_summary() failed (status=%ld)\n", __FUNCTION__, status); max = SMP_CACHE_BYTES; + /* Safest setup for "flush_icache_range()" */ + ia64_i_cache_stride_shift = I_CACHE_STRIDE_SHIFT; goto out; } @@ -647,14 +663,31 @@ get_max_cacheline_size (void) &cci); if (status != 0) { printk(KERN_ERR - "%s: ia64_pal_cache_config_info(l=%lu) failed (status=%ld)\n", + "%s: ia64_pal_cache_config_info(l=%lu, 2) failed (status=%ld)\n", __FUNCTION__, l, status); max = SMP_CACHE_BYTES; + /* The safest setup for "flush_icache_range()" */ + cci.pcci_stride = I_CACHE_STRIDE_SHIFT; + cci.pcci_unified = 1; } line_size = 1 << cci.pcci_line_size; if (line_size > max) max = line_size; - } + if (!cci.pcci_unified) { + status = ia64_pal_cache_config_info(l, + /* cache_type (instruction)= */ 1, + &cci); + if (status != 0) { + printk(KERN_ERR + "%s: ia64_pal_cache_config_info(l=%lu, 1) failed (status=%ld)\n", + __FUNCTION__, l, status); + /* The safest setup for "flush_icache_range()" */ + cci.pcci_stride = I_CACHE_STRIDE_SHIFT; + } + } + if (cci.pcci_stride < ia64_i_cache_stride_shift) + ia64_i_cache_stride_shift = cci.pcci_stride; + } out: if (max > ia64_max_cacheline_size) ia64_max_cacheline_size = max; diff --git a/arch/ia64/lib/flush.S b/arch/ia64/lib/flush.S index a1af9146cfdb..3e2cfa2c6d39 100644 --- a/arch/ia64/lib/flush.S +++ b/arch/ia64/lib/flush.S @@ -3,37 +3,59 @@ * * Copyright (C) 1999-2001, 2005 Hewlett-Packard Co * David Mosberger-Tang + * + * 05/28/05 Zoltan Menyhart Dynamic stride size */ + #include -#include + /* * flush_icache_range(start,end) - * Must flush range from start to end-1 but nothing else (need to + * + * Make i-cache(s) coherent with d-caches. + * + * Must deal with range from start to end-1 but nothing else (need to * be careful not to touch addresses that may be unmapped). + * + * Note: "in0" and "in1" are preserved for debugging purposes. */ GLOBAL_ENTRY(flush_icache_range) + .prologue - alloc r2=ar.pfs,2,0,0,0 - sub r8=in1,in0,1 + alloc r2=ar.pfs,2,0,0,0 + movl r3=ia64_i_cache_stride_shift + mov r21=1 ;; - shr.u r8=r8,5 // we flush 32 bytes per iteration - .save ar.lc, r3 - mov r3=ar.lc // save ar.lc + ld8 r20=[r3] // r20: stride shift + sub r22=in1,r0,1 // last byte address + ;; + shr.u r23=in0,r20 // start / (stride size) + shr.u r22=r22,r20 // (last byte address) / (stride size) + shl r21=r21,r20 // r21: stride size of the i-cache(s) + ;; + sub r8=r22,r23 // number of strides - 1 + shl r24=r23,r20 // r24: addresses for "fc.i" = + // "start" rounded down to stride boundary + .save ar.lc,r3 + mov r3=ar.lc // save ar.lc ;; .body - - mov ar.lc=r8 + mov ar.lc=r8 ;; -.Loop: fc.i in0 // issuable on M2 only - add in0=32,in0 + /* + * 32 byte aligned loop, even number of (actually 2) bundles + */ +.Loop: fc.i r24 // issuable on M0 only + add r24=r21,r24 // we flush "stride size" bytes per iteration + nop.i 0 br.cloop.sptk.few .Loop ;; sync.i ;; srlz.i ;; - mov ar.lc=r3 // restore ar.lc + mov ar.lc=r3 // restore ar.lc br.ret.sptk.many rp END(flush_icache_range) From 7c2a6c62c013a4ea57243536fc7f3987e4ba04bc Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Tue, 12 Jul 2005 16:03:00 -0700 Subject: [PATCH 4/6] [IA64] Altix pcibus_to_node implementation The Altix subarch does not provide node information via ACPI. Instead hooks are used to fixup pci structures. This patch determines the nodes for Altix PCI busses. Remote Bridges: --------------- Altix supports remote I/O nodes without memory or processors but with bridges. The TIOCA type of bridge is an AGP bridge and the PROM provides information about the closest node. That information will be returned by pcibus_to_node. The TIOCP remote bridge type is a PCI bridge but the PROM does not provide a closest node id. pcibus_to_node will return -1 for devices on those bridges meaning that device control structures may be allocated on any node. Safeguard: ---------- Should the fixups result in invalid node information for a pci controller then a warning will be printed and pcibus_to_node will return -1. This patch also fixes the "FIXME" in sn_dma_alloc_coherent. This means that dma_alloc_coherent will now use alloc_pages_node to allocate memory local to the node that the PCI device is connected to. Signed-off-by: Christoph Lameter Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/io_init.c | 20 ++++++++++++++++++-- arch/ia64/sn/pci/pci_dma.c | 16 +++++++++++++--- arch/ia64/sn/pci/pcibr/pcibr_provider.c | 10 +++++++++- arch/ia64/sn/pci/tioca_provider.c | 4 +++- include/asm-ia64/sn/pcibr_provider.h | 2 +- include/asm-ia64/sn/pcibus_provider_defs.h | 3 ++- 6 files changed, 46 insertions(+), 9 deletions(-) diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index a67f39e448cb..a6649baf629a 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -61,7 +61,7 @@ sn_default_pci_unmap(struct pci_dev *pdev, dma_addr_t addr, int direction) } static void * -sn_default_pci_bus_fixup(struct pcibus_bussoft *soft) +sn_default_pci_bus_fixup(struct pcibus_bussoft *soft, struct pci_controller *controller) { return NULL; } @@ -362,7 +362,7 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) provider_soft = NULL; if (provider->bus_fixup) - provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr); + provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr, controller); if (provider_soft == NULL) return; /* fixup failed or not applicable */ @@ -380,6 +380,22 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) SN_PCIBUS_BUSSOFT(bus)->bs_xwidget_info = &(hubdev_info->hdi_xwidget_info[SN_PCIBUS_BUSSOFT(bus)->bs_xid]); + /* + * If the node information we obtained during the fixup phase is invalid + * then set controller->node to -1 (undetermined) + */ + if (controller->node >= num_online_nodes()) { + struct pcibus_bussoft *b = SN_PCIBUS_BUSSOFT(bus); + + printk(KERN_WARNING "Device ASIC=%u XID=%u PBUSNUM=%lu" + "L_IO=%lx L_MEM=%lx BASE=%lx\n", + b->bs_asic_type, b->bs_xid, b->bs_persist_busnum, + b->bs_legacy_io, b->bs_legacy_mem, b->bs_base); + printk(KERN_WARNING "on node %d but only %d nodes online." + "Association set to undetermined.\n", + controller->node, num_online_nodes()); + controller->node = -1; + } return; error_return: diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c index a2f7a88aefbb..0e4b9ad9ef02 100644 --- a/arch/ia64/sn/pci/pci_dma.c +++ b/arch/ia64/sn/pci/pci_dma.c @@ -79,6 +79,7 @@ void *sn_dma_alloc_coherent(struct device *dev, size_t size, { void *cpuaddr; unsigned long phys_addr; + int node; struct pci_dev *pdev = to_pci_dev(dev); struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); @@ -86,10 +87,19 @@ void *sn_dma_alloc_coherent(struct device *dev, size_t size, /* * Allocate the memory. - * FIXME: We should be doing alloc_pages_node for the node closest - * to the PCI device. */ - if (!(cpuaddr = (void *)__get_free_pages(GFP_ATOMIC, get_order(size)))) + node = pcibus_to_node(pdev->bus); + if (likely(node >=0)) { + struct page *p = alloc_pages_node(node, GFP_ATOMIC, get_order(size)); + + if (likely(p)) + cpuaddr = page_address(p); + else + return NULL; + } else + cpuaddr = (void *)__get_free_pages(GFP_ATOMIC, get_order(size)); + + if (unlikely(!cpuaddr)) return NULL; memset(cpuaddr, 0x0, size); diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c index 9813da56d311..b95e928636a1 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c @@ -85,7 +85,7 @@ pcibr_error_intr_handler(int irq, void *arg, struct pt_regs *regs) } void * -pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft) +pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller) { int nasid, cnode, j; struct hubdev_info *hubdev_info; @@ -158,6 +158,14 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft) memset(soft->pbi_int_ate_resource.ate, 0, (soft->pbi_int_ate_size * sizeof(uint64_t))); + if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) + /* + * TIO PCI Bridge with no closest node information. + * FIXME: Find another way to determine the closest node + */ + controller->node = -1; + else + controller->node = cnode; return soft; } diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c index 51cc4e63092c..5d76a7581465 100644 --- a/arch/ia64/sn/pci/tioca_provider.c +++ b/arch/ia64/sn/pci/tioca_provider.c @@ -581,7 +581,7 @@ tioca_error_intr_handler(int irq, void *arg, struct pt_regs *pt) * the caller. */ static void * -tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft) +tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller) { struct tioca_common *tioca_common; struct tioca_kernel *tioca_kern; @@ -646,6 +646,8 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft) __FUNCTION__, SGI_TIOCA_ERROR, (int)tioca_common->ca_common.bs_persist_busnum); + /* Setup locality information */ + controller->node = tioca_kern->ca_closest_node; return tioca_common; } diff --git a/include/asm-ia64/sn/pcibr_provider.h b/include/asm-ia64/sn/pcibr_provider.h index f9b8d2164007..2b42d9ece26b 100644 --- a/include/asm-ia64/sn/pcibr_provider.h +++ b/include/asm-ia64/sn/pcibr_provider.h @@ -128,7 +128,7 @@ pcibr_lock(struct pcibus_info *pcibus_info) #define pcibr_unlock(pcibus_info, flag) spin_unlock_irqrestore(&pcibus_info->pbi_lock, flag) extern int pcibr_init_provider(void); -extern void *pcibr_bus_fixup(struct pcibus_bussoft *); +extern void *pcibr_bus_fixup(struct pcibus_bussoft *, struct pci_controller *); extern dma_addr_t pcibr_dma_map(struct pci_dev *, unsigned long, size_t); extern dma_addr_t pcibr_dma_map_consistent(struct pci_dev *, unsigned long, size_t); extern void pcibr_dma_unmap(struct pci_dev *, dma_addr_t, int); diff --git a/include/asm-ia64/sn/pcibus_provider_defs.h b/include/asm-ia64/sn/pcibus_provider_defs.h index 04e27d5b3820..976f5eff0539 100644 --- a/include/asm-ia64/sn/pcibus_provider_defs.h +++ b/include/asm-ia64/sn/pcibus_provider_defs.h @@ -37,6 +37,7 @@ struct pcibus_bussoft { struct xwidget_info *bs_xwidget_info; }; +struct pci_controller; /* * SN pci bus indirection */ @@ -45,7 +46,7 @@ struct sn_pcibus_provider { dma_addr_t (*dma_map)(struct pci_dev *, unsigned long, size_t); dma_addr_t (*dma_map_consistent)(struct pci_dev *, unsigned long, size_t); void (*dma_unmap)(struct pci_dev *, dma_addr_t, int); - void * (*bus_fixup)(struct pcibus_bussoft *); + void * (*bus_fixup)(struct pcibus_bussoft *, struct pci_controller *); }; extern struct sn_pcibus_provider *sn_pci_provider[]; From 59a0a8aa6ab6e46926e8d12694593267c0869440 Mon Sep 17 00:00:00 2001 From: Dean Nelson Date: Wed, 13 Jul 2005 05:45:00 -0700 Subject: [PATCH 5/6] [IA64] fix call of smp_processor_id() by XPC while XPC calls smp_processor_id() twice from xpc_setup_infrastructure() with preemption enabled, which gets flagged if 'DEBUG_PREEMPT=y'. This patch replaces the two calls to smp_processor_id() by a single call to raw_smp_processor_id() since any CPU within the partition will do. Signed-off-by: Dean Nelson Acked-by: Christoph Hellwig Signed-off-by: Tony Luck --- arch/ia64/sn/kernel/xpc_channel.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c index 6d02dac8056f..94698bea7be0 100644 --- a/arch/ia64/sn/kernel/xpc_channel.c +++ b/arch/ia64/sn/kernel/xpc_channel.c @@ -72,7 +72,7 @@ xpc_initialize_channels(struct xpc_partition *part, partid_t partid) enum xpc_retval xpc_setup_infrastructure(struct xpc_partition *part) { - int ret; + int ret, cpuid; struct timer_list *timer; partid_t partid = XPC_PARTID(part); @@ -223,9 +223,9 @@ xpc_setup_infrastructure(struct xpc_partition *part) xpc_vars_part[partid].openclose_args_pa = __pa(part->local_openclose_args); xpc_vars_part[partid].IPI_amo_pa = __pa(part->local_IPI_amo_va); - xpc_vars_part[partid].IPI_nasid = cpuid_to_nasid(smp_processor_id()); - xpc_vars_part[partid].IPI_phys_cpuid = - cpu_physical_id(smp_processor_id()); + cpuid = raw_smp_processor_id(); /* any CPU in this partition will do */ + xpc_vars_part[partid].IPI_nasid = cpuid_to_nasid(cpuid); + xpc_vars_part[partid].IPI_phys_cpuid = cpu_physical_id(cpuid); xpc_vars_part[partid].nchannels = part->nchannels; xpc_vars_part[partid].magic = XPC_VP_MAGIC1; From f62c4a96f74d6c6dd56d1742697e94a5c2085e87 Mon Sep 17 00:00:00 2001 From: David Mosberger-Tang Date: Tue, 12 Jul 2005 21:51:00 -0700 Subject: [PATCH 6/6] [IA64] Make PCDP work again. Mark's patch added "attribute((packed))" for pcdp_uart, without accounting for the fact that the structure definition _relied_ on implicit padding by 6 bytes. Fix is to make the padding explicit. Signed-off-by: David Mosberger-Tang Signed-off-by: Tony Luck --- drivers/firmware/pcdp.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/firmware/pcdp.h b/drivers/firmware/pcdp.h index e72cc47de33b..ce910d68bd19 100644 --- a/drivers/firmware/pcdp.h +++ b/drivers/firmware/pcdp.h @@ -52,6 +52,8 @@ struct pcdp_uart { u32 clock_rate; u8 pci_prog_intfc; u8 flags; + u16 conout_index; + u32 reserved; } __attribute__((packed)); #define PCDP_IF_PCI 1