* Re: [PATCH 1/3] msi vector targeting abstractions
From: Jun'ichi Nomura @ 2006-03-21 16:29 UTC (permalink / raw)
To: Mark Maule
Cc: Tony Luck, linux-ia64, gregkh, linux-kernel, linuxppc64-dev,
linux-pci
In-Reply-To: <20060321143449.9913.55794.57267@lnx-maule.americas.sgi.com>
Hi Mark,
Mark Maule wrote:
> Index: linux-2.6.16/include/asm-ia64/msi.h
> ===================================================================
> --- linux-2.6.16.orig/include/asm-ia64/msi.h 2006-03-19 23:53:29.000000000 -0600
> +++ linux-2.6.16/include/asm-ia64/msi.h 2006-03-20 14:50:53.331368084 -0600
> @@ -14,4 +14,16 @@
> #define ack_APIC_irq ia64_eoi
> #define MSI_TARGET_CPU_SHIFT 4
>
> +extern struct msi_ops msi_apic_ops;
> +
> +static inline int msi_arch_init(void)
> +{
> + if (platform_msi_init)
> + return platform_msi_init();
> +
> + /* default ops for most ia64 platforms */
> + msi_register(&msi_apic_ops);
> + return 0;
> +}
> +
> #endif /* ASM_MSI_H */
It turned out that the above code breaks configs other
than CONFIG_IA64_SN and CONFIG_IA64_GENERIC.
e.g. CONFIG_IA64_DIG.
In file included from /build/16.msi/drivers/pci/msi.h:71,
from /build/16.msi/drivers/pci/msi.c:24:
include2/asm/msi.h: In function `msi_arch_init':
include2/asm/msi.h:22: error: called object is not a function
make[3]: *** [drivers/pci/msi.o] Error 1
Something like below might fix this problem:
if (platform_msi_init) {
ia64_mv_msi_init_t *fn = platform_msi_init;
return (*fn)();
}
Thanks,
--
Jun'ichi Nomura, NEC Solutions (America), Inc.
^ permalink raw reply
* Re: [PATCH 2/11] powerpc: Remove unused iommu_off logic from pSeries_init_early()
From: Olof Johansson @ 2006-03-21 16:15 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20060321094627.44FAC679F9@ozlabs.org>
On Tue, Mar 21, 2006 at 08:45:58PM +1100, Michael Ellerman wrote:
> When iommu_init_early_pSeries() was added, ages ago, we forgot to remove
> the code that checks /chosen/linux,iommu-off in pSeries_init_early(). We
> do it now in iommu_init_early_pSeries().
>
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Acked-by: Olof Johansson <olof@lixom.net>
^ permalink raw reply
* Re: VLAN support on TSEC for MPC8541
From: Brian Waite @ 2006-03-21 14:48 UTC (permalink / raw)
To: linuxppc-embedded; +Cc: Bizhan Gholikhamseh (bgholikh)
In-Reply-To: <F795765B112E7344AF36AA9112796415019ECE6A@xmb-sjc-212.amer.cisco.com>
[-- Attachment #1: Type: text/plain, Size: 394 bytes --]
On Tuesday 21 March 2006 9:04 am, Bizhan Gholikhamseh (bgholikh) wrote:
> Hi All,
> I have asked this question in past with no response. Are there any VLAN
> implementation of TSEC driver for MPC8541 (with CPM core)?
>
> Many thanks in advance,
> Bizhan
Yes it was answered, and quite directly I might add.
http://marc.theaimsgroup.com/?l=linuxppc-embedded&m=114166772622557&w=2
Thanks
Brian
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 3/3] altix: msi support
From: Mark Maule @ 2006-03-21 14:34 UTC (permalink / raw)
To: linuxppc64-dev, linux-pci, linux-ia64, linux-kernel
Cc: j-nomura, Mark Maule, Tony Luck, gregkh
In-Reply-To: <20060321143444.9913.48372.11324@lnx-maule.americas.sgi.com>
MSI callouts for altix. Involves a fair amount of code reorg in sn irq.c
code as well as adding some extensions to the altix PCI provider abstaction.
Signed-off-by: Mark Maule <maule@sgi.com>
Index: linux-2.6.16/arch/ia64/sn/kernel/io_init.c
===================================================================
--- linux-2.6.16.orig/arch/ia64/sn/kernel/io_init.c 2006-03-20 15:06:57.714084166 -0600
+++ linux-2.6.16/arch/ia64/sn/kernel/io_init.c 2006-03-20 22:18:39.159006426 -0600
@@ -56,7 +56,7 @@
*/
static dma_addr_t
-sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size)
+sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size, int type)
{
return 0;
}
Index: linux-2.6.16/arch/ia64/sn/kernel/irq.c
===================================================================
--- linux-2.6.16.orig/arch/ia64/sn/kernel/irq.c 2006-03-20 22:06:25.118460888 -0600
+++ linux-2.6.16/arch/ia64/sn/kernel/irq.c 2006-03-20 22:18:39.160959362 -0600
@@ -26,11 +26,11 @@
int sn_force_interrupt_flag = 1;
extern int sn_ioif_inited;
-static struct list_head **sn_irq_lh;
+struct list_head **sn_irq_lh;
static spinlock_t sn_irq_info_lock = SPIN_LOCK_UNLOCKED; /* non-IRQ lock */
-static inline u64 sn_intr_alloc(nasid_t local_nasid, int local_widget,
- u64 sn_irq_info,
+u64 sn_intr_alloc(nasid_t local_nasid, int local_widget,
+ struct sn_irq_info *sn_irq_info,
int req_irq, nasid_t req_nasid,
int req_slice)
{
@@ -40,12 +40,13 @@
SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_INTERRUPT,
(u64) SAL_INTR_ALLOC, (u64) local_nasid,
- (u64) local_widget, (u64) sn_irq_info, (u64) req_irq,
+ (u64) local_widget, __pa(sn_irq_info), (u64) req_irq,
(u64) req_nasid, (u64) req_slice);
+
return ret_stuff.status;
}
-static inline void sn_intr_free(nasid_t local_nasid, int local_widget,
+void sn_intr_free(nasid_t local_nasid, int local_widget,
struct sn_irq_info *sn_irq_info)
{
struct ia64_sal_retval ret_stuff;
@@ -112,73 +113,91 @@
static void sn_irq_info_free(struct rcu_head *head);
-static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
+struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
+ nasid_t nasid, int slice)
{
- struct sn_irq_info *sn_irq_info, *sn_irq_info_safe;
- int cpuid, cpuphys;
+ int vector;
+ int cpuphys;
+ int64_t bridge;
+ int local_widget, status;
+ nasid_t local_nasid;
+ struct sn_irq_info *new_irq_info;
+ struct sn_pcibus_provider *pci_provider;
- cpuid = first_cpu(mask);
- cpuphys = cpu_physical_id(cpuid);
+ new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC);
+ if (new_irq_info == NULL)
+ return NULL;
- list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe,
- sn_irq_lh[irq], list) {
- u64 bridge;
- int local_widget, status;
- nasid_t local_nasid;
- struct sn_irq_info *new_irq_info;
- struct sn_pcibus_provider *pci_provider;
-
- new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC);
- if (new_irq_info == NULL)
- break;
- memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info));
-
- bridge = (u64) new_irq_info->irq_bridge;
- if (!bridge) {
- kfree(new_irq_info);
- break; /* irq is not a device interrupt */
- }
+ memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info));
- local_nasid = NASID_GET(bridge);
+ bridge = (u64) new_irq_info->irq_bridge;
+ if (!bridge) {
+ kfree(new_irq_info);
+ return NULL; /* irq is not a device interrupt */
+ }
- if (local_nasid & 1)
- local_widget = TIO_SWIN_WIDGETNUM(bridge);
- else
- local_widget = SWIN_WIDGETNUM(bridge);
-
- /* Free the old PROM new_irq_info structure */
- sn_intr_free(local_nasid, local_widget, new_irq_info);
- /* Update kernels new_irq_info with new target info */
- unregister_intr_pda(new_irq_info);
-
- /* allocate a new PROM new_irq_info struct */
- status = sn_intr_alloc(local_nasid, local_widget,
- __pa(new_irq_info), irq,
- cpuid_to_nasid(cpuid),
- cpuid_to_slice(cpuid));
-
- /* SAL call failed */
- if (status) {
- kfree(new_irq_info);
- break;
- }
+ local_nasid = NASID_GET(bridge);
+
+ if (local_nasid & 1)
+ local_widget = TIO_SWIN_WIDGETNUM(bridge);
+ else
+ local_widget = SWIN_WIDGETNUM(bridge);
+
+ vector = sn_irq_info->irq_irq;
+ /* Free the old PROM new_irq_info structure */
+ sn_intr_free(local_nasid, local_widget, new_irq_info);
+ /* Update kernels new_irq_info with new target info */
+ unregister_intr_pda(new_irq_info);
+
+ /* allocate a new PROM new_irq_info struct */
+ status = sn_intr_alloc(local_nasid, local_widget,
+ new_irq_info, vector,
+ nasid, slice);
+
+ /* SAL call failed */
+ if (status) {
+ kfree(new_irq_info);
+ return NULL;
+ }
+
+ cpuphys = nasid_slice_to_cpuid(nasid, slice);
+ new_irq_info->irq_cpuid = cpuphys;
+ register_intr_pda(new_irq_info);
+
+ pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type];
- new_irq_info->irq_cpuid = cpuid;
- register_intr_pda(new_irq_info);
+ /*
+ * If this represents a line interrupt, target it. If it's
+ * an msi (irq_int_bit < 0), it's already targeted.
+ */
+ if (new_irq_info->irq_int_bit >= 0 &&
+ pci_provider && pci_provider->target_interrupt)
+ (pci_provider->target_interrupt)(new_irq_info);
- pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type];
- if (pci_provider && pci_provider->target_interrupt)
- (pci_provider->target_interrupt)(new_irq_info);
-
- spin_lock(&sn_irq_info_lock);
- list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
- spin_unlock(&sn_irq_info_lock);
- call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
+ spin_lock(&sn_irq_info_lock);
+ list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
+ spin_unlock(&sn_irq_info_lock);
+ call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
#ifdef CONFIG_SMP
- set_irq_affinity_info((irq & 0xff), cpuphys, 0);
+ set_irq_affinity_info((vector & 0xff), cpuphys, 0);
#endif
- }
+
+ return new_irq_info;
+}
+
+static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
+{
+ struct sn_irq_info *sn_irq_info, *sn_irq_info_safe;
+ nasid_t nasid;
+ int slice;
+
+ nasid = cpuid_to_nasid(first_cpu(mask));
+ slice = cpuid_to_slice(first_cpu(mask));
+
+ list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe,
+ sn_irq_lh[irq], list)
+ (void)sn_retarget_vector(sn_irq_info, nasid, slice);
}
struct hw_interrupt_type irq_type_sn = {
Index: linux-2.6.16/arch/ia64/sn/pci/pci_dma.c
===================================================================
--- linux-2.6.16.orig/arch/ia64/sn/pci/pci_dma.c 2006-03-20 15:06:57.715060633 -0600
+++ linux-2.6.16/arch/ia64/sn/pci/pci_dma.c 2006-03-20 22:18:39.188300475 -0600
@@ -11,7 +11,7 @@
#include <linux/module.h>
#include <asm/dma.h>
-#include <asm/sn/pcibr_provider.h>
+#include <asm/sn/intr.h>
#include <asm/sn/pcibus_provider_defs.h>
#include <asm/sn/pcidev.h>
#include <asm/sn/sn_sal.h>
@@ -113,7 +113,8 @@
* resources.
*/
- *dma_handle = provider->dma_map_consistent(pdev, phys_addr, size);
+ *dma_handle = provider->dma_map_consistent(pdev, phys_addr, size,
+ SN_DMA_ADDR_PHYS);
if (!*dma_handle) {
printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__);
free_pages((unsigned long)cpuaddr, get_order(size));
@@ -176,7 +177,7 @@
BUG_ON(dev->bus != &pci_bus_type);
phys_addr = __pa(cpu_addr);
- dma_addr = provider->dma_map(pdev, phys_addr, size);
+ dma_addr = provider->dma_map(pdev, phys_addr, size, SN_DMA_ADDR_PHYS);
if (!dma_addr) {
printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__);
return 0;
@@ -260,7 +261,8 @@
for (i = 0; i < nhwentries; i++, sg++) {
phys_addr = SG_ENT_PHYS_ADDRESS(sg);
sg->dma_address = provider->dma_map(pdev,
- phys_addr, sg->length);
+ phys_addr, sg->length,
+ SN_DMA_ADDR_PHYS);
if (!sg->dma_address) {
printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__);
Index: linux-2.6.16/arch/ia64/sn/pci/pcibr/pcibr_dma.c
===================================================================
--- linux-2.6.16.orig/arch/ia64/sn/pci/pcibr/pcibr_dma.c 2006-03-20 15:06:57.715060633 -0600
+++ linux-2.6.16/arch/ia64/sn/pci/pcibr/pcibr_dma.c 2006-03-20 22:18:39.200994563 -0600
@@ -41,7 +41,7 @@
static dma_addr_t
pcibr_dmamap_ate32(struct pcidev_info *info,
- u64 paddr, size_t req_size, u64 flags)
+ u64 paddr, size_t req_size, u64 flags, int dma_flags)
{
struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info;
@@ -81,9 +81,12 @@
if (IS_PCIX(pcibus_info))
ate_flags &= ~(PCI32_ATE_PREF);
- xio_addr =
- IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
- PHYS_TO_TIODMA(paddr);
+ if (SN_DMA_ADDRTYPE(dma_flags == SN_DMA_ADDR_PHYS))
+ xio_addr = IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
+ PHYS_TO_TIODMA(paddr);
+ else
+ xio_addr = paddr;
+
offset = IOPGOFF(xio_addr);
ate = ate_flags | (xio_addr - offset);
@@ -91,6 +94,13 @@
if (IS_PIC_SOFT(pcibus_info)) {
ate |= (pcibus_info->pbi_hub_xid << PIC_ATE_TARGETID_SHFT);
}
+
+ /*
+ * If we're mapping for MSI, set the MSI bit in the ATE
+ */
+ if (dma_flags & SN_DMA_MSI)
+ ate |= PCI32_ATE_MSI;
+
ate_write(pcibus_info, ate_index, ate_count, ate);
/*
@@ -105,20 +115,27 @@
if (pcibus_info->pbi_devreg[internal_device] & PCIBR_DEV_SWAP_DIR)
ATE_SWAP_ON(pci_addr);
+
return pci_addr;
}
static dma_addr_t
pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr,
- u64 dma_attributes)
+ u64 dma_attributes, int dma_flags)
{
struct pcibus_info *pcibus_info = (struct pcibus_info *)
((info->pdi_host_pcidev_info)->pdi_pcibus_info);
u64 pci_addr;
/* Translate to Crosstalk View of Physical Address */
- pci_addr = (IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
- PHYS_TO_TIODMA(paddr)) | dma_attributes;
+ if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS)
+ pci_addr = IS_PIC_SOFT(pcibus_info) ?
+ PHYS_TO_DMA(paddr) :
+ PHYS_TO_TIODMA(paddr) | dma_attributes;
+ else
+ pci_addr = IS_PIC_SOFT(pcibus_info) ?
+ paddr :
+ paddr | dma_attributes;
/* Handle Bus mode */
if (IS_PCIX(pcibus_info))
@@ -130,7 +147,9 @@
((u64) pcibus_info->
pbi_hub_xid << PIC_PCI64_ATTR_TARG_SHFT);
} else
- pci_addr |= TIOCP_PCI64_CMDTYPE_MEM;
+ pci_addr |= (dma_flags & SN_DMA_MSI) ?
+ TIOCP_PCI64_CMDTYPE_MSI :
+ TIOCP_PCI64_CMDTYPE_MEM;
/* If PCI mode, func zero uses VCHAN0, every other func uses VCHAN1 */
if (!IS_PCIX(pcibus_info) && PCI_FUNC(info->pdi_linux_pcidev->devfn))
@@ -141,7 +160,7 @@
static dma_addr_t
pcibr_dmatrans_direct32(struct pcidev_info * info,
- u64 paddr, size_t req_size, u64 flags)
+ u64 paddr, size_t req_size, u64 flags, int dma_flags)
{
struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info;
struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info->
@@ -156,8 +175,14 @@
return 0;
}
- xio_addr = IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
- PHYS_TO_TIODMA(paddr);
+ if (dma_flags & SN_DMA_MSI)
+ return 0;
+
+ if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS)
+ xio_addr = IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
+ PHYS_TO_TIODMA(paddr);
+ else
+ xio_addr = paddr;
xio_base = pcibus_info->pbi_dir_xbase;
offset = xio_addr - xio_base;
@@ -327,7 +352,7 @@
*/
dma_addr_t
-pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size)
+pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size, int dma_flags)
{
dma_addr_t dma_handle;
struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev);
@@ -344,11 +369,11 @@
*/
dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr,
- PCI64_ATTR_PREF);
+ PCI64_ATTR_PREF, dma_flags);
} else {
/* Handle 32-63 bit cards via direct mapping */
dma_handle = pcibr_dmatrans_direct32(pcidev_info, phys_addr,
- size, 0);
+ size, 0, dma_flags);
if (!dma_handle) {
/*
* It is a 32 bit card and we cannot do direct mapping,
@@ -356,7 +381,8 @@
*/
dma_handle = pcibr_dmamap_ate32(pcidev_info, phys_addr,
- size, PCI32_ATE_PREF);
+ size, PCI32_ATE_PREF,
+ dma_flags);
}
}
@@ -365,18 +391,18 @@
dma_addr_t
pcibr_dma_map_consistent(struct pci_dev * hwdev, unsigned long phys_addr,
- size_t size)
+ size_t size, int dma_flags)
{
dma_addr_t dma_handle;
struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev);
if (hwdev->dev.coherent_dma_mask == ~0UL) {
dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr,
- PCI64_ATTR_BAR);
+ PCI64_ATTR_BAR, dma_flags);
} else {
dma_handle = (dma_addr_t) pcibr_dmamap_ate32(pcidev_info,
phys_addr, size,
- PCI32_ATE_BAR);
+ PCI32_ATE_BAR, dma_flags);
}
return dma_handle;
Index: linux-2.6.16/arch/ia64/sn/pci/tioca_provider.c
===================================================================
--- linux-2.6.16.orig/arch/ia64/sn/pci/tioca_provider.c 2006-03-20 15:06:57.716037100 -0600
+++ linux-2.6.16/arch/ia64/sn/pci/tioca_provider.c 2006-03-20 22:18:39.206853373 -0600
@@ -515,11 +515,17 @@
* use the GART mapped mode.
*/
static u64
-tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count)
+tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
{
u64 mapaddr;
/*
+ * Not supported for now ...
+ */
+ if (dma_flags & SN_DMA_MSI)
+ return 0;
+
+ /*
* If card is 64 or 48 bit addresable, use a direct mapping. 32
* bit direct is so restrictive w.r.t. where the memory resides that
* we don't use it even though CA has some support.
Index: linux-2.6.16/arch/ia64/sn/pci/tioce_provider.c
===================================================================
--- linux-2.6.16.orig/arch/ia64/sn/pci/tioce_provider.c 2006-03-20 15:06:57.716037100 -0600
+++ linux-2.6.16/arch/ia64/sn/pci/tioce_provider.c 2006-03-20 22:18:39.212712182 -0600
@@ -52,7 +52,8 @@
(ATE_PAGE((start)+(len)-1, pagesize) - ATE_PAGE(start, pagesize) + 1)
#define ATE_VALID(ate) ((ate) & (1UL << 63))
-#define ATE_MAKE(addr, ps) (((addr) & ~ATE_PAGEMASK(ps)) | (1UL << 63))
+#define ATE_MAKE(addr, ps, msi) \
+ (((addr) & ~ATE_PAGEMASK(ps)) | (1UL << 63) | ((msi)?(1UL << 62):0))
/*
* Flavors of ate-based mapping supported by tioce_alloc_map()
@@ -78,15 +79,17 @@
*
* 63 - must be 1 to indicate d64 mode to CE hardware
* 62 - barrier bit ... controlled with tioce_dma_barrier()
- * 61 - 0 since this is not an MSI transaction
+ * 61 - msi bit ... specified through dma_flags
* 60:54 - reserved, MBZ
*/
static u64
-tioce_dma_d64(unsigned long ct_addr)
+tioce_dma_d64(unsigned long ct_addr, int dma_flags)
{
u64 bus_addr;
bus_addr = ct_addr | (1UL << 63);
+ if (dma_flags & SN_DMA_MSI)
+ bus_addr |= (1UL << 61);
return bus_addr;
}
@@ -143,7 +146,7 @@
*/
static u64
tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
- u64 ct_addr, int len)
+ u64 ct_addr, int len, int dma_flags)
{
int i;
int j;
@@ -152,6 +155,7 @@
int entries;
int nates;
int pagesize;
+ int msi_capable, msi_wanted;
u64 *ate_shadow;
u64 *ate_reg;
u64 addr;
@@ -173,6 +177,7 @@
ate_reg = ce_mmr->ce_ure_ate3240;
pagesize = ce_kern->ce_ate3240_pagesize;
bus_base = TIOCE_M32_MIN;
+ msi_capable = 1;
break;
case TIOCE_ATE_M40:
first = 0;
@@ -181,6 +186,7 @@
ate_reg = ce_mmr->ce_ure_ate40;
pagesize = MB(64);
bus_base = TIOCE_M40_MIN;
+ msi_capable = 0;
break;
case TIOCE_ATE_M40S:
/*
@@ -193,11 +199,16 @@
ate_reg = ce_mmr->ce_ure_ate3240;
pagesize = GB(16);
bus_base = TIOCE_M40S_MIN;
+ msi_capable = 0;
break;
default:
return 0;
}
+ msi_wanted = dma_flags & SN_DMA_MSI;
+ if (msi_wanted && !msi_capable)
+ return 0;
+
nates = ATE_NPAGES(ct_addr, len, pagesize);
if (nates > entries)
return 0;
@@ -226,7 +237,7 @@
for (j = 0; j < nates; j++) {
u64 ate;
- ate = ATE_MAKE(addr, pagesize);
+ ate = ATE_MAKE(addr, pagesize, msi_wanted);
ate_shadow[i + j] = ate;
writeq(ate, &ate_reg[i + j]);
addr += pagesize;
@@ -253,7 +264,7 @@
* Map @paddr into 32-bit bus space of the CE associated with @pcidev_info.
*/
static u64
-tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr)
+tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr, int dma_flags)
{
int dma_ok;
int port;
@@ -263,6 +274,9 @@
u64 ct_lower;
dma_addr_t bus_addr;
+ if (dma_flags & SN_DMA_MSI)
+ return 0;
+
ct_upper = ct_addr & ~0x3fffffffUL;
ct_lower = ct_addr & 0x3fffffffUL;
@@ -387,7 +401,7 @@
*/
static u64
tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count,
- int barrier)
+ int barrier, int dma_flags)
{
unsigned long flags;
u64 ct_addr;
@@ -403,15 +417,18 @@
if (dma_mask < 0x7fffffffUL)
return 0;
- ct_addr = PHYS_TO_TIODMA(paddr);
+ if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS)
+ ct_addr = PHYS_TO_TIODMA(paddr);
+ else
+ ct_addr = paddr;
/*
* If the device can generate 64 bit addresses, create a D64 map.
- * Since this should never fail, bypass the rest of the checks.
*/
if (dma_mask == ~0UL) {
- mapaddr = tioce_dma_d64(ct_addr);
- goto dma_map_done;
+ mapaddr = tioce_dma_d64(ct_addr, dma_flags);
+ if (mapaddr)
+ goto dma_map_done;
}
pcidev_to_tioce(pdev, NULL, &ce_kern, &port);
@@ -454,18 +471,22 @@
if (byte_count > MB(64)) {
mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40S,
- port, ct_addr, byte_count);
+ port, ct_addr, byte_count,
+ dma_flags);
if (!mapaddr)
mapaddr =
tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1,
- ct_addr, byte_count);
+ ct_addr, byte_count,
+ dma_flags);
} else {
mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1,
- ct_addr, byte_count);
+ ct_addr, byte_count,
+ dma_flags);
if (!mapaddr)
mapaddr =
tioce_alloc_map(ce_kern, TIOCE_ATE_M40S,
- port, ct_addr, byte_count);
+ port, ct_addr, byte_count,
+ dma_flags);
}
}
@@ -473,7 +494,7 @@
* 32-bit direct is the next mode to try
*/
if (!mapaddr && dma_mask >= 0xffffffffUL)
- mapaddr = tioce_dma_d32(pdev, ct_addr);
+ mapaddr = tioce_dma_d32(pdev, ct_addr, dma_flags);
/*
* Last resort, try 32-bit ATE-based map.
@@ -481,12 +502,12 @@
if (!mapaddr)
mapaddr =
tioce_alloc_map(ce_kern, TIOCE_ATE_M32, -1, ct_addr,
- byte_count);
+ byte_count, dma_flags);
spin_unlock_irqrestore(&ce_kern->ce_lock, flags);
dma_map_done:
- if (mapaddr & barrier)
+ if (mapaddr && barrier)
mapaddr = tioce_dma_barrier(mapaddr, 1);
return mapaddr;
@@ -502,9 +523,9 @@
* in the address.
*/
static u64
-tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count)
+tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
{
- return tioce_do_dma_map(pdev, paddr, byte_count, 0);
+ return tioce_do_dma_map(pdev, paddr, byte_count, 0, dma_flags);
}
/**
@@ -516,9 +537,9 @@
* Simply call tioce_do_dma_map() to create a map with the barrier bit set
* in the address.
*/ static u64
-tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count)
+tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
{
- return tioce_do_dma_map(pdev, paddr, byte_count, 1);
+ return tioce_do_dma_map(pdev, paddr, byte_count, 1, dma_flags);
}
/**
Index: linux-2.6.16/include/asm-ia64/sn/intr.h
===================================================================
--- linux-2.6.16.orig/include/asm-ia64/sn/intr.h 2006-03-20 15:06:57.717013566 -0600
+++ linux-2.6.16/include/asm-ia64/sn/intr.h 2006-03-20 22:18:39.226382739 -0600
@@ -10,6 +10,7 @@
#define _ASM_IA64_SN_INTR_H
#include <linux/rcupdate.h>
+#include <asm/sn/types.h>
#define SGI_UART_VECTOR 0xe9
@@ -40,6 +41,7 @@
int irq_cpuid; /* kernel logical cpuid */
int irq_irq; /* the IRQ number */
int irq_int_bit; /* Bridge interrupt pin */
+ /* <0 means MSI */
u64 irq_xtalkaddr; /* xtalkaddr IRQ is sent to */
int irq_bridge_type;/* pciio asic type (pciio.h) */
void *irq_bridge; /* bridge generating irq */
@@ -53,6 +55,12 @@
};
extern void sn_send_IPI_phys(int, long, int, int);
+extern u64 sn_intr_alloc(nasid_t, int,
+ struct sn_irq_info *,
+ int, nasid_t, int);
+extern void sn_intr_free(nasid_t, int, struct sn_irq_info *);
+extern struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *, nasid_t, int);
+extern struct list_head **sn_irq_lh;
#define CPU_VECTOR_TO_IRQ(cpuid,vector) (vector)
Index: linux-2.6.16/include/asm-ia64/sn/pcibr_provider.h
===================================================================
--- linux-2.6.16.orig/include/asm-ia64/sn/pcibr_provider.h 2006-03-20 15:06:57.717013566 -0600
+++ linux-2.6.16/include/asm-ia64/sn/pcibr_provider.h 2006-03-20 22:18:39.228335675 -0600
@@ -55,6 +55,7 @@
#define PCI32_ATE_V (0x1 << 0)
#define PCI32_ATE_CO (0x1 << 1)
#define PCI32_ATE_PREC (0x1 << 2)
+#define PCI32_ATE_MSI (0x1 << 2)
#define PCI32_ATE_PREF (0x1 << 3)
#define PCI32_ATE_BAR (0x1 << 4)
#define PCI32_ATE_ADDR_SHFT 12
@@ -117,8 +118,8 @@
extern int pcibr_init_provider(void);
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 dma_addr_t pcibr_dma_map(struct pci_dev *, unsigned long, size_t, int type);
+extern dma_addr_t pcibr_dma_map_consistent(struct pci_dev *, unsigned long, size_t, int type);
extern void pcibr_dma_unmap(struct pci_dev *, dma_addr_t, int);
/*
Index: linux-2.6.16/include/asm-ia64/sn/pcibus_provider_defs.h
===================================================================
--- linux-2.6.16.orig/include/asm-ia64/sn/pcibus_provider_defs.h 2006-03-20 15:06:57.717013566 -0600
+++ linux-2.6.16/include/asm-ia64/sn/pcibus_provider_defs.h 2006-03-20 22:18:39.231265080 -0600
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved.
*/
#ifndef _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H
#define _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H
@@ -45,13 +45,24 @@
*/
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);
+ dma_addr_t (*dma_map)(struct pci_dev *, unsigned long, size_t, int flags);
+ dma_addr_t (*dma_map_consistent)(struct pci_dev *, unsigned long, size_t, int flags);
void (*dma_unmap)(struct pci_dev *, dma_addr_t, int);
void * (*bus_fixup)(struct pcibus_bussoft *, struct pci_controller *);
void (*force_interrupt)(struct sn_irq_info *);
void (*target_interrupt)(struct sn_irq_info *);
};
+/*
+ * Flags used by the map interfaces
+ * bits 3:0 specifies format of passed in address
+ * bit 4 specifies that address is to be used for MSI
+ */
+
+#define SN_DMA_ADDRTYPE(x) ((x) & 0xf)
+#define SN_DMA_ADDR_PHYS 1 /* address is an xio address. */
+#define SN_DMA_ADDR_XIO 2 /* address is phys memory */
+#define SN_DMA_MSI 0x10 /* Bus address is to be used for MSI */
+
extern struct sn_pcibus_provider *sn_pci_provider[];
#endif /* _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H */
Index: linux-2.6.16/include/asm-ia64/sn/tiocp.h
===================================================================
--- linux-2.6.16.orig/include/asm-ia64/sn/tiocp.h 2006-03-20 15:06:57.717990033 -0600
+++ linux-2.6.16/include/asm-ia64/sn/tiocp.h 2006-03-20 22:18:39.234194485 -0600
@@ -3,13 +3,14 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2003-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2003-2005 Silicon Graphics, Inc. All rights reserved.
*/
#ifndef _ASM_IA64_SN_PCI_TIOCP_H
#define _ASM_IA64_SN_PCI_TIOCP_H
#define TIOCP_HOST_INTR_ADDR 0x003FFFFFFFFFFFFFUL
#define TIOCP_PCI64_CMDTYPE_MEM (0x1ull << 60)
+#define TIOCP_PCI64_CMDTYPE_MSI (0x3ull << 60)
/*****************************************************************************
Index: linux-2.6.16/drivers/pci/msi-altix.c
===================================================================
--- linux-2.6.16.orig/drivers/pci/msi-altix.c 2006-03-20 22:01:01.802923681 -0600
+++ linux-2.6.16/drivers/pci/msi-altix.c 2006-03-20 22:20:19.426676136 -0600
@@ -6,13 +6,205 @@
* Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved.
*/
-#include <asm/errno.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/cpumask.h>
+
+#include <asm/sn/addrs.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/pcidev.h>
+#include <asm/sn/nodepda.h>
+
+#include "msi.h"
+
+struct sn_msi_info {
+ u64 pci_addr;
+ struct sn_irq_info *sn_irq_info;
+};
+
+static struct sn_msi_info *sn_msi_info;
+
+static void
+sn_msi_teardown(unsigned int vector)
+{
+ nasid_t nasid;
+ int widget;
+ struct pci_dev *pdev;
+ struct pcidev_info *sn_pdev;
+ struct sn_irq_info *sn_irq_info;
+ struct pcibus_bussoft *bussoft;
+ struct sn_pcibus_provider *provider;
+
+ sn_irq_info = sn_msi_info[vector].sn_irq_info;
+ if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
+ return;
+
+ sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
+ pdev = sn_pdev->pdi_linux_pcidev;
+ provider = SN_PCIDEV_BUSPROVIDER(pdev);
+
+ (*provider->dma_unmap)(pdev,
+ sn_msi_info[vector].pci_addr,
+ PCI_DMA_FROMDEVICE);
+ sn_msi_info[vector].pci_addr = 0;
+
+ bussoft = SN_PCIDEV_BUSSOFT(pdev);
+ nasid = NASID_GET(bussoft->bs_base);
+ widget = (nasid & 1) ?
+ TIO_SWIN_WIDGETNUM(bussoft->bs_base) :
+ SWIN_WIDGETNUM(bussoft->bs_base);
+
+ sn_intr_free(nasid, widget, sn_irq_info);
+ sn_msi_info[vector].sn_irq_info = NULL;
+
+ return;
+}
int
-sn_msi_init(void)
+sn_msi_setup(struct pci_dev *pdev, unsigned int vector,
+ u32 *addr_hi, u32 *addr_lo, u32 *data)
{
+ int widget;
+ int status;
+ nasid_t nasid;
+ u64 bus_addr;
+ struct sn_irq_info *sn_irq_info;
+ struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev);
+ struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
+
+ if (bussoft == NULL)
+ return -EINVAL;
+
+ if (provider == NULL || provider->dma_map_consistent == NULL)
+ return -EINVAL;
+
+ /*
+ * Set up the vector plumbing. Let the prom (via sn_intr_alloc)
+ * decide which cpu to direct this msi at by default.
+ */
+
+ nasid = NASID_GET(bussoft->bs_base);
+ widget = (nasid & 1) ?
+ TIO_SWIN_WIDGETNUM(bussoft->bs_base) :
+ SWIN_WIDGETNUM(bussoft->bs_base);
+
+ sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
+ if (! sn_irq_info)
+ return -ENOMEM;
+
+ status = sn_intr_alloc(nasid, widget, sn_irq_info, vector, -1, -1);
+ if (status) {
+ kfree(sn_irq_info);
+ return -ENOMEM;
+ }
+
+ sn_irq_info->irq_int_bit = -1; /* mark this as an MSI irq */
+ sn_irq_fixup(pdev, sn_irq_info);
+
+ /* Prom probably should fill these in, but doesn't ... */
+ sn_irq_info->irq_bridge_type = bussoft->bs_asic_type;
+ sn_irq_info->irq_bridge = (void *)bussoft->bs_base;
+
/*
- * return error until MSI is supported on altix platforms
+ * Map the xio address into bus space
*/
- return -EINVAL;
+ bus_addr = (*provider->dma_map_consistent)(pdev,
+ sn_irq_info->irq_xtalkaddr,
+ sizeof(sn_irq_info->irq_xtalkaddr),
+ SN_DMA_MSI|SN_DMA_ADDR_XIO);
+ if (! bus_addr) {
+ sn_intr_free(nasid, widget, sn_irq_info);
+ kfree(sn_irq_info);
+ return -ENOMEM;
+ }
+
+ sn_msi_info[vector].sn_irq_info = sn_irq_info;
+ sn_msi_info[vector].pci_addr = bus_addr;
+
+ *addr_hi = (u32)(bus_addr >> 32);
+ *addr_lo = (u32)(bus_addr & 0x00000000ffffffff);
+
+ /*
+ * In the SN platform, bit 16 is a "send vector" bit which
+ * must be present in order to move the vector through the system.
+ */
+ *data = 0x100 + (unsigned int)vector;
+
+#ifdef CONFIG_SMP
+ set_irq_affinity_info((vector & 0xff), sn_irq_info->irq_cpuid, 0);
+#endif
+
+ return 0;
+}
+
+static void
+sn_msi_target(unsigned int vector, unsigned int cpu,
+ u32 *addr_hi, u32 *addr_lo)
+{
+ int slice;
+ nasid_t nasid;
+ u64 bus_addr;
+ struct pci_dev *pdev;
+ struct pcidev_info *sn_pdev;
+ struct sn_irq_info *sn_irq_info;
+ struct sn_irq_info *new_irq_info;
+ struct sn_pcibus_provider *provider;
+
+ sn_irq_info = sn_msi_info[vector].sn_irq_info;
+ if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
+ return;
+
+ /*
+ * Release XIO resources for the old MSI PCI address
+ */
+
+ sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
+ pdev = sn_pdev->pdi_linux_pcidev;
+ provider = SN_PCIDEV_BUSPROVIDER(pdev);
+
+ bus_addr = (u64)(*addr_hi) << 32 | (u64)(*addr_lo);
+ (*provider->dma_unmap)(pdev, bus_addr, PCI_DMA_FROMDEVICE);
+ sn_msi_info[vector].pci_addr = 0;
+
+ nasid = cpuid_to_nasid(cpu);
+ slice = cpuid_to_slice(cpu);
+
+ new_irq_info = sn_retarget_vector(sn_irq_info, nasid, slice);
+ sn_msi_info[vector].sn_irq_info = new_irq_info;
+ if (new_irq_info == NULL)
+ return;
+
+ /*
+ * Map the xio address into bus space
+ */
+
+ bus_addr = (*provider->dma_map_consistent)(pdev,
+ new_irq_info->irq_xtalkaddr,
+ sizeof(new_irq_info->irq_xtalkaddr),
+ SN_DMA_MSI|SN_DMA_ADDR_XIO);
+
+ sn_msi_info[vector].pci_addr = bus_addr;
+ *addr_hi = (u32)(bus_addr >> 32);
+ *addr_lo = (u32)(bus_addr & 0x00000000ffffffff);
+}
+
+struct msi_ops sn_msi_ops = {
+ .setup = sn_msi_setup,
+ .teardown = sn_msi_teardown,
+#ifdef CONFIG_SMP
+ .target = sn_msi_target,
+#endif
+};
+
+int
+sn_msi_init(void)
+{
+ sn_msi_info =
+ kzalloc(sizeof(struct sn_msi_info) * NR_VECTORS, GFP_KERNEL);
+ if (! sn_msi_info)
+ return -ENOMEM;
+
+ msi_register(&sn_msi_ops);
+ return 0;
}
^ permalink raw reply
* [PATCH 2/3] per-platform IA64_{FIRST,LAST}_DEVICE_VECTOR definitions
From: Mark Maule @ 2006-03-21 14:34 UTC (permalink / raw)
To: linuxppc64-dev, linux-pci, linux-ia64, linux-kernel
Cc: j-nomura, Mark Maule, Tony Luck, gregkh
In-Reply-To: <20060321143444.9913.48372.11324@lnx-maule.americas.sgi.com>
Abstract IA64_FIRST_DEVICE_VECTOR/IA64_LAST_DEVICE_VECTOR since SN platforms
use a subset of the IA64 range. Implement this by making the above macros
global variables which the platform can override in it setup code.
Also add a reserve_irq_vector() routine used by SN to mark a vector's as
in-use when that weren't allocated through assign_irq_vector().
Signed-off-by: Mark Maule <maule@sgi.com>
Index: linux-2.6.16/arch/ia64/kernel/irq_ia64.c
===================================================================
--- linux-2.6.16.orig/arch/ia64/kernel/irq_ia64.c 2006-03-20 15:06:59.260807181 -0600
+++ linux-2.6.16/arch/ia64/kernel/irq_ia64.c 2006-03-20 22:06:24.719085314 -0600
@@ -46,6 +46,10 @@
#define IRQ_DEBUG 0
+/* These can be overridden in platform_irq_init */
+int ia64_first_device_vector = IA64_DEF_FIRST_DEVICE_VECTOR;
+int ia64_last_device_vector = IA64_DEF_LAST_DEVICE_VECTOR;
+
/* default base addr of IPI table */
void __iomem *ipi_base_addr = ((void __iomem *)
(__IA64_UNCACHED_OFFSET | IA64_IPI_DEFAULT_BASE_ADDR));
@@ -60,7 +64,7 @@
};
EXPORT_SYMBOL(isa_irq_to_vector_map);
-static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_NUM_DEVICE_VECTORS)];
+static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_MAX_DEVICE_VECTORS)];
int
assign_irq_vector (int irq)
@@ -89,6 +93,19 @@
printk(KERN_WARNING "%s: double free!\n", __FUNCTION__);
}
+int
+reserve_irq_vector (int vector)
+{
+ int pos;
+
+ if (vector < IA64_FIRST_DEVICE_VECTOR ||
+ vector > IA64_LAST_DEVICE_VECTOR)
+ return -EINVAL;
+
+ pos = vector - IA64_FIRST_DEVICE_VECTOR;
+ return test_and_set_bit(pos, ia64_vector_mask);
+}
+
#ifdef CONFIG_SMP
# define IS_RESCHEDULE(vec) (vec == IA64_IPI_RESCHEDULE)
#else
Index: linux-2.6.16/arch/ia64/sn/kernel/irq.c
===================================================================
--- linux-2.6.16.orig/arch/ia64/sn/kernel/irq.c 2006-03-20 15:06:59.260807181 -0600
+++ linux-2.6.16/arch/ia64/sn/kernel/irq.c 2006-03-21 07:17:34.074494614 -0600
@@ -202,6 +202,9 @@
int i;
irq_desc_t *base_desc = irq_desc;
+ ia64_first_device_vector = IA64_SN2_FIRST_DEVICE_VECTOR;
+ ia64_last_device_vector = IA64_SN2_LAST_DEVICE_VECTOR;
+
for (i = 0; i < NR_IRQS; i++) {
if (base_desc[i].handler == &no_irq_type) {
base_desc[i].handler = &irq_type_sn;
@@ -285,6 +288,7 @@
/* link it into the sn_irq[irq] list */
spin_lock(&sn_irq_info_lock);
list_add_rcu(&sn_irq_info->list, sn_irq_lh[sn_irq_info->irq_irq]);
+ reserve_irq_vector(sn_irq_info->irq_irq);
spin_unlock(&sn_irq_info_lock);
register_intr_pda(sn_irq_info);
@@ -310,8 +314,11 @@
spin_lock(&sn_irq_info_lock);
list_del_rcu(&sn_irq_info->list);
spin_unlock(&sn_irq_info_lock);
+ if (list_empty(sn_irq_lh[sn_irq_info->irq_irq]))
+ free_irq_vector(sn_irq_info->irq_irq);
call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
pci_dev_put(pci_dev);
+
}
static inline void
Index: linux-2.6.16/include/asm-ia64/hw_irq.h
===================================================================
--- linux-2.6.16.orig/include/asm-ia64/hw_irq.h 2006-03-20 15:06:59.260807181 -0600
+++ linux-2.6.16/include/asm-ia64/hw_irq.h 2006-03-20 22:06:25.161425498 -0600
@@ -47,9 +47,19 @@
#define IA64_CMC_VECTOR 0x1f /* corrected machine-check interrupt vector */
/*
* Vectors 0x20-0x2f are reserved for legacy ISA IRQs.
+ * Use vectors 0x30-0xe7 as the default device vector range for ia64.
+ * Platforms may choose to reduce this range in platform_irq_setup, but the
+ * platform range must fall within
+ * [IA64_DEF_FIRST_DEVICE_VECTOR..IA64_DEF_LAST_DEVICE_VECTOR]
*/
-#define IA64_FIRST_DEVICE_VECTOR 0x30
-#define IA64_LAST_DEVICE_VECTOR 0xe7
+extern int ia64_first_device_vector;
+extern int ia64_last_device_vector;
+
+#define IA64_DEF_FIRST_DEVICE_VECTOR 0x30
+#define IA64_DEF_LAST_DEVICE_VECTOR 0xe7
+#define IA64_FIRST_DEVICE_VECTOR ia64_first_device_vector
+#define IA64_LAST_DEVICE_VECTOR ia64_last_device_vector
+#define IA64_MAX_DEVICE_VECTORS (IA64_DEF_LAST_DEVICE_VECTOR - IA64_DEF_FIRST_DEVICE_VECTOR + 1)
#define IA64_NUM_DEVICE_VECTORS (IA64_LAST_DEVICE_VECTOR - IA64_FIRST_DEVICE_VECTOR + 1)
#define IA64_MCA_RENDEZ_VECTOR 0xe8 /* MCA rendez interrupt */
@@ -83,6 +93,7 @@
extern int assign_irq_vector (int irq); /* allocate a free vector */
extern void free_irq_vector (int vector);
+extern int reserve_irq_vector (int vector);
extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect);
extern void register_percpu_irq (ia64_vector vec, struct irqaction *action);
Index: linux-2.6.16/drivers/pci/msi.c
===================================================================
--- linux-2.6.16.orig/drivers/pci/msi.c 2006-03-20 22:01:01.802923681 -0600
+++ linux-2.6.16/drivers/pci/msi.c 2006-03-20 22:06:25.218060665 -0600
@@ -35,7 +35,7 @@
#ifndef CONFIG_X86_IO_APIC
int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1};
-u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 };
+u8 irq_vector[NR_IRQ_VECTORS];
#endif
static struct msi_ops *msi_ops;
@@ -379,6 +379,11 @@
printk(KERN_WARNING "PCI: MSI cache init failed\n");
return status;
}
+
+#ifndef CONFIG_X86_IO_APIC
+ irq_vector[0] = FIRST_DEVICE_VECTOR;
+#endif
+
last_alloc_vector = assign_irq_vector(AUTO_ASSIGN);
if (last_alloc_vector < 0) {
pci_msi_enable = 0;
^ permalink raw reply
* [PATCH 1/3] msi vector targeting abstractions
From: Mark Maule @ 2006-03-21 14:34 UTC (permalink / raw)
To: linuxppc64-dev, linux-pci, linux-ia64, linux-kernel
Cc: j-nomura, Mark Maule, Tony Luck, gregkh
In-Reply-To: <20060321143444.9913.48372.11324@lnx-maule.americas.sgi.com>
Abstract portions of the MSI core for platforms that do not use standard
APIC interrupt controllers. This is implemented through a new arch-specific
msi setup routine, and a set of msi ops which can be set on a per platform
basis.
Signed-off-by: Mark Maule <maule@sgi.com>
Index: linux-2.6.16/drivers/pci/msi.c
===================================================================
--- linux-2.6.16.orig/drivers/pci/msi.c 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16/drivers/pci/msi.c 2006-03-21 07:17:39.987000963 -0600
@@ -23,8 +23,6 @@
#include "pci.h"
#include "msi.h"
-#define MSI_TARGET_CPU first_cpu(cpu_online_map)
-
static DEFINE_SPINLOCK(msi_lock);
static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL };
static kmem_cache_t* msi_cachep;
@@ -40,6 +38,15 @@
u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 };
#endif
+static struct msi_ops *msi_ops;
+
+int
+msi_register(struct msi_ops *ops)
+{
+ msi_ops = ops;
+ return 0;
+}
+
static void msi_cache_ctor(void *p, kmem_cache_t *cache, unsigned long flags)
{
memset(p, 0, NR_IRQS * sizeof(struct msi_desc));
@@ -92,7 +99,7 @@
static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
{
struct msi_desc *entry;
- struct msg_address address;
+ u32 address_hi, address_lo;
unsigned int irq = vector;
unsigned int dest_cpu = first_cpu(cpu_mask);
@@ -108,28 +115,36 @@
if (!(pos = pci_find_capability(entry->dev, PCI_CAP_ID_MSI)))
return;
+ pci_read_config_dword(entry->dev, msi_upper_address_reg(pos),
+ &address_hi);
pci_read_config_dword(entry->dev, msi_lower_address_reg(pos),
- &address.lo_address.value);
- address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK;
- address.lo_address.value |= (cpu_physical_id(dest_cpu) <<
- MSI_TARGET_CPU_SHIFT);
- entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu);
+ &address_lo);
+
+ msi_ops->target(vector, dest_cpu, &address_hi, &address_lo);
+
+ pci_write_config_dword(entry->dev, msi_upper_address_reg(pos),
+ address_hi);
pci_write_config_dword(entry->dev, msi_lower_address_reg(pos),
- address.lo_address.value);
+ address_lo);
set_native_irq_info(irq, cpu_mask);
break;
}
case PCI_CAP_ID_MSIX:
{
- int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
- PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET;
+ int offset_hi =
+ entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
+ PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET;
+ int offset_lo =
+ entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
+ PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET;
+
+ address_hi = readl(entry->mask_base + offset_hi);
+ address_lo = readl(entry->mask_base + offset_lo);
- address.lo_address.value = readl(entry->mask_base + offset);
- address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK;
- address.lo_address.value |= (cpu_physical_id(dest_cpu) <<
- MSI_TARGET_CPU_SHIFT);
- entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu);
- writel(address.lo_address.value, entry->mask_base + offset);
+ msi_ops->target(vector, dest_cpu, &address_hi, &address_lo);
+
+ writel(address_hi, entry->mask_base + offset_hi);
+ writel(address_lo, entry->mask_base + offset_lo);
set_native_irq_info(irq, cpu_mask);
break;
}
@@ -251,30 +266,6 @@
.set_affinity = set_msi_affinity
};
-static void msi_data_init(struct msg_data *msi_data,
- unsigned int vector)
-{
- memset(msi_data, 0, sizeof(struct msg_data));
- msi_data->vector = (u8)vector;
- msi_data->delivery_mode = MSI_DELIVERY_MODE;
- msi_data->level = MSI_LEVEL_MODE;
- msi_data->trigger = MSI_TRIGGER_MODE;
-}
-
-static void msi_address_init(struct msg_address *msi_address)
-{
- unsigned int dest_id;
- unsigned long dest_phys_id = cpu_physical_id(MSI_TARGET_CPU);
-
- memset(msi_address, 0, sizeof(struct msg_address));
- msi_address->hi_address = (u32)0;
- dest_id = (MSI_ADDRESS_HEADER << MSI_ADDRESS_HEADER_SHIFT);
- msi_address->lo_address.u.dest_mode = MSI_PHYSICAL_MODE;
- msi_address->lo_address.u.redirection_hint = MSI_REDIRECTION_HINT_MODE;
- msi_address->lo_address.u.dest_id = dest_id;
- msi_address->lo_address.value |= (dest_phys_id << MSI_TARGET_CPU_SHIFT);
-}
-
static int msi_free_vector(struct pci_dev* dev, int vector, int reassign);
static int assign_msi_vector(void)
{
@@ -369,6 +360,20 @@
return status;
}
+ if ((status = msi_arch_init()) < 0) {
+ pci_msi_enable = 0;
+ printk(KERN_WARNING
+ "PCI: MSI arch init failed. MSI disabled.\n");
+ return status;
+ }
+
+ if (! msi_ops) {
+ printk(KERN_WARNING
+ "PCI: MSI ops not registered. MSI disabled.\n");
+ status = -EINVAL;
+ return status;
+ }
+
if ((status = msi_cache_init()) < 0) {
pci_msi_enable = 0;
printk(KERN_WARNING "PCI: MSI cache init failed\n");
@@ -514,9 +519,11 @@
**/
static int msi_capability_init(struct pci_dev *dev)
{
+ int status;
struct msi_desc *entry;
- struct msg_address address;
- struct msg_data data;
+ u32 address_lo;
+ u32 address_hi;
+ u32 data;
int pos, vector;
u16 control;
@@ -543,23 +550,27 @@
entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos,
is_64bit_address(control));
}
+ /* Configure MSI capability structure */
+ status = msi_ops->setup(dev, vector,
+ &address_hi,
+ &address_lo,
+ &data);
+ if (status < 0) {
+ dev->irq = entry->msi_attrib.default_vector;
+ kmem_cache_free(msi_cachep, entry);
+ return status;
+ }
/* Replace with MSI handler */
irq_handler_init(PCI_CAP_ID_MSI, vector, entry->msi_attrib.maskbit);
- /* Configure MSI capability structure */
- msi_address_init(&address);
- msi_data_init(&data, vector);
- entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
- MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
- pci_write_config_dword(dev, msi_lower_address_reg(pos),
- address.lo_address.value);
+
+ pci_write_config_dword(dev, msi_lower_address_reg(pos), address_lo);
if (is_64bit_address(control)) {
pci_write_config_dword(dev,
- msi_upper_address_reg(pos), address.hi_address);
- pci_write_config_word(dev,
- msi_data_reg(pos, 1), *((u32*)&data));
+ msi_upper_address_reg(pos), address_hi);
+ pci_write_config_word(dev, msi_data_reg(pos, 1), data);
} else
- pci_write_config_word(dev,
- msi_data_reg(pos, 0), *((u32*)&data));
+ pci_write_config_word(dev, msi_data_reg(pos, 0), data);
+
if (entry->msi_attrib.maskbit) {
unsigned int maskbits, temp;
/* All MSIs are unmasked by default, Mask them all */
@@ -594,13 +605,15 @@
struct msix_entry *entries, int nvec)
{
struct msi_desc *head = NULL, *tail = NULL, *entry = NULL;
- struct msg_address address;
- struct msg_data data;
+ u32 address_hi;
+ u32 address_lo;
+ u32 data;
int vector, pos, i, j, nr_entries, temp = 0;
u32 phys_addr, table_offset;
u16 control;
u8 bir;
void __iomem *base;
+ int status;
pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
/* Request & Map MSI-X table region */
@@ -647,18 +660,20 @@
/* Replace with MSI-X handler */
irq_handler_init(PCI_CAP_ID_MSIX, vector, 1);
/* Configure MSI-X capability structure */
- msi_address_init(&address);
- msi_data_init(&data, vector);
- entry->msi_attrib.current_cpu =
- ((address.lo_address.u.dest_id >>
- MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
- writel(address.lo_address.value,
+ status = msi_ops->setup(dev, vector,
+ &address_hi,
+ &address_lo,
+ &data);
+ if (status < 0)
+ break;
+
+ writel(address_lo,
base + j * PCI_MSIX_ENTRY_SIZE +
PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
- writel(address.hi_address,
+ writel(address_hi,
base + j * PCI_MSIX_ENTRY_SIZE +
PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
- writel(*(u32*)&data,
+ writel(data,
base + j * PCI_MSIX_ENTRY_SIZE +
PCI_MSIX_ENTRY_DATA_OFFSET);
attach_msi_entry(entry, vector);
@@ -793,6 +808,8 @@
void __iomem *base;
unsigned long flags;
+ msi_ops->teardown(vector);
+
spin_lock_irqsave(&msi_lock, flags);
entry = msi_desc[vector];
if (!entry || entry->dev != dev) {
Index: linux-2.6.16/include/asm-i386/msi.h
===================================================================
--- linux-2.6.16.orig/include/asm-i386/msi.h 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16/include/asm-i386/msi.h 2006-03-20 14:45:09.540950385 -0600
@@ -12,4 +12,12 @@
#define LAST_DEVICE_VECTOR 232
#define MSI_TARGET_CPU_SHIFT 12
+extern struct msi_ops msi_apic_ops;
+
+static inline int msi_arch_init(void)
+{
+ msi_register(&msi_apic_ops);
+ return 0;
+}
+
#endif /* ASM_MSI_H */
Index: linux-2.6.16/include/asm-x86_64/msi.h
===================================================================
--- linux-2.6.16.orig/include/asm-x86_64/msi.h 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16/include/asm-x86_64/msi.h 2006-03-20 14:45:09.542903318 -0600
@@ -13,4 +13,12 @@
#define LAST_DEVICE_VECTOR 232
#define MSI_TARGET_CPU_SHIFT 12
+extern struct msi_ops msi_apic_ops;
+
+static inline int msi_arch_init(void)
+{
+ msi_register(&msi_apic_ops);
+ return 0;
+}
+
#endif /* ASM_MSI_H */
Index: linux-2.6.16/include/asm-ia64/machvec.h
===================================================================
--- linux-2.6.16.orig/include/asm-ia64/machvec.h 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16/include/asm-ia64/machvec.h 2006-03-20 14:49:38.415888062 -0600
@@ -74,6 +74,7 @@
typedef unsigned short ia64_mv_readw_relaxed_t (const volatile void __iomem *);
typedef unsigned int ia64_mv_readl_relaxed_t (const volatile void __iomem *);
typedef unsigned long ia64_mv_readq_relaxed_t (const volatile void __iomem *);
+typedef int ia64_mv_msi_init_t (void);
static inline void
machvec_noop (void)
@@ -146,6 +147,7 @@
# define platform_readw_relaxed ia64_mv.readw_relaxed
# define platform_readl_relaxed ia64_mv.readl_relaxed
# define platform_readq_relaxed ia64_mv.readq_relaxed
+# define platform_msi_init ia64_mv.msi_init
# endif
/* __attribute__((__aligned__(16))) is required to make size of the
@@ -194,6 +196,7 @@
ia64_mv_readw_relaxed_t *readw_relaxed;
ia64_mv_readl_relaxed_t *readl_relaxed;
ia64_mv_readq_relaxed_t *readq_relaxed;
+ ia64_mv_msi_init_t *msi_init;
} __attribute__((__aligned__(16))); /* align attrib? see above comment */
#define MACHVEC_INIT(name) \
@@ -238,6 +241,7 @@
platform_readw_relaxed, \
platform_readl_relaxed, \
platform_readq_relaxed, \
+ platform_msi_init, \
}
extern struct ia64_machine_vector ia64_mv;
@@ -386,5 +390,8 @@
#ifndef platform_readq_relaxed
# define platform_readq_relaxed __ia64_readq_relaxed
#endif
+#ifndef platform_msi_init
+# define platform_msi_init NULL
+#endif
#endif /* _ASM_IA64_MACHVEC_H */
Index: linux-2.6.16/include/asm-ia64/machvec_sn2.h
===================================================================
--- linux-2.6.16.orig/include/asm-ia64/machvec_sn2.h 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16/include/asm-ia64/machvec_sn2.h 2006-03-20 14:45:09.548762117 -0600
@@ -66,6 +66,7 @@
extern ia64_mv_dma_sync_sg_for_device sn_dma_sync_sg_for_device;
extern ia64_mv_dma_mapping_error sn_dma_mapping_error;
extern ia64_mv_dma_supported sn_dma_supported;
+extern ia64_mv_msi_init_t sn_msi_init;
/*
* This stuff has dual use!
@@ -115,6 +116,11 @@
#define platform_dma_sync_sg_for_device sn_dma_sync_sg_for_device
#define platform_dma_mapping_error sn_dma_mapping_error
#define platform_dma_supported sn_dma_supported
+#ifdef CONFIG_PCI_MSI
+#define platform_msi_init sn_msi_init
+#else
+#define platform_msi_init NULL
+#endif
#include <asm/sn/io.h>
Index: linux-2.6.16/include/asm-ia64/msi.h
===================================================================
--- linux-2.6.16.orig/include/asm-ia64/msi.h 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16/include/asm-ia64/msi.h 2006-03-20 14:50:53.331368084 -0600
@@ -14,4 +14,16 @@
#define ack_APIC_irq ia64_eoi
#define MSI_TARGET_CPU_SHIFT 4
+extern struct msi_ops msi_apic_ops;
+
+static inline int msi_arch_init(void)
+{
+ if (platform_msi_init)
+ return platform_msi_init();
+
+ /* default ops for most ia64 platforms */
+ msi_register(&msi_apic_ops);
+ return 0;
+}
+
#endif /* ASM_MSI_H */
Index: linux-2.6.16/drivers/pci/Makefile
===================================================================
--- linux-2.6.16.orig/drivers/pci/Makefile 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16/drivers/pci/Makefile 2006-03-20 22:00:54.079057888 -0600
@@ -26,7 +26,11 @@
obj-$(CONFIG_PPC64) += setup-bus.o
obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
obj-$(CONFIG_X86_VISWS) += setup-irq.o
-obj-$(CONFIG_PCI_MSI) += msi.o
+
+msiobj-y := msi.o msi-apic.o
+msiobj-$(CONFIG_IA64_GENERIC) += msi-altix.o
+msiobj-$(CONFIG_IA64_SGI_SN2) += msi-altix.o
+obj-$(CONFIG_PCI_MSI) += $(msiobj-y)
#
# ACPI Related PCI FW Functions
Index: linux-2.6.16/drivers/pci/msi-apic.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16/drivers/pci/msi-apic.c 2006-03-20 22:01:01.802923681 -0600
@@ -0,0 +1,100 @@
+/*
+ * MSI hooks for standard x86 apic
+ */
+
+#include <linux/pci.h>
+#include <linux/irq.h>
+
+#include "msi.h"
+
+/*
+ * Shifts for APIC-based data
+ */
+
+#define MSI_DATA_VECTOR_SHIFT 0
+#define MSI_DATA_VECTOR(v) (((u8)v) << MSI_DATA_VECTOR_SHIFT)
+
+#define MSI_DATA_DELIVERY_SHIFT 8
+#define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_SHIFT)
+#define MSI_DATA_DELIVERY_LOWPRI (1 << MSI_DATA_DELIVERY_SHIFT)
+
+#define MSI_DATA_LEVEL_SHIFT 14
+#define MSI_DATA_LEVEL_DEASSERT (0 << MSI_DATA_LEVEL_SHIFT)
+#define MSI_DATA_LEVEL_ASSERT (1 << MSI_DATA_LEVEL_SHIFT)
+
+#define MSI_DATA_TRIGGER_SHIFT 15
+#define MSI_DATA_TRIGGER_EDGE (0 << MSI_DATA_TRIGGER_SHIFT)
+#define MSI_DATA_TRIGGER_LEVEL (1 << MSI_DATA_TRIGGER_SHIFT)
+
+/*
+ * Shift/mask fields for APIC-based bus address
+ */
+
+#define MSI_ADDR_HEADER 0xfee00000
+
+#define MSI_ADDR_DESTID_MASK 0xfff0000f
+#define MSI_ADDR_DESTID_CPU(cpu) ((cpu) << MSI_TARGET_CPU_SHIFT)
+
+#define MSI_ADDR_DESTMODE_SHIFT 2
+#define MSI_ADDR_DESTMODE_PHYS (0 << MSI_ADDR_DESTMODE_SHIFT)
+#define MSI_ADDR_DESTMODE_LOGIC (1 << MSI_ADDR_DESTMODE_SHIFT)
+
+#define MSI_ADDR_REDIRECTION_SHIFT 3
+#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT)
+#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT)
+
+
+static void
+msi_target_apic(unsigned int vector,
+ unsigned int dest_cpu,
+ u32 *address_hi, /* in/out */
+ u32 *address_lo) /* in/out */
+{
+ u32 addr = *address_lo;
+
+ addr &= MSI_ADDR_DESTID_MASK;
+ addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(dest_cpu));
+
+ *address_lo = addr;
+}
+
+static int
+msi_setup_apic(struct pci_dev *pdev, /* unused in generic */
+ unsigned int vector,
+ u32 *address_hi,
+ u32 *address_lo,
+ u32 *data)
+{
+ unsigned long dest_phys_id;
+
+ dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map));
+
+ *address_hi = 0;
+ *address_lo = MSI_ADDR_HEADER |
+ MSI_ADDR_DESTMODE_PHYS |
+ MSI_ADDR_REDIRECTION_CPU |
+ MSI_ADDR_DESTID_CPU(dest_phys_id);
+
+ *data = MSI_DATA_TRIGGER_EDGE |
+ MSI_DATA_LEVEL_ASSERT |
+ MSI_DATA_DELIVERY_FIXED |
+ MSI_DATA_VECTOR(vector);
+
+ return 0;
+}
+
+static void
+msi_teardown_apic(unsigned int vector)
+{
+ return; /* no-op */
+}
+
+/*
+ * Generic ops used on most IA archs/platforms. Set with msi_register()
+ */
+
+struct msi_ops msi_apic_ops = {
+ .setup = msi_setup_apic,
+ .teardown = msi_teardown_apic,
+ .target = msi_target_apic,
+};
Index: linux-2.6.16/drivers/pci/msi.h
===================================================================
--- linux-2.6.16.orig/drivers/pci/msi.h 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16/drivers/pci/msi.h 2006-03-20 14:55:40.935888578 -0600
@@ -6,6 +6,68 @@
#ifndef MSI_H
#define MSI_H
+/*
+ * MSI operation vector. Used by the msi core code (drivers/pci/msi.c)
+ * to abstract platform-specific tasks relating to MSI address generation
+ * and resource management.
+ */
+struct msi_ops {
+ /**
+ * setup - generate an MSI bus address and data for a given vector
+ * @pdev: PCI device context (in)
+ * @vector: vector allocated by the msi core (in)
+ * @addr_hi: upper 32 bits of PCI bus MSI address (out)
+ * @addr_lo: lower 32 bits of PCI bus MSI address (out)
+ * @data: MSI data payload (out)
+ *
+ * Description: The setup op is used to generate a PCI bus addres and
+ * data which the msi core will program into the card MSI capability
+ * registers. The setup routine is responsible for picking an initial
+ * cpu to target the MSI at. The setup routine is responsible for
+ * examining pdev to determine the MSI capabilities of the card and
+ * generating a suitable address/data. The setup routine is
+ * responsible for allocating and tracking any system resources it
+ * needs to route the MSI to the cpu it picks, and for associating
+ * those resources with the passed in vector.
+ *
+ * Returns 0 if the MSI address/data was successfully setup.
+ **/
+
+ int (*setup) (struct pci_dev *pdev, unsigned int vector,
+ u32 *addr_hi, u32 *addr_lo, u32 *data);
+
+ /**
+ * teardown - release resources allocated by setup
+ * @vector: vector context for resources (in)
+ *
+ * Description: The teardown op is used to release any resources
+ * that were allocated in the setup routine associated with the passed
+ * in vector.
+ **/
+
+ void (*teardown) (unsigned int vector);
+
+ /**
+ * target - retarget an MSI at a different cpu
+ * @vector: vector context for resources (in)
+ * @cpu: new cpu to direct vector at (in)
+ * @addr_hi: new value of PCI bus upper 32 bits (in/out)
+ * @addr_lo: new value of PCI bus lower 32 bits (in/out)
+ *
+ * Description: The target op is used to redirect an MSI vector
+ * at a different cpu. addr_hi/addr_lo coming in are the existing
+ * values that the MSI core has programmed into the card. The
+ * target code is responsible for freeing any resources (if any)
+ * associated with the old address, and generating a new PCI bus
+ * addr_hi/addr_lo that will redirect the vector at the indicated cpu.
+ **/
+
+ void (*target) (unsigned int vector, unsigned int cpu,
+ u32 *addr_hi, u32 *addr_lo);
+};
+
+extern int msi_register(struct msi_ops *ops);
+
#include <asm/msi.h>
/*
@@ -63,67 +125,6 @@
#define msix_mask(address) (address | PCI_MSIX_FLAGS_BITMASK)
#define msix_is_pending(address) (address & PCI_MSIX_FLAGS_PENDMASK)
-/*
- * MSI Defined Data Structures
- */
-#define MSI_ADDRESS_HEADER 0xfee
-#define MSI_ADDRESS_HEADER_SHIFT 12
-#define MSI_ADDRESS_HEADER_MASK 0xfff000
-#define MSI_ADDRESS_DEST_ID_MASK 0xfff0000f
-#define MSI_TARGET_CPU_MASK 0xff
-#define MSI_DELIVERY_MODE 0
-#define MSI_LEVEL_MODE 1 /* Edge always assert */
-#define MSI_TRIGGER_MODE 0 /* MSI is edge sensitive */
-#define MSI_PHYSICAL_MODE 0
-#define MSI_LOGICAL_MODE 1
-#define MSI_REDIRECTION_HINT_MODE 0
-
-struct msg_data {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
- __u32 vector : 8;
- __u32 delivery_mode : 3; /* 000b: FIXED | 001b: lowest prior */
- __u32 reserved_1 : 3;
- __u32 level : 1; /* 0: deassert | 1: assert */
- __u32 trigger : 1; /* 0: edge | 1: level */
- __u32 reserved_2 : 16;
-#elif defined(__BIG_ENDIAN_BITFIELD)
- __u32 reserved_2 : 16;
- __u32 trigger : 1; /* 0: edge | 1: level */
- __u32 level : 1; /* 0: deassert | 1: assert */
- __u32 reserved_1 : 3;
- __u32 delivery_mode : 3; /* 000b: FIXED | 001b: lowest prior */
- __u32 vector : 8;
-#else
-#error "Bitfield endianness not defined! Check your byteorder.h"
-#endif
-} __attribute__ ((packed));
-
-struct msg_address {
- union {
- struct {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
- __u32 reserved_1 : 2;
- __u32 dest_mode : 1; /*0:physic | 1:logic */
- __u32 redirection_hint: 1; /*0: dedicated CPU
- 1: lowest priority */
- __u32 reserved_2 : 4;
- __u32 dest_id : 24; /* Destination ID */
-#elif defined(__BIG_ENDIAN_BITFIELD)
- __u32 dest_id : 24; /* Destination ID */
- __u32 reserved_2 : 4;
- __u32 redirection_hint: 1; /*0: dedicated CPU
- 1: lowest priority */
- __u32 dest_mode : 1; /*0:physic | 1:logic */
- __u32 reserved_1 : 2;
-#else
-#error "Bitfield endianness not defined! Check your byteorder.h"
-#endif
- }u;
- __u32 value;
- }lo_address;
- __u32 hi_address;
-} __attribute__ ((packed));
-
struct msi_desc {
struct {
__u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */
@@ -132,7 +133,7 @@
__u8 reserved: 1; /* reserved */
__u8 entry_nr; /* specific enabled entry */
__u8 default_vector; /* default pre-assigned vector */
- __u8 current_cpu; /* current destination cpu */
+ __u8 unused; /* formerly unused destination cpu*/
}msi_attrib;
struct {
Index: linux-2.6.16/drivers/pci/msi-altix.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16/drivers/pci/msi-altix.c 2006-03-21 07:17:34.077424014 -0600
@@ -0,0 +1,18 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved.
+ */
+
+#include <asm/errno.h>
+
+int
+sn_msi_init(void)
+{
+ /*
+ * return error until MSI is supported on altix platforms
+ */
+ return -EINVAL;
+}
^ permalink raw reply
* [PATCH 0/3] msi abstractions and support for altix
From: Mark Maule @ 2006-03-21 14:34 UTC (permalink / raw)
To: linuxppc64-dev, linux-pci, linux-ia64, linux-kernel
Cc: j-nomura, Mark Maule, Tony Luck, gregkh
Resend #6: resubmit against 2.6.16 base
Patch set to abstract portions of the MSI core so that it can be used on
architectures which don't use standard interrupt controllers.
Changes from Resend #5
+ Move altix msi ops down into drivers/pci/msi-altix.c
+ Simplify ia64 platform_msi_init machvec
Changes from Resend #4
+ Fix an x86_64 build problem
+ Fix an ia64 CONFIG_IA64_GENERIC build problem
+ Fix a bug in the new ia64 reserve_irq_vector()
+ Restore dev->irq if msi_ops->setup fails
+ Redo msi-altix.patch so it applies on 2.6.16-rc1
Changes from Resend #3
+ Move external declarations of msi_apic_ops out of routines, and up earlier
in the respective .h files.
+ Add comments to the msi_ops structure declaration
Changes from Resend #2
+ Cleanup the ia64 platform_msi_init macro so it works on non-altix ia64
Changes from initial version
+ Change uintXX_t to uXX
+ Change _callouts to _ops
+ Renamed the _generic routines to _apic and moved them to a new file
msi-apic.c
+ Have each msi_arch_init() routine call msi_register() with the desired
msi ops for that platform.
+ Moved msi_address, msi_data, and related defs out of msi.h and into
msi-apic.c, replaced by shifts/masks.
+ Rolled msi-arch-init.patch and msi-callouts.patch into a single msi-ops.patch
Mark
1/3 msi-ops.patch
Add an msi_arch_init() hook which can be used to perform platform
specific setup prior to msi use.
Define a set of msi ops to implement the platform-specific tasks:
setup - set up plumbing to get a vector directed at a default
cpu, and return the corresponding MSI bus address and data.
teardown - inverse of msi_setup
target - retarget a vector to a given cpu
Define the routine msi_register() called from msi_arch_init()
to set the desired ops.
Move a bunch of apic-specific code out of the msi core .h/.c and
into a new msi-apic.c file.
2/3 ia64-per-platform-device-vector.patch
For the ia64 arch, allow per-platform definitions of
IA64_FIRST_DEVICE_VECTOR and IA64_LAST_DEVICE_VECTOR.
3/3 msi-altix.patch
Altix specific callouts to implement MSI.
^ permalink raw reply
* VLAN support on TSEC for MPC8541
From: Bizhan Gholikhamseh (bgholikh) @ 2006-03-21 14:04 UTC (permalink / raw)
To: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 178 bytes --]
Hi All,
I have asked this question in past with no response. Are there any VLAN
implementation of TSEC driver for MPC8541 (with CPM core)?
Many thanks in advance,
Bizhan
[-- Attachment #2: Type: text/html, Size: 826 bytes --]
^ permalink raw reply
* [PATCH 11/11] powerpc: Remove calculation of io hole
From: Michael Ellerman @ 2006-03-21 9:46 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <1142934351.193140.181086235013.qpush@concordia>
In mm_init_ppc64() we calculate the location of the "IO hole", but then
no one ever looks at the value. So don't bother.
That's actually all mm_init_ppc64() does, so get rid of it too.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/kernel/setup_64.c | 2 -
arch/powerpc/mm/init_64.c | 48 -----------------------------------------
include/asm-powerpc/lmb.h | 2 -
include/asm-powerpc/mmu.h | 1
4 files changed, 53 deletions(-)
Index: to-merge/arch/powerpc/kernel/setup_64.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/setup_64.c
+++ to-merge/arch/powerpc/kernel/setup_64.c
@@ -497,8 +497,6 @@ void __init setup_system(void)
#endif
printk("-----------------------------------------------------\n");
- mm_init_ppc64();
-
DBG(" <- setup_system()\n");
}
Index: to-merge/arch/powerpc/mm/init_64.c
===================================================================
--- to-merge.orig/arch/powerpc/mm/init_64.c
+++ to-merge/arch/powerpc/mm/init_64.c
@@ -84,54 +84,6 @@
/* max amount of RAM to use */
unsigned long __max_memory;
-/* info on what we think the IO hole is */
-unsigned long io_hole_start;
-unsigned long io_hole_size;
-
-/*
- * Do very early mm setup.
- */
-void __init mm_init_ppc64(void)
-{
-#ifndef CONFIG_PPC_ISERIES
- unsigned long i;
-#endif
-
- ppc64_boot_msg(0x100, "MM Init");
-
- /* This is the story of the IO hole... please, keep seated,
- * unfortunately, we are out of oxygen masks at the moment.
- * So we need some rough way to tell where your big IO hole
- * is. On pmac, it's between 2G and 4G, on POWER3, it's around
- * that area as well, on POWER4 we don't have one, etc...
- * We need that as a "hint" when sizing the TCE table on POWER3
- * So far, the simplest way that seem work well enough for us it
- * to just assume that the first discontinuity in our physical
- * RAM layout is the IO hole. That may not be correct in the future
- * (and isn't on iSeries but then we don't care ;)
- */
-
-#ifndef CONFIG_PPC_ISERIES
- for (i = 1; i < lmb.memory.cnt; i++) {
- unsigned long base, prevbase, prevsize;
-
- prevbase = lmb.memory.region[i-1].base;
- prevsize = lmb.memory.region[i-1].size;
- base = lmb.memory.region[i].base;
- if (base > (prevbase + prevsize)) {
- io_hole_start = prevbase + prevsize;
- io_hole_size = base - (prevbase + prevsize);
- break;
- }
- }
-#endif /* CONFIG_PPC_ISERIES */
- if (io_hole_start)
- printk("IO Hole assumed to be %lx -> %lx\n",
- io_hole_start, io_hole_start + io_hole_size - 1);
-
- ppc64_boot_msg(0x100, "MM Init Done");
-}
-
void free_initmem(void)
{
unsigned long addr;
Index: to-merge/include/asm-powerpc/lmb.h
===================================================================
--- to-merge.orig/include/asm-powerpc/lmb.h
+++ to-merge/include/asm-powerpc/lmb.h
@@ -54,8 +54,6 @@ extern void __init lmb_enforce_memory_li
extern void lmb_dump_all(void);
-extern unsigned long io_hole_start;
-
static inline unsigned long
lmb_size_bytes(struct lmb_region *type, unsigned long region_nr)
{
Index: to-merge/include/asm-powerpc/mmu.h
===================================================================
--- to-merge.orig/include/asm-powerpc/mmu.h
+++ to-merge/include/asm-powerpc/mmu.h
@@ -236,7 +236,6 @@ extern void htab_initialize_secondary(vo
extern void hpte_init_native(void);
extern void hpte_init_lpar(void);
extern void hpte_init_iSeries(void);
-extern void mm_init_ppc64(void);
extern long pSeries_lpar_hpte_insert(unsigned long hpte_group,
unsigned long va, unsigned long prpn,
^ permalink raw reply
* [PATCH 10/11] powerpc: iseries: Add bootargs to /chosen
From: Michael Ellerman @ 2006-03-21 9:46 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <1142934351.193140.181086235013.qpush@concordia>
Add the command line args to the device tree as /chosen/bootargs.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/iseries/setup.c | 1 +
1 files changed, 1 insertion(+)
Index: to-merge/arch/powerpc/platforms/iseries/setup.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/iseries/setup.c
+++ to-merge/arch/powerpc/platforms/iseries/setup.c
@@ -931,6 +931,7 @@ void build_flat_dt(struct iseries_flat_d
/* /chosen */
dt_start_node(dt, "chosen");
dt_prop_u32(dt, "linux,platform", PLATFORM_ISERIES_LPAR);
+ dt_prop_str(dt, "bootargs", cmd_line);
if (cmd_mem_limit)
dt_prop_u64(dt, "linux,memory-limit", cmd_mem_limit);
dt_end_node(dt);
^ permalink raw reply
* [PATCH 9/11] powerpc: iseries: Add /system-id, /model and /compatible
From: Michael Ellerman @ 2006-03-21 9:46 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <1142934351.193140.181086235013.qpush@concordia>
Add /system-id, /model and /compatible to the iSeries device tree.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/iseries/setup.c | 20 ++++++++++++++++++++
1 files changed, 20 insertions(+)
Index: to-merge/arch/powerpc/platforms/iseries/setup.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/iseries/setup.c
+++ to-merge/arch/powerpc/platforms/iseries/setup.c
@@ -50,6 +50,7 @@
#include <asm/iseries/hv_call_xm.h>
#include <asm/iseries/it_lp_queue.h>
#include <asm/iseries/mf.h>
+#include <asm/iseries/it_exp_vpd_panel.h>
#include <asm/iseries/hv_lp_event.h>
#include <asm/iseries/lpar_map.h>
#include <asm/udbg.h>
@@ -888,6 +889,24 @@ void dt_cpus(struct iseries_flat_dt *dt)
dt_end_node(dt);
}
+void dt_model(struct iseries_flat_dt *dt)
+{
+ char buf[16] = "IBM,";
+
+ /* "IBM," + mfgId[2:3] + systemSerial[1:5] */
+ strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2);
+ strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5);
+ buf[11] = '\0';
+ dt_prop_str(dt, "system-id", buf);
+
+ /* "IBM," + machineType[0:4] */
+ strne2a(buf + 4, xItExtVpdPanel.machineType, 4);
+ buf[8] = '\0';
+ dt_prop_str(dt, "model", buf);
+
+ dt_prop_str(dt, "compatible", "IBM,iSeries");
+}
+
void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size)
{
u64 tmp[2];
@@ -898,6 +917,7 @@ void build_flat_dt(struct iseries_flat_d
dt_prop_u32(dt, "#address-cells", 2);
dt_prop_u32(dt, "#size-cells", 2);
+ dt_model(dt);
/* /memory */
dt_start_node(dt, "memory@0");
^ permalink raw reply
* [PATCH 8/11] powerpc: Add strne2a() to convert a string from EBCDIC to ASCII
From: Michael Ellerman @ 2006-03-21 9:46 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <1142934351.193140.181086235013.qpush@concordia>
Add strne2a() which converts a string from EBCDIC to ASCII.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/lib/e2a.c | 10 ++++++++++
include/asm-powerpc/system.h | 2 ++
2 files changed, 12 insertions(+)
Index: to-merge/arch/powerpc/lib/e2a.c
===================================================================
--- to-merge.orig/arch/powerpc/lib/e2a.c
+++ to-merge/arch/powerpc/lib/e2a.c
@@ -103,4 +103,14 @@ unsigned char e2a(unsigned char x)
}
EXPORT_SYMBOL(e2a);
+unsigned char* strne2a(unsigned char *dest, const unsigned char *src, size_t n)
+{
+ int i;
+ n = strnlen(src, n);
+
+ for (i = 0; i < n; i++)
+ dest[i] = e2a(src[i]);
+
+ return dest;
+}
Index: to-merge/include/asm-powerpc/system.h
===================================================================
--- to-merge.orig/include/asm-powerpc/system.h
+++ to-merge/include/asm-powerpc/system.h
@@ -171,6 +171,8 @@ extern u32 booke_wdt_period;
/* EBCDIC -> ASCII conversion for [0-9A-Z] on iSeries */
extern unsigned char e2a(unsigned char);
+extern unsigned char* strne2a(unsigned char *dest,
+ const unsigned char *src, size_t n);
struct device_node;
extern void note_scsi_host(struct device_node *, void *);
^ permalink raw reply
* [PATCH 7/11] powerpc: iseries: Make more stuff static in platforms/iseries/mf.c
From: Michael Ellerman @ 2006-03-21 9:46 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <1142934351.193140.181086235013.qpush@concordia>
Make mf_get_rtc(), mf_get_boot_rtc() and mf_set_rtc() static, cause they can
be. We need to move mf_set_rtc() to avoid a forward declaration.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/iseries/mf.c | 78 ++++++++++++++++++------------------
include/asm-powerpc/iseries/mf.h | 4 -
2 files changed, 39 insertions(+), 43 deletions(-)
Index: to-merge/arch/powerpc/platforms/iseries/mf.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/iseries/mf.c
+++ to-merge/arch/powerpc/platforms/iseries/mf.c
@@ -706,6 +706,43 @@ static void get_rtc_time_complete(void *
complete(&rtc->com);
}
+static int mf_set_rtc(struct rtc_time *tm)
+{
+ char ce_time[12];
+ u8 day, mon, hour, min, sec, y1, y2;
+ unsigned year;
+
+ year = 1900 + tm->tm_year;
+ y1 = year / 100;
+ y2 = year % 100;
+
+ sec = tm->tm_sec;
+ min = tm->tm_min;
+ hour = tm->tm_hour;
+ day = tm->tm_mday;
+ mon = tm->tm_mon + 1;
+
+ BIN_TO_BCD(sec);
+ BIN_TO_BCD(min);
+ BIN_TO_BCD(hour);
+ BIN_TO_BCD(mon);
+ BIN_TO_BCD(day);
+ BIN_TO_BCD(y1);
+ BIN_TO_BCD(y2);
+
+ memset(ce_time, 0, sizeof(ce_time));
+ ce_time[3] = 0x41;
+ ce_time[4] = y1;
+ ce_time[5] = y2;
+ ce_time[6] = sec;
+ ce_time[7] = min;
+ ce_time[8] = hour;
+ ce_time[10] = day;
+ ce_time[11] = mon;
+
+ return signal_ce_msg(ce_time, NULL);
+}
+
static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm)
{
tm->tm_wday = 0;
@@ -761,7 +798,7 @@ static int rtc_set_tm(int rc, u8 *ce_msg
return 0;
}
-int mf_get_rtc(struct rtc_time *tm)
+static int mf_get_rtc(struct rtc_time *tm)
{
struct ce_msg_comp_data ce_complete;
struct rtc_time_data rtc_data;
@@ -794,7 +831,7 @@ static void get_boot_rtc_time_complete(v
rtc->busy = 0;
}
-int mf_get_boot_rtc(struct rtc_time *tm)
+static int mf_get_boot_rtc(struct rtc_time *tm)
{
struct ce_msg_comp_data ce_complete;
struct boot_rtc_time_data rtc_data;
@@ -816,43 +853,6 @@ int mf_get_boot_rtc(struct rtc_time *tm)
return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);
}
-int mf_set_rtc(struct rtc_time *tm)
-{
- char ce_time[12];
- u8 day, mon, hour, min, sec, y1, y2;
- unsigned year;
-
- year = 1900 + tm->tm_year;
- y1 = year / 100;
- y2 = year % 100;
-
- sec = tm->tm_sec;
- min = tm->tm_min;
- hour = tm->tm_hour;
- day = tm->tm_mday;
- mon = tm->tm_mon + 1;
-
- BIN_TO_BCD(sec);
- BIN_TO_BCD(min);
- BIN_TO_BCD(hour);
- BIN_TO_BCD(mon);
- BIN_TO_BCD(day);
- BIN_TO_BCD(y1);
- BIN_TO_BCD(y2);
-
- memset(ce_time, 0, sizeof(ce_time));
- ce_time[3] = 0x41;
- ce_time[4] = y1;
- ce_time[5] = y2;
- ce_time[6] = sec;
- ce_time[7] = min;
- ce_time[8] = hour;
- ce_time[10] = day;
- ce_time[11] = mon;
-
- return signal_ce_msg(ce_time, NULL);
-}
-
#ifdef CONFIG_PROC_FS
static int proc_mf_dump_cmdline(char *page, char **start, off_t off,
Index: to-merge/include/asm-powerpc/iseries/mf.h
===================================================================
--- to-merge.orig/include/asm-powerpc/iseries/mf.h
+++ to-merge/include/asm-powerpc/iseries/mf.h
@@ -48,8 +48,4 @@ extern void mf_display_progress(u16 valu
extern void mf_init(void);
-extern int mf_get_rtc(struct rtc_time *tm);
-extern int mf_get_boot_rtc(struct rtc_time *tm);
-extern int mf_set_rtc(struct rtc_time *tm);
-
#endif /* _ASM_POWERPC_ISERIES_MF_H */
^ permalink raw reply
* [PATCH 6/11] powerpc: iseries: Remove pointless iSeries_(restart|power_off|halt)
From: Michael Ellerman @ 2006-03-21 9:46 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <1142934351.193140.181086235013.qpush@concordia>
These routines just call through to the mf routines, so point ppc_md straight
at the mf routines. We need to pass the cmd through to mf_reboot to make it
work, but that seems reasonable.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/iseries/mf.c | 2 +-
arch/powerpc/platforms/iseries/setup.c | 30 +++---------------------------
include/asm-powerpc/iseries/mf.h | 2 +-
3 files changed, 5 insertions(+), 29 deletions(-)
Index: to-merge/arch/powerpc/platforms/iseries/mf.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/iseries/mf.c
+++ to-merge/arch/powerpc/platforms/iseries/mf.c
@@ -599,7 +599,7 @@ void mf_power_off(void)
* Global kernel interface to tell the VSP object in the primary
* partition to reboot this partition.
*/
-void mf_reboot(void)
+void mf_reboot(char *cmd)
{
printk(KERN_INFO "mf.c: Preparing to bounce...\n");
signal_ce_msg_simple(0x4e, NULL);
Index: to-merge/arch/powerpc/platforms/iseries/setup.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/iseries/setup.c
+++ to-merge/arch/powerpc/platforms/iseries/setup.c
@@ -554,30 +554,6 @@ static void iSeries_show_cpuinfo(struct
seq_printf(m, "machine\t\t: 64-bit iSeries Logical Partition\n");
}
-/*
- * Document me.
- */
-static void iSeries_restart(char *cmd)
-{
- mf_reboot();
-}
-
-/*
- * Document me.
- */
-static void iSeries_power_off(void)
-{
- mf_power_off();
-}
-
-/*
- * Document me.
- */
-static void iSeries_halt(void)
-{
- mf_power_off();
-}
-
static void __init iSeries_progress(char * st, unsigned short code)
{
printk("Progress: [%04x] - %s\n", (unsigned)code, st);
@@ -716,9 +692,9 @@ struct machdep_calls __initdata iseries_
.get_irq = iSeries_get_irq,
.init_early = iSeries_init_early,
.pcibios_fixup = iSeries_pci_final_fixup,
- .restart = iSeries_restart,
- .power_off = iSeries_power_off,
- .halt = iSeries_halt,
+ .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,
Index: to-merge/include/asm-powerpc/iseries/mf.h
===================================================================
--- to-merge.orig/include/asm-powerpc/iseries/mf.h
+++ to-merge/include/asm-powerpc/iseries/mf.h
@@ -41,7 +41,7 @@ extern void mf_deallocate_lp_events(HvLp
unsigned count, MFCompleteHandler hdlr, void *userToken);
extern void mf_power_off(void);
-extern void mf_reboot(void);
+extern void mf_reboot(char *cmd);
extern void mf_display_src(u32 word);
extern void mf_display_progress(u16 value);
^ permalink raw reply
* [PATCH 5/11] powerpc: iseries: mf related cleanups
From: Michael Ellerman @ 2006-03-21 9:46 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <1142934351.193140.181086235013.qpush@concordia>
Some cleanups in the iSeries code.
- Make mf_display_progress() check mf_initialized rather than the caller.
- Set mf_initialized in mf_init() rather than in setup.c
- Then move mf_initialized into mf.c, the only place it's used.
- Move the mf related logic from iSeries_progress() to mf_display_progress()
- Use a #define to size the pending_event_prealloc array
- Use that define in the initialsation loop rather than sizeof jiggery pokery
- Remove stupid comment(s)
- Mark stuff static and/or __init
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/iseries/mf.c | 32 +++++++++++++++++++++++---------
arch/powerpc/platforms/iseries/setup.c | 11 +----------
include/asm-powerpc/iseries/mf.h | 1 -
3 files changed, 24 insertions(+), 20 deletions(-)
Index: to-merge/arch/powerpc/platforms/iseries/mf.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/iseries/mf.c
+++ to-merge/arch/powerpc/platforms/iseries/mf.c
@@ -46,6 +46,7 @@
#include "setup.h"
extern int piranha_simulator;
+static int mf_initialized = 0;
/*
* This is the structure layout for the Machine Facilites LPAR event
@@ -143,7 +144,8 @@ static spinlock_t pending_event_spinlock
static struct pending_event *pending_event_head;
static struct pending_event *pending_event_tail;
static struct pending_event *pending_event_avail;
-static struct pending_event pending_event_prealloc[16];
+#define PENDING_EVENT_PREALLOC_LEN 16
+static struct pending_event pending_event_prealloc[PENDING_EVENT_PREALLOC_LEN];
/*
* Put a pending event onto the available queue, so it can get reused.
@@ -625,7 +627,7 @@ void mf_display_src(u32 word)
/*
* Display a single word SRC of the form "PROGXXXX" on the VSP control panel.
*/
-void mf_display_progress(u16 value)
+static __init void mf_display_progress_src(u16 value)
{
u8 ce[12];
u8 src[72];
@@ -649,30 +651,42 @@ void mf_display_progress(u16 value)
* Clear the VSP control panel. Used to "erase" an SRC that was
* previously displayed.
*/
-void mf_clear_src(void)
+static void mf_clear_src(void)
{
signal_ce_msg_simple(0x4b, NULL);
}
+void __init mf_display_progress(u16 value)
+{
+ if (piranha_simulator || !mf_initialized)
+ return;
+
+ if (0xFFFF == value)
+ mf_clear_src();
+ else
+ mf_display_progress_src(value);
+}
+
/*
* Initialization code here.
*/
-void mf_init(void)
+void __init mf_init(void)
{
int i;
- /* initialize */
spin_lock_init(&pending_event_spinlock);
- for (i = 0;
- i < sizeof(pending_event_prealloc) / sizeof(*pending_event_prealloc);
- ++i)
+
+ for (i = 0; i < PENDING_EVENT_PREALLOC_LEN; i++)
free_pending_event(&pending_event_prealloc[i]);
+
HvLpEvent_registerHandler(HvLpEvent_Type_MachineFac, &hv_handler);
/* virtual continue ack */
signal_ce_msg_simple(0x57, NULL);
- /* initialization complete */
+ mf_initialized = 1;
+ mb();
+
printk(KERN_NOTICE "mf.c: iSeries Linux LPAR Machine Facilities "
"initialized\n");
}
Index: to-merge/arch/powerpc/platforms/iseries/setup.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/iseries/setup.c
+++ to-merge/arch/powerpc/platforms/iseries/setup.c
@@ -89,8 +89,6 @@ extern unsigned long embedded_sysmap_end
extern unsigned long iSeries_recal_tb;
extern unsigned long iSeries_recal_titan;
-static int mf_initialized;
-
static unsigned long cmd_mem_limit;
struct MemoryBlock {
@@ -347,8 +345,6 @@ static void __init iSeries_init_early(vo
HvCallEvent_setLpEventQueueInterruptProc(0, 0);
mf_init();
- mf_initialized = 1;
- mb();
/* If we were passed an initrd, set the ROOT_DEV properly if the values
* look sensible. If not, clear initrd reference.
@@ -585,12 +581,7 @@ static void iSeries_halt(void)
static void __init iSeries_progress(char * st, unsigned short code)
{
printk("Progress: [%04x] - %s\n", (unsigned)code, st);
- if (!piranha_simulator && mf_initialized) {
- if (code != 0xffff)
- mf_display_progress(code);
- else
- mf_clear_src();
- }
+ mf_display_progress(code);
}
static void __init iSeries_fixup_klimit(void)
Index: to-merge/include/asm-powerpc/iseries/mf.h
===================================================================
--- to-merge.orig/include/asm-powerpc/iseries/mf.h
+++ to-merge/include/asm-powerpc/iseries/mf.h
@@ -45,7 +45,6 @@ extern void mf_reboot(void);
extern void mf_display_src(u32 word);
extern void mf_display_progress(u16 value);
-extern void mf_clear_src(void);
extern void mf_init(void);
^ permalink raw reply
* [PATCH 4/11] powerpc: Replace platform_is_lpar() with a firmware feature
From: Michael Ellerman @ 2006-03-21 9:45 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <1142934351.193140.181086235013.qpush@concordia>
It has been decreed that platform numbers are evil, so as a step in that
direction, replace platform_is_lpar() with a FW_FEATURE_LPAR bit.
Currently FW_FEATURE_LPAR really means i/pSeries LPAR, in the future we might
have to clean that up if we need to be more specific about what LPAR actually
means. But that's another patch ...
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/mm/hash_utils_64.c | 4 ++--
arch/powerpc/oprofile/op_model_power4.c | 3 ++-
arch/powerpc/platforms/iseries/setup.c | 10 +++++++---
arch/powerpc/platforms/pseries/iommu.c | 2 +-
arch/powerpc/platforms/pseries/setup.c | 11 +++++++----
arch/powerpc/platforms/pseries/smp.c | 2 +-
arch/powerpc/platforms/pseries/xics.c | 3 ++-
include/asm-powerpc/firmware.h | 7 ++++---
include/asm-powerpc/processor.h | 1 -
9 files changed, 26 insertions(+), 17 deletions(-)
Index: to-merge/arch/powerpc/mm/hash_utils_64.c
===================================================================
--- to-merge.orig/arch/powerpc/mm/hash_utils_64.c
+++ to-merge/arch/powerpc/mm/hash_utils_64.c
@@ -422,7 +422,7 @@ void __init htab_initialize(void)
htab_hash_mask = pteg_count - 1;
- if (platform_is_lpar()) {
+ if (firmware_has_feature(FW_FEATURE_LPAR)) {
/* Using a hypervisor which owns the htab */
htab_address = NULL;
_SDR1 = 0;
@@ -517,7 +517,7 @@ void __init htab_initialize(void)
void htab_initialize_secondary(void)
{
- if (!platform_is_lpar())
+ if (!firmware_has_feature(FW_FEATURE_LPAR))
mtspr(SPRN_SDR1, _SDR1);
}
Index: to-merge/arch/powerpc/oprofile/op_model_power4.c
===================================================================
--- to-merge.orig/arch/powerpc/oprofile/op_model_power4.c
+++ to-merge/arch/powerpc/oprofile/op_model_power4.c
@@ -10,6 +10,7 @@
#include <linux/oprofile.h>
#include <linux/init.h>
#include <linux/smp.h>
+#include <asm/firmware.h>
#include <asm/ptrace.h>
#include <asm/system.h>
#include <asm/processor.h>
@@ -232,7 +233,7 @@ static unsigned long get_pc(struct pt_re
mmcra = mfspr(SPRN_MMCRA);
/* Were we in the hypervisor? */
- if (platform_is_lpar() && (mmcra & MMCRA_SIHV))
+ if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & MMCRA_SIHV))
/* function descriptor madness */
return *((unsigned long *)hypervisor_bucket);
Index: to-merge/arch/powerpc/platforms/iseries/setup.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/iseries/setup.c
+++ to-merge/arch/powerpc/platforms/iseries/setup.c
@@ -303,8 +303,6 @@ static void __init iSeries_init_early(vo
{
DBG(" -> iSeries_init_early()\n");
- ppc64_firmware_features = FW_FEATURE_ISERIES;
-
ppc64_interrupt_controller = IC_ISERIES;
#if defined(CONFIG_BLK_DEV_INITRD)
@@ -711,7 +709,13 @@ void __init iSeries_init_IRQ(void) { }
static int __init iseries_probe(int platform)
{
- return PLATFORM_ISERIES_LPAR == platform;
+ if (PLATFORM_ISERIES_LPAR != platform)
+ return 0;
+
+ ppc64_firmware_features |= FW_FEATURE_ISERIES;
+ ppc64_firmware_features |= FW_FEATURE_LPAR;
+
+ return 1;
}
struct machdep_calls __initdata iseries_md = {
Index: to-merge/arch/powerpc/platforms/pseries/iommu.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/pseries/iommu.c
+++ to-merge/arch/powerpc/platforms/pseries/iommu.c
@@ -580,7 +580,7 @@ void iommu_init_early_pSeries(void)
return;
}
- if (platform_is_lpar()) {
+ if (firmware_has_feature(FW_FEATURE_LPAR)) {
if (firmware_has_feature(FW_FEATURE_MULTITCE)) {
ppc_md.tce_build = tce_buildmulti_pSeriesLP;
ppc_md.tce_free = tce_freemulti_pSeriesLP;
Index: to-merge/arch/powerpc/platforms/pseries/setup.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/pseries/setup.c
+++ to-merge/arch/powerpc/platforms/pseries/setup.c
@@ -246,7 +246,7 @@ static void __init pSeries_setup_arch(vo
ppc_md.idle_loop = default_idle;
}
- if (platform_is_lpar())
+ if (firmware_has_feature(FW_FEATURE_LPAR))
ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;
else
ppc_md.enable_pmcs = power4_enable_pmcs;
@@ -324,12 +324,12 @@ static void __init pSeries_init_early(vo
fw_feature_init();
- if (platform_is_lpar())
+ if (firmware_has_feature(FW_FEATURE_LPAR))
hpte_init_lpar();
else
hpte_init_native();
- if (platform_is_lpar())
+ if (firmware_has_feature(FW_FEATURE_LPAR))
find_udbg_vterm();
if (firmware_has_feature(FW_FEATURE_DABR))
@@ -385,6 +385,9 @@ static int __init pSeries_probe(int plat
* it here ...
*/
+ if (platform == PLATFORM_PSERIES_LPAR)
+ ppc64_firmware_features |= FW_FEATURE_LPAR;
+
return 1;
}
@@ -524,7 +527,7 @@ static void pseries_shared_idle(void)
static int pSeries_pci_probe_mode(struct pci_bus *bus)
{
- if (platform_is_lpar())
+ if (firmware_has_feature(FW_FEATURE_LPAR))
return PCI_PROBE_DEVTREE;
return PCI_PROBE_NORMAL;
}
Index: to-merge/arch/powerpc/platforms/pseries/smp.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/pseries/smp.c
+++ to-merge/arch/powerpc/platforms/pseries/smp.c
@@ -443,7 +443,7 @@ void __init smp_init_pSeries(void)
smp_ops->cpu_die = pSeries_cpu_die;
/* Processors can be added/removed only on LPAR */
- if (platform_is_lpar())
+ if (firmware_has_feature(FW_FEATURE_LPAR))
pSeries_reconfig_notifier_register(&pSeries_smp_nb);
#endif
Index: to-merge/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/pseries/xics.c
+++ to-merge/arch/powerpc/platforms/pseries/xics.c
@@ -20,6 +20,7 @@
#include <linux/gfp.h>
#include <linux/radix-tree.h>
#include <linux/cpu.h>
+#include <asm/firmware.h>
#include <asm/prom.h>
#include <asm/io.h>
#include <asm/pgtable.h>
@@ -536,7 +537,7 @@ nextnode:
of_node_put(np);
}
- if (platform_is_lpar())
+ if (firmware_has_feature(FW_FEATURE_LPAR))
ops = &pSeriesLP_ops;
else {
#ifdef CONFIG_SMP
Index: to-merge/include/asm-powerpc/firmware.h
===================================================================
--- to-merge.orig/include/asm-powerpc/firmware.h
+++ to-merge/include/asm-powerpc/firmware.h
@@ -41,6 +41,7 @@
#define FW_FEATURE_MULTITCE (1UL<<19)
#define FW_FEATURE_SPLPAR (1UL<<20)
#define FW_FEATURE_ISERIES (1UL<<21)
+#define FW_FEATURE_LPAR (1UL<<22)
enum {
#ifdef CONFIG_PPC64
@@ -51,10 +52,10 @@ enum {
FW_FEATURE_MIGRATE | FW_FEATURE_PERFMON | FW_FEATURE_CRQ |
FW_FEATURE_VIO | FW_FEATURE_RDMA | FW_FEATURE_LLAN |
FW_FEATURE_BULK | FW_FEATURE_XDABR | FW_FEATURE_MULTITCE |
- FW_FEATURE_SPLPAR,
+ FW_FEATURE_SPLPAR | FW_FEATURE_LPAR,
FW_FEATURE_PSERIES_ALWAYS = 0,
- FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES,
- FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES,
+ FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
+ FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR,
FW_FEATURE_POSSIBLE =
#ifdef CONFIG_PPC_PSERIES
FW_FEATURE_PSERIES_POSSIBLE |
Index: to-merge/include/asm-powerpc/processor.h
===================================================================
--- to-merge.orig/include/asm-powerpc/processor.h
+++ to-merge/include/asm-powerpc/processor.h
@@ -52,7 +52,6 @@
#ifdef __KERNEL__
#define platform_is_pseries() (_machine == PLATFORM_PSERIES || \
_machine == PLATFORM_PSERIES_LPAR)
-#define platform_is_lpar() (!!(_machine & PLATFORM_LPAR))
#if defined(CONFIG_PPC_MULTIPLATFORM)
extern int _machine;
^ permalink raw reply
* [PATCH 3/11] powerpc: trivial: Cleanup whitespace in cputable.h
From: Michael Ellerman @ 2006-03-21 9:45 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <1142934351.193140.181086235013.qpush@concordia>
Remove redundant whitespace in include/asm-powerpc/cputable.h
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
include/asm-powerpc/cputable.h | 34 +++++++++++++++++-----------------
1 files changed, 17 insertions(+), 17 deletions(-)
Index: to-merge/include/asm-powerpc/cputable.h
===================================================================
--- to-merge.orig/include/asm-powerpc/cputable.h
+++ to-merge/include/asm-powerpc/cputable.h
@@ -102,19 +102,19 @@ extern void do_cpu_ftr_fixups(unsigned l
#define CPU_FTR_NEED_COHERENT ASM_CONST(0x0000000000020000)
#define CPU_FTR_NO_BTIC ASM_CONST(0x0000000000040000)
#define CPU_FTR_BIG_PHYS ASM_CONST(0x0000000000080000)
-#define CPU_FTR_NODSISRALIGN ASM_CONST(0x0000000000100000)
+#define CPU_FTR_NODSISRALIGN ASM_CONST(0x0000000000100000)
#ifdef __powerpc64__
/* Add the 64b processor unique features in the top half of the word */
-#define CPU_FTR_SLB ASM_CONST(0x0000000100000000)
-#define CPU_FTR_16M_PAGE ASM_CONST(0x0000000200000000)
-#define CPU_FTR_TLBIEL ASM_CONST(0x0000000400000000)
-#define CPU_FTR_NOEXECUTE ASM_CONST(0x0000000800000000)
-#define CPU_FTR_IABR ASM_CONST(0x0000002000000000)
-#define CPU_FTR_MMCRA ASM_CONST(0x0000004000000000)
+#define CPU_FTR_SLB ASM_CONST(0x0000000100000000)
+#define CPU_FTR_16M_PAGE ASM_CONST(0x0000000200000000)
+#define CPU_FTR_TLBIEL ASM_CONST(0x0000000400000000)
+#define CPU_FTR_NOEXECUTE ASM_CONST(0x0000000800000000)
+#define CPU_FTR_IABR ASM_CONST(0x0000002000000000)
+#define CPU_FTR_MMCRA ASM_CONST(0x0000004000000000)
#define CPU_FTR_CTRL ASM_CONST(0x0000008000000000)
-#define CPU_FTR_SMT ASM_CONST(0x0000010000000000)
-#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0000020000000000)
+#define CPU_FTR_SMT ASM_CONST(0x0000010000000000)
+#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0000020000000000)
#define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0000040000000000)
#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0000080000000000)
#define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0000100000000000)
@@ -123,15 +123,15 @@ extern void do_cpu_ftr_fixups(unsigned l
#else
/* ensure on 32b processors the flags are available for compiling but
* don't do anything */
-#define CPU_FTR_SLB ASM_CONST(0x0)
-#define CPU_FTR_16M_PAGE ASM_CONST(0x0)
-#define CPU_FTR_TLBIEL ASM_CONST(0x0)
-#define CPU_FTR_NOEXECUTE ASM_CONST(0x0)
-#define CPU_FTR_IABR ASM_CONST(0x0)
-#define CPU_FTR_MMCRA ASM_CONST(0x0)
+#define CPU_FTR_SLB ASM_CONST(0x0)
+#define CPU_FTR_16M_PAGE ASM_CONST(0x0)
+#define CPU_FTR_TLBIEL ASM_CONST(0x0)
+#define CPU_FTR_NOEXECUTE ASM_CONST(0x0)
+#define CPU_FTR_IABR ASM_CONST(0x0)
+#define CPU_FTR_MMCRA ASM_CONST(0x0)
#define CPU_FTR_CTRL ASM_CONST(0x0)
-#define CPU_FTR_SMT ASM_CONST(0x0)
-#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0)
+#define CPU_FTR_SMT ASM_CONST(0x0)
+#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0)
#define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0)
#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0)
#define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0)
^ permalink raw reply
* [PATCH 2/11] powerpc: Remove unused iommu_off logic from pSeries_init_early()
From: Michael Ellerman @ 2006-03-21 9:45 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <1142934351.193140.181086235013.qpush@concordia>
When iommu_init_early_pSeries() was added, ages ago, we forgot to remove
the code that checks /chosen/linux,iommu-off in pSeries_init_early(). We
do it now in iommu_init_early_pSeries().
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/pseries/setup.c | 7 +------
1 files changed, 1 insertion(+), 6 deletions(-)
Index: to-merge/arch/powerpc/platforms/pseries/setup.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/pseries/setup.c
+++ to-merge/arch/powerpc/platforms/pseries/setup.c
@@ -320,19 +320,14 @@ static int pseries_set_xdabr(unsigned lo
*/
static void __init pSeries_init_early(void)
{
- int iommu_off = 0;
-
DBG(" -> pSeries_init_early()\n");
fw_feature_init();
if (platform_is_lpar())
hpte_init_lpar();
- else {
+ else
hpte_init_native();
- iommu_off = (of_chosen &&
- get_property(of_chosen, "linux,iommu-off", NULL));
- }
if (platform_is_lpar())
find_udbg_vterm();
^ permalink raw reply
* [PATCH 1/11] powerpc: Unconfuse htab_bolt_mapping() callers
From: Michael Ellerman @ 2006-03-21 9:45 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
htab_bolt_mapping() takes a vstart and pstart parameter, but all but one of
its callers actually pass it vstart and vstart. Luckily before it passes
paddr (calculated from paddr) to the hpte_insert routines it calls
virt_to_abs() (aka. __pa()) on the address, so there isn't actually a bug.
map_io_page() however does pass pstart properly, so currently it's broken
AFAICT because we're calling __pa(paddr) which will get us something very
large. Presumably no one's calling map_io_page() in the right context.
Anyway, change htab_bolt_mapping() callers to properly pass pstart, and then
use it properly in htab_bolt_mapping(), ie. don't call __pa() on it again.
Booted on p5 LPAR, iSeries and Power3.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/mm/hash_utils_64.c | 27 ++++++++++++++-------------
1 files changed, 14 insertions(+), 13 deletions(-)
Index: to-merge/arch/powerpc/mm/hash_utils_64.c
===================================================================
--- to-merge.orig/arch/powerpc/mm/hash_utils_64.c
+++ to-merge/arch/powerpc/mm/hash_utils_64.c
@@ -169,7 +169,7 @@ int htab_bolt_mapping(unsigned long vsta
#ifdef CONFIG_PPC_ISERIES
if (_machine == PLATFORM_ISERIES_LPAR)
ret = iSeries_hpte_insert(hpteg, va,
- __pa(vaddr),
+ paddr,
tmp_mode,
HPTE_V_BOLTED,
psize);
@@ -178,7 +178,7 @@ int htab_bolt_mapping(unsigned long vsta
#ifdef CONFIG_PPC_PSERIES
if (_machine & PLATFORM_LPAR)
ret = pSeries_lpar_hpte_insert(hpteg, va,
- virt_to_abs(paddr),
+ paddr,
tmp_mode,
HPTE_V_BOLTED,
psize);
@@ -186,7 +186,7 @@ int htab_bolt_mapping(unsigned long vsta
#endif
#ifdef CONFIG_PPC_MULTIPLATFORM
ret = native_hpte_insert(hpteg, va,
- virt_to_abs(paddr),
+ paddr,
tmp_mode, HPTE_V_BOLTED,
psize);
#endif
@@ -392,7 +392,7 @@ static unsigned long __init htab_get_tab
#ifdef CONFIG_MEMORY_HOTPLUG
void create_section_mapping(unsigned long start, unsigned long end)
{
- BUG_ON(htab_bolt_mapping(start, end, start,
+ BUG_ON(htab_bolt_mapping(start, end, __pa(start),
_PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX,
mmu_linear_psize));
}
@@ -473,21 +473,22 @@ void __init htab_initialize(void)
if (dart_tablebase != 0 && dart_tablebase >= base
&& dart_tablebase < (base + size)) {
+ unsigned long dart_table_end = dart_tablebase + 16 * MB;
if (base != dart_tablebase)
BUG_ON(htab_bolt_mapping(base, dart_tablebase,
- base, mode_rw,
- mmu_linear_psize));
- if ((base + size) > (dart_tablebase + 16*MB))
+ __pa(base), mode_rw,
+ mmu_linear_psize));
+ if ((base + size) > dart_table_end)
BUG_ON(htab_bolt_mapping(dart_tablebase+16*MB,
- base + size,
- dart_tablebase+16*MB,
+ base + size,
+ __pa(dart_table_end),
mode_rw,
mmu_linear_psize));
continue;
}
#endif /* CONFIG_U3_DART */
- BUG_ON(htab_bolt_mapping(base, base + size, base,
- mode_rw, mmu_linear_psize));
+ BUG_ON(htab_bolt_mapping(base, base + size, __pa(base),
+ mode_rw, mmu_linear_psize));
}
/*
@@ -504,8 +505,8 @@ void __init htab_initialize(void)
if (base + size >= tce_alloc_start)
tce_alloc_start = base + size + 1;
- BUG_ON(htab_bolt_mapping(tce_alloc_start, tce_alloc_end,
- tce_alloc_start, mode_rw,
+ BUG_ON(htab_bolt_mapping(tce_alloc_start, tce_alloc_end,
+ __pa(tce_alloc_start), mode_rw,
mmu_linear_psize));
}
^ permalink raw reply
* Re: [RFC] powerpc: cell interrupt controller updates
From: Benjamin Herrenschmidt @ 2006-03-21 6:27 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Jens Osterkamp, stk, Milton Miller, Paul Mackerras, hpenner,
linuxppc64-dev
In-Reply-To: <200601180020.17301.arnd@arndb.de>
On Wed, 2006-01-18 at 00:20 +0100, Arnd Bergmann wrote:
> The interrupt-parent relationship between the spider and iic controllers
> is just an approximation, each spider pic can also send interrupts to any
> other interrupt controller in the system (all six of them, if you count
> the SMT threads as separate interrupt targets), but for best performance, it
> is usually wise to use local interrupt delivery.
We could either express that by having a new property that we could call
"multiple-parents" or something like that with a list of parents... or
we could have a "virtual" iic that is a single controller in the
device-tree (the later makes a lot of sense I think) with sub-nodes for
the actual iic's to be used maybe by the iic driver for probing... I
still need to think about that one though..
Ben.
^ permalink raw reply
* [RFC/PATCH] powerpc: Make BUG_ON & WARN_ON play nice with compile-time optimisations
From: Michael Ellerman @ 2006-03-21 5:51 UTC (permalink / raw)
To: Paul Mackerras, linuxppc-dev
In-Reply-To: <200603211445.32454.michael@ellerman.id.au>
Although we could do this. It relys on firmware_has_feature() being a macro,
but perhaps that's ok. This isn't exactly ideal, as it encourages us to use
macros where we could otherwise use static inlines, but perhaps it's ok.
Given this:
void test(void)
{
constant_false();
BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
constant_true();
BUG_ON(!firmware_has_feature(FW_FEATURE_ISERIES));
non_constant();
BUG_ON(firmware_has_feature(FW_FEATURE_SPLPAR));
constant_false();
WARN_ON(firmware_has_feature(FW_FEATURE_ISERIES));
constant_true();
WARN_ON(!firmware_has_feature(FW_FEATURE_ISERIES));
non_constant();
WARN_ON(firmware_has_feature(FW_FEATURE_SPLPAR));
}
I get assembly like so, which looks good to me:
bl .constant_false
bl .constant_true
1: twi 31,0,0
.section __bug_table,"a"
.llong 1b,400,.LC12,__func__.21353
.previous
bl .non_constant
ld 9,.LC13@toc(2)
ld 0,0(9)
rldicl 0,0,44,63
1: tdnei 0,0
.section __bug_table,"a"
.llong 1b,403,.LC12,__func__.21353
.previous
bl .constant_false
bl .constant_true
1: twi 31,0,0
.section __bug_table,"a"
.llong 1b,16777625,.LC12,__func__.21353
.previous
bl .non_constant
ld 9,.LC13@toc(2)
ld 0,0(9)
rldicl 0,0,44,63
1: tdnei 0,0
.section __bug_table,"a"
.llong 1b,16777628,.LC12,__func__.21353
.previous
include/asm-powerpc/bug.h | 24 ++++++++++++++++++++++--
include/asm-powerpc/firmware.h | 8 +++-----
2 files changed, 25 insertions(+), 7 deletions(-)
Index: to-merge/include/asm-powerpc/bug.h
===================================================================
--- to-merge.orig/include/asm-powerpc/bug.h
+++ to-merge/include/asm-powerpc/bug.h
@@ -40,17 +40,36 @@ struct bug_entry *find_bug(unsigned long
} while (0)
#define BUG_ON(x) do { \
- __asm__ __volatile__( \
+ if (__builtin_constant_p(x)) { \
+ if (x) \
+ BUG(); \
+ } else { \
+ __asm__ __volatile__( \
"1: "PPC_TLNEI" %0,0\n" \
".section __bug_table,\"a\"\n" \
"\t"PPC_LONG" 1b,%1,%2,%3\n" \
".previous" \
: : "r" ((long)(x)), "i" (__LINE__), \
"i" (__FILE__), "i" (__FUNCTION__)); \
+ } \
} while (0)
-#define WARN_ON(x) do { \
+#define WARN() do { \
__asm__ __volatile__( \
+ "1: twi 31,0,0\n" \
+ ".section __bug_table,\"a\"\n" \
+ "\t"PPC_LONG" 1b,%0,%1,%2\n" \
+ ".previous" \
+ : : "i" (__LINE__ + BUG_WARNING_TRAP), \
+ "i" (__FILE__), "i" (__FUNCTION__)); \
+} while (0)
+
+#define WARN_ON(x) do { \
+ if (__builtin_constant_p(x)) { \
+ if (x) \
+ WARN(); \
+ } else { \
+ __asm__ __volatile__( \
"1: "PPC_TLNEI" %0,0\n" \
".section __bug_table,\"a\"\n" \
"\t"PPC_LONG" 1b,%1,%2,%3\n" \
@@ -58,6 +77,7 @@ struct bug_entry *find_bug(unsigned long
: : "r" ((long)(x)), \
"i" (__LINE__ + BUG_WARNING_TRAP), \
"i" (__FILE__), "i" (__FUNCTION__)); \
+ } \
} while (0)
#define HAVE_ARCH_BUG
Index: to-merge/include/asm-powerpc/firmware.h
===================================================================
--- to-merge.orig/include/asm-powerpc/firmware.h
+++ to-merge/include/asm-powerpc/firmware.h
@@ -83,11 +83,9 @@ enum {
*/
extern unsigned long ppc64_firmware_features;
-static inline unsigned long firmware_has_feature(unsigned long feature)
-{
- return (FW_FEATURE_ALWAYS & feature) ||
- (FW_FEATURE_POSSIBLE & ppc64_firmware_features & feature);
-}
+#define firmware_has_feature(feature) \
+ ((FW_FEATURE_ALWAYS & (feature)) || \
+ (FW_FEATURE_POSSIBLE & ppc64_firmware_features & (feature)))
extern void system_reset_fwnmi(void);
extern void machine_check_fwnmi(void);
^ permalink raw reply
* Re: [PATCH 5/7] powerpc numa: Consolidate handling of Power4 special case
From: Jon Mason @ 2006-03-21 3:54 UTC (permalink / raw)
To: Nathan Lynch; +Cc: linuxppc-dev
In-Reply-To: <11429013752643-git-send-email-nathanl@austin.ibm.com>
On Mon, Mar 20, 2006 at 06:36:15PM -0600, Nathan Lynch wrote:
> Code to handle Power4's invalid node id (0xffff) is duplicated for cpu
> and memory. Better to handle this case in one place --
> of_node_to_nid. Overall behavior should be unchanged.
>
> Signed-off-by: Nathan Lynch <nathanl@austin.ibm.com>
>
> ---
>
> arch/powerpc/mm/numa.c | 23 +++++++++++------------
> 1 files changed, 11 insertions(+), 12 deletions(-)
>
> d9dd3889e58eeb34d1130d2514fea905ca2cab6a
> diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
> index e511ca1..4a6cbb0 100644
> --- a/arch/powerpc/mm/numa.c
> +++ b/arch/powerpc/mm/numa.c
> @@ -207,6 +207,11 @@ static int of_node_to_nid(struct device_
> device->full_name);
> nid = 0;
> }
> +
> + /* POWER4 LPAR uses 0xffff as invalid node */
> + if (nid == 0xffff)
A #define for 0xffff would make the code much nicer. Something like
POWER4_LPAR_INVALID_NODEID could also enable you to remove the above
comment.
Thanks,
Jon
> + nid = 0;
> +
> return nid;
> }
>
> @@ -297,14 +302,9 @@ static int __cpuinit numa_setup_cpu(unsi
> nid = of_node_to_nid(cpu);
>
> if (nid >= num_online_nodes()) {
> - /*
> - * POWER4 LPAR uses 0xffff as invalid node,
> - * dont warn in this case.
> - */
> - if (nid != 0xffff)
> - printk(KERN_ERR "WARNING: cpu %ld "
> - "maps to invalid NUMA node %d\n",
> - lcpu, nid);
> + printk(KERN_ERR "WARNING: cpu %ld "
> + "maps to invalid NUMA node %d\n",
> + lcpu, nid);
> nid = 0;
> }
> out:
> @@ -442,10 +442,9 @@ new_range:
> nid = of_node_to_nid(memory);
>
> if (nid >= MAX_NUMNODES) {
> - if (nid != 0xffff)
> - printk(KERN_ERR "WARNING: memory at %lx maps "
> - "to invalid NUMA node %d\n", start,
> - nid);
> + printk(KERN_ERR "WARNING: memory at %lx maps "
> + "to invalid NUMA node %d\n", start,
> + nid);
> nid = 0;
> }
>
> --
> 1.2.4
>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH] powerpc: Make BUG_ON & WARN_ON play nice with compile-time optimisations
From: Michael Ellerman @ 2006-03-21 3:45 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20060207052220.917C668A92@ozlabs.org>
[-- Attachment #1: Type: text/plain, Size: 1698 bytes --]
On Tue, 7 Feb 2006 16:22, Michael Ellerman wrote:
> Currently if you do BUG_ON(0) you'll still get a trap instruction in your
> object, although it'll never trigger. That's ok, but a bit ugly, it'd be
> nice if the compiler could completely eliminate any trace of the BUG_ON.
>
> So update the BUG_ON & WARN_ON macros to make this possible. From the
> comment in the patch:
>
> The if statement in BUG_ON and WARN_ON gives the compiler a chance to do
> compile-time optimisation and possibly elide the entire block. The check
> for !__builtin_constant(x) has the oppposite effect, if we must do the
> test at runtime then we avoid a spurious compare and branch by ensuring
> the if condition is always true.
>
> I've confirmed it works in both cases, if the condition is false at compile
> time we get no code emitted for the BUG statement. If the condition needs
> to be evaluated at runtime we get the same code we used to, ie. only one
> test in the trap instruction.
Turns out this doesn't always do what we want, depending on what the condition
for the BUG_ON() is. Specifically the __builtin_constant_p() sometimes fails
to recognise that the condition will be constant, and so we end up with:
558: 38 00 00 00 li r0,0
55c: 0b 00 00 00 tdnei r0,0
Which is harmless but not really good enough. When gcc gets fixed
(http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26724) we can think about this
again.
cheers
--
Michael Ellerman
IBM OzLabs
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)
We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH] powerpc: Add FSL SEC node to documentation
From: Hollis Blanchard @ 2006-03-21 2:14 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20060320195945.004fdf26.kim.phillips@freescale.com>
On Monday 20 March 2006 19:59, Kim Phillips wrote:
> diff --git a/Documentation/powerpc/booting-without-of.txt=20
b/Documentation/powerpc/booting-without-of.txt
> index d02c649..72f3241 100644
> --- a/Documentation/powerpc/booting-without-of.txt
> +++ b/Documentation/powerpc/booting-without-of.txt
> @@ -1365,6 +1365,79 @@ platforms are moved over to use the flat
> =A0=A0=A0=A0=A0=A0};
> =A0
> =A0
> + =A0 g) Freescale SOC SEC Security Engines
> +
> + =A0 Required properties:
> +
> + =A0 =A0- device_type : Should be "crypto"
> + =A0 =A0- model : Model of the device. =A0Should be "SEC1" or "SEC2"
> + =A0 =A0- compatible : Should be "talitos"
[snip]
Have you consulted with any other vendors regarding these properties? I kno=
w=20
there is no IEEE1275 binding for these sorts of devices, but we can at leas=
t=20
attempt to standardize it (even in the absence of the Open Firmware Working=
=20
Group)...
=2DHollis
^ permalink raw reply
* [PATCH 0/7] powerpc numa updates and fixes
From: Nathan Lynch @ 2006-03-21 0:33 UTC (permalink / raw)
To: linuxppc-dev
The following series has some minor bugfixes and updates for numa for
2.6.17.
Tested on Power4 (lpar and non-) and Power5.
numa.c | 156 +++++++++++++++++++++--------------------------
1 files changed, 72 insertions(+), 84 deletions(-)
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox