Commit 0c23664e authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6:
  [SPARC64]: Optimize fault kprobe handling just like powerpc.
  [SPARC]: Wire up utimensat syscall.
  [SPARC64]: Fix request_irq() ignored result warnings in PCI controller code.
  [SPARC64]: Kill asm-sparc64/pbm.h
  [ATYFB]: Fix sparc includes.
  [QLA2XXX]: Fix build on sparc.
  [SPARC64]: Removal of trivial pci_controller_info uses.
  [SPARC64]: Move index info pci_pbm_info.
  [SPARC64]: Move {setup,teardown}_msi_irq into pci_pbm_info.
  [SPARC64]: Move pci_ops into pci_pbm_info.
  [SPARC64] SBUS: Error interrupt registry cleanups.
  [SPARC64] PCI: Use root list of pbm's instead of pci_controller_info's
  [SPARC64] PCI: Kill PROM_PCIRNG_MAX and PROM_PCIIMAP_MAX.
  [SPARC64] PCI: Use common routine to fetch PBM properties.
parents 6ec129c3 127cda1e
......@@ -80,6 +80,7 @@ sys_call_table:
/*295*/ .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
/*300*/ .long sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
/*305*/ .long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
/*310*/ .long sys_utimensat
#ifdef CONFIG_SUNOS_EMUL
/* Now the SunOS syscall table. */
......@@ -196,5 +197,6 @@ sunos_sys_table:
.long sunos_nosys, sunos_nosys, sunos_nosys
.long sunos_nosys, sunos_nosys, sunos_nosys
.long sunos_nosys
/*310*/ .long sunos_nosys
#endif
......@@ -13,16 +13,17 @@
#include <linux/string.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/pci.h>
#include <asm/system.h>
#include <asm/page.h>
#include <asm/pbm.h>
#include <asm/ebus.h>
#include <asm/oplib.h>
#include <asm/prom.h>
#include <asm/of_device.h>
#include <asm/bpp.h>
#include <asm/irq.h>
#include <asm/io.h>
/* EBUS dma library. */
......
......@@ -313,7 +313,7 @@ out:
return 1;
}
static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
{
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
......@@ -403,15 +403,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
if (post_kprobe_handler(args->regs))
ret = NOTIFY_STOP;
break;
case DIE_GPF:
case DIE_PAGE_FAULT:
/* kprobe_running() needs smp_processor_id() */
preempt_disable();
if (kprobe_running() &&
kprobe_fault_handler(args->regs, args->trapnr))
ret = NOTIFY_STOP;
preempt_enable();
break;
default:
break;
}
......
......@@ -14,12 +14,12 @@
#include <linux/sched.h>
#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/pci.h>
#include <linux/msi.h>
#include <linux/irq.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/pbm.h>
#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/ebus.h>
......@@ -48,10 +48,10 @@ asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn,
#else
/* List of all PCI controllers found in the system. */
struct pci_controller_info *pci_controller_root = NULL;
struct pci_pbm_info *pci_pbm_root = NULL;
/* Each PCI controller found gets a unique index. */
int pci_num_controllers = 0;
/* Each PBM found gets a unique index. */
int pci_num_pbms = 0;
volatile int pci_poke_in_progress;
volatile int pci_poke_cpu = -1;
......@@ -291,7 +291,7 @@ extern const struct pci_iommu_ops pci_sun4u_iommu_ops,
/* Find each controller in the system, attach and initialize
* software state structure for each and link into the
* pci_controller_root. Setup the controller enough such
* pci_pbm_root. Setup the controller enough such
* that bus scanning can be done.
*/
static void __init pci_controller_probe(void)
......@@ -743,7 +743,6 @@ int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev,
struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm)
{
struct pci_controller_info *p = pbm->parent;
struct device_node *node = pbm->prom_node;
struct pci_dev *host_pdev;
struct pci_bus *bus;
......@@ -751,7 +750,7 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm)
printk("PCI: Scanning PBM %s\n", node->full_name);
/* XXX parent device? XXX */
bus = pci_create_bus(NULL, pbm->pci_first_busno, p->pci_ops, pbm);
bus = pci_create_bus(NULL, pbm->pci_first_busno, pbm->pci_ops, pbm);
if (!bus) {
printk(KERN_ERR "Failed to create bus for %s\n",
node->full_name);
......@@ -776,10 +775,10 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm)
static void __init pci_scan_each_controller_bus(void)
{
struct pci_controller_info *p;
struct pci_pbm_info *pbm;
for (p = pci_controller_root; p; p = p->next)
p->scan_bus(p);
for (pbm = pci_pbm_root; pbm; pbm = pbm->next)
pbm->scan_bus(pbm);
}
extern void power_init(void);
......@@ -787,7 +786,7 @@ extern void power_init(void);
static int __init pcibios_init(void)
{
pci_controller_probe();
if (pci_controller_root == NULL)
if (pci_pbm_root == NULL)
return 0;
pci_scan_each_controller_bus();
......@@ -922,10 +921,8 @@ static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struc
enum pci_mmap_state mmap_state)
{
struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
struct pci_controller_info *p;
unsigned long space_size, user_offset, user_size;
p = pbm->parent;
if (mmap_state == pci_mmap_io) {
space_size = (pbm->io_space.end -
pbm->io_space.start) + 1;
......@@ -1078,11 +1075,7 @@ int pci_domain_nr(struct pci_bus *pbus)
if (pbm == NULL || pbm->parent == NULL) {
ret = -ENXIO;
} else {
struct pci_controller_info *p = pbm->parent;
ret = p->index;
ret = ((ret << 1) +
((pbm == &pbm->parent->pbm_B) ? 1 : 0));
ret = pbm->index;
}
return ret;
......@@ -1093,17 +1086,12 @@ EXPORT_SYMBOL(pci_domain_nr);
int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
{
struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
struct pci_controller_info *p = pbm->parent;
int virt_irq, err;
int virt_irq;
if (!pbm->msi_num || !p->setup_msi_irq)
if (!pbm->setup_msi_irq)
return -EINVAL;
err = p->setup_msi_irq(&virt_irq, pdev, desc);
if (err)
return err;
return 0;
return pbm->setup_msi_irq(&virt_irq, pdev, desc);
}
void arch_teardown_msi_irq(unsigned int virt_irq)
......@@ -1111,12 +1099,11 @@ void arch_teardown_msi_irq(unsigned int virt_irq)
struct msi_desc *entry = get_irq_msi(virt_irq);
struct pci_dev *pdev = entry->dev;
struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
struct pci_controller_info *p = pbm->parent;
if (!pbm->msi_num || !p->setup_msi_irq)
if (!pbm->teardown_msi_irq)
return;
return p->teardown_msi_irq(virt_irq, pdev);
return pbm->teardown_msi_irq(virt_irq, pdev);
}
#endif /* !(CONFIG_PCI_MSI) */
......
......@@ -9,12 +9,26 @@
#include <linux/pci.h>
#include <linux/device.h>
#include <asm/pbm.h>
#include <asm/prom.h>
#include <asm/of_device.h>
#include <asm/oplib.h>
#include "pci_impl.h"
void pci_get_pbm_props(struct pci_pbm_info *pbm)
{
const u32 *val = of_get_property(pbm->prom_node, "bus-range", NULL);
pbm->pci_first_busno = val[0];
pbm->pci_last_busno = val[1];
val = of_get_property(pbm->prom_node, "ino-bitmap", NULL);
if (val) {
pbm->ino_bitmap = (((u64)val[1] << 32UL) |
((u64)val[0] << 0UL));
}
}
static void pci_register_legacy_regions(struct resource *io_res,
struct resource *mem_res)
{
......@@ -149,8 +163,7 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm)
}
/* Generic helper routines for PCI error reporting. */
void pci_scan_for_target_abort(struct pci_controller_info *p,
struct pci_pbm_info *pbm,
void pci_scan_for_target_abort(struct pci_pbm_info *pbm,
struct pci_bus *pbus)
{
struct pci_dev *pdev;
......@@ -165,18 +178,16 @@ void pci_scan_for_target_abort(struct pci_controller_info *p,
PCI_STATUS_REC_TARGET_ABORT));
if (error_bits) {
pci_write_config_word(pdev, PCI_STATUS, error_bits);
printk("PCI%d(PBM%c): Device [%s] saw Target Abort [%016x]\n",
p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'),
pci_name(pdev), status);
printk("%s: Device %s saw Target Abort [%016x]\n",
pbm->name, pci_name(pdev), status);
}
}
list_for_each_entry(bus, &pbus->children, node)
pci_scan_for_target_abort(p, pbm, bus);
pci_scan_for_target_abort(pbm, bus);
}
void pci_scan_for_master_abort(struct pci_controller_info *p,
struct pci_pbm_info *pbm,
void pci_scan_for_master_abort(struct pci_pbm_info *pbm,
struct pci_bus *pbus)
{
struct pci_dev *pdev;
......@@ -190,18 +201,16 @@ void pci_scan_for_master_abort(struct pci_controller_info *p,
(status & (PCI_STATUS_REC_MASTER_ABORT));
if (error_bits) {
pci_write_config_word(pdev, PCI_STATUS, error_bits);
printk("PCI%d(PBM%c): Device [%s] received Master Abort [%016x]\n",
p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'),
pci_name(pdev), status);
printk("%s: Device %s received Master Abort [%016x]\n",
pbm->name, pci_name(pdev), status);
}
}
list_for_each_entry(bus, &pbus->children, node)
pci_scan_for_master_abort(p, pbm, bus);
pci_scan_for_master_abort(pbm, bus);
}
void pci_scan_for_parity_error(struct pci_controller_info *p,
struct pci_pbm_info *pbm,
void pci_scan_for_parity_error(struct pci_pbm_info *pbm,
struct pci_bus *pbus)
{
struct pci_dev *pdev;
......@@ -216,12 +225,11 @@ void pci_scan_for_parity_error(struct pci_controller_info *p,
PCI_STATUS_DETECTED_PARITY));
if (error_bits) {
pci_write_config_word(pdev, PCI_STATUS, error_bits);
printk("PCI%d(PBM%c): Device [%s] saw Parity Error [%016x]\n",
p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'),
pci_name(pdev), status);
printk("%s: Device %s saw Parity Error [%016x]\n",
pbm->name, pci_name(pdev), status);
}
}
list_for_each_entry(bus, &pbus->children, node)
pci_scan_for_parity_error(p, pbm, bus);
pci_scan_for_parity_error(pbm, bus);
}
......@@ -7,7 +7,6 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <asm/pbm.h>
#include <asm/oplib.h>
#include <asm/prom.h>
......@@ -160,21 +159,9 @@ static struct pci_ops pci_fire_ops = {
.write = fire_write_pci_cfg,
};
static void pbm_scan_bus(struct pci_controller_info *p,
struct pci_pbm_info *pbm)
static void pci_fire_scan_bus(struct pci_pbm_info *pbm)
{
pbm->pci_bus = pci_scan_one_pbm(pbm);
}
static void pci_fire_scan_bus(struct pci_controller_info *p)
{
struct device_node *dp;
if ((dp = p->pbm_A.prom_node) != NULL)
pbm_scan_bus(p, &p->pbm_A);
if ((dp = p->pbm_B.prom_node) != NULL)
pbm_scan_bus(p, &p->pbm_B);
/* XXX register error interrupt handlers XXX */
}
......@@ -313,18 +300,24 @@ static void pci_fire_hw_init(struct pci_pbm_info *pbm)
}
static void pci_fire_pbm_init(struct pci_controller_info *p,
struct device_node *dp, u32 portid)
struct device_node *dp, u32 portid)
{
const struct linux_prom64_registers *regs;
struct pci_pbm_info *pbm;
const u32 *ino_bitmap;
const unsigned int *busrange;
if ((portid & 1) == 0)
pbm = &p->pbm_A;
else
pbm = &p->pbm_B;
pbm->next = pci_pbm_root;
pci_pbm_root = pbm;
pbm->scan_bus = pci_fire_scan_bus;
pbm->pci_ops = &pci_fire_ops;
pbm->index = pci_num_pbms++;
pbm->portid = portid;
pbm->parent = p;
pbm->prom_node = dp;
......@@ -338,13 +331,7 @@ static void pci_fire_pbm_init(struct pci_controller_info *p,
pci_determine_mem_io_space(pbm);
ino_bitmap = of_get_property(dp, "ino-bitmap", NULL);
pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) |
((u64)ino_bitmap[0] << 0UL));
busrange = of_get_property(dp, "bus-range", NULL);
pbm->pci_first_busno = busrange[0];
pbm->pci_last_busno = busrange[1];
pci_get_pbm_props(pbm);
pci_fire_hw_init(pbm);
pci_fire_pbm_iommu_init(pbm);
......@@ -362,19 +349,11 @@ void fire_pci_init(struct device_node *dp, const char *model_name)
struct pci_controller_info *p;
u32 portid = of_getintprop_default(dp, "portid", 0xff);
struct iommu *iommu;
struct pci_pbm_info *pbm;
for (p = pci_controller_root; p; p = p->next) {
struct pci_pbm_info *pbm;
if (p->pbm_A.prom_node && p->pbm_B.prom_node)
continue;
pbm = (p->pbm_A.prom_node ?
&p->pbm_A :
&p->pbm_B);
for (pbm = pci_pbm_root; pbm; pbm = pbm->next) {
if (portid_compare(pbm->portid, portid)) {
pci_fire_pbm_init(p, dp, portid);
pci_fire_pbm_init(pbm->parent, dp, portid);
return;
}
}
......@@ -395,14 +374,7 @@ void fire_pci_init(struct device_node *dp, const char *model_name)
p->pbm_B.iommu = iommu;
p->next = pci_controller_root;
pci_controller_root = p;
p->index = pci_num_controllers++;
p->scan_bus = pci_fire_scan_bus;
/* XXX MSI support XXX */
p->pci_ops = &pci_fire_ops;
/* Like PSYCHO and SCHIZO we have a 2GB aligned area
* for memory space.
......
......@@ -8,15 +8,129 @@
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/pci.h>
#include <linux/msi.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/iommu.h>
extern struct pci_controller_info *pci_controller_root;
/* The abstraction used here is that there are PCI controllers,
* each with one (Sabre) or two (PSYCHO/SCHIZO) PCI bus modules
* underneath. Each PCI bus module uses an IOMMU (shared by both
* PBMs of a controller, or per-PBM), and if a streaming buffer
* is present, each PCI bus module has it's own. (ie. the IOMMU
* might be shared between PBMs, the STC is never shared)
* Furthermore, each PCI bus module controls it's own autonomous
* PCI bus.
*/
#define PCI_STC_FLUSHFLAG_INIT(STC) \
(*((STC)->strbuf_flushflag) = 0UL)
#define PCI_STC_FLUSHFLAG_SET(STC) \
(*((STC)->strbuf_flushflag) != 0UL)
struct pci_controller_info;
struct pci_pbm_info {
struct pci_pbm_info *next;
int index;
/* PCI controller we sit under. */
struct pci_controller_info *parent;
/* Physical address base of controller registers. */
unsigned long controller_regs;
/* Physical address base of PBM registers. */
unsigned long pbm_regs;
/* Physical address of DMA sync register, if any. */
unsigned long sync_reg;
/* Opaque 32-bit system bus Port ID. */
u32 portid;
/* Opaque 32-bit handle used for hypervisor calls. */
u32 devhandle;
/* Chipset version information. */
int chip_type;
#define PBM_CHIP_TYPE_SABRE 1
#define PBM_CHIP_TYPE_PSYCHO 2
#define PBM_CHIP_TYPE_SCHIZO 3
#define PBM_CHIP_TYPE_SCHIZO_PLUS 4
#define PBM_CHIP_TYPE_TOMATILLO 5
int chip_version;
int chip_revision;
/* Name used for top-level resources. */
char *name;
/* OBP specific information. */
struct device_node *prom_node;
u64 ino_bitmap;
/* PBM I/O and Memory space resources. */
struct resource io_space;
struct resource mem_space;
/* Base of PCI Config space, can be per-PBM or shared. */
unsigned long config_space;
/* State of 66MHz capabilities on this PBM. */
int is_66mhz_capable;
int all_devs_66mhz;
#ifdef CONFIG_PCI_MSI
/* MSI info. */
u32 msiq_num;
u32 msiq_ent_count;
u32 msiq_first;
u32 msiq_first_devino;
u32 msi_num;
u32 msi_first;
u32 msi_data_mask;
u32 msix_data_width;
u64 msi32_start;
u64 msi64_start;
u32 msi32_len;
u32 msi64_len;
void *msi_queues;
unsigned long *msi_bitmap;
int (*setup_msi_irq)(unsigned int *virt_irq_p, struct pci_dev *pdev,
struct msi_desc *entry);
void (*teardown_msi_irq)(unsigned int virt_irq, struct pci_dev *pdev);
#endif /* !(CONFIG_PCI_MSI) */
/* This PBM's streaming buffer. */
struct strbuf stc;
/* IOMMU state, potentially shared by both PBM segments. */
struct iommu *iommu;
/* Now things for the actual PCI bus probes. */
unsigned int pci_first_busno;
unsigned int pci_last_busno;
struct pci_bus *pci_bus;
void (*scan_bus)(struct pci_pbm_info *);
struct pci_ops *pci_ops;
};
struct pci_controller_info {
/* The PCI bus modules controlled by us. */
struct pci_pbm_info pbm_A;
struct pci_pbm_info pbm_B;
};
extern struct pci_pbm_info *pci_pbm_root;
extern unsigned long pci_memspace_mask;
extern int pci_num_controllers;
extern int pci_num_pbms;
/* PCI bus scanning and fixup support. */
extern void pci_iommu_table_init(struct iommu *iommu, int tsbsize,
u32 dma_offset, u32 dma_addr_mask);
extern void pci_get_pbm_props(struct pci_pbm_info *pbm);
extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm);
extern void pci_determine_mem_io_space(struct pci_pbm_info *pbm);
......@@ -30,9 +144,9 @@ extern int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev,
u32 value);
/* Error reporting support. */
extern void pci_scan_for_target_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *);
extern void pci_scan_for_master_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *);
extern void pci_scan_for_parity_error(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *);
extern void pci_scan_for_target_abort(struct pci_pbm_info *, struct pci_bus *);
extern void pci_scan_for_master_abort(struct pci_pbm_info *, struct pci_bus *);
extern void pci_scan_for_parity_error(struct pci_pbm_info *, struct pci_bus *);
/* Configuration space access. */
extern void pci_config_read8(u8 *addr, u8 *ret);
......
......@@ -8,10 +8,12 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/delay.h>
#include <linux/pci.h>
#include <asm/pbm.h>
#include <asm/oplib.h>
#include "iommu_common.h"
#include "pci_impl.h"
#define PCI_STC_CTXMATCH_ADDR(STC, CTX) \
((STC)->strbuf_ctxmatch_base + ((CTX) << 3))
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -13,7 +13,6 @@
#include <linux/irq.h>
#include <linux/msi.h>
#include <asm/pbm.h>
#include <asm/iommu.h>
#include <asm/irq.h>
#include <asm/upa.h>
......@@ -677,29 +676,15 @@ static struct pci_ops pci_sun4v_ops = {
};
static void pbm_scan_bus(struct pci_controller_info *p,
struct pci_pbm_info *pbm)
{
pbm->pci_bus = pci_scan_one_pbm(pbm);
}
static void pci_sun4v_scan_bus(struct pci_controller_info *p)
static void pci_sun4v_scan_bus(struct pci_pbm_info *pbm)
{
struct property *prop;
struct device_node *dp;
if ((dp = p->pbm_A.prom_node) != NULL) {
prop = of_find_property(dp, "66mhz-capable", NULL);
p->pbm_A.is_66mhz_capable = (prop != NULL);
pbm_scan_bus(p, &p->pbm_A);
}
if ((dp = p->pbm_B.prom_node) != NULL) {
prop = of_find_property(dp, "66mhz-capable", NULL);
p->pbm_B.is_66mhz_capable = (prop != NULL);
pbm_scan_bus(p, &p->pbm_B);
}
dp = pbm->prom_node;
prop = of_find_property(dp, "66mhz-capable", NULL);
pbm->is_66mhz_capable = (prop != NULL);
pbm->pci_bus = pci_scan_one_pbm(pbm);
/* XXX register error interrupt handlers XXX */
}
......@@ -802,20 +787,6 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
pbm->name, sz);
}
static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm)
{
struct property *prop;
unsigned int *busrange;
prop = of_find_property(pbm->prom_node, "bus-range", NULL);
busrange = prop->value;
pbm->pci_first_busno = busrange[0];
pbm->pci_last_busno = busrange[1];
}
#ifdef CONFIG_PCI_MSI
struct pci_sun4v_msiq_entry {
u64 version_type;
......@@ -1019,114 +990,6 @@ h_error:
return -EINVAL;
}
static void pci_sun4v_msi_init(struct pci_pbm_info *pbm)
{
const u32 *val;
int len;
val = of_get_property(pbm->prom_node, "#msi-eqs", &len);
if (!val || len != 4)
goto no_msi;
pbm->msiq_num = *val;
if (pbm->msiq_num) {
const struct msiq_prop {
u32 first_msiq;
u32 num_msiq;
u32 first_devino;
} *mqp;
const struct msi_range_prop {
u32 first_msi;
u32 num_msi;
} *mrng;
const struct addr_range_prop {
u32 msi32_high;
u32 msi32_low;
u32 msi32_len;
u32 msi64_high;
u32 msi64_low;
u32 msi64_len;
} *arng;
val = of_get_property(pbm->prom_node, "msi-eq-size", &len);
if (!val || len != 4)
goto no_msi;
pbm->msiq_ent_count = *val;
mqp = of_get_property(pbm->prom_node,
"msi-eq-to-devino", &len);
if (!mqp || len != sizeof(struct msiq_prop))
goto no_msi;
pbm->msiq_first = mqp->first_msiq;
pbm->msiq_first_devino = mqp->first_devino;
val = of_get_property(pbm->prom_node, "#msi", &len);
if (!val || len != 4)
goto no_msi;
pbm->msi_num = *val;
mrng = of_get_property(pbm->prom_node, "msi-ranges", &len);
if (!mrng || len != sizeof(struct msi_range_prop))
goto no_msi;
pbm->msi_first = mrng->first_msi;
val = of_get_property(pbm->prom_node, "msi-data-mask", &len);
if (!val || len != 4)
goto no_msi;
pbm->msi_data_mask = *val;
val = of_get_property(pbm->prom_node, "msix-data-width", &len);
if (!val || len != 4)
goto no_msi;
pbm->msix_data_width = *val;
arng = of_get_property(pbm->prom_node, "msi-address-ranges",
&len);
if (!arng || len != sizeof(struct addr_range_prop))
goto no_msi;
pbm->msi32_start = ((u64)arng->msi32_high << 32) |
(u64) arng->msi32_low;
pbm->msi64_start = ((u64)arng->msi64_high << 32) |
(u64) arng->msi64_low;
pbm->msi32_len = arng->msi32_len;
pbm->msi64_len = arng->msi64_len;
if (msi_bitmap_alloc(pbm))
goto no_msi;
if (msi_queue_alloc(pbm)) {
msi_bitmap_free(pbm);
goto no_msi;
}
printk(KERN_INFO "%s: MSI Queue first[%u] num[%u] count[%u] "
"devino[0x%x]\n",
pbm->name,
pbm->msiq_first, pbm->msiq_num,
pbm->msiq_ent_count,
pbm->msiq_first_devino);
printk(KERN_INFO "%s: MSI first[%u] num[%u] mask[0x%x] "
"width[%u]\n",
pbm->name,
pbm->msi_first, pbm->msi_num, pbm->msi_data_mask,
pbm->msix_data_width);
printk(KERN_INFO "%s: MSI addr32[0x%lx:0x%x] "
"addr64[0x%lx:0x%x]\n",
pbm->name,
pbm->msi32_start, pbm->msi32_len,
pbm->msi64_start, pbm->msi64_len);
printk(KERN_INFO "%s: MSI queues at RA [%p]\n",
pbm->name,
pbm->msi_queues);
}
return;
no_msi:
pbm->msiq_num = 0;
printk(KERN_INFO "%s: No MSI support.\n", pbm->name);
}
static int alloc_msi(struct pci_pbm_info *pbm)
{
......@@ -1245,6 +1108,117 @@ static void pci_sun4v_teardown_msi_irq(unsigned int virt_irq,
*/
sun4v_destroy_msi(virt_irq);
}
static void pci_sun4v_msi_init(struct pci_pbm_info *pbm)
{
const u32 *val;
int len;
val = of_get_property(pbm->prom_node, "#msi-eqs", &len);
if (!val || len != 4)
goto no_msi;
pbm->msiq_num = *val;
if (pbm->msiq_num) {
const struct msiq_prop {
u32 first_msiq;
u32 num_msiq;
u32 first_devino;
} *mqp;
const struct msi_range_prop {
u32 first_msi;
u32 num_msi;
} *mrng;
const struct addr_range_prop {
u32 msi32_high;
u32 msi32_low;
u32 msi32_len;
u32 msi64_high;
u32 msi64_low;
u32 msi64_len;
} *arng;
val = of_get_property(pbm->prom_node, "msi-eq-size", &len);
if (!val || len != 4)
goto no_msi;
pbm->msiq_ent_count = *val;
mqp = of_get_property(pbm->prom_node,
"msi-eq-to-devino", &len);
if (!mqp || len != sizeof(struct msiq_prop))
goto no_msi;
pbm->msiq_first = mqp->first_msiq;
pbm->msiq_first_devino = mqp->first_devino;
val = of_get_property(pbm->prom_node, "#msi", &len);
if (!val || len != 4)
goto no_msi;
pbm->msi_num = *val;
mrng = of_get_property(pbm->prom_node, "msi-ranges", &len);
if (!mrng || len != sizeof(struct msi_range_prop))
goto no_msi;
pbm->msi_first = mrng->first_msi;
val = of_get_property(pbm->prom_node, "msi-data-mask", &len);
if (!val || len != 4)
goto no_msi;
pbm->msi_data_mask = *val;
val = of_get_property(pbm->prom_node, "msix-data-width", &len);
if (!val || len != 4)
goto no_msi;
pbm->msix_data_width = *val;
arng = of_get_property(pbm->prom_node, "msi-address-ranges",
&len);
if (!arng || len != sizeof(struct addr_range_prop))
goto no_msi;
pbm->msi32_start = ((u64)arng->msi32_high << 32) |
(u64) arng->msi32_low;
pbm->msi64_start = ((u64)arng->msi64_high << 32) |
(u64) arng->msi64_low;
pbm->msi32_len = arng->msi32_len;
pbm->msi64_len = arng->msi64_len;
if (msi_bitmap_alloc(pbm))
goto no_msi;
if (msi_queue_alloc(pbm)) {
msi_bitmap_free(pbm);
goto no_msi;
}
printk(KERN_INFO "%s: MSI Queue first[%u] num[%u] count[%u] "
"devino[0x%x]\n",
pbm->name,
pbm->msiq_first, pbm->msiq_num,
pbm->msiq_ent_count,
pbm->msiq_first_devino);
printk(KERN_INFO "%s: MSI first[%u] num[%u] mask[0x%x] "
"width[%u]\n",
pbm->name,
pbm->msi_first, pbm->msi_num, pbm->msi_data_mask,
pbm->msix_data_width);
printk(KERN_INFO "%s: MSI addr32[0x%lx:0x%x] "
"addr64[0x%lx:0x%x]\n",
pbm->name,
pbm->msi32_start, pbm->msi32_len,
pbm->msi64_start, pbm->msi64_len);
printk(KERN_INFO "%s: MSI queues at RA [%p]\n",
pbm->name,
pbm->msi_queues);
}
pbm->setup_msi_irq = pci_sun4v_setup_msi_irq;
pbm->teardown_msi_irq = pci_sun4v_teardown_msi_irq;
return;
no_msi:
pbm->msiq_num = 0;
printk(KERN_INFO "%s: No MSI support.\n", pbm->name);
}
#else /* CONFIG_PCI_MSI */
static void pci_sun4v_msi_init(struct pci_pbm_info *pbm)
{
......@@ -1260,6 +1234,14 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node
else
pbm = &p->pbm_A;
pbm->next = pci_pbm_root;
pci_pbm_root = pbm;
pbm->scan_bus = pci_sun4v_scan_bus;
pbm->pci_ops = &pci_sun4v_ops;
pbm->index = pci_num_pbms++;
pbm->parent = p;
pbm->prom_node = dp;
......@@ -1271,7 +1253,7 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node
pci_determine_mem_io_space(pbm);
pci_sun4v_get_bus_range(pbm);
pci_get_pbm_props(pbm);
pci_sun4v_iommu_init(pbm);
pci_sun4v_msi_init(pbm);
}
......@@ -1279,6 +1261,7 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node
void sun4v_pci_init(struct device_node *dp, char *model_name)
{
struct pci_controller_info *p;
struct pci_pbm_info *pbm;
struct iommu *iommu;
struct property *prop;
struct linux_prom64_registers *regs;
......@@ -1290,18 +1273,9 @@ void sun4v_pci_init(struct device_node *dp, char *model_name)
devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff;
for (p = pci_controller_root; p; p = p->next) {
struct pci_pbm_info *pbm;
if (p->pbm_A.prom_node && p->pbm_B.prom_node)
continue;
pbm = (p->pbm_A.prom_node ?
&p->pbm_A :
&p->pbm_B);
for (pbm = pci_pbm_root; pbm; pbm = pbm->next) {
if (pbm->devhandle == (devhandle ^ 0x40)) {
pci_sun4v_pbm_init(p, dp, devhandle);
pci_sun4v_pbm_init(pbm->parent, dp, devhandle);
return;
}
}
......@@ -1331,18 +1305,6 @@ void sun4v_pci_init(struct device_node *dp, char *model_name)
p->pbm_B.iommu = iommu;
p->next = pci_controller_root;
pci_controller_root = p;
p->index = pci_num_controllers++;
p->scan_bus = pci_sun4v_scan_bus;
#ifdef CONFIG_PCI_MSI
p->setup_msi_irq = pci_sun4v_setup_msi_irq;
p->teardown_msi_irq = pci_sun4v_teardown_msi_irq;
#endif
p->pci_ops = &pci_sun4v_ops;
/* Like PSYCHO and SCHIZO we have a 2GB aligned area
* for memory space.
*/
......
......@@ -1002,24 +1002,24 @@ static void __init sysio_register_error_handlers(struct sbus_bus *sbus)
u64 control;
irq = sbus_build_irq(sbus, SYSIO_UE_INO);
if (request_irq(irq, sysio_ue_handler,
IRQF_SHARED, "SYSIO UE", sbus) < 0) {
if (request_irq(irq, sysio_ue_handler, 0,
"SYSIO_UE", sbus) < 0) {
prom_printf("SYSIO[%x]: Cannot register UE interrupt.\n",
sbus->portid);
prom_halt();
}
irq = sbus_build_irq(sbus, SYSIO_CE_INO);
if (request_irq(irq, sysio_ce_handler,
IRQF_SHARED, "SYSIO CE", sbus) < 0) {
if (request_irq(irq, sysio_ce_handler, 0,
"SYSIO_CE", sbus) < 0) {
prom_printf("SYSIO[%x]: Cannot register CE interrupt.\n",
sbus->portid);
prom_halt();
}
irq = sbus_build_irq(sbus, SYSIO_SBUSERR_INO);
if (request_irq(irq, sysio_sbus_error_handler,
IRQF_SHARED, "SYSIO SBUS Error", sbus) < 0) {
if (request_irq(irq, sysio_sbus_error_handler, 0,
"SYSIO_SBERR", sbus) < 0) {
prom_printf("SYSIO[%x]: Cannot register SBUS Error interrupt.\n",
sbus->portid);
prom_halt();
......
......@@ -793,7 +793,7 @@ asmlinkage long sys32_utimes(char __user *filename,
tv[1].tv_nsec = 1000 * ktvs[1].tv_usec;
}
return do_utimes(AT_FDCWD, filename, tvs ? tv : NULL);
return do_utimes(AT_FDCWD, filename, tvs ? tv : NULL, 0);
}
/* These are here just in case some old sparc32 binary calls it. */
......
......@@ -81,6 +81,7 @@ sys_call_table32:
.word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare
/*300*/ .word compat_sys_set_robust_list, compat_sys_get_robust_list, compat_sys_migrate_pages, compat_sys_mbind, compat_sys_get_mempolicy
.word compat_sys_set_mempolicy, compat_sys_kexec_load, compat_sys_move_pages, sys_getcpu, compat_sys_epoll_pwait
/*310*/ .word compat_sys_utimensat
#endif /* CONFIG_COMPAT */
......@@ -152,6 +153,7 @@ sys_call_table:
.word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
/*300*/ .word sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
.word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
/*310*/ .word sys_utimensat
#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
defined(CONFIG_SOLARIS_EMUL_MODULE)
......@@ -269,5 +271,6 @@ sunos_sys_table:
.word sunos_nosys, sunos_nosys, sunos_nosys
.word sunos_nosys, sunos_nosys, sunos_nosys
.word sunos_nosys
/*310*/ .long sunos_nosys
#endif
......@@ -32,36 +32,23 @@
#include <asm/mmu_context.h>
#ifdef CONFIG_KPROBES
ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
/* Hook to register for page fault notifications */
int register_page_fault_notifier(struct notifier_block *nb)
static inline int notify_page_fault(struct pt_regs *regs)
{
return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
}
int unregister_page_fault_notifier(struct notifier_block *nb)
{
return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
}
static inline int notify_page_fault(enum die_val val, const char *str,
struct pt_regs *regs, long err, int trap, int sig)
{
struct die_args args = {
.regs = regs,
.str = str,
.err = err,
.trapnr = trap,
.signr = sig
};
return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
int ret = 0;
/* kprobe_running() needs smp_processor_id() */
if (!user_mode(regs)) {
preempt_disable();
if (kprobe_running() && kprobe_fault_handler(regs, 0))
ret = 1;
preempt_enable();
}
return ret;
}
#else
static inline int notify_page_fault(enum die_val val, const char *str,
struct pt_regs *regs, long err, int trap, int sig)
static inline int notify_page_fault(struct pt_regs *regs)
{
return NOTIFY_DONE;
return 0;
}
#endif
......@@ -120,9 +107,6 @@ static void __kprobes unhandled_fault(unsigned long address,
printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %016lx\n",
(tsk->mm ? (unsigned long) tsk->mm->pgd :
(unsigned long) tsk->active_mm->pgd));
if (notify_die(DIE_GPF, "general protection fault", regs,
0, 0, SIGSEGV) == NOTIFY_STOP)
return;
die_if_kernel("Oops", regs);
}
......@@ -299,8 +283,7 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
fault_code = get_thread_fault_code();
if (notify_page_fault(DIE_PAGE_FAULT, "page_fault", regs,
fault_code, 0, SIGSEGV) == NOTIFY_STOP)
if (notify_page_fault(regs))
return;
si_code = SEGV_MAPERR;
......
......@@ -13,7 +13,6 @@
#ifdef CONFIG_SPARC
#include <asm/prom.h>
#include <asm/pbm.h>
#endif
/* XXX(hch): this is ugly, but we don't want to pull in exioctl.h */
......@@ -1397,9 +1396,8 @@ static void qla2xxx_nvram_wwn_from_ofw(scsi_qla_host_t *ha, nvram_t *nv)
{
#ifdef CONFIG_SPARC
struct pci_dev *pdev = ha->pdev;
struct pcidev_cookie *pcp = pdev->sysdata;
struct device_node *dp = pcp->prom_node;
u8 *val;
struct device_node *dp = pci_device_to_OF_node(pdev);
const u8 *val;
int len;
val = of_get_property(dp, "port-wwn", &len);
......@@ -3370,9 +3368,8 @@ static void qla24xx_nvram_wwn_from_ofw(scsi_qla_host_t *ha, struct nvram_24xx *n
{
#ifdef CONFIG_SPARC
struct pci_dev *pdev = ha->pdev;
struct pcidev_cookie *pcp = pdev->sysdata;
struct device_node *dp = pcp->prom_node;
u8 *val;
struct device_node *dp = pci_device_to_OF_node(pdev);
const u8 *val;
int len;
val = of_get_property(dp, "port-wwn", &len);
......
......@@ -80,8 +80,9 @@
#include "../macmodes.h"
#endif
#ifdef __sparc__
#include <asm/pbm.h>
#include <asm/fbio.h>
#include <asm/oplib.h>
#include <asm/prom.h>
#endif
#ifdef CONFIG_ADB_PMU
......
......@@ -11,7 +11,6 @@
#include <asm/uaccess.h>
#ifdef __sparc__
#include <asm/pbm.h>
#include <asm/fbio.h>
#endif
......
......@@ -326,8 +326,9 @@
#define __NR_move_pages 307
#define __NR_getcpu 308
#define __NR_epoll_pwait 309
#define __NR_utimensat 310
#define NR_SYSCALLS 310
#define NR_SYSCALLS 311
#ifdef __KERNEL__
#define __ARCH_WANT_IPC_PARSE_VERSION
......
......@@ -7,8 +7,19 @@
struct pt_regs;
extern int register_page_fault_notifier(struct notifier_block *);
extern int unregister_page_fault_notifier(struct notifier_block *);
/*
* These are only here because kprobes.c wants them to implement a
* blatant layering violation. Will hopefully go away soon once all
* architectures are updated.
*/
static inline int register_page_fault_notifier(struct notifier_block *nb)
{
return 0;
}
static inline int unregister_page_fault_notifier(struct notifier_block *nb)
{
return 0;
}
extern void bad_trap(struct pt_regs *, long);
......@@ -20,7 +31,6 @@ enum die_val {
DIE_DIE,
DIE_TRAP,
DIE_TRAP_TL1,
DIE_GPF,
DIE_CALL,
DIE_PAGE_FAULT,
};
......
......@@ -43,4 +43,5 @@ struct kprobe_ctlblk {
extern int kprobe_exceptions_notify(struct notifier_block *self,
unsigned long val, void *data);
extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
#endif /* _SPARC64_KPROBES_H */
/* pbm.h: UltraSparc PCI controller software state.
*
* Copyright (C) 1997, 1998, 1999, 2007 David S. Miller (davem@davemloft.net)
*/
#ifndef __SPARC64_PBM_H
#define __SPARC64_PBM_H
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/ioport.h>
#include <linux/spinlock.h>
#include <linux/msi.h>
#include <asm/io.h>
#include <asm/page.h>
#include <asm/oplib.h>
#include <asm/prom.h>
#include <asm/of_device.h>
#include <asm/iommu.h>
/* The abstraction used here is that there are PCI controllers,
* each with one (Sabre) or two (PSYCHO/SCHIZO) PCI bus modules
* underneath. Each PCI bus module uses an IOMMU (shared by both
* PBMs of a controller, or per-PBM), and if a streaming buffer
* is present, each PCI bus module has it's own. (ie. the IOMMU
* might be shared between PBMs, the STC is never shared)
* Furthermore, each PCI bus module controls it's own autonomous
* PCI bus.
*/
extern void pci_iommu_table_init(struct iommu *iommu, int tsbsize, u32 dma_offset, u32 dma_addr_mask);
#define PCI_STC_FLUSHFLAG_INIT(STC) \
(*((STC)->strbuf_flushflag) = 0UL)
#define PCI_STC_FLUSHFLAG_SET(STC) \
(*((STC)->strbuf_flushflag) != 0UL)
/* There can be quite a few ranges and interrupt maps on a PCI
* segment. Thus...
*/
#define PROM_PCIRNG_MAX 64
#define PROM_PCIIMAP_MAX 64
struct pci_controller_info;
struct pci_pbm_info {
/* PCI controller we sit under. */
struct pci_controller_info *parent;
/* Physical address base of controller registers. */
unsigned long controller_regs;
/* Physical address base of PBM registers. */
unsigned long pbm_regs;
/* Physical address of DMA sync register, if any. */
unsigned long sync_reg;
/* Opaque 32-bit system bus Port ID. */
u32 portid;
/* Opaque 32-bit handle used for hypervisor calls. */
u32 devhandle;
/* Chipset version information. */
int chip_type;
#define PBM_CHIP_TYPE_SABRE 1
#define PBM_CHIP_TYPE_PSYCHO 2
#define PBM_CHIP_TYPE_SCHIZO 3
#define PBM_CHIP_TYPE_SCHIZO_PLUS 4
#define PBM_CHIP_TYPE_TOMATILLO 5
int chip_version;
int chip_revision;
/* Name used for top-level resources. */
char *name;
/* OBP specific information. */
struct device_node *prom_node;
u64 ino_bitmap;
/* PBM I/O and Memory space resources. */
struct resource io_space;
struct resource mem_space;
/* Base of PCI Config space, can be per-PBM or shared. */
unsigned long config_space;
/* State of 66MHz capabilities on this PBM. */
int is_66mhz_capable;
int all_devs_66mhz;
#ifdef CONFIG_PCI_MSI
/* MSI info. */
u32 msiq_num;
u32 msiq_ent_count;
u32 msiq_first;
u32 msiq_first_devino;
u32 msi_num;
u32 msi_first;
u32 msi_data_mask;
u32 msix_data_width;
u64 msi32_start;
u64 msi64_start;
u32 msi32_len;
u32 msi64_len;
void *msi_queues;
unsigned long *msi_bitmap;
#endif /* !(CONFIG_PCI_MSI) */
/* This PBM's streaming buffer. */
struct strbuf stc;
/* IOMMU state, potentially shared by both PBM segments. */
struct iommu *iommu;
/* Now things for the actual PCI bus probes. */
unsigned int pci_first_busno;
unsigned int pci_last_busno;
struct pci_bus *pci_bus;
};
struct pci_controller_info {
/* List of all PCI controllers. */
struct pci_controller_info *next;
/* Each controller gets a unique index, used mostly for
* error logging purposes.
*/
int index;
/* The PCI bus modules controlled by us. */
struct pci_pbm_info pbm_A;
struct pci_pbm_info pbm_B;
/* Operations which are controller specific. */
void (*scan_bus)(struct pci_controller_info *);
#ifdef CONFIG_PCI_MSI
int (*setup_msi_irq)(unsigned int *virt_irq_p, struct pci_dev *pdev,
struct msi_desc *entry);
void (*teardown_msi_irq)(unsigned int virt_irq, struct pci_dev *pdev);
#endif
/* Now things for the actual PCI bus probes. */
struct pci_ops *pci_ops;
unsigned int pci_first_busno;
unsigned int pci_last_busno;
};
#endif /* !(__SPARC64_PBM_H) */
......@@ -328,8 +328,9 @@
#define __NR_move_pages 307
#define __NR_getcpu 308
#define __NR_epoll_pwait 309
#define __NR_utimensat 310
#define NR_SYSCALLS 310
#define NR_SYSCALLS 311
#ifdef __KERNEL__
/* sysconf options, for SunOS compatibility */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment