Commit 260aae1b authored by Linus Torvalds's avatar Linus Torvalds

Merge http://ppc.bkbits.net/for-linus-ppc64

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 036171f7 ea3c96e3
...@@ -37,6 +37,10 @@ config COMPAT ...@@ -37,6 +37,10 @@ config COMPAT
bool bool
default y default y
config FRAME_POINTER
bool
default y
source "init/Kconfig" source "init/Kconfig"
......
...@@ -66,7 +66,6 @@ ...@@ -66,7 +66,6 @@
extern volatile unsigned char *chrp_int_ack_special; extern volatile unsigned char *chrp_int_ack_special;
void chrp_progress(char *, unsigned short); void chrp_progress(char *, unsigned short);
void chrp_request_regions(void);
extern void openpic_init_IRQ(void); extern void openpic_init_IRQ(void);
extern void init_ras_IRQ(void); extern void init_ras_IRQ(void);
...@@ -141,11 +140,12 @@ chrp_setup_arch(void) ...@@ -141,11 +140,12 @@ chrp_setup_arch(void)
fwnmi_init(); fwnmi_init();
#ifndef CONFIG_PPC_ISERIES
/* Find and initialize PCI host bridges */ /* Find and initialize PCI host bridges */
/* iSeries needs to be done much later. */ /* iSeries needs to be done much later. */
#ifndef CONFIG_PPC_ISERIES eeh_init();
find_and_init_phbs(); find_and_init_phbs();
#endif #endif
/* Find the Open PIC if present */ /* Find the Open PIC if present */
root = find_path_device("/"); root = find_path_device("/");
...@@ -169,11 +169,6 @@ chrp_setup_arch(void) ...@@ -169,11 +169,6 @@ chrp_setup_arch(void)
void __init void __init
chrp_init2(void) chrp_init2(void)
{ {
/*
* It is sensitive, when this is called (not too earlu)
* -- tibit
*/
chrp_request_regions();
/* Manually leave the kernel version on the panel. */ /* Manually leave the kernel version on the panel. */
ppc_md.progress("Linux ppc64\n", 0); ppc_md.progress("Linux ppc64\n", 0);
ppc_md.progress(UTS_RELEASE, 0); ppc_md.progress(UTS_RELEASE, 0);
......
...@@ -43,25 +43,25 @@ static int ibm_set_eeh_option; ...@@ -43,25 +43,25 @@ static int ibm_set_eeh_option;
static int ibm_set_slot_reset; static int ibm_set_slot_reset;
static int ibm_read_slot_reset_state; static int ibm_read_slot_reset_state;
int eeh_implemented; static int eeh_implemented;
#define EEH_MAX_OPTS 4096 #define EEH_MAX_OPTS 4096
static char *eeh_opts; static char *eeh_opts;
static int eeh_opts_last; static int eeh_opts_last;
static int eeh_check_opts_config(struct pci_dev *dev, int default_state);
pte_t *find_linux_pte(pgd_t *pgdir, unsigned long va); /* from htab.c */
static int eeh_check_opts_config(struct device_node *dn,
int class_code, int vendor_id, int device_id,
int default_state);
unsigned long eeh_token(unsigned long phb, unsigned long bus, unsigned long devfn, unsigned long offset) unsigned long eeh_token_to_phys(unsigned long token)
{ {
if (phb > 0xff) if (REGION_ID(token) == EEH_REGION_ID) {
panic("eeh_token: phb 0x%lx is too large\n", phb); unsigned long vaddr = IO_TOKEN_TO_ADDR(token);
if (offset & 0x0fffffff00000000) pte_t *ptep = find_linux_pte(ioremap_mm.pgd, vaddr);
panic("eeh_token: offset 0x%lx is out of range\n", offset); unsigned long pa = pte_pfn(*ptep) << PAGE_SHIFT;
return ((IO_UNMAPPED_REGION_ID << 60) | (phb << 48UL) | ((bus & 0xff) << 40UL) | (devfn << 32UL) | (offset & 0xffffffff)); return pa | (vaddr & (PAGE_SIZE-1));
} } else
return token;
int eeh_get_state(unsigned long ea)
{
return 0;
} }
/* Check for an eeh failure at the given token address. /* Check for an eeh failure at the given token address.
...@@ -73,40 +73,54 @@ int eeh_get_state(unsigned long ea) ...@@ -73,40 +73,54 @@ int eeh_get_state(unsigned long ea)
*/ */
unsigned long eeh_check_failure(void *token, unsigned long val) unsigned long eeh_check_failure(void *token, unsigned long val)
{ {
unsigned long config_addr = (unsigned long)token >> 24; /* PPBBDDRR */ unsigned long addr;
unsigned long phbidx = (config_addr >> 24) & 0xff; struct pci_dev *dev;
struct pci_controller *phb; struct device_node *dn;
unsigned long ret, rets[2]; unsigned long ret, rets[2];
config_addr &= 0xffff00; /* 00BBDD00 */ /* IO BAR access could get us here...or if we manually force EEH
* operation on even if the hardware won't support it.
*/
if (!eeh_implemented || ibm_read_slot_reset_state == RTAS_UNKNOWN_SERVICE)
return val;
if (phbidx >= global_phb_number) { /* Finding the phys addr + pci device is quite expensive.
panic("EEH: checking token %p phb index of %ld is greater than max of %d\n", token, phbidx, global_phb_number-1); * However, the RTAS call is MUCH slower.... :(
*/
addr = eeh_token_to_phys((unsigned long)token);
dev = pci_find_dev_by_addr(addr);
if (!dev) {
printk("EEH: no pci dev found for addr=0x%lx\n", addr);
return val;
} }
phb = phbtab[phbidx]; dn = pci_device_to_OF_node(dev);
if (!dn) {
ret = rtas_call(ibm_read_slot_reset_state, 3, 3, rets, printk("EEH: no pci dn found for addr=0x%lx\n", addr);
config_addr, BUID_HI(phb->buid), BUID_LO(phb->buid)); return val;
if (ret == 0 && rets[1] == 1 && rets[0] >= 2) { }
struct pci_dev *dev;
int bus = ((unsigned long)token >> 40) & 0xffff; /* include PHB# in bus */ /* Access to IO BARs might get this far and still not want checking. */
int devfn = (config_addr >> 8) & 0xff; if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) || dn->eeh_mode & EEH_MODE_NOCHECK)
return val;
dev = pci_find_slot(bus, devfn);
if (dev) {
printk(KERN_ERR "EEH: MMIO failure (%ld) on device:\n %s %s\n", /* Now test for an EEH failure. This is VERY expensive.
rets[0], dev->slot_name, dev->dev.name); * Note that the eeh_config_addr may be a parent device
PPCDBG_ENTER_DEBUGGER(); * in the case of a device behind a bridge, or it may be
* function zero of a multi-function device.
* In any case they must share a common PHB.
*/
if (dn->eeh_config_addr) {
ret = rtas_call(ibm_read_slot_reset_state, 3, 3, rets,
dn->eeh_config_addr, BUID_HI(dn->phb->buid), BUID_LO(dn->phb->buid));
if (ret == 0 && rets[1] == 1 && rets[0] >= 2) {
panic("EEH: MMIO failure (%ld) on device:\n %s %s\n", panic("EEH: MMIO failure (%ld) on device:\n %s %s\n",
rets[0], dev->slot_name, dev->dev.name); rets[0], dev->slot_name, dev->dev.name);
} else {
printk(KERN_ERR "EEH: MMIO failure (%ld) on device buid %lx, config_addr %lx\n", rets[0], phb->buid, config_addr);
PPCDBG_ENTER_DEBUGGER();
panic("EEH: MMIO failure (%ld) on device buid %lx, config_addr %lx\n", rets[0], phb->buid, config_addr);
} }
} }
eeh_false_positives++; eeh_false_positives++;
return val; /* good case */ return val; /* good case */
} }
struct eeh_early_enable_info { struct eeh_early_enable_info {
...@@ -120,13 +134,69 @@ static void *early_enable_eeh(struct device_node *dn, void *data) ...@@ -120,13 +134,69 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
{ {
struct eeh_early_enable_info *info = data; struct eeh_early_enable_info *info = data;
long ret; long ret;
char *status = get_property(dn, "status", 0);
u32 *class_code = (u32 *)get_property(dn, "class-code", 0);
u32 *vendor_id =(u32 *) get_property(dn, "vendor-id", 0);
u32 *device_id = (u32 *)get_property(dn, "device-id", 0);
u32 *regs;
int enable;
if (status && strcmp(status, "ok") != 0)
return NULL; /* ignore devices with bad status */
/* Weed out PHBs or other bad nodes. */
if (!class_code || !vendor_id || !device_id)
return NULL;
/* Ignore known PHBs and EADs bridges */
if (*vendor_id == PCI_VENDOR_ID_IBM &&
(*device_id == 0x0102 || *device_id == 0x008b ||
*device_id == 0x0188 || *device_id == 0x0302))
return NULL;
/* Now decide if we are going to "Disable" EEH checking
* for this device. We still run with the EEH hardware active,
* but we won't be checking for ff's. This means a driver
* could return bad data (very bad!), an interrupt handler could
* hang waiting on status bits that won't change, etc.
* But there are a few cases like display devices that make sense.
*/
enable = 1; /* i.e. we will do checking */
if ((*class_code >> 16) == PCI_BASE_CLASS_DISPLAY)
enable = 0;
if (!eeh_check_opts_config(dn, *class_code, *vendor_id, *device_id, enable)) {
if (enable) {
printk(KERN_INFO "EEH: %s user requested to run without EEH.\n", dn->full_name);
enable = 0;
}
}
if (!enable)
dn->eeh_mode = EEH_MODE_NOCHECK;
/* Try to enable eeh */ /* This device may already have an EEH parent. */
ret = rtas_call(ibm_set_eeh_option, 4, 1, NULL, if (dn->parent && (dn->parent->eeh_mode & EEH_MODE_SUPPORTED)) {
CONFIG_ADDR(dn->busno, dn->devfn), /* Parent supports EEH. */
info->buid_hi, info->buid_lo, EEH_ENABLE); dn->eeh_mode |= EEH_MODE_SUPPORTED;
if (ret == 0) dn->eeh_config_addr = dn->parent->eeh_config_addr;
info->adapters_enabled++; return NULL;
}
/* Ok..see if this device supports EEH. */
regs = (u32 *)get_property(dn, "reg", 0);
if (regs) {
/* First register entry is addr (00BBSS00) */
/* Try to enable eeh */
ret = rtas_call(ibm_set_eeh_option, 4, 1, NULL,
regs[0], info->buid_hi, info->buid_lo,
EEH_ENABLE);
if (ret == 0) {
info->adapters_enabled++;
dn->eeh_mode |= EEH_MODE_SUPPORTED;
dn->eeh_config_addr = regs[0];
}
}
return NULL; return NULL;
} }
...@@ -157,7 +227,13 @@ void eeh_init(void) ...@@ -157,7 +227,13 @@ void eeh_init(void)
ibm_set_slot_reset = rtas_token("ibm,set-slot-reset"); ibm_set_slot_reset = rtas_token("ibm,set-slot-reset");
ibm_read_slot_reset_state = rtas_token("ibm,read-slot-reset-state"); ibm_read_slot_reset_state = rtas_token("ibm,read-slot-reset-state");
if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE) /* Allow user to force eeh mode on or off -- even if the hardware
* doesn't exist. This allows driver writers to at least test use
* of I/O macros even if we can't actually test for EEH failure.
*/
if (eeh_force_on > eeh_force_off)
eeh_implemented = 1;
else if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE)
return; return;
if (eeh_force_off > eeh_force_on) { if (eeh_force_off > eeh_force_on) {
...@@ -168,8 +244,6 @@ void eeh_init(void) ...@@ -168,8 +244,6 @@ void eeh_init(void)
return; return;
} }
if (eeh_force_on > eeh_force_off)
eeh_implemented = 1; /* User is forcing it on. */
/* Enable EEH for all adapters. Note that eeh requires buid's */ /* Enable EEH for all adapters. Note that eeh requires buid's */
info.adapters_enabled = 0; info.adapters_enabled = 0;
...@@ -197,44 +271,6 @@ void eeh_init(void) ...@@ -197,44 +271,6 @@ void eeh_init(void)
} }
/* Given a PCI device check if eeh should be configured or not.
* This may look at firmware properties and/or kernel cmdline options.
*/
int is_eeh_configured(struct pci_dev *dev)
{
struct device_node *dn = pci_device_to_OF_node(dev);
struct pci_controller *phb = PCI_GET_PHB_PTR(dev);
unsigned long ret, rets[2];
int eeh_capable;
int default_state = 1; /* default enable EEH if we can. */
if (dn == NULL || phb == NULL || !eeh_implemented)
return 0;
/* Hack: turn off eeh for display class devices by default.
* This fixes matrox accel framebuffer.
*/
if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
default_state = 0;
/* Ignore known PHBs and EADs bridges */
if (dev->vendor == PCI_VENDOR_ID_IBM &&
(dev->device == 0x0102 || dev->device == 0x008b))
default_state = 0;
if (!eeh_check_opts_config(dev, default_state)) {
if (default_state)
printk(KERN_INFO "EEH: %s %s user requested to run without EEH.\n", dev->slot_name, dev->dev.name);
return 0;
}
ret = rtas_call(ibm_read_slot_reset_state, 3, 3, rets,
CONFIG_ADDR(dn->busno, dn->devfn),
BUID_HI(phb->buid), BUID_LO(phb->buid));
eeh_capable = (ret == 0 && rets[1] == 1);
return eeh_capable;
}
int eeh_set_option(struct pci_dev *dev, int option) int eeh_set_option(struct pci_dev *dev, int option)
{ {
struct device_node *dn = pci_device_to_OF_node(dev); struct device_node *dn = pci_device_to_OF_node(dev);
...@@ -249,6 +285,30 @@ int eeh_set_option(struct pci_dev *dev, int option) ...@@ -249,6 +285,30 @@ int eeh_set_option(struct pci_dev *dev, int option)
} }
/* If EEH is implemented, find the PCI device using given phys addr
* and check to see if eeh failure checking is disabled.
* Remap the addr (trivially) to the EEH region if not.
* For addresses not known to PCI the vaddr is simply returned unchanged.
*/
void *eeh_ioremap(unsigned long addr, void *vaddr)
{
struct pci_dev *dev;
struct device_node *dn;
if (!eeh_implemented)
return vaddr;
dev = pci_find_dev_by_addr(addr);
if (!dev)
return vaddr;
dn = pci_device_to_OF_node(dev);
if (!dn)
return vaddr;
if (dn->eeh_mode & EEH_MODE_NOCHECK)
return vaddr;
return (void *)IO_ADDR_TO_TOKEN(vaddr);
}
static int eeh_proc_falsepositive_read(char *page, char **start, off_t off, static int eeh_proc_falsepositive_read(char *page, char **start, off_t off,
int count, int *eof, void *data) int count, int *eof, void *data)
{ {
...@@ -279,28 +339,24 @@ static int __init eeh_init_proc(void) ...@@ -279,28 +339,24 @@ static int __init eeh_init_proc(void)
* This lets the user specify stupid combinations of options, * This lets the user specify stupid combinations of options,
* but at least the result should be very predictable. * but at least the result should be very predictable.
*/ */
static int eeh_check_opts_config(struct pci_dev *dev, int default_state) static int eeh_check_opts_config(struct device_node *dn,
int class_code, int vendor_id, int device_id,
int default_state)
{ {
struct device_node *dn = pci_device_to_OF_node(dev); char devname[32], classname[32];
struct pci_controller *phb = PCI_GET_PHB_PTR(dev);
char devname[32], classname[32], phbname[32];
char *strs[8], *s; char *strs[8], *s;
int nstrs, i; int nstrs, i;
int ret = default_state; int ret = default_state;
if (dn == NULL || phb == NULL)
return 0;
/* Build list of strings to match */ /* Build list of strings to match */
nstrs = 0; nstrs = 0;
s = (char *)get_property(dn, "ibm,loc-code", 0); s = (char *)get_property(dn, "ibm,loc-code", 0);
if (s) if (s)
strs[nstrs++] = s; strs[nstrs++] = s;
sprintf(devname, "dev%04x:%04x", dev->vendor, dev->device); sprintf(devname, "dev%04x:%04x", vendor_id, device_id);
strs[nstrs++] = devname; strs[nstrs++] = devname;
sprintf(classname, "class%04x", dev->class); sprintf(classname, "class%04x", class_code);
strs[nstrs++] = classname; strs[nstrs++] = classname;
sprintf(phbname, "pci@%lx", phb->buid);
strs[nstrs++] = phbname;
strs[nstrs++] = ""; /* yes, this matches the empty string */ strs[nstrs++] = ""; /* yes, this matches the empty string */
/* Now see if any string matches the eeh_opts list. /* Now see if any string matches the eeh_opts list.
...@@ -332,7 +388,6 @@ static int eeh_check_opts_config(struct pci_dev *dev, int default_state) ...@@ -332,7 +388,6 @@ static int eeh_check_opts_config(struct pci_dev *dev, int default_state)
* *
* dev#:# vendor:device id in hex (e.g. dev1022:2000) * dev#:# vendor:device id in hex (e.g. dev1022:2000)
* class# class id in hex (e.g. class0200) * class# class id in hex (e.g. class0200)
* pci@buid all devices under phb (e.g. pci@fef00000)
* *
* If no location code is specified all devices are assumed * If no location code is specified all devices are assumed
* so eeh-off means eeh by default is off. * so eeh-off means eeh by default is off.
...@@ -340,13 +395,11 @@ static int eeh_check_opts_config(struct pci_dev *dev, int default_state) ...@@ -340,13 +395,11 @@ static int eeh_check_opts_config(struct pci_dev *dev, int default_state)
/* This is implemented as a null separated list of strings. /* This is implemented as a null separated list of strings.
* Each string looks like this: "+X" or "-X" * Each string looks like this: "+X" or "-X"
* where X is a loc code, dev, class or pci string (as shown above) * where X is a loc code, vendor:device, class (as shown above)
* or empty which is used to indicate all. * or empty which is used to indicate all.
* *
* We interpret this option string list during the buswalk * We interpret this option string list so that it will literally
* so that it will literally behave left-to-right even if * behave left-to-right even if some combinations don't make sense.
* some combinations don't make sense. Give the user exactly
* what they want! :)
*/ */
static int __init eeh_parm(char *str, int state) static int __init eeh_parm(char *str, int state)
......
...@@ -393,7 +393,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) ...@@ -393,7 +393,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
mm = &init_mm; mm = &init_mm;
vsid = get_kernel_vsid(ea); vsid = get_kernel_vsid(ea);
break; break;
case IO_UNMAPPED_REGION_ID: case EEH_REGION_ID:
/* /*
* Should only be hit if there is an access to MMIO space * Should only be hit if there is an access to MMIO space
* which is protected by EEH. * which is protected by EEH.
......
...@@ -95,10 +95,23 @@ void list_device_nodes(void); ...@@ -95,10 +95,23 @@ void list_device_nodes(void);
struct pci_dev; struct pci_dev;
extern struct list_head iSeries_Global_Device_List; LIST_HEAD(iSeries_Global_Device_List);
int DeviceCount = 0; int DeviceCount = 0;
/* Counters and control flags. */
static long Pci_Io_Read_Count = 0;
static long Pci_Io_Write_Count = 0;
static long Pci_Cfg_Read_Count = 0;
static long Pci_Cfg_Write_Count= 0;
static long Pci_Error_Count = 0;
static int Pci_Retry_Max = 3; /* Only retry 3 times */
static int Pci_Error_Flag = 1; /* Set Retry Error on. */
static int Pci_Trace_Flag = 0;
/********************************************************************************** /**********************************************************************************
* Log Error infor in Flight Recorder to system Console. * Log Error infor in Flight Recorder to system Console.
* Filter out the device not there errors. * Filter out the device not there errors.
...@@ -912,17 +925,3 @@ iSeries_pcibios_init_early(void) ...@@ -912,17 +925,3 @@ iSeries_pcibios_init_early(void)
//ppc_md.pcibios_write_config_dword = iSeries_Node_write_config_dword; //ppc_md.pcibios_write_config_dword = iSeries_Node_write_config_dword;
} }
/************************************************************************/
/* Set the slot reset line to the state passed in. */
/* This is the platform specific for code for the pci_reset_device */
/* function. */
/************************************************************************/
int pci_set_reset(struct pci_dev* PciDev, int State) {
struct iSeries_Device_Node* DeviceNode = (struct iSeries_Device_Node*)PciDev->sysdata;
if (DeviceNode == NULL) {
printk("PCI: Pci Reset Failed, Device Node not found for pci_dev %p\n",PciDev);
return -1;
}
DeviceNode->ReturnCode = HvCallPci_setSlotReset(ISERIES_BUS(DeviceNode),0x00,DeviceNode->AgentId,State);
return DeviceNode->ReturnCode;
}
...@@ -410,7 +410,7 @@ static int shutdown( void ) ...@@ -410,7 +410,7 @@ static int shutdown( void )
mf_powerOff(); mf_powerOff();
} }
else else
printk( KERN_ALERT "mf.c: init has been successfully notified to proceed with shutdown\n" ); printk( KERN_INFO "mf.c: init has been successfully notified to proceed with shutdown\n" );
return rc; return rc;
} }
...@@ -436,7 +436,7 @@ static void intReceived( struct IoMFLpEvent * event ) ...@@ -436,7 +436,7 @@ static void intReceived( struct IoMFLpEvent * event )
case 0x5B: /* power control notification */ case 0x5B: /* power control notification */
if ( (event->xUnion.xCEMsgData.xCEMsg[5]&0x20) != 0 ) if ( (event->xUnion.xCEMsgData.xCEMsg[5]&0x20) != 0 )
{ {
printk( KERN_ALERT "mf.c: Commencing partition shutdown\n" ); printk( KERN_INFO "mf.c: Commencing partition shutdown\n" );
if ( shutdown() == 0 ) if ( shutdown() == 0 )
signalCEMsg( "\x00\x00\x00\xDB\x00\x00\x00\x00\x00\x00\x00\x00", NULL ); signalCEMsg( "\x00\x00\x00\xDB\x00\x00\x00\x00\x00\x00\x00\x00", NULL );
} }
...@@ -479,7 +479,7 @@ static void intReceived( struct IoMFLpEvent * event ) ...@@ -479,7 +479,7 @@ static void intReceived( struct IoMFLpEvent * event )
signalEvent( NULL ); signalEvent( NULL );
break; break;
case 1: /* IT sys shutdown */ case 1: /* IT sys shutdown */
printk( KERN_ALERT "mf.c: Commencing system shutdown\n" ); printk( KERN_INFO "mf.c: Commencing system shutdown\n" );
shutdown(); shutdown();
break; break;
} }
...@@ -666,7 +666,7 @@ void mf_deallocateLpEvents( HvLpIndex targetLp, ...@@ -666,7 +666,7 @@ void mf_deallocateLpEvents( HvLpIndex targetLp,
*/ */
void mf_powerOff( void ) void mf_powerOff( void )
{ {
printk( KERN_ALERT "mf.c: Down it goes...\n" ); printk( KERN_INFO "mf.c: Down it goes...\n" );
signalCEMsg( "\x00\x00\x00\x4D\x00\x00\x00\x00\x00\x00\x00\x00", NULL ); signalCEMsg( "\x00\x00\x00\x4D\x00\x00\x00\x00\x00\x00\x00\x00", NULL );
for (;;); for (;;);
} }
...@@ -677,7 +677,7 @@ void mf_powerOff( void ) ...@@ -677,7 +677,7 @@ void mf_powerOff( void )
*/ */
void mf_reboot( void ) void mf_reboot( void )
{ {
printk( KERN_ALERT "mf.c: Preparing to bounce...\n" ); printk( KERN_INFO "mf.c: Preparing to bounce...\n" );
signalCEMsg( "\x00\x00\x00\x4E\x00\x00\x00\x00\x00\x00\x00\x00", NULL ); signalCEMsg( "\x00\x00\x00\x4E\x00\x00\x00\x00\x00\x00\x00\x00", NULL );
for (;;); for (;;);
} }
......
...@@ -508,7 +508,7 @@ _GLOBAL(kernel_thread) ...@@ -508,7 +508,7 @@ _GLOBAL(kernel_thread)
/* Why isn't this a) automatic, b) written in 'C'? */ /* Why isn't this a) automatic, b) written in 'C'? */
.balign 8 .balign 8
_GLOBAL(sys_call_table32) _GLOBAL(sys_call_table32)
.llong .sys_ni_syscall /* 0 - old setup syscall */ .llong .sys_restart_syscall /* 0 */
.llong .sys_exit .llong .sys_exit
.llong .sys_fork .llong .sys_fork
.llong .sys_read .llong .sys_read
...@@ -756,7 +756,7 @@ _GLOBAL(sys_call_table32) ...@@ -756,7 +756,7 @@ _GLOBAL(sys_call_table32)
.balign 8 .balign 8
_GLOBAL(sys_call_table) _GLOBAL(sys_call_table)
.llong .sys_ni_syscall /* 0 - old setup syscall */ .llong .sys_restart_syscall /* 0 */
.llong .sys_exit .llong .sys_exit
.llong .sys_fork .llong .sys_fork
.llong .sys_read .llong .sys_read
......
...@@ -39,7 +39,6 @@ ...@@ -39,7 +39,6 @@
#include <asm/ppcdebug.h> #include <asm/ppcdebug.h>
#include <asm/naca.h> #include <asm/naca.h>
#include <asm/pci_dma.h> #include <asm/pci_dma.h>
#include <asm/eeh.h>
#include "xics.h" #include "xics.h"
#include "open_pic.h" #include "open_pic.h"
...@@ -50,8 +49,6 @@ ...@@ -50,8 +49,6 @@
*******************************************************************/ *******************************************************************/
struct pci_controller *alloc_phb(struct device_node *dev, char *model, struct pci_controller *alloc_phb(struct device_node *dev, char *model,
unsigned int addr_size_words) ; unsigned int addr_size_words) ;
static int rtas_fake_read(struct device_node *dn, int offset, int nbytes,
unsigned long *returnval);
/* RTAS tokens */ /* RTAS tokens */
static int read_pci_config; static int read_pci_config;
...@@ -74,8 +71,6 @@ static int rtas_read_config(struct device_node *dn, int where, int size, u32 *va ...@@ -74,8 +71,6 @@ static int rtas_read_config(struct device_node *dn, int where, int size, u32 *va
buid = dn->phb->buid; buid = dn->phb->buid;
if (buid) { if (buid) {
ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval, addr, buid >> 32, buid & 0xffffffff, size); ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval, addr, buid >> 32, buid & 0xffffffff, size);
if (ret < 0|| (returnval == 0xffffffff))
ret = rtas_fake_read(dn, where, size, &returnval);
} else { } else {
ret = rtas_call(read_pci_config, 2, 2, &returnval, addr, size); ret = rtas_call(read_pci_config, 2, 2, &returnval, addr, size);
} }
...@@ -142,48 +137,6 @@ struct pci_ops rtas_pci_ops = { ...@@ -142,48 +137,6 @@ struct pci_ops rtas_pci_ops = {
rtas_pci_write_config rtas_pci_write_config
}; };
/*
* Handle the case where rtas refuses to do a pci config read.
* This currently only happens with some PHBs in which case we totally fake
* out the values (and call it a speedwagaon -- something we could look up
* in the device tree).
*/
static int
rtas_fake_read(struct device_node *dn, int offset, int nbytes, unsigned long *returnval)
{
char *device_type = (char *)get_property(dn, "device_type", 0);
u32 *class_code = (u32 *)get_property(dn, "class-code", 0);
*returnval = ~0; /* float by default */
/* udbg_printf("rtas_fake_read dn=%p, offset=0x%02x, nbytes=%d, device_type=%s\n", dn, offset, nbytes, device_type ? device_type : "<none>"); */
if (device_type && strcmp(device_type, "pci") != 0)
return -3; /* Not a phb or bridge */
/* NOTE: class_code != NULL => EADS pci bridge. Else a PHB */
if (nbytes == 1) {
if (offset == PCI_HEADER_TYPE)
*returnval = 0x80; /* multifunction */
else if (offset == PCI_INTERRUPT_PIN || offset == PCI_INTERRUPT_LINE)
*returnval = 0;
} else if (nbytes == 2) {
if (offset == PCI_SUBSYSTEM_VENDOR_ID || offset == PCI_SUBSYSTEM_ID)
*returnval = 0;
else if (offset == PCI_COMMAND)
*returnval = PCI_COMMAND_PARITY|PCI_COMMAND_MASTER|PCI_COMMAND_MEMORY;
} else if (nbytes == 4) {
if (offset == PCI_VENDOR_ID)
*returnval = 0x1014 | ((class_code ? 0x8b : 0x102) << 16); /* a phb */
else if (offset == PCI_REVISION_ID)
*returnval = (class_code ? PCI_CLASS_BRIDGE_PCI : PCI_CLASS_BRIDGE_HOST) << 16; /* revs are zero */
else if ((offset >= PCI_BASE_ADDRESS_0 && offset <= PCI_BASE_ADDRESS_5) || offset == PCI_ROM_ADDRESS)
*returnval = 0;
}
/* printk("fake: %s nbytes=%d, offset=%lx ret=%lx\n", class_code ? "EADS" : "PHB", nbytes, offset, *returnval); */
return 0;
}
/****************************************************************** /******************************************************************
* pci_read_irq_line * pci_read_irq_line
* *
...@@ -250,8 +203,6 @@ find_and_init_phbs(void) ...@@ -250,8 +203,6 @@ find_and_init_phbs(void)
ibm_read_pci_config = rtas_token("ibm,read-pci-config"); ibm_read_pci_config = rtas_token("ibm,read-pci-config");
ibm_write_pci_config = rtas_token("ibm,write-pci-config"); ibm_write_pci_config = rtas_token("ibm,write-pci-config");
eeh_init();
if (naca->interrupt_controller == IC_OPEN_PIC) { if (naca->interrupt_controller == IC_OPEN_PIC) {
opprop = (unsigned int *)get_property(find_path_device("/"), opprop = (unsigned int *)get_property(find_path_device("/"),
"platform-open-pic", NULL); "platform-open-pic", NULL);
...@@ -350,24 +301,15 @@ find_and_init_phbs(void) ...@@ -350,24 +301,15 @@ find_and_init_phbs(void)
res = &phb->io_resource; res = &phb->io_resource;
res->name = Pci_Node->full_name; res->name = Pci_Node->full_name;
res->flags = IORESOURCE_IO; res->flags = IORESOURCE_IO;
if (is_eeh_implemented()) { phb->io_base_virt = __ioremap(phb->io_base_phys, range.size, _PAGE_NO_CACHE);
if (!isa_io_base && has_isa) { if (!pci_io_base) {
/* map a page for ISA ports. Not EEH protected. */ pci_io_base = (unsigned long)phb->io_base_virt;
isa_io_base = (unsigned long)__ioremap(phb->io_base_phys, PAGE_SIZE, _PAGE_NO_CACHE); if (has_isa)
} isa_io_base = pci_io_base;
res->start = phb->io_base_virt = eeh_token(index, 0, 0, 0);
res->end = eeh_token(index, 0xff, 0xff, 0xffffffff);
} else {
phb->io_base_virt = ioremap(phb->io_base_phys, range.size);
if (!pci_io_base) {
pci_io_base = (unsigned long)phb->io_base_virt;
if (has_isa)
isa_io_base = pci_io_base;
}
res->start = ((((unsigned long) range.child_addr.a_mid) << 32) | (range.child_addr.a_lo));
res->start += (unsigned long)phb->io_base_virt;
res->end = res->start + range.size - 1;
} }
res->start = ((((unsigned long) range.child_addr.a_mid) << 32) | (range.child_addr.a_lo));
res->start += (unsigned long)phb->io_base_virt - pci_io_base;
res->end = res->start + range.size - 1;
res->parent = NULL; res->parent = NULL;
res->sibling = NULL; res->sibling = NULL;
res->child = NULL; res->child = NULL;
...@@ -391,13 +333,8 @@ find_and_init_phbs(void) ...@@ -391,13 +333,8 @@ find_and_init_phbs(void)
++memno; ++memno;
res->name = Pci_Node->full_name; res->name = Pci_Node->full_name;
res->flags = IORESOURCE_MEM; res->flags = IORESOURCE_MEM;
if (is_eeh_implemented()) { res->start = range.parent_addr;
res->start = eeh_token(index, 0, 0, 0); res->end = range.parent_addr + range.size - 1;
res->end = eeh_token(index, 0xff, 0xff, 0xffffffff);
} else {
res->start = range.parent_addr;
res->end = range.parent_addr + range.size - 1;
}
res->parent = NULL; res->parent = NULL;
res->sibling = NULL; res->sibling = NULL;
res->child = NULL; res->child = NULL;
...@@ -574,7 +511,6 @@ fixup_resources(struct pci_dev *dev) ...@@ -574,7 +511,6 @@ fixup_resources(struct pci_dev *dev)
int i; int i;
struct pci_controller *phb = PCI_GET_PHB_PTR(dev); struct pci_controller *phb = PCI_GET_PHB_PTR(dev);
struct device_node *dn; struct device_node *dn;
unsigned long eeh_disable_bit;
/* Add IBM loc code (slot) as a prefix to the device names for service */ /* Add IBM loc code (slot) as a prefix to the device names for service */
dn = pci_device_to_OF_node(dev); dn = pci_device_to_OF_node(dev);
...@@ -591,20 +527,6 @@ fixup_resources(struct pci_dev *dev) ...@@ -591,20 +527,6 @@ fixup_resources(struct pci_dev *dev)
} }
} }
if (is_eeh_implemented()) {
if (is_eeh_configured(dev)) {
eeh_disable_bit = 0;
if (eeh_set_option(dev, EEH_ENABLE) != 0) {
printk("PCI: failed to enable EEH for %s %s\n", dev->slot_name, dev->dev.name);
eeh_disable_bit = EEH_TOKEN_DISABLED;
}
} else {
/* Assume device is by default EEH_DISABLE'd */
printk("PCI: eeh NOT configured for %s %s\n", dev->slot_name, dev->dev.name);
eeh_disable_bit = EEH_TOKEN_DISABLED;
}
}
PPCDBG(PPCDBG_PHBINIT, "fixup_resources:\n"); PPCDBG(PPCDBG_PHBINIT, "fixup_resources:\n");
PPCDBG(PPCDBG_PHBINIT, "\tphb = 0x%016LX\n", phb); PPCDBG(PPCDBG_PHBINIT, "\tphb = 0x%016LX\n", phb);
PPCDBG(PPCDBG_PHBINIT, "\tphb->pci_io_offset = 0x%016LX\n", phb->pci_io_offset); PPCDBG(PPCDBG_PHBINIT, "\tphb->pci_io_offset = 0x%016LX\n", phb->pci_io_offset);
...@@ -633,19 +555,9 @@ fixup_resources(struct pci_dev *dev) ...@@ -633,19 +555,9 @@ fixup_resources(struct pci_dev *dev)
} }
if (dev->resource[i].flags & IORESOURCE_IO) { if (dev->resource[i].flags & IORESOURCE_IO) {
if (is_eeh_implemented()) { unsigned long offset = (unsigned long)phb->io_base_virt - pci_io_base;
unsigned int busno = dev->bus ? dev->bus->number : 0; dev->resource[i].start += offset;
unsigned long size = dev->resource[i].end - dev->resource[i].start; dev->resource[i].end += offset;
unsigned long addr = (unsigned long)__ioremap(dev->resource[i].start + phb->io_base_phys, size, _PAGE_NO_CACHE);
if (!addr)
panic("fixup_resources: ioremap failed!\n");
dev->resource[i].start = eeh_token(phb->global_number, busno, dev->devfn, addr) | eeh_disable_bit;
dev->resource[i].end = dev->resource[i].start + size;
} else {
unsigned long offset = (unsigned long)phb->io_base_virt;
dev->resource[i].start += offset;
dev->resource[i].end += offset;
}
PPCDBG(PPCDBG_PHBINIT, "\t\t-> now [%lx .. %lx]\n", PPCDBG(PPCDBG_PHBINIT, "\t\t-> now [%lx .. %lx]\n",
dev->resource[i].start, dev->resource[i].end); dev->resource[i].start, dev->resource[i].end);
} else if (dev->resource[i].flags & IORESOURCE_MEM) { } else if (dev->resource[i].flags & IORESOURCE_MEM) {
...@@ -653,18 +565,8 @@ fixup_resources(struct pci_dev *dev) ...@@ -653,18 +565,8 @@ fixup_resources(struct pci_dev *dev)
/* Bogus. Probably an unused bridge. */ /* Bogus. Probably an unused bridge. */
dev->resource[i].end = 0; dev->resource[i].end = 0;
} else { } else {
if (is_eeh_implemented()) { dev->resource[i].start += phb->pci_mem_offset;
unsigned int busno = dev->bus ? dev->bus->number : 0; dev->resource[i].end += phb->pci_mem_offset;
unsigned long size = dev->resource[i].end - dev->resource[i].start;
unsigned long addr = (unsigned long)__ioremap(dev->resource[i].start + phb->pci_mem_offset, size, _PAGE_NO_CACHE);
if (!addr)
panic("fixup_resources: ioremap failed!\n");
dev->resource[i].start = eeh_token(phb->global_number, busno, dev->devfn, addr) | eeh_disable_bit;
dev->resource[i].end = dev->resource[i].start + size;
} else {
dev->resource[i].start += phb->pci_mem_offset;
dev->resource[i].end += phb->pci_mem_offset;
}
} }
PPCDBG(PPCDBG_PHBINIT, "\t\t-> now [%lx..%lx]\n", PPCDBG(PPCDBG_PHBINIT, "\t\t-> now [%lx..%lx]\n",
dev->resource[i].start, dev->resource[i].end); dev->resource[i].start, dev->resource[i].end);
...@@ -699,7 +601,6 @@ pSeries_pcibios_fixup(void) ...@@ -699,7 +601,6 @@ pSeries_pcibios_fixup(void)
struct pci_dev *dev; struct pci_dev *dev;
PPCDBG(PPCDBG_PHBINIT, "pSeries_pcibios_fixup: start\n"); PPCDBG(PPCDBG_PHBINIT, "pSeries_pcibios_fixup: start\n");
pci_assign_all_busses = 0;
check_s7a(); check_s7a();
...@@ -742,12 +643,6 @@ pci_find_hose_for_OF_device(struct device_node *node) ...@@ -742,12 +643,6 @@ pci_find_hose_for_OF_device(struct device_node *node)
void void
pSeries_pcibios_init(void) pSeries_pcibios_init(void)
{ {
PPCDBG(PPCDBG_PHBINIT, "\tppc64_pcibios_init Entry.\n");
if (get_property(find_path_device("/rtas"),"ibm,fw-phb-id",NULL) != NULL) {
PPCDBG(PPCDBG_PHBINIT, "\tFound: ibm,fw-phb-id\n");
Pci_Large_Bus_System = 1;
}
} }
/* /*
...@@ -759,25 +654,3 @@ pSeries_pcibios_init_early(void) ...@@ -759,25 +654,3 @@ pSeries_pcibios_init_early(void)
ppc_md.pcibios_read_config = rtas_read_config; ppc_md.pcibios_read_config = rtas_read_config;
ppc_md.pcibios_write_config = rtas_write_config; ppc_md.pcibios_write_config = rtas_write_config;
} }
/************************************************************************/
/* Get a char* of the device physical location(U0.3-P1-I8) */
/* See the Product Topology in the RS/6000 Architecture. */
/************************************************************************/
int device_Location(struct pci_dev *PciDev, char *BufPtr)
{
struct device_node *DevNode = (struct device_node *)PciDev->sysdata;
return sprintf(BufPtr,"PCI: Bus%3d, Device%3d, Vendor %04X, Location %-12s",
PciDev->bus->number,
PCI_SLOT(PciDev->devfn),
PciDev->vendor,
(char*)get_property(DevNode,"ibm,loc-code",0));
}
/************************************************************************/
/* Set the slot reset line to the state passed in. */
/* This is the platform specific for code for the pci_reset_device */
/* function. */
/************************************************************************/
int pci_set_reset(struct pci_dev *PciDev, int state)
{
return -1;
}
/* /*
* Port for PPC64 David Engebretsen, IBM Corp. * Port for PPC64 David Engebretsen, IBM Corp.
* Contains common pci routines for ppc64 platform, pSeries and iSeries brands. * Contains common pci routines for ppc64 platform, pSeries and iSeries brands.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#include <asm/naca.h> #include <asm/naca.h>
#include <asm/pci_dma.h> #include <asm/pci_dma.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/eeh.h>
#include "pci.h" #include "pci.h"
...@@ -43,50 +42,21 @@ ...@@ -43,50 +42,21 @@
*/ */
unsigned long isa_io_base = 0; /* NULL if no ISA bus */ unsigned long isa_io_base = 0; /* NULL if no ISA bus */
unsigned long pci_io_base = 0; unsigned long pci_io_base = 0;
unsigned long isa_mem_base = 0;
unsigned long pci_dram_offset = 0;
/******************************************************************
* Forward declare of prototypes
******************************************************************/
static void pcibios_fixup_resources(struct pci_dev* dev); static void pcibios_fixup_resources(struct pci_dev* dev);
static void fixup_broken_pcnet32(struct pci_dev* dev); static void fixup_broken_pcnet32(struct pci_dev* dev);
static void fixup_windbond_82c105(struct pci_dev* dev); static void fixup_windbond_82c105(struct pci_dev* dev);
void fixup_resources(struct pci_dev* dev); void fixup_resources(struct pci_dev* dev);
void iSeries_pcibios_init(void); void iSeries_pcibios_init(void);
void pSeries_pcibios_init(void); void pSeries_pcibios_init(void);
int pci_assign_all_busses = 0;
struct pci_controller* hose_head; struct pci_controller* hose_head;
struct pci_controller** hose_tail = &hose_head; struct pci_controller** hose_tail = &hose_head;
LIST_HEAD(iSeries_Global_Device_List);
/*******************************************************************
* Counters and control flags.
*******************************************************************/
long Pci_Io_Read_Count = 0;
long Pci_Io_Write_Count = 0;
long Pci_Cfg_Read_Count = 0;
long Pci_Cfg_Write_Count= 0;
long Pci_Error_Count = 0;
int Pci_Retry_Max = 3; /* Only retry 3 times */
int Pci_Error_Flag = 1; /* Set Retry Error on. */
int Pci_Trace_Flag = 0;
/******************************************************************
*
******************************************************************/
int global_phb_number = 0; /* Global phb counter */ int global_phb_number = 0; /* Global phb counter */
int Pci_Large_Bus_System = 0;
int Pci_Set_IOA_Address = 0;
int Pci_Manage_Phb_Space = 0;
struct pci_controller *phbtab[PCI_MAX_PHB]; struct pci_controller *phbtab[PCI_MAX_PHB];
static int pci_bus_count;
/* Cached ISA bridge dev. */ /* Cached ISA bridge dev. */
struct pci_dev *ppc64_isabridge_dev = NULL; struct pci_dev *ppc64_isabridge_dev = NULL;
...@@ -121,6 +91,43 @@ static void fixup_windbond_82c105(struct pci_dev* dev) ...@@ -121,6 +91,43 @@ static void fixup_windbond_82c105(struct pci_dev* dev)
} }
/* Given an mmio phys address, find a pci device that implements
* this address. This is of course expensive, but only used
* for device initialization or error paths.
* For io BARs it is assumed the pci_io_base has already been added
* into addr.
*
* Bridges are ignored although they could be used to optimize the search.
*/
struct pci_dev *pci_find_dev_by_addr(unsigned long addr)
{
struct pci_dev *dev;
int i;
unsigned long ioaddr;
ioaddr = (addr > isa_io_base) ? addr - isa_io_base : 0;
pci_for_each_dev(dev) {
if ((dev->class >> 8) == PCI_BASE_CLASS_BRIDGE)
continue;
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
unsigned long start = pci_resource_start(dev,i);
unsigned long end = pci_resource_end(dev,i);
unsigned int flags = pci_resource_flags(dev,i);
if (start == 0 || ~start == 0 ||
end == 0 || ~end == 0)
continue;
if ((flags & IORESOURCE_IO) &&
(ioaddr >= start && ioaddr <= end))
return dev;
else if ((flags & IORESOURCE_MEM) &&
(addr >= start && addr <= end))
return dev;
}
}
return NULL;
}
void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *pbus, void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *pbus,
struct pbus_set_ranges_data *pranges) struct pbus_set_ranges_data *pranges)
{ {
...@@ -402,10 +409,9 @@ pcibios_init(void) ...@@ -402,10 +409,9 @@ pcibios_init(void)
bus = pci_scan_bus(hose->first_busno, hose->ops, hose->arch_data); bus = pci_scan_bus(hose->first_busno, hose->ops, hose->arch_data);
hose->bus = bus; hose->bus = bus;
hose->last_busno = bus->subordinate; hose->last_busno = bus->subordinate;
if (pci_assign_all_busses || next_busno <= hose->last_busno) if (next_busno <= hose->last_busno)
next_busno = hose->last_busno+1; next_busno = hose->last_busno+1;
} }
pci_bus_count = next_busno;
/* Call machine dependant fixup */ /* Call machine dependant fixup */
if (ppc_md.pcibios_fixup) { if (ppc_md.pcibios_fixup) {
...@@ -419,6 +425,9 @@ pcibios_init(void) ...@@ -419,6 +425,9 @@ pcibios_init(void)
pcibios_assign_resources(); pcibios_assign_resources();
#ifndef CONFIG_PPC_ISERIES #ifndef CONFIG_PPC_ISERIES
void chrp_request_regions(void);
chrp_request_regions();
pci_fix_bus_sysdata(); pci_fix_bus_sysdata();
create_tce_tables(); create_tce_tables();
...@@ -439,18 +448,6 @@ pcibios_init(void) ...@@ -439,18 +448,6 @@ pcibios_init(void)
subsys_initcall(pcibios_init); subsys_initcall(pcibios_init);
int __init
pcibios_assign_all_busses(void)
{
return pci_assign_all_busses;
}
unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
unsigned long start, unsigned long size)
{
return start;
}
void __init pcibios_fixup_bus(struct pci_bus *bus) void __init pcibios_fixup_bus(struct pci_bus *bus)
{ {
#ifndef CONFIG_PPC_ISERIES #ifndef CONFIG_PPC_ISERIES
...@@ -486,21 +483,15 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) ...@@ -486,21 +483,15 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
/* Transparent resource -- don't try to "fix" it. */ /* Transparent resource -- don't try to "fix" it. */
continue; continue;
} }
if (is_eeh_implemented()) { if (res->flags & IORESOURCE_IO) {
if (res->flags & (IORESOURCE_IO|IORESOURCE_MEM)) { unsigned long offset = (unsigned long)phb->io_base_virt - pci_io_base;
res->start = eeh_token(phb->global_number, bus->number, 0, 0); res->start += offset;
res->end = eeh_token(phb->global_number, bus->number, 0xff, 0xffffffff); res->end += offset;
} } else if (phb->pci_mem_offset
} else { && (res->flags & IORESOURCE_MEM)) {
if (res->flags & IORESOURCE_IO) { if (res->start < phb->pci_mem_offset) {
res->start += (unsigned long)phb->io_base_virt; res->start += phb->pci_mem_offset;
res->end += (unsigned long)phb->io_base_virt; res->end += phb->pci_mem_offset;
} else if (phb->pci_mem_offset
&& (res->flags & IORESOURCE_MEM)) {
if (res->start < phb->pci_mem_offset) {
res->start += phb->pci_mem_offset;
res->end += phb->pci_mem_offset;
}
} }
} }
} }
...@@ -551,50 +542,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) ...@@ -551,50 +542,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
return 0; return 0;
} }
struct pci_controller*
pci_bus_to_hose(int bus)
{
struct pci_controller* hose = hose_head;
for (; hose; hose = hose->next)
if (bus >= hose->first_busno && bus <= hose->last_busno)
return hose;
return NULL;
}
void*
pci_bus_io_base(unsigned int bus)
{
struct pci_controller *hose;
hose = pci_bus_to_hose(bus);
if (!hose)
return NULL;
return hose->io_base_virt;
}
unsigned long
pci_bus_io_base_phys(unsigned int bus)
{
struct pci_controller *hose;
hose = pci_bus_to_hose(bus);
if (!hose)
return 0;
return hose->io_base_phys;
}
unsigned long
pci_bus_mem_base_phys(unsigned int bus)
{
struct pci_controller *hose;
hose = pci_bus_to_hose(bus);
if (!hose)
return 0;
return hose->pci_mem_offset;
}
/* /*
* Return the index of the PCI controller for device pdev. * Return the index of the PCI controller for device pdev.
*/ */
...@@ -732,123 +679,6 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, ...@@ -732,123 +679,6 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
return ret; return ret;
} }
/************************************************************************/
/* Formats the device information and location for service. */
/* - Pass in pci_dev* pointer to the device. */
/* - Pass in buffer to place the data. Danger here is the buffer must */
/* be as big as the client says it is. Should be at least 128 bytes.*/
/* Return will the length of the string data put in the buffer. */
/* The brand specific method device_Location is called. */
/* Format: */
/* PCI: Bus 0, Device 26, Vendor 0x12AE Frame 1, Card C10 Ethernet */
/* PCI: Bus 0, Device 26, Vendor 0x12AE Location U0.3-P1-I8 Ethernet */
/* For pSeries, see the Product Topology in the RS/6000 Architecture. */
/* For iSeries, see the Service Manuals. */
/************************************************************************/
int format_device_location(struct pci_dev* PciDev,char* BufPtr, int BufferSize)
{
struct device_node* DevNode = (struct device_node*)PciDev->sysdata;
int LineLen = 0;
if (DevNode != NULL && BufferSize >= 128) {
LineLen += device_Location(PciDev,BufPtr+LineLen);
LineLen += sprintf(BufPtr+LineLen," %12s",pci_class_name(PciDev->class >> 8) );
}
return LineLen;
}
/************************************************************************
* Saves the config registers for a device. *
************************************************************************
* Note: This does byte reads so the data may appear byte swapped, *
* The data returned in the pci_config_reg_save_area structure can be *
* used to the restore of the data. If the save failed, the data *
* will not be restore. Yes I know, you are most likey toast. *
************************************************************************/
int pci_save_config_regs(struct pci_dev* PciDev,struct pci_config_reg_save_area* SaveArea)
{
memset(SaveArea,0x00,sizeof(struct pci_config_reg_save_area) );
SaveArea->PciDev = PciDev;
SaveArea->RCode = 0;
SaveArea->Register = 0;
/******************************************************************
* Save All the Regs, NOTE: restore skips the first 16 bytes. *
******************************************************************/
while (SaveArea->Register < REG_SAVE_SIZE && SaveArea->RCode == 0) {
SaveArea->RCode = pci_read_config_byte(PciDev, SaveArea->Register, &SaveArea->Regs[SaveArea->Register]);
++SaveArea->Register;
}
if (SaveArea->RCode != 0) { /* Ouch */
SaveArea->Flags = 0x80;
printk("PCI: pci_restore_save_regs failed! %p\n 0x%04X",PciDev,SaveArea->RCode);
}
else {
SaveArea->Flags = 0x01;
}
return SaveArea->RCode;
}
/************************************************************************
* Restores the registers saved via the save function. See the save *
* function for details. *
************************************************************************/
int pci_restore_config_regs(struct pci_dev* PciDev,struct pci_config_reg_save_area* SaveArea)
{
if (SaveArea->PciDev != PciDev || SaveArea->Flags == 0x80 || SaveArea->RCode != 0) {
printk("PCI: pci_restore_config_regs failed! %p\n",PciDev);
return -1;
}
/******************************************************************
* Don't touch the Cmd or BIST regs, user must restore those. *
* Restore PCI_VENDOR_ID & PCI_DEVICE_ID *
* Restore PCI_CACHE_LINE_SIZE & PCI_LATENCY_TIMER *
* Restore Saved Regs from 0x10 to 0x3F *
******************************************************************/
SaveArea->Register = 0;
while(SaveArea->Register < REG_SAVE_SIZE && SaveArea->RCode == 0) {
SaveArea->RCode = pci_write_config_byte(PciDev,SaveArea->Register,SaveArea->Regs[SaveArea->Register]);
++SaveArea->Register;
if ( SaveArea->Register == PCI_COMMAND) SaveArea->Register = PCI_CACHE_LINE_SIZE;
else if (SaveArea->Register == PCI_HEADER_TYPE) SaveArea->Register = PCI_BASE_ADDRESS_0;
}
if (SaveArea->RCode != 0) {
printk("PCI: pci_restore_config_regs failed! %p\n 0x%04X",PciDev,SaveArea->RCode);
}
return SaveArea->RCode;
}
/************************************************************************/
/* Interface to toggle the reset line */
/* Time is in .1 seconds, need for seconds. */
/************************************************************************/
int pci_reset_device(struct pci_dev* PciDev, int AssertTime, int DelayTime)
{
unsigned long AssertDelay, WaitDelay;
int RtnCode;
/********************************************************************
* Set defaults, Assert is .5 second, Wait is 3 seconds.
********************************************************************/
if (AssertTime == 0) AssertDelay = ( 5 * HZ)/10;
else AssertDelay = (AssertTime*HZ)/10;
if (WaitDelay == 0) WaitDelay = (30 * HZ)/10;
else WaitDelay = (DelayTime* HZ)/10;
/********************************************************************
* Assert reset, wait, de-assert reset, wait for IOA to reset.
* - Don't waste the CPU time on jiffies.
********************************************************************/
RtnCode = pci_set_reset(PciDev,1);
if (RtnCode == 0) {
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(AssertDelay); /* Sleep for the time */
RtnCode = pci_set_reset(PciDev,0);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(WaitDelay);
}
if (RtnCode != 0) {
printk("PCI: Bus%3d, Device%3d, Reset Failed:0x%04X\n",PciDev->bus->number,PCI_SLOT(PciDev->devfn),RtnCode );
}
return RtnCode;
}
/***************************************************** /*****************************************************
* Dump Resource information * Dump Resource information
*****************************************************/ *****************************************************/
......
...@@ -13,16 +13,6 @@ ...@@ -13,16 +13,6 @@
#include <asm/pci-bridge.h> #include <asm/pci-bridge.h>
extern unsigned long isa_io_base; extern unsigned long isa_io_base;
extern unsigned long isa_mem_base;
extern unsigned long pci_dram_offset;
/*******************************************************************
* Platform independant variables referenced.
*******************************************************************
* Set pci_assign_all_busses to 1 if you want the kernel to re-assign
* all PCI bus numbers.
*******************************************************************/
extern int pci_assign_all_busses;
extern struct pci_controller* pci_alloc_pci_controller(char *model, enum phb_types controller_type); extern struct pci_controller* pci_alloc_pci_controller(char *model, enum phb_types controller_type);
extern struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node); extern struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node);
...@@ -39,13 +29,8 @@ extern struct pci_controller *phbtab[]; ...@@ -39,13 +29,8 @@ extern struct pci_controller *phbtab[];
*******************************************************************/ *******************************************************************/
extern unsigned long find_and_init_phbs(void); extern unsigned long find_and_init_phbs(void);
extern void fixup_resources(struct pci_dev *dev);
extern void ppc64_pcibios_init(void); extern void ppc64_pcibios_init(void);
extern int pci_set_reset(struct pci_dev*,int);
extern int device_Location(struct pci_dev*,char*);
extern int format_device_location(struct pci_dev*,char*, int );
extern struct pci_dev *ppc64_isabridge_dev; /* may be NULL if no ISA bus */ extern struct pci_dev *ppc64_isabridge_dev; /* may be NULL if no ISA bus */
/******************************************************************* /*******************************************************************
...@@ -56,6 +41,7 @@ typedef void *(*traverse_func)(struct device_node *me, void *data); ...@@ -56,6 +41,7 @@ typedef void *(*traverse_func)(struct device_node *me, void *data);
void *traverse_pci_devices(struct device_node *start, traverse_func pre, traverse_func post, void *data); void *traverse_pci_devices(struct device_node *start, traverse_func pre, traverse_func post, void *data);
void *traverse_all_pci_devices(traverse_func pre); void *traverse_all_pci_devices(traverse_func pre);
struct pci_dev *pci_find_dev_by_addr(unsigned long addr);
void pci_devs_phb_init(void); void pci_devs_phb_init(void);
void pci_fix_bus_sysdata(void); void pci_fix_bus_sysdata(void);
struct device_node *fetch_dev_dn(struct pci_dev *dev); struct device_node *fetch_dev_dn(struct pci_dev *dev);
...@@ -64,12 +50,6 @@ void iSeries_pcibios_init_early(void); ...@@ -64,12 +50,6 @@ void iSeries_pcibios_init_early(void);
void pSeries_pcibios_init_early(void); void pSeries_pcibios_init_early(void);
void pSeries_pcibios_init(void); void pSeries_pcibios_init(void);
/*******************************************************************
* Platform configuration flags.. (Live in pci.c)
*******************************************************************/
extern int Pci_Large_Bus_System; /* System has > 256 buses */
extern int Pci_Manage_Phb_Space; /* Manage Phb Space for IOAs*/
/******************************************************************* /*******************************************************************
* Helper macros for extracting data from pci structures. * Helper macros for extracting data from pci structures.
* PCI_GET_PHB_PTR(struct pci_dev*) returns the Phb pointer. * PCI_GET_PHB_PTR(struct pci_dev*) returns the Phb pointer.
...@@ -88,8 +68,4 @@ extern void dumpPci_Controller(struct pci_controller* phb); ...@@ -88,8 +68,4 @@ extern void dumpPci_Controller(struct pci_controller* phb);
extern void dumpPci_Bus(struct pci_bus* Pci_Bus); extern void dumpPci_Bus(struct pci_bus* Pci_Bus);
extern void dumpPci_Dev(struct pci_dev* Pci_Dev); extern void dumpPci_Dev(struct pci_dev* Pci_Dev);
extern void dump_Phb_tree(void);
extern void dump_Bus_tree(void);
extern void dump_Dev_tree(void);
#endif /* __PPC_KERNEL_PCI_H__ */ #endif /* __PPC_KERNEL_PCI_H__ */
...@@ -805,6 +805,7 @@ void create_pci_bus_tce_table( unsigned long token ) { ...@@ -805,6 +805,7 @@ void create_pci_bus_tce_table( unsigned long token ) {
/***********************************************************************/ /***********************************************************************/
static struct TceTable* findHwTceTable(struct TceTable * newTceTable ) static struct TceTable* findHwTceTable(struct TceTable * newTceTable )
{ {
#ifdef CONFIG_PPC_ISERIES
struct list_head* Device_Node_Ptr = iSeries_Global_Device_List.next; struct list_head* Device_Node_Ptr = iSeries_Global_Device_List.next;
/* Cache the compare values. */ /* Cache the compare values. */
u64 startOffset = newTceTable->startOffset; u64 startOffset = newTceTable->startOffset;
...@@ -825,6 +826,7 @@ static struct TceTable* findHwTceTable(struct TceTable * newTceTable ) ...@@ -825,6 +826,7 @@ static struct TceTable* findHwTceTable(struct TceTable * newTceTable )
/* Get next Device Node in List */ /* Get next Device Node in List */
Device_Node_Ptr = Device_Node_Ptr->next; Device_Node_Ptr = Device_Node_Ptr->next;
} }
#endif
return NULL; return NULL;
} }
......
...@@ -67,84 +67,6 @@ update_dn_pci_info(struct device_node *dn, void *data) ...@@ -67,84 +67,6 @@ update_dn_pci_info(struct device_node *dn, void *data)
return NULL; return NULL;
} }
/*
* Hit all the BARs of all the devices with values from OF.
* This is unnecessary on most systems, but also harmless.
*/
static void * __init
write_OF_bars(struct device_node *dn, void *data)
{
char *name = get_property(dn, "name", 0);
char *device_type = get_property(dn, "device_type", 0);
char devname[128];
sprintf(devname, "%04x:%02x.%x %s (%s)", dn->busno, PCI_SLOT(dn->devfn), PCI_FUNC(dn->devfn), name ? name : "<no name>", device_type ? device_type : "<unknown type>");
if (device_type && strcmp(device_type, "pci") == 0 &&
get_property(dn, "class-code", 0) == 0)
return NULL; /* This is probably a phb. Skip it. */
if (dn->n_addrs == 0)
return NULL; /* This is normal for some adapters or bridges */
if (dn->addrs == NULL) {
/* This shouldn't happen. */
printk(KERN_WARNING "write_OF_bars %s: device has %d BARs, but no addrs recorded\n", devname, dn->n_addrs);
return NULL;
}
#ifndef CONFIG_PPC_ISERIES
int i;
u32 oldbar, newbar, newbartest;
u8 config_offset;
for (i = 0; i < dn->n_addrs; i++) {
newbar = dn->addrs[i].address;
config_offset = dn->addrs[i].space & 0xff;
if (ppc_md.pcibios_read_config(dn, config_offset, 4, &oldbar) != PCIBIOS_SUCCESSFUL) {
printk(KERN_WARNING "write_OF_bars %s: read BAR%d failed\n", devname, i);
continue;
}
/* Need to update this BAR. */
if (ppc_md.pcibios_write_config(dn, config_offset, 4, newbar) != PCIBIOS_SUCCESSFUL) {
printk(KERN_WARNING "write_OF_bars %s: write BAR%d with 0x%08x failed (old was 0x%08x)\n", devname, i, newbar, oldbar);
continue;
}
/* sanity check */
if (ppc_md.pcibios_read_config(dn, config_offset, 4, &newbartest) != PCIBIOS_SUCCESSFUL) {
printk(KERN_WARNING "write_OF_bars %s: sanity test read BAR%d failed?\n", devname, i);
continue;
}
if ((newbar & PCI_BASE_ADDRESS_MEM_MASK) != (newbartest & PCI_BASE_ADDRESS_MEM_MASK)) {
printk(KERN_WARNING "write_OF_bars %s: oops...BAR%d read back as 0x%08x%s!\n", devname, i, newbartest, (oldbar & PCI_BASE_ADDRESS_MEM_MASK) == (newbartest & PCI_BASE_ADDRESS_MEM_MASK) ? " (original value)" : "");
continue;
}
}
#endif
return NULL;
}
#if 0
/* Traverse_func that starts the BIST (self test) */
static void * __init
startBIST(struct device_node *dn, void *data)
{
struct pci_controller *phb = (struct pci_controller *)data;
u8 bist;
char *name = get_property(dn, "name", 0);
udbg_printf("startBIST: %s phb=%p, device=%p\n", name ? name : "<unknown>", phb, dn);
if (ppc_md.pcibios_read_config_byte(dn, PCI_BIST, &bist) == PCIBIOS_SUCCESSFUL) {
if (bist & PCI_BIST_CAPABLE) {
udbg_printf(" -> is BIST capable!\n", phb, dn);
/* Start bist here */
}
}
return NULL;
}
#endif
/****************************************************************** /******************************************************************
* Traverse a device tree stopping each PCI device in the tree. * Traverse a device tree stopping each PCI device in the tree.
* This is done depth first. As each node is processed, a "pre" * This is done depth first. As each node is processed, a "pre"
...@@ -227,39 +149,6 @@ is_devfn_node(struct device_node *dn, void *data) ...@@ -227,39 +149,6 @@ is_devfn_node(struct device_node *dn, void *data)
return (devfn == dn->devfn && busno == dn->busno) ? dn : NULL; return (devfn == dn->devfn && busno == dn->busno) ? dn : NULL;
} }
/* Same as is_devfn_node except ignore the "fn" part of the "devfn".
*/
static void *
is_devfn_sub_node(struct device_node *dn, void *data)
{
int busno = ((unsigned long)data >> 8) & 0xff;
int devfn = ((unsigned long)data) & 0xf8;
return (devfn == (dn->devfn & 0xf8) && busno == dn->busno) ? dn : NULL;
}
/* Given an existing EADs (pci bridge) device node create a fake one
* that will simulate function zero. Make it a sibling of other_eads.
*/
static struct device_node *
create_eads_node(struct device_node *other_eads)
{
struct device_node *eads = (struct device_node *)kmalloc(sizeof(struct device_node), GFP_KERNEL);
if (!eads) return NULL; /* huh? */
*eads = *other_eads;
eads->devfn &= ~7; /* make it function zero */
eads->tce_table = NULL;
/*
* NOTE: share properties. We could copy but for now this should
* suffice. The full_name is also incorrect...but seems harmless.
*/
eads->child = NULL;
eads->next = NULL;
other_eads->allnext = eads;
other_eads->sibling = eads;
return eads;
}
/* This is the "slow" path for looking up a device_node from a /* This is the "slow" path for looking up a device_node from a
* pci_dev. It will hunt for the device under it's parent's * pci_dev. It will hunt for the device under it's parent's
* phb and then update sysdata for a future fastpath. * phb and then update sysdata for a future fastpath.
...@@ -285,43 +174,6 @@ struct device_node *fetch_dev_dn(struct pci_dev *dev) ...@@ -285,43 +174,6 @@ struct device_node *fetch_dev_dn(struct pci_dev *dev)
if (dn) { if (dn) {
dev->sysdata = dn; dev->sysdata = dn;
/* ToDo: call some device init hook here */ /* ToDo: call some device init hook here */
} else {
/* Now it is very possible that we can't find the device
* because it is not the zero'th device of a mutifunction
* device and we don't have permission to read the zero'th
* device. If this is the case, Linux would ordinarily skip
* all the other functions.
*/
if ((searchval & 0x7) == 0) {
struct device_node *thisdevdn;
/* Ok, we are looking for fn == 0. Let's check for other functions. */
thisdevdn = (struct device_node *)traverse_pci_devices(phb_dn, is_devfn_sub_node, NULL, (void *)searchval);
if (thisdevdn) {
/* Ah ha! There does exist a sub function.
* Now this isn't an exact match for
* searchval, but in order to get Linux to
* believe the sub functions exist we will
* need to manufacture a fake device_node for
* this zero'th function. To keept this
* simple for now we only handle pci bridges
* and we just hand back the found node which
* isn't correct, but Linux won't care.
*/
char *device_type = (char *)get_property(thisdevdn, "device_type", 0);
if (device_type && strcmp(device_type, "pci") == 0) {
return create_eads_node(thisdevdn);
}
}
}
/* ToDo: device not found...probe for it anyway with a fake dn?
struct device_node fake_dn;
memset(&fake_dn, 0, sizeof(fake_dn));
fake_dn.phb = phb;
fake_dn.busno = dev->bus->number;
fake_dn.devfn = dev->devfn;
... now do ppc_md.pcibios_read_config_dword(&fake_dn.....)
... if ok, alloc a real device_node and dn = real_dn;
*/
} }
return dn; return dn;
} }
...@@ -336,14 +188,6 @@ pci_devs_phb_init(void) ...@@ -336,14 +188,6 @@ pci_devs_phb_init(void)
{ {
/* This must be done first so the device nodes have valid pci info! */ /* This must be done first so the device nodes have valid pci info! */
traverse_all_pci_devices(update_dn_pci_info); traverse_all_pci_devices(update_dn_pci_info);
/* Hack for regatta which does not init the bars correctly */
traverse_all_pci_devices(write_OF_bars);
#if 0
traverse_all_pci_devices(startBIST);
mdelay(5000);
traverse_all_pci_devices(checkBIST);
#endif
} }
......
...@@ -78,9 +78,7 @@ EXPORT_SYMBOL(register_ioctl32_conversion); ...@@ -78,9 +78,7 @@ EXPORT_SYMBOL(register_ioctl32_conversion);
EXPORT_SYMBOL(unregister_ioctl32_conversion); EXPORT_SYMBOL(unregister_ioctl32_conversion);
EXPORT_SYMBOL(isa_io_base); EXPORT_SYMBOL(isa_io_base);
EXPORT_SYMBOL(isa_mem_base);
EXPORT_SYMBOL(pci_io_base); EXPORT_SYMBOL(pci_io_base);
EXPORT_SYMBOL(pci_dram_offset);
EXPORT_SYMBOL(find_next_zero_bit); EXPORT_SYMBOL(find_next_zero_bit);
...@@ -246,5 +244,7 @@ EXPORT_SYMBOL(debugger_fault_handler); ...@@ -246,5 +244,7 @@ EXPORT_SYMBOL(debugger_fault_handler);
EXPORT_SYMBOL(tb_ticks_per_usec); EXPORT_SYMBOL(tb_ticks_per_usec);
#ifdef CONFIG_PROFILING
EXPORT_SYMBOL_GPL(register_profile_notifier); EXPORT_SYMBOL_GPL(register_profile_notifier);
EXPORT_SYMBOL_GPL(unregister_profile_notifier); EXPORT_SYMBOL_GPL(unregister_profile_notifier);
#endif
...@@ -388,48 +388,61 @@ void initialize_paca_hardware_interrupt_stack(void) ...@@ -388,48 +388,61 @@ void initialize_paca_hardware_interrupt_stack(void)
} }
} }
extern char _stext[], _etext[]; extern char _stext[], _etext[], __init_begin[], __init_end[];
static char *ppc_find_proc_name(unsigned *p, char *buf, unsigned buflen) static char *ppc_find_proc_name(unsigned *p, char *buf, unsigned buflen)
{ {
unsigned long tb_flags; unsigned long tb_flags;
unsigned short name_len; unsigned short name_len;
unsigned long tb_start, code_start, code_ptr, code_offset; unsigned long tb_start, code_start, code_ptr, code_offset;
unsigned code_len; unsigned int code_len;
strcpy( buf, "Unknown" ); unsigned long end;
strcpy(buf, "Unknown");
code_ptr = (unsigned long)p; code_ptr = (unsigned long)p;
code_offset = 0; code_offset = 0;
if ( ( (unsigned long)p >= (unsigned long)_stext ) && ( (unsigned long)p <= (unsigned long)_etext ) ) {
while ( (unsigned long)p <= (unsigned long)_etext ) { /* handle functions in text and init sections */
if ( *p == 0 ) { if (((unsigned long)p >= (unsigned long)_stext) &&
tb_start = (unsigned long)p; ((unsigned long)p < (unsigned long)_etext))
++p; /* Point to traceback flags */ end = (unsigned long)_etext;
tb_flags = *((unsigned long *)p); else if (((unsigned long)p >= (unsigned long)__init_begin) &&
p += 2; /* Skip over traceback flags */ ((unsigned long)p < (unsigned long)__init_end))
if ( tb_flags & TB_NAME_PRESENT ) { end = (unsigned long)__init_end;
if ( tb_flags & TB_PARMINFO ) else
++p; /* skip over parminfo data */ return buf;
if ( tb_flags & TB_HAS_TBOFF ) {
code_len = *p; /* get code length */ while ((unsigned long)p < end) {
code_start = tb_start - code_len; if (*p == 0) {
code_offset = code_ptr - code_start + 1; tb_start = (unsigned long)p;
if ( code_offset > 0x100000 ) ++p; /* Point to traceback flags */
break; tb_flags = *((unsigned long *)p);
++p; /* skip over code size */ p += 2; /* Skip over traceback flags */
} if (tb_flags & TB_NAME_PRESENT) {
name_len = *((unsigned short *)p); if (tb_flags & TB_PARMINFO)
if ( name_len > (buflen-20) ) ++p; /* skip over parminfo data */
name_len = buflen-20; if (tb_flags & TB_HAS_TBOFF) {
memcpy( buf, ((char *)p)+2, name_len ); code_len = *p; /* get code length */
buf[name_len] = 0; code_start = tb_start - code_len;
if ( code_offset ) code_offset = code_ptr - code_start + 1;
sprintf( buf+name_len, "+0x%lx", code_offset-1 ); if (code_offset > 0x100000)
break;
++p; /* skip over code size */
} }
break; name_len = *((unsigned short *)p);
if (name_len > (buflen-20))
name_len = buflen-20;
memcpy(buf, ((char *)p)+2, name_len);
buf[name_len] = 0;
if (code_offset)
sprintf(buf+name_len, "+0x%lx",
code_offset-1);
} }
++p; break;
} }
++p;
} }
return buf; return buf;
} }
......
...@@ -1988,8 +1988,7 @@ interpret_isa_props(struct device_node *np, unsigned long mem_start, ...@@ -1988,8 +1988,7 @@ interpret_isa_props(struct device_node *np, unsigned long mem_start,
adr = (struct address_range *) mem_start; adr = (struct address_range *) mem_start;
while ((l -= sizeof(struct reg_property)) >= 0) { while ((l -= sizeof(struct reg_property)) >= 0) {
adr[i].space = rp[i].space; adr[i].space = rp[i].space;
adr[i].address = rp[i].address adr[i].address = rp[i].address;
+ (adr[i].space? 0: _ISA_MEM_BASE);
adr[i].size = rp[i].size; adr[i].size = rp[i].size;
++i; ++i;
} }
......
...@@ -450,9 +450,14 @@ static void handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, ...@@ -450,9 +450,14 @@ static void handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
if (regs->trap == 0x0C00 /* System Call! */ if (regs->trap == 0x0C00 /* System Call! */
&& ((int)regs->result == -ERESTARTNOHAND || && ((int)regs->result == -ERESTARTNOHAND ||
(int)regs->result == -ERESTART_RESTARTBLOCK ||
((int)regs->result == -ERESTARTSYS && ((int)regs->result == -ERESTARTSYS &&
!(ka->sa.sa_flags & SA_RESTART)))) !(ka->sa.sa_flags & SA_RESTART)))) {
if ((int)regs->result == -ERESTART_RESTARTBLOCK)
current_thread_info()->restart_block.fn
= do_no_restart_syscall;
regs->result = -EINTR; regs->result = -EINTR;
}
/* Set up Signal Frame */ /* Set up Signal Frame */
if (ka->sa.sa_flags & SA_SIGINFO) { if (ka->sa.sa_flags & SA_SIGINFO) {
...@@ -560,13 +565,18 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -560,13 +565,18 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
handle_signal(signr, &info, oldset, regs, &newsp, frame); handle_signal(signr, &info, oldset, regs, &newsp, frame);
} }
if (regs->trap == 0x0C00 /* System Call! */ && if (regs->trap == 0x0C00) { /* System Call! */
((int)regs->result == -ERESTARTNOHAND || if ((int)regs->result == -ERESTARTNOHAND ||
(int)regs->result == -ERESTARTSYS || (int)regs->result == -ERESTARTSYS ||
(int)regs->result == -ERESTARTNOINTR)) { (int)regs->result == -ERESTARTNOINTR) {
regs->gpr[3] = regs->orig_gpr3; regs->gpr[3] = regs->orig_gpr3;
regs->nip -= 4; /* Back up & retry system call */ regs->nip -= 4; /* Back up & retry system call */
regs->result = 0; regs->result = 0;
} else if ((int)regs->result == -ERESTART_RESTARTBLOCK) {
regs->gpr[0] = __NR_restart_syscall;
regs->nip -= 4;
regs->result = 0;
}
} }
if (newsp == frame) if (newsp == frame)
......
...@@ -968,9 +968,14 @@ static void handle_signal32(unsigned long sig, siginfo_t *info, ...@@ -968,9 +968,14 @@ static void handle_signal32(unsigned long sig, siginfo_t *info,
if (regs->trap == 0x0C00 /* System Call! */ if (regs->trap == 0x0C00 /* System Call! */
&& ((int)regs->result == -ERESTARTNOHAND || && ((int)regs->result == -ERESTARTNOHAND ||
(int)regs->result == -ERESTART_RESTARTBLOCK ||
((int)regs->result == -ERESTARTSYS && ((int)regs->result == -ERESTARTSYS &&
!(ka->sa.sa_flags & SA_RESTART)))) !(ka->sa.sa_flags & SA_RESTART)))) {
if ((int)regs->result == -ERESTART_RESTARTBLOCK)
current_thread_info()->restart_block.fn
= do_no_restart_syscall;
regs->result = -EINTR; regs->result = -EINTR;
}
/* /*
* Set up the signal frame * Set up the signal frame
...@@ -1132,13 +1137,18 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs) ...@@ -1132,13 +1137,18 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
handle_signal32(signr, &info, oldset, regs, &newsp, frame); handle_signal32(signr, &info, oldset, regs, &newsp, frame);
} }
if (regs->trap == 0x0C00 /* System Call! */ && if (regs->trap == 0x0C00) { /* System Call! */
((int)regs->result == -ERESTARTNOHAND || if ((int)regs->result == -ERESTARTNOHAND ||
(int)regs->result == -ERESTARTSYS || (int)regs->result == -ERESTARTSYS ||
(int)regs->result == -ERESTARTNOINTR)) { (int)regs->result == -ERESTARTNOINTR) {
regs->gpr[3] = regs->orig_gpr3; regs->gpr[3] = regs->orig_gpr3;
regs->nip -= 4; /* Back up & retry system call */ regs->nip -= 4; /* Back up & retry system call */
regs->result = 0; regs->result = 0;
} else if ((int)regs->result == -ERESTART_RESTARTBLOCK) {
regs->gpr[0] = __NR_restart_syscall;
regs->nip -= 4;
regs->result = 0;
}
} }
if (newsp == frame) if (newsp == frame)
......
...@@ -208,40 +208,42 @@ static long do_readv_writev32(int type, struct file *file, ...@@ -208,40 +208,42 @@ static long do_readv_writev32(int type, struct file *file,
asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count) asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count)
{ {
struct file *file; struct file *file;
int ret; int ret = -EBADF;
file = fget(fd); file = fget(fd);
if(!file) if (!file || !(file->f_mode & FMODE_READ))
return -EBADF; goto out;
if (!(file->f_mode & FMODE_READ)) ret = -EINVAL;
return -EBADF;
if (!file->f_op || (!file->f_op->readv && !file->f_op->read)) if (!file->f_op || (!file->f_op->readv && !file->f_op->read))
return -EINVAL; goto out;
ret = do_readv_writev32(READ, file, vector, count); ret = do_readv_writev32(READ, file, vector, count);
fput(file); out:
if (file)
fput(file);
return ret; return ret;
} }
asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count) asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count)
{ {
struct file *file; struct file *file;
int ret; int ret = -EBADF;
file = fget(fd); file = fget(fd);
if(!file) if (!file || !(file->f_mode & FMODE_WRITE))
return -EBADF; goto out;
if (!(file->f_mode & FMODE_WRITE)) ret = -EINVAL;
return -EBADF;
if (!file->f_op || (!file->f_op->writev && !file->f_op->write)) if (!file->f_op || (!file->f_op->writev && !file->f_op->write))
return -EINVAL; goto out;
ret = do_readv_writev32(WRITE, file, vector, count); ret = do_readv_writev32(WRITE, file, vector, count);
fput(file); out:
if (file)
fput(file);
return ret; return ret;
} }
......
...@@ -91,6 +91,7 @@ unsigned int default_distrib_server = 0; ...@@ -91,6 +91,7 @@ unsigned int default_distrib_server = 0;
/* RTAS service tokens */ /* RTAS service tokens */
int ibm_get_xive; int ibm_get_xive;
int ibm_set_xive; int ibm_set_xive;
int ibm_int_on;
int ibm_int_off; int ibm_int_off;
struct xics_interrupt_node { struct xics_interrupt_node {
...@@ -162,6 +163,14 @@ xics_enable_irq( ...@@ -162,6 +163,14 @@ xics_enable_irq(
irq, call_status, status); irq, call_status, status);
return; return;
} }
/* Now unmask the interrupt (often a no-op) */
call_status = rtas_call(ibm_int_on, 1, 1, (unsigned long*)&status,
irq);
if( call_status != 0 ) {
printk("xics_disable_irq on: irq=%x: rtas_call failed, retn=%lx\n",
irq, call_status);
return;
}
} }
void void
...@@ -302,6 +311,7 @@ xics_init_IRQ( void ) ...@@ -302,6 +311,7 @@ xics_init_IRQ( void )
ibm_get_xive = rtas_token("ibm,get-xive"); ibm_get_xive = rtas_token("ibm,get-xive");
ibm_set_xive = rtas_token("ibm,set-xive"); ibm_set_xive = rtas_token("ibm,set-xive");
ibm_int_on = rtas_token("ibm,int-on");
ibm_int_off = rtas_token("ibm,int-off"); ibm_int_off = rtas_token("ibm,int-off");
np = find_type_devices("PowerPC-External-Interrupt-Presentation"); np = find_type_devices("PowerPC-External-Interrupt-Presentation");
......
...@@ -132,12 +132,10 @@ ioremap(unsigned long addr, unsigned long size) ...@@ -132,12 +132,10 @@ ioremap(unsigned long addr, unsigned long size)
#ifdef CONFIG_PPC_ISERIES #ifdef CONFIG_PPC_ISERIES
return (void*)addr; return (void*)addr;
#else #else
if(mem_init_done && (addr >> 60UL)) { void *ret = __ioremap(addr, size, _PAGE_NO_CACHE);
if (IS_EEH_TOKEN_DISABLED(addr)) if(mem_init_done)
return (void *)IO_TOKEN_TO_ADDR(addr); return eeh_ioremap(addr, ret); /* may remap the addr */
return (void*)addr; /* already mapped address or EEH token. */ return ret;
}
return __ioremap(addr, size, _PAGE_NO_CACHE);
#endif #endif
} }
......
...@@ -27,25 +27,26 @@ ...@@ -27,25 +27,26 @@
struct pci_dev; struct pci_dev;
#define IO_UNMAPPED_REGION_ID 0xaUL /* I/O addresses are converted to EEH "tokens" such that a driver will cause
* a bad page fault if the address is used directly (i.e. these addresses are
#define IO_TOKEN_TO_ADDR(token) ((((unsigned long)(token)) & 0xFFFFFFFF) | (0xEUL << 60)) * never actually mapped. Translation between IO <-> EEH region is 1 to 1.
/* Flag bits encoded in the 3 unused function bits of devfn */ */
#define EEH_TOKEN_DISABLED (1UL << 34UL) /* eeh is disabled for this token */ #define IO_TOKEN_TO_ADDR(token) (((unsigned long)(token) & ~(0xfUL << REGION_SHIFT)) | \
#define IS_EEH_TOKEN_DISABLED(token) ((unsigned long)(token) & EEH_TOKEN_DISABLED) (IO_REGION_ID << REGION_SHIFT))
#define IO_ADDR_TO_TOKEN(addr) (((unsigned long)(addr) & ~(0xfUL << REGION_SHIFT)) | \
(EEH_REGION_ID << REGION_SHIFT))
#define EEH_STATE_OVERRIDE 1 /* IOA does not require eeh traps */ /* Values for eeh_mode bits in device_node */
#define EEH_STATE_FAILURE 16 /* */ #define EEH_MODE_SUPPORTED (1<<0)
#define EEH_MODE_NOCHECK (1<<1)
/* This is for profiling only */ /* This is for profiling only */
extern unsigned long eeh_total_mmio_ffs; extern unsigned long eeh_total_mmio_ffs;
extern int eeh_implemented;
void eeh_init(void); void eeh_init(void);
static inline int is_eeh_implemented(void) { return eeh_implemented; }
int eeh_get_state(unsigned long ea); int eeh_get_state(unsigned long ea);
unsigned long eeh_check_failure(void *token, unsigned long val); unsigned long eeh_check_failure(void *token, unsigned long val);
void *eeh_ioremap(unsigned long addr, void *vaddr);
#define EEH_DISABLE 0 #define EEH_DISABLE 0
#define EEH_ENABLE 1 #define EEH_ENABLE 1
...@@ -58,15 +59,11 @@ int eeh_set_option(struct pci_dev *dev, int options); ...@@ -58,15 +59,11 @@ int eeh_set_option(struct pci_dev *dev, int options);
*/ */
int is_eeh_configured(struct pci_dev *dev); int is_eeh_configured(struct pci_dev *dev);
/* Generate an EEH token. /* Translate a (possible) eeh token to a physical addr.
* The high nibble of the offset is cleared, otherwise bounds checking is performed. * If "token" is not an eeh token it is simply returned under
* Use IO_TOKEN_TO_ADDR(token) to translate this token back to a mapped virtual addr. * the assumption that it is already a physical addr.
* Do NOT do this to perform IO -- use the read/write macros!
*/ */
unsigned long eeh_token(unsigned long phb, unsigned long eeh_token_to_phys(unsigned long token);
unsigned long bus,
unsigned long devfn,
unsigned long offset);
extern void *memcpy(void *, const void *, unsigned long); extern void *memcpy(void *, const void *, unsigned long);
extern void *memset(void *,int, unsigned long); extern void *memset(void *,int, unsigned long);
...@@ -77,15 +74,16 @@ extern void *memset(void *,int, unsigned long); ...@@ -77,15 +74,16 @@ extern void *memset(void *,int, unsigned long);
* If EEH is off for a device and it is a memory BAR, ioremap will * If EEH is off for a device and it is a memory BAR, ioremap will
* map it to the IOREGION. In this case addr == vaddr and since these * map it to the IOREGION. In this case addr == vaddr and since these
* should be in registers we compare them first. Next we check for * should be in registers we compare them first. Next we check for
* all ones which is perhaps fastest as ~val. Finally we weed out * ff's which indicates a (very) possible failure.
* EEH disabled IO BARs.
* *
* If this macro yields TRUE, the caller relays to eeh_check_failure() * If this macro yields TRUE, the caller relays to eeh_check_failure()
* which does further tests out of line. * which does further tests out of line.
*/ */
/* #define EEH_POSSIBLE_ERROR(addr, vaddr, val) ((vaddr) != (addr) && ~(val) == 0 && !IS_EEH_TOKEN_DISABLED(addr)) */ /* #define EEH_POSSIBLE_IO_ERROR(val) (~(val) == 0) */
/* #define EEH_POSSIBLE_ERROR(addr, vaddr, val) ((vaddr) != (addr) && EEH_POSSIBLE_IO_ERROR(val) */
/* This version is rearranged to collect some profiling data */ /* This version is rearranged to collect some profiling data */
#define EEH_POSSIBLE_ERROR(addr, vaddr, val) (~(val) == 0 && (++eeh_total_mmio_ffs, (vaddr) != (addr) && !IS_EEH_TOKEN_DISABLED(addr))) #define EEH_POSSIBLE_IO_ERROR(val) (~(val) == 0 && ++eeh_total_mmio_ffs)
#define EEH_POSSIBLE_ERROR(addr, vaddr, val) (EEH_POSSIBLE_IO_ERROR(val) && (vaddr) != (addr))
/* /*
* MMIO read/write operations with EEH support. * MMIO read/write operations with EEH support.
...@@ -149,38 +147,56 @@ static inline void eeh_memcpy_toio(void *dest, void *src, unsigned long n) { ...@@ -149,38 +147,56 @@ static inline void eeh_memcpy_toio(void *dest, void *src, unsigned long n) {
memcpy(vdest, src, n); memcpy(vdest, src, n);
} }
static inline void eeh_insb(volatile u8 *addr, void *buf, int n) { /* The I/O macros must handle ISA ports as well as PCI I/O bars.
volatile u8 *vaddr = (volatile u8 *)IO_TOKEN_TO_ADDR(addr); * ISA does not implement EEH and ISA may not exist in the system.
_insb(vaddr, buf, n); * For PCI we check for EEH failures.
/* ToDo: look for ff's in buf[n] */ */
#define _IO_IS_ISA(port) ((port) < 0x10000)
#define _IO_HAS_ISA_BUS (isa_io_base != 0)
static inline u8 eeh_inb(unsigned long port) {
u8 val;
if (_IO_IS_ISA(port) && !_IO_HAS_ISA_BUS)
return ~0;
val = in_8((u8 *)(port+pci_io_base));
if (!_IO_IS_ISA(port) && EEH_POSSIBLE_IO_ERROR(val))
return eeh_check_failure((void*)(port+pci_io_base), val);
return val;
} }
static inline void eeh_outsb(volatile u8 *addr, const void *buf, int n) { static inline void eeh_outb(u8 val, unsigned long port) {
volatile u8 *vaddr = (volatile u8 *)IO_TOKEN_TO_ADDR(addr); if (!_IO_IS_ISA(port) || _IO_HAS_ISA_BUS)
_outsb(vaddr, buf, n); return out_8((u8 *)(port+pci_io_base), val);
} }
static inline void eeh_insw_ns(volatile u16 *addr, void *buf, int n) { static inline u16 eeh_inw(unsigned long port) {
volatile u16 *vaddr = (volatile u16 *)IO_TOKEN_TO_ADDR(addr); u16 val;
_insw_ns(vaddr, buf, n); if (_IO_IS_ISA(port) && !_IO_HAS_ISA_BUS)
/* ToDo: look for ffff's in buf[n] */ return ~0;
val = in_le16((u16 *)(port+pci_io_base));
if (!_IO_IS_ISA(port) && EEH_POSSIBLE_IO_ERROR(val))
return eeh_check_failure((void*)(port+pci_io_base), val);
return val;
} }
static inline void eeh_outsw_ns(volatile u16 *addr, const void *buf, int n) { static inline void eeh_outw(u16 val, unsigned long port) {
volatile u16 *vaddr = (volatile u16 *)IO_TOKEN_TO_ADDR(addr); if (!_IO_IS_ISA(port) || _IO_HAS_ISA_BUS)
_outsw_ns(vaddr, buf, n); return out_le16((u16 *)(port+pci_io_base), val);
} }
static inline void eeh_insl_ns(volatile u32 *addr, void *buf, int n) { static inline u32 eeh_inl(unsigned long port) {
volatile u32 *vaddr = (volatile u32 *)IO_TOKEN_TO_ADDR(addr); u32 val;
_insl_ns(vaddr, buf, n); if (_IO_IS_ISA(port) && !_IO_HAS_ISA_BUS)
/* ToDo: look for ffffffff's in buf[n] */ return ~0;
val = in_le32((u32 *)(port+pci_io_base));
if (!_IO_IS_ISA(port) && EEH_POSSIBLE_IO_ERROR(val))
return eeh_check_failure((void*)(port+pci_io_base), val);
return val;
} }
static inline void eeh_outsl_ns(volatile u32 *addr, const void *buf, int n) { static inline void eeh_outl(u32 val, unsigned long port) {
volatile u32 *vaddr = (volatile u32 *)IO_TOKEN_TO_ADDR(addr); if (!_IO_IS_ISA(port) || _IO_HAS_ISA_BUS)
_outsl_ns(vaddr, buf, n); return out_le32((u32 *)(port+pci_io_base), val);
} }
#endif /* _EEH_H */ #endif /* _EEH_H */
...@@ -13,12 +13,6 @@ ...@@ -13,12 +13,6 @@
#undef EDEADLOCK #undef EDEADLOCK
#define EDEADLOCK 58 /* File locking deadlock error */ #define EDEADLOCK 58 /* File locking deadlock error */
/* Should never be seen by user programs */ #define _LAST_ERRNO 516
#define ERESTARTSYS 512
#define ERESTARTNOINTR 513
#define ERESTARTNOHAND 514 /* restart if no handler.. */
#define ENOIOCTLCMD 515 /* No ioctl command */
#define _LAST_ERRNO 515
#endif #endif
...@@ -57,6 +57,7 @@ ...@@ -57,6 +57,7 @@
#define H_IPI 0x6c #define H_IPI 0x6c
#define H_IPOLL 0x70 #define H_IPOLL 0x70
#define H_XIRR 0x74 #define H_XIRR 0x74
#define H_PERFMON 0x7c
#define HSC ".long 0x44000022\n" #define HSC ".long 0x44000022\n"
#define H_ENTER_r3 "li 3, 0x08\n" #define H_ENTER_r3 "li 3, 0x08\n"
......
...@@ -130,6 +130,7 @@ enum HvCall_VaryOffChunkRc ...@@ -130,6 +130,7 @@ enum HvCall_VaryOffChunkRc
#define HvCallBaseRouter28 HvCallBase + 28 #define HvCallBaseRouter28 HvCallBase + 28
#define HvCallBaseRouter29 HvCallBase + 29 #define HvCallBaseRouter29 HvCallBase + 29
#define HvCallBaseRouter30 HvCallBase + 30 #define HvCallBaseRouter30 HvCallBase + 30
#define HvCallBaseSetDebugBus HvCallBase + 31
#define HvCallCcSetDABR HvCallCc + 7 #define HvCallCcSetDABR HvCallCc + 7
...@@ -205,5 +206,10 @@ static inline void HvCall_setDABR(unsigned long val) ...@@ -205,5 +206,10 @@ static inline void HvCall_setDABR(unsigned long val)
HvCall1(HvCallCcSetDABR, val); HvCall1(HvCallCcSetDABR, val);
} }
static inline void HvCall_setDebugBus(unsigned long val)
{
HvCall1(HvCallBaseSetDebugBus, val);
}
#endif // _HVCALL_H #endif // _HVCALL_H
...@@ -25,13 +25,7 @@ ...@@ -25,13 +25,7 @@
#undef __IO_DEBUG #undef __IO_DEBUG
extern unsigned long isa_io_base; extern unsigned long isa_io_base;
extern unsigned long isa_mem_base;
extern unsigned long pci_io_base; extern unsigned long pci_io_base;
extern unsigned long pci_dram_offset;
extern int have_print;
#define _IO_BASE isa_io_base
#define _ISA_MEM_BASE isa_mem_base
#define PCI_DRAM_OFFSET pci_dram_offset
#ifdef CONFIG_PPC_ISERIES #ifdef CONFIG_PPC_ISERIES
#define readb(addr) iSeries_Read_Byte((void*)(addr)) #define readb(addr) iSeries_Read_Byte((void*)(addr))
...@@ -50,36 +44,45 @@ extern int have_print; ...@@ -50,36 +44,45 @@ extern int have_print;
#define outw(data,addr) writew(data,((unsigned long)(addr))) #define outw(data,addr) writew(data,((unsigned long)(addr)))
#define outl(data,addr) writel(data,((unsigned long)(addr))) #define outl(data,addr) writel(data,((unsigned long)(addr)))
#else #else
#define IS_MAPPED_VADDR(port) ((unsigned long)(port) >> 60UL)
#define readb(addr) eeh_readb((void*)(addr)) #define readb(addr) eeh_readb((void*)(addr))
#define readw(addr) eeh_readw((void*)(addr)) #define readw(addr) eeh_readw((void*)(addr))
#define readl(addr) eeh_readl((void*)(addr)) #define readl(addr) eeh_readl((void*)(addr))
#define writeb(data, addr) eeh_writeb((data), ((void*)(addr))) #define writeb(data, addr) eeh_writeb((data), ((void*)(addr)))
#define writew(data, addr) eeh_writew((data), ((void*)(addr))) #define writew(data, addr) eeh_writew((data), ((void*)(addr)))
#define writel(data, addr) eeh_writel((data), ((void*)(addr))) #define writel(data, addr) eeh_writel((data), ((void*)(addr)))
#define memset_io(a,b,c) eeh_memset((void *)(a),(b),(c)) #define memset_io(a,b,c) eeh_memset_io((void *)(a),(b),(c))
#define memcpy_fromio(a,b,c) eeh_memcpy_fromio((a),(void *)(b),(c)) #define memcpy_fromio(a,b,c) eeh_memcpy_fromio((a),(void *)(b),(c))
#define memcpy_toio(a,b,c) eeh_memcpy_toio((void *)(a),(b),(c)) #define memcpy_toio(a,b,c) eeh_memcpy_toio((void *)(a),(b),(c))
#define inb(port) _inb((unsigned long)port) #define inb(port) eeh_inb((unsigned long)port)
#define outb(val, port) _outb(val, (unsigned long)port) #define outb(val, port) eeh_outb(val, (unsigned long)port)
#define inw(port) _inw((unsigned long)port) #define inw(port) eeh_inw((unsigned long)port)
#define outw(val, port) _outw(val, (unsigned long)port) #define outw(val, port) eeh_outw(val, (unsigned long)port)
#define inl(port) _inl((unsigned long)port) #define inl(port) eeh_inl((unsigned long)port)
#define outl(val, port) _outl(val, (unsigned long)port) #define outl(val, port) eeh_outl(val, (unsigned long)port)
/* /*
* The insw/outsw/insl/outsl macros don't do byte-swapping. * The insw/outsw/insl/outsl macros don't do byte-swapping.
* They are only used in practice for transferring buffers which * They are only used in practice for transferring buffers which
* are arrays of bytes, and byte-swapping is not appropriate in * are arrays of bytes, and byte-swapping is not appropriate in
* that case. - paulus */ * that case. - paulus */
#define insb(port, buf, ns) eeh_insb((u8 *)(port), (buf), (ns)) #define insb(port, buf, ns) _insb((u8 *)((port)+pci_io_base), (buf), (ns))
#define outsb(port, buf, ns) eeh_outsb((u8 *)(port), (buf), (ns)) #define outsb(port, buf, ns) _outsb((u8 *)((port)+pci_io_base), (buf), (ns))
#define insw(port, buf, ns) eeh_insw_ns((u16 *)(port), (buf), (ns)) #define insw(port, buf, ns) _insw_ns((u16 *)((port)+pci_io_base), (buf), (ns))
#define outsw(port, buf, ns) eeh_outsw_ns((u16 *)(port), (buf), (ns)) #define outsw(port, buf, ns) _outsw_ns((u16 *)((port)+pci_io_base), (buf), (ns))
#define insl(port, buf, nl) eeh_insl_ns((u32 *)(port), (buf), (nl)) #define insl(port, buf, nl) _insl_ns((u32 *)((port)+pci_io_base), (buf), (nl))
#define outsl(port, buf, nl) eeh_outsl_ns((u32 *)(port), (buf), (nl)) #define outsl(port, buf, nl) _outsl_ns((u32 *)((port)+pci_io_base), (buf), (nl))
#endif #endif
extern void _insb(volatile u8 *port, void *buf, int ns);
extern void _outsb(volatile u8 *port, const void *buf, int ns);
extern void _insw(volatile u16 *port, void *buf, int ns);
extern void _outsw(volatile u16 *port, const void *buf, int ns);
extern void _insl(volatile u32 *port, void *buf, int nl);
extern void _outsl(volatile u32 *port, const void *buf, int nl);
extern void _insw_ns(volatile u16 *port, void *buf, int ns);
extern void _outsw_ns(volatile u16 *port, const void *buf, int ns);
extern void _insl_ns(volatile u32 *port, void *buf, int nl);
extern void _outsl_ns(volatile u32 *port, const void *buf, int nl);
/* /*
* output pause versions need a delay at least for the * output pause versions need a delay at least for the
...@@ -92,27 +95,15 @@ extern int have_print; ...@@ -92,27 +95,15 @@ extern int have_print;
#define inl_p(port) inl(port) #define inl_p(port) inl(port)
#define outl_p(val, port) (udelay(1), outl((val, (port))) #define outl_p(val, port) (udelay(1), outl((val, (port)))
extern void _insb(volatile u8 *port, void *buf, int ns);
extern void _outsb(volatile u8 *port, const void *buf, int ns);
extern void _insw(volatile u16 *port, void *buf, int ns);
extern void _outsw(volatile u16 *port, const void *buf, int ns);
extern void _insl(volatile u32 *port, void *buf, int nl);
extern void _outsl(volatile u32 *port, const void *buf, int nl);
extern void _insw_ns(volatile u16 *port, void *buf, int ns);
extern void _outsw_ns(volatile u16 *port, const void *buf, int ns);
extern void _insl_ns(volatile u32 *port, void *buf, int nl);
extern void _outsl_ns(volatile u32 *port, const void *buf, int nl);
/* /*
* The *_ns versions below don't do byte-swapping. * The *_ns versions below don't do byte-swapping.
* Neither do the standard versions now, these are just here * Neither do the standard versions now, these are just here
* for older code. * for older code.
*/ */
#define insw_ns(port, buf, ns) insw(port, buf, ns) #define insw_ns(port, buf, ns) _insw_ns((u16 *)((port)+pci_io_base), (buf), (ns))
#define outsw_ns(port, buf, ns) outsw(port, buf, ns) #define outsw_ns(port, buf, ns) _outsw_ns((u16 *)((port)+pci_io_base), (buf), (ns))
#define insl_ns(port, buf, nl) insl(port, buf, nl) #define insl_ns(port, buf, nl) _insl_ns((u32 *)((port)+pci_io_base), (buf), (nl))
#define outsl_ns(port, buf, nl) outsl(port, buf, nl) #define outsl_ns(port, buf, nl) _outsl_ns((u32 *)((port)+pci_io_base), (buf), (nl))
#define IO_SPACE_LIMIT ~(0UL) #define IO_SPACE_LIMIT ~(0UL)
...@@ -249,49 +240,6 @@ static inline void out_be32(volatile unsigned *addr, int val) ...@@ -249,49 +240,6 @@ static inline void out_be32(volatile unsigned *addr, int val)
#ifndef CONFIG_PPC_ISERIES #ifndef CONFIG_PPC_ISERIES
#include <asm/eeh.h> #include <asm/eeh.h>
static inline u8 _inb(unsigned long port) {
if (IS_MAPPED_VADDR(port))
return readb((void *)port);
else if (_IO_BASE)
return in_8((u8 *)((port)+_IO_BASE));
else
return 0xff;
}
static inline void _outb(u8 val, unsigned long port) {
if (IS_MAPPED_VADDR(port))
return writeb(val, (void *)port);
else if (_IO_BASE)
out_8((u8 *)((port)+_IO_BASE), val);
}
static inline u16 _inw(unsigned long port) {
if (IS_MAPPED_VADDR(port))
return readw((void *)port);
else if (_IO_BASE)
return in_le16((u16 *)((port)+_IO_BASE));
else
return 0xffff;
}
static inline void _outw(u16 val, unsigned long port) {
if (IS_MAPPED_VADDR(port))
return writew(val, (void *)port);
else if (_IO_BASE)
out_le16((u16 *)((port)+_IO_BASE), val);
}
static inline u32 _inl(unsigned long port) {
if (IS_MAPPED_VADDR(port))
return readl((void *)port);
else if (_IO_BASE)
return in_le32((u32 *)((port)+_IO_BASE));
else
return 0xffffffff;
}
static inline void _outl(u32 val, unsigned long port) {
if (IS_MAPPED_VADDR(port))
return writel(val, (void *)port);
else if (_IO_BASE)
out_le32((u32 *)((port)+_IO_BASE), val);
}
#endif #endif
#ifdef __KERNEL__ #ifdef __KERNEL__
......
...@@ -168,8 +168,10 @@ static inline int get_order(unsigned long size) ...@@ -168,8 +168,10 @@ static inline int get_order(unsigned long size)
#define KERNELBASE PAGE_OFFSET #define KERNELBASE PAGE_OFFSET
#define VMALLOCBASE 0xD000000000000000 #define VMALLOCBASE 0xD000000000000000
#define IOREGIONBASE 0xE000000000000000 #define IOREGIONBASE 0xE000000000000000
#define EEHREGIONBASE 0xA000000000000000
#define IO_REGION_ID (IOREGIONBASE>>REGION_SHIFT) #define IO_REGION_ID (IOREGIONBASE>>REGION_SHIFT)
#define EEH_REGION_ID (EEHREGIONBASE>>REGION_SHIFT)
#define VMALLOC_REGION_ID (VMALLOCBASE>>REGION_SHIFT) #define VMALLOC_REGION_ID (VMALLOCBASE>>REGION_SHIFT)
#define KERNEL_REGION_ID (KERNELBASE>>REGION_SHIFT) #define KERNEL_REGION_ID (KERNELBASE>>REGION_SHIFT)
#define USER_REGION_ID (0UL) #define USER_REGION_ID (0UL)
......
...@@ -12,17 +12,6 @@ ...@@ -12,17 +12,6 @@
struct device_node; struct device_node;
struct pci_controller; struct pci_controller;
/*
* pci_io_base returns the memory address at which you can access
* the I/O space for PCI bus number `bus' (or NULL on error).
*/
extern void *pci_bus_io_base(unsigned int bus);
extern unsigned long pci_bus_io_base_phys(unsigned int bus);
extern unsigned long pci_bus_mem_base_phys(unsigned int bus);
/* Get the PCI host controller for a bus */
extern struct pci_controller* pci_bus_to_hose(int bus);
/* Get the PCI host controller for an OF device */ /* Get the PCI host controller for an OF device */
extern struct pci_controller* extern struct pci_controller*
pci_find_hose_for_OF_device(struct device_node* node); pci_find_hose_for_OF_device(struct device_node* node);
...@@ -92,6 +81,7 @@ static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev) ...@@ -92,6 +81,7 @@ static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev)
else else
return fetch_dev_dn(dev); return fetch_dev_dn(dev);
} }
/* Use this macro after the PCI bus walk for max performance when it /* Use this macro after the PCI bus walk for max performance when it
* is known that sysdata is correct. * is known that sysdata is correct.
*/ */
......
...@@ -9,18 +9,17 @@ ...@@ -9,18 +9,17 @@
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
/* Values for the `which' argument to sys_pciconfig_iobase syscall. */ #include <linux/types.h>
#define IOBASE_BRIDGE_NUMBER 0 #include <linux/slab.h>
#define IOBASE_MEMORY 1 #include <linux/string.h>
#define IOBASE_IO 2 #include <asm/scatterlist.h>
#define IOBASE_ISA_IO 3 #include <asm/io.h>
#define IOBASE_ISA_MEM 4 #include <asm/prom.h>
/* Can be used to override the logic in pci_scan_bus for skipping static inline int pcibios_assign_all_busses(void)
* already-configured bus numbers - to be used for buggy BIOSes {
* or architectures with incomplete PCI setup by the loader. return 0;
*/ }
extern int pcibios_assign_all_busses(void);
#define PCIBIOS_MIN_IO 0x1000 #define PCIBIOS_MIN_IO 0x1000
#define PCIBIOS_MIN_MEM 0x10000000 #define PCIBIOS_MIN_MEM 0x10000000
...@@ -35,31 +34,8 @@ static inline void pcibios_penalize_isa_irq(int irq) ...@@ -35,31 +34,8 @@ static inline void pcibios_penalize_isa_irq(int irq)
/* We don't do dynamic PCI IRQ allocation */ /* We don't do dynamic PCI IRQ allocation */
} }
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <asm/scatterlist.h>
#include <asm/io.h>
#include <asm/prom.h>
struct pci_dev; struct pci_dev;
#define REG_SAVE_SIZE 64
/************************************************************************
* Structure to hold the data for PCI Register Save/Restore functions. *
************************************************************************/
struct pci_config_reg_save_area {
struct pci_dev* PciDev; /* Pointer to device(Sanity Check) */
int Flags; /* Control & Info Flags */
int RCode; /* Return Code on Save/Restore */
int Register; /* Pointer to current register. */
u8 Regs[REG_SAVE_SIZE]; /* Save Area */
};
/************************************************************************
* Functions to support device reset *
************************************************************************/
extern int pci_reset_device(struct pci_dev*, int, int);
extern int pci_save_config_regs(struct pci_dev*,struct pci_config_reg_save_area*);
extern int pci_restore_config_regs(struct pci_dev*,struct pci_config_reg_save_area*);
extern char* pci_card_location(struct pci_dev*); extern char* pci_card_location(struct pci_dev*);
extern void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, extern void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
...@@ -68,7 +44,7 @@ extern void pci_free_consistent(struct pci_dev *hwdev, size_t size, ...@@ -68,7 +44,7 @@ extern void pci_free_consistent(struct pci_dev *hwdev, size_t size,
void *vaddr, dma_addr_t dma_handle); void *vaddr, dma_addr_t dma_handle);
extern dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, extern dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr,
size_t size, int direction); size_t size, int direction);
extern void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, extern void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
size_t size, int direction); size_t size, int direction);
extern int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, extern int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
......
...@@ -125,12 +125,18 @@ struct device_node { ...@@ -125,12 +125,18 @@ struct device_node {
int n_intrs; int n_intrs;
struct interrupt_info *intrs; struct interrupt_info *intrs;
char *full_name; char *full_name;
/* PCI stuff probably doesn't belong here */
int busno; /* for pci devices */ int busno; /* for pci devices */
int bussubno; /* for pci devices */ int bussubno; /* for pci devices */
int devfn; /* for pci devices */ int devfn; /* for pci devices */
#define DN_STATUS_BIST_FAILED (1<<0)
int status; /* Current device status (non-zero is bad) */
int eeh_mode; /* See eeh.h for possible EEH_MODEs */
int eeh_config_addr;
struct pci_controller *phb; /* for pci devices */ struct pci_controller *phb; /* for pci devices */
struct TceTable *tce_table; /* for phb's or bridges */ struct TceTable *tce_table; /* for phb's or bridges */
#define DN_STATUS_BIST_FAILED (1<<0)
struct property *properties; struct property *properties;
struct device_node *parent; struct device_node *parent;
struct device_node *child; struct device_node *child;
......
...@@ -23,6 +23,7 @@ struct thread_info { ...@@ -23,6 +23,7 @@ struct thread_info {
unsigned long flags; /* low level flags */ unsigned long flags; /* low level flags */
int cpu; /* cpu we're on */ int cpu; /* cpu we're on */
int preempt_count; /* not used at present */ int preempt_count; /* not used at present */
struct restart_block restart_block;
}; };
/* /*
...@@ -37,6 +38,9 @@ struct thread_info { ...@@ -37,6 +38,9 @@ struct thread_info {
.flags = 0, \ .flags = 0, \
.cpu = 0, \ .cpu = 0, \
.preempt_count = 1, \ .preempt_count = 1, \
.restart_block = { \
.fn = do_no_restart_syscall, \
}, \
} }
#define init_thread_info (init_thread_union.thread_info) #define init_thread_info (init_thread_union.thread_info)
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#define __NR_restart_syscall 0
#define __NR_exit 1 #define __NR_exit 1
#define __NR_fork 2 #define __NR_fork 2
#define __NR_read 3 #define __NR_read 3
......
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