* Re: [PATCH]: e1000: prevent statistics from getting garbled during reset.
From: Jeff V. Merkey @ 2006-03-31 18:40 UTC (permalink / raw)
To: Linas Vepstas
Cc: netdev, linux-kernel, jesse.brandeburg, linuxppc-dev,
john.ronciak, jeffrey.t.kirsher, linux-pci, Jeff Garzik
In-Reply-To: <20060331170319.GV2172@austin.ibm.com>
Linas Vepstas wrote:
>On Thu, Mar 30, 2006 at 09:14:56PM -0700, Jeffrey V. Merkey wrote:
>
>
>>Yes, we need one. The adapter needs to maintain these stats from the
>>registers in the kernel structure and not
>>its own local variables.
>>
>>
>
>Did you read the code to see what the adapter does with these stats?
>Among other things, it uses them to adaptively modulate transmit rates
>to avoid collisions. Just clearing the hardware-private stats will mess
>up that function.
>
>
>
I noticed that.
>>That way, when someone calls to clear the stats
>>for testing and analysis purposes,
>>they zero out and are reset.
>>
>>
>
>1) ifdown/ifup is guarenteed to to clear things. Try that.
>
>
No, not dynamic. I'll patch the driver locally, thanks.
Jeff
>2) What's wrong with taking deltas? Typical through-put performance
>measurement is done by pre-loading the pipes (i.e. running for
>a few minutes wihtout measuring, then starting the measurement).
>I'd think that snapshotting the numbers would be easier, and is
>trivially doable in user-space. I guess I don't understand why
>you need a new kernel featre to imlement this.
>
>--linas
>
>
>
^ permalink raw reply
* Re: [PATCH]: e1000: prevent statistics from getting garbled during reset.
From: Rick Jones @ 2006-03-31 17:36 UTC (permalink / raw)
Cc: netdev, linux-pci, linux-kernel, linuxppc-dev
In-Reply-To: <20060331170319.GV2172@austin.ibm.com>
> 2) What's wrong with taking deltas? Typical through-put performance
> measurement is done by pre-loading the pipes (i.e. running for
> a few minutes wihtout measuring, then starting the measurement).
> I'd think that snapshotting the numbers would be easier, and is
> trivially doable in user-space. I guess I don't understand why
> you need a new kernel featre to imlement this.
ftp://ftp.cup.hp.com/dist/networking/tools/beforeafter.tar.gz
Not my code, I've used it with success against ethtool -S output.
rick jones
^ permalink raw reply
* Re: [PATCH] powerpc/pseries: EEH Cleanup
From: Linas Vepstas @ 2006-03-31 18:04 UTC (permalink / raw)
To: Nathan Fontenot, Paul Mackerras; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <200603311013.22208.nfont@austin.ibm.com>
Please apply.
This patch removes unnecessary exports, marks functions as static when
possible, and simplifies some list-related code.
Signed-off-by: Nathan Fontenot <nfont@austin.ibm.com>
Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
----
Paul, please apply and forward upstream.
On Fri, Mar 31, 2006 at 10:13:21AM -0600, Nathan Fontenot wrote:
> This patch removes unnecessary exports, marks functions as static when
> possible, and simplifies some list-related code.
Nathan's original patch did not apply cleanly for me, nor did it build
cleanly. However, the one below does.
Linas.
arch/powerpc/platforms/pseries/eeh.c | 62 ++++++++++++++++-------------------
include/asm-powerpc/eeh.h | 20 -----------
2 files changed, 30 insertions(+), 52 deletions(-)
Index: linux-2.6.16-git19/arch/powerpc/platforms/pseries/eeh.c
===================================================================
--- linux-2.6.16-git19.orig/arch/powerpc/platforms/pseries/eeh.c 2006-03-31 11:38:49.000000000 -0600
+++ linux-2.6.16-git19/arch/powerpc/platforms/pseries/eeh.c 2006-03-31 11:54:24.901762378 -0600
@@ -865,7 +865,7 @@ void __init eeh_init(void)
* on the CEC architecture, type of the device, on earlier boot
* command-line arguments & etc.
*/
-void eeh_add_device_early(struct device_node *dn)
+static void eeh_add_device_early(struct device_node *dn)
{
struct pci_controller *phb;
struct eeh_early_enable_info info;
@@ -882,7 +882,6 @@ void eeh_add_device_early(struct device_
info.buid_lo = BUID_LO(phb->buid);
early_enable_eeh(dn, &info);
}
-EXPORT_SYMBOL_GPL(eeh_add_device_early);
void eeh_add_device_tree_early(struct device_node *dn)
{
@@ -893,20 +892,6 @@ void eeh_add_device_tree_early(struct de
}
EXPORT_SYMBOL_GPL(eeh_add_device_tree_early);
-void eeh_add_device_tree_late(struct pci_bus *bus)
-{
- struct pci_dev *dev;
-
- list_for_each_entry(dev, &bus->devices, bus_list) {
- eeh_add_device_late(dev);
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
- struct pci_bus *subbus = dev->subordinate;
- if (subbus)
- eeh_add_device_tree_late(subbus);
- }
- }
-}
-
/**
* eeh_add_device_late - perform EEH initialization for the indicated pci device
* @dev: pci device for which to set up EEH
@@ -914,7 +899,7 @@ void eeh_add_device_tree_late(struct pci
* This routine must be used to complete EEH initialization for PCI
* devices that were added after system boot (e.g. hotplug, dlpar).
*/
-void eeh_add_device_late(struct pci_dev *dev)
+static void eeh_add_device_late(struct pci_dev *dev)
{
struct device_node *dn;
struct pci_dn *pdn;
@@ -933,16 +918,33 @@ void eeh_add_device_late(struct pci_dev
pci_addr_cache_insert_device (dev);
}
-EXPORT_SYMBOL_GPL(eeh_add_device_late);
+
+void eeh_add_device_tree_late(struct pci_bus *bus)
+{
+ struct pci_dev *dev;
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ eeh_add_device_late(dev);
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ struct pci_bus *subbus = dev->subordinate;
+ if (subbus)
+ eeh_add_device_tree_late(subbus);
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(eeh_add_device_tree_late);
/**
* eeh_remove_device - undo EEH setup for the indicated pci device
* @dev: pci device to be removed
*
- * This routine should be when a device is removed from a running
- * system (e.g. by hotplug or dlpar).
+ * This routine should be called when a device is removed from
+ * a running system (e.g. by hotplug or dlpar). It unregisters
+ * the PCI device from the EEH subsystem. I/O errors affecting
+ * this device will no longer be detected after this call; thus,
+ * i/o errors affecting this slot may leave this device unusable.
*/
-void eeh_remove_device(struct pci_dev *dev)
+static void eeh_remove_device(struct pci_dev *dev)
{
struct device_node *dn;
if (!dev || !eeh_subsystem_enabled)
@@ -958,21 +960,17 @@ void eeh_remove_device(struct pci_dev *d
PCI_DN(dn)->pcidev = NULL;
pci_dev_put (dev);
}
-EXPORT_SYMBOL_GPL(eeh_remove_device);
void eeh_remove_bus_device(struct pci_dev *dev)
{
+ struct pci_bus *bus = dev->subordinate;
+ struct pci_dev *child, *tmp;
+
eeh_remove_device(dev);
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
- struct pci_bus *bus = dev->subordinate;
- struct list_head *ln;
- if (!bus)
- return;
- for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
- struct pci_dev *pdev = pci_dev_b(ln);
- if (pdev)
- eeh_remove_bus_device(pdev);
- }
+
+ if (bus && dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ list_for_each_entry_safe(child, tmp, &bus->devices, bus_list)
+ eeh_remove_bus_device(child);
}
}
EXPORT_SYMBOL_GPL(eeh_remove_bus_device);
Index: linux-2.6.16-git19/include/asm-powerpc/eeh.h
===================================================================
--- linux-2.6.16-git19.orig/include/asm-powerpc/eeh.h 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16-git19/include/asm-powerpc/eeh.h 2006-03-31 11:47:35.000000000 -0600
@@ -60,24 +60,10 @@ void __init pci_addr_cache_build(void);
* device (including config space i/o). Call eeh_add_device_late
* to finish the eeh setup for this device.
*/
-void eeh_add_device_early(struct device_node *);
-void eeh_add_device_late(struct pci_dev *dev);
void eeh_add_device_tree_early(struct device_node *);
void eeh_add_device_tree_late(struct pci_bus *);
/**
- * eeh_remove_device - undo EEH setup for the indicated pci device
- * @dev: pci device to be removed
- *
- * This routine should be called when a device is removed from
- * a running system (e.g. by hotplug or dlpar). It unregisters
- * the PCI device from the EEH subsystem. I/O errors affecting
- * this device will no longer be detected after this call; thus,
- * i/o errors affecting this slot may leave this device unusable.
- */
-void eeh_remove_device(struct pci_dev *);
-
-/**
* eeh_remove_device_recursive - undo EEH for device & children.
* @dev: pci device to be removed
*
@@ -116,12 +102,6 @@ static inline int eeh_dn_check_failure(s
static inline void pci_addr_cache_build(void) { }
-static inline void eeh_add_device_early(struct device_node *dn) { }
-
-static inline void eeh_add_device_late(struct pci_dev *dev) { }
-
-static inline void eeh_remove_device(struct pci_dev *dev) { }
-
static inline void eeh_add_device_tree_early(struct device_node *dn) { }
static inline void eeh_add_device_tree_late(struct pci_bus *bus) { }
^ permalink raw reply
* Re: mpc5200b and floating point
From: Roger Larsson @ 2006-03-31 18:27 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <20060331133619.GD7738@localhost.localdomain>
On fredag 31 mars 2006 15.36, Sascha Hauer wrote:
> Hi,
>
> I'm working with a mpc5200b custom board and I'm trying to run an
> application with floating point. All floating point variables seem to
> zero all the time. Since I'm not very familiar with powerpc it might be
> something stupid I have overlooked.
Since a lot of PowerPC do not have floating point processor your tools
might be setup to compile without it (compare with sse2 on x86).
Check your compiler flags again.
Define -mcpu= and -mhard-float
Undefine -msoft-float
/RogerL
^ permalink raw reply
* Re: mpc5200b and floating point
From: White @ 2006-03-31 18:36 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <20060331133619.GD7738@localhost.localdomain>
Am Fri, 31 Mar 2006 15:36:20 +0200 schrieb Sascha Hauer
<s.hauer@pengutronix.de> :
Please check your Toolchain.
Have you build it ?
Do you use glibc or something like uclibc ?
At my beginning with mpc5200 i hat simular problems.
I had the wrong Compilerflags during build of my ToolChain.
(uclibc).
Good Luck.
> Hi,
>
> I'm working with a mpc5200b custom board and I'm trying to run an
> application with floating point. All floating point variables seem to
> zero all the time. Since I'm not very familiar with powerpc it might be
> something stupid I have overlooked.
> Any hints?
>
> Thank you,
>
> Sascha Hauer
>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>
^ permalink raw reply
* Re: [PATCH]: e1000: prevent statistics from getting garbled during reset.
From: Linas Vepstas @ 2006-03-31 17:06 UTC (permalink / raw)
To: Greg KH
Cc: netdev, linux-kernel, jesse.brandeburg, linuxppc-dev,
john.ronciak, jeffrey.t.kirsher, linux-pci, Jeff Garzik
In-Reply-To: <20060331054654.GA6632@kroah.com>
On Thu, Mar 30, 2006 at 09:46:54PM -0800, Greg KH wrote:
>
> (hint, use a tab...)
glurg.
[PATCH]: e1000: prevent statistics from getting garbled during reset.
If a PCI bus error/fault triggers a PCI bus reset, attempts to get the
ethernet packet count statistics from the hardware will fail, returning
garbage data upstream. This patch skips statistics data collection
if the PCI device is not on the bus.
This patch presumes that an earlier patch,
[PATCH] PCI Error Recovery: e1000 network device driver
has already been applied.
Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
----
drivers/net/e1000/e1000_main.c | 6 +++++-
1 files changed, 5 insertions(+), 1 deletion(-)
Index: linux-2.6.16-git6/drivers/net/e1000/e1000_main.c
===================================================================
--- linux-2.6.16-git6.orig/drivers/net/e1000/e1000_main.c 2006-03-30 17:51:37.924162779 -0600
+++ linux-2.6.16-git6/drivers/net/e1000/e1000_main.c 2006-03-30 17:54:07.659188391 -0600
@@ -3069,14 +3069,18 @@ void
e1000_update_stats(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
+ struct pci_dev *pdev = adapter->pdev;
unsigned long flags;
uint16_t phy_tmp;
#define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
- /* Prevent stats update while adapter is being reset */
+ /* Prevent stats update while adapter is being reset,
+ * or if the pci connection is down. */
if (adapter->link_speed == 0)
return;
+ if (pdev->error_state && pdev->error_state != pci_channel_io_normal)
+ return;
spin_lock_irqsave(&adapter->stats_lock, flags);
^ permalink raw reply
* Re: mpc5200b and floating point
From: Dan Malek @ 2006-03-31 18:58 UTC (permalink / raw)
To: Roger Larsson; +Cc: linuxppc-embedded
In-Reply-To: <200603312027.22359.roger.larsson@norran.net>
On Mar 31, 2006, at 1:27 PM, Roger Larsson wrote:
> Since a lot of PowerPC do not have floating point processor your tools
> might be setup to compile without it (compare with sse2 on x86).
Nearly all of the PowerPC do have floating point, only a few do not.
It's highly unlikely to find a PowerPC tool set that was custom
built to not enable floating point. Don't forget that the compiler
flags are only a small part of the picture, you need matching
compiler run time support and application libraries as well.
Just using the compiler flags and not selecting the proper
libraries will not be a positive experience.
-- Dan
^ permalink raw reply
* [PATCH] powerpc/pseries: whitespace cleanups
From: Nathan Fontenot @ 2006-03-31 21:09 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
This patch is nothing but whitespace cleanup for eeh.c. This removes spaces
between function calls and their parameters, edits lines that are longer than
80 characters and puts function return variables and function names on one
line.
Signed-off-by: Nathan Fontenot <nfont@austin.ibm.com>
Index: nfont/kernel/arch/powerpc/platforms/pseries/eeh.c
===================================================================
--- nfont.orig/kernel/arch/powerpc/platforms/pseries/eeh.c 2006-03-31
09:02:17.%N -0600
+++ nfont/kernel/arch/powerpc/platforms/pseries/eeh.c 2006-03-31 14:34:43.%N
-0600
@@ -111,7 +111,7 @@ static unsigned long slot_resets;
/* --------------------------------------------------------------- */
/* Below lies the EEH event infrastructure */
-void eeh_slot_error_detail (struct pci_dn *pdn, int severity)
+void eeh_slot_error_detail(struct pci_dn *pdn, int severity)
{
int config_addr;
unsigned long flags;
@@ -126,13 +126,10 @@ void eeh_slot_error_detail (struct pci_d
if (pdn->eeh_pe_config_addr)
config_addr = pdn->eeh_pe_config_addr;
- rc = rtas_call(ibm_slot_error_detail,
- 8, 1, NULL, config_addr,
- BUID_HI(pdn->phb->buid),
- BUID_LO(pdn->phb->buid), NULL, 0,
- virt_to_phys(slot_errbuf),
- eeh_error_buf_size,
- severity);
+ rc = rtas_call(ibm_slot_error_detail, 8, 1, NULL, config_addr,
+ BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid),
+ NULL, 0, virt_to_phys(slot_errbuf),
+ eeh_error_buf_size, severity);
if (rc == 0)
log_error(slot_errbuf, ERR_TYPE_RTAS_LOG, 0);
@@ -184,7 +181,7 @@ static inline unsigned long eeh_token_to
return pa | (token & (PAGE_SIZE-1));
}
-/**
+/**
* Return the "partitionable endpoint" (pe) under which this device lies
*/
struct device_node * find_device_pe(struct device_node *dn)
@@ -203,8 +200,7 @@ struct device_node * find_device_pe(stru
* and the slot is frozen, then the driver can deadlock in
* an interrupt context, which is bad.
*/
-
-static void __eeh_mark_slot (struct device_node *dn, int mode_flag)
+static void __eeh_mark_slot(struct device_node *dn, int mode_flag)
{
while (dn) {
if (PCI_DN(dn)) {
@@ -217,13 +213,13 @@ static void __eeh_mark_slot (struct devi
dev->error_state = pci_channel_io_frozen;
if (dn->child)
- __eeh_mark_slot (dn->child, mode_flag);
+ __eeh_mark_slot(dn->child, mode_flag);
}
dn = dn->sibling;
}
}
-void eeh_mark_slot (struct device_node *dn, int mode_flag)
+void eeh_mark_slot(struct device_node *dn, int mode_flag)
{
dn = find_device_pe (dn);
@@ -232,36 +228,36 @@ void eeh_mark_slot (struct device_node *
dn = dn->parent;
PCI_DN(dn)->eeh_mode |= mode_flag;
- __eeh_mark_slot (dn->child, mode_flag);
+ __eeh_mark_slot(dn->child, mode_flag);
}
-static void __eeh_clear_slot (struct device_node *dn, int mode_flag)
+static void __eeh_clear_slot(struct device_node *dn, int mode_flag)
{
while (dn) {
if (PCI_DN(dn)) {
PCI_DN(dn)->eeh_mode &= ~mode_flag;
PCI_DN(dn)->eeh_check_count = 0;
if (dn->child)
- __eeh_clear_slot (dn->child, mode_flag);
+ __eeh_clear_slot(dn->child, mode_flag);
}
dn = dn->sibling;
}
}
-void eeh_clear_slot (struct device_node *dn, int mode_flag)
+void eeh_clear_slot(struct device_node *dn, int mode_flag)
{
unsigned long flags;
spin_lock_irqsave(&confirm_error_lock, flags);
-
+
dn = find_device_pe (dn);
-
+
/* Back up one, since config addrs might be shared */
if (PCI_DN(dn) && PCI_DN(dn)->eeh_pe_config_addr)
dn = dn->parent;
PCI_DN(dn)->eeh_mode &= ~mode_flag;
PCI_DN(dn)->eeh_check_count = 0;
- __eeh_clear_slot (dn->child, mode_flag);
+ __eeh_clear_slot(dn->child, mode_flag);
spin_unlock_irqrestore(&confirm_error_lock, flags);
}
@@ -305,8 +301,8 @@ int eeh_dn_check_failure(struct device_n
pdn->eeh_mode & EEH_MODE_NOCHECK) {
ignored_check++;
#ifdef DEBUG
- printk ("EEH:ignored check (%x) for %s %s\n",
- pdn->eeh_mode, pci_name (dev), dn->full_name);
+ printk("EEH:ignored check (%x) for %s %s\n",
+ pdn->eeh_mode, pci_name(dev), dn->full_name);
#endif
return 0;
}
@@ -327,16 +323,17 @@ int eeh_dn_check_failure(struct device_n
if (pdn->eeh_mode & EEH_MODE_ISOLATED) {
pdn->eeh_check_count ++;
if (pdn->eeh_check_count >= EEH_MAX_FAILS) {
- printk (KERN_ERR "EEH: Device driver ignored %d bad
reads, panicing\n",
- pdn->eeh_check_count);
+ printk(KERN_ERR "EEH: Device driver ignored %d bad "
+ "reads, panicing\n", pdn->eeh_check_count);
dump_stack();
-
+
/* re-read the slot reset state */
if (read_slot_reset_state(pdn, rets) != 0)
rets[0] = -1; /* reset state unknown */
- /* If we are here, then we hit an infinite loop. Stop.
*/
- panic("EEH: MMIO halt (%d) on device:%s\n", rets[0],
pci_name(dev));
+ /* If we're here, then we hit an infinite loop. Stop.
*/+ panic("EEH: MMIO halt (%d) on device:%s\n",
+ rets[0], pci_name(dev));
}
goto dn_unlock;
}
@@ -352,8 +349,8 @@ int eeh_dn_check_failure(struct device_n
/* If the call to firmware failed, punt */
if (ret != 0) {
- printk(KERN_WARNING "EEH: read_slot_reset_state() failed;
rc=%d dn=%s\n",
- ret, dn->full_name);
+ printk(KERN_WARNING "EEH: read_slot_reset_state() failed; "
+ "rc=%d dn=%s\n", ret, dn->full_name);
false_positives++;
rc = 0;
goto dn_unlock;
@@ -361,8 +358,8 @@ int eeh_dn_check_failure(struct device_n
/* If EEH is not supported on this device, punt. */
if (rets[1] != 1) {
- printk(KERN_WARNING "EEH: event on unsupported device, rc=%d
dn=%s\n",
- ret, dn->full_name);
+ printk(KERN_WARNING "EEH: event on unsupported device, rc=%d "
+ "dn=%s\n", ret, dn->full_name);
false_positives++;
rc = 0;
goto dn_unlock;
@@ -384,11 +381,11 @@ int eeh_dn_check_failure(struct device_n
}
slot_resets++;
-
+
/* Avoid repeated reports of this failure, including problems
* with other functions on this device, and functions under
* bridges. */
- eeh_mark_slot (dn, EEH_MODE_ISOLATED);
+ eeh_mark_slot(dn, EEH_MODE_ISOLATED);
spin_unlock_irqrestore(&confirm_error_lock, flags);
state = pci_channel_io_normal;
@@ -396,12 +393,13 @@ int eeh_dn_check_failure(struct device_n
state = pci_channel_io_frozen;
if (rets[0] == 5)
state = pci_channel_io_perm_failure;
- eeh_send_failure_event (dn, dev, state, rets[2]);
+ eeh_send_failure_event(dn, dev, state, rets[2]);
/* Most EEH events are due to device driver bugs. Having
* a stack trace will help the device-driver authors figure
* out what happened. So print that out. */
- if (rets[0] != 5) dump_stack();
+ if (rets[0] != 5)
+ dump_stack();
return 1;
dn_unlock:
@@ -438,7 +436,7 @@ unsigned long eeh_check_failure(const vo
}
dn = pci_device_to_OF_node(dev);
- eeh_dn_check_failure (dn, dev);
+ eeh_dn_check_failure(dn, dev);
pci_dev_put(dev);
return val;
@@ -453,26 +451,29 @@ EXPORT_SYMBOL(eeh_check_failure);
* a number of milliseconds to wait until the PCI slot is
* ready to be used.
*/
-static int
-eeh_slot_availability(struct pci_dn *pdn)
+static int eeh_slot_availability(struct pci_dn *pdn)
{
int rc;
int rets[3];
rc = read_slot_reset_state(pdn, rets);
- if (rc) return rc;
+ if (rc)
+ return rc;
- if (rets[1] == 0) return -1; /* EEH is not supported */
- if (rets[0] == 0) return 0; /* Oll Korrect */
+ if (rets[1] == 0)
+ return -1; /* EEH is not supported */
+ if (rets[0] == 0)
+ return 0; /* Oll Korrect */
if (rets[0] == 5) {
- if (rets[2] == 0) return -1; /* permanently unavailable */
+ if (rets[2] == 0)
+ return -1; /* permanently unavailable */
return rets[2]; /* number of millisecs to wait */
}
if (rets[0] == 1)
return 250;
- printk (KERN_ERR "EEH: Slot unavailable: rc=%d, rets=%d %d %d\n",
+ printk(KERN_ERR "EEH: Slot unavailable: rc=%d, rets=%d %d %d\n",
rc, rets[0], rets[1], rets[2]);
return -1;
}
@@ -486,18 +487,16 @@ eeh_slot_availability(struct pci_dn *pdn
* safe to call in an interrupt context.
*
*/
-
-static void
-rtas_pci_slot_reset(struct pci_dn *pdn, int state)
+static void rtas_pci_slot_reset(struct pci_dn *pdn, int state)
{
int config_addr;
int rc;
- BUG_ON (pdn==NULL);
+ BUG_ON (pdn==NULL);
if (!pdn->phb) {
- printk (KERN_WARNING "EEH: in slot reset, device node %s has
no phb\n",
- pdn->node->full_name);
+ printk(KERN_WARNING "EEH: in slot reset, device node %s "
+ "has no phb\n", pdn->node->full_name);
return;
}
@@ -506,14 +505,13 @@ rtas_pci_slot_reset(struct pci_dn *pdn,
if (pdn->eeh_pe_config_addr)
config_addr = pdn->eeh_pe_config_addr;
- rc = rtas_call(ibm_set_slot_reset,4,1, NULL,
- config_addr,
- BUID_HI(pdn->phb->buid),
- BUID_LO(pdn->phb->buid),
+ rc = rtas_call(ibm_set_slot_reset,4,1, NULL, config_addr,
+ BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid),
state);
if (rc) {
- printk (KERN_WARNING "EEH: Unable to reset the failed slot,
(%d) #RST=%d dn=%s\n",
- rc, state, pdn->node->full_name);
+ printk(KERN_WARNING "EEH: Unable to reset the failed slot, "
+ "(%d) #RST=%d dn=%s\n", rc, state,
+ pdn->node->full_name);
return;
}
}
@@ -523,39 +521,38 @@ rtas_pci_slot_reset(struct pci_dn *pdn,
*
* Return 0 if success, else a non-zero value.
*/
-
-int
-rtas_set_slot_reset(struct pci_dn *pdn)
+int rtas_set_slot_reset(struct pci_dn *pdn)
{
int i, rc;
- rtas_pci_slot_reset (pdn, 1);
+ rtas_pci_slot_reset(pdn, 1);
/* The PCI bus requires that the reset be held high for at least
* a 100 milliseconds. We wait a bit longer 'just in case'. */
#define PCI_BUS_RST_HOLD_TIME_MSEC 250
- msleep (PCI_BUS_RST_HOLD_TIME_MSEC);
-
- /* We might get hit with another EEH freeze as soon as the
+ msleep(PCI_BUS_RST_HOLD_TIME_MSEC);
+
+ /* We might get hit with another EEH freeze as soon as the
* pci slot reset line is dropped. Make sure we don't miss
* these, and clear the flag now. */
- eeh_clear_slot (pdn->node, EEH_MODE_ISOLATED);
+ eeh_clear_slot(pdn->node, EEH_MODE_ISOLATED);
- rtas_pci_slot_reset (pdn, 0);
+ rtas_pci_slot_reset(pdn, 0);
/* After a PCI slot has been reset, the PCI Express spec requires
* a 1.5 second idle time for the bus to stabilize, before starting
* up traffic. */
#define PCI_BUS_SETTLE_TIME_MSEC 1800
- msleep (PCI_BUS_SETTLE_TIME_MSEC);
+ msleep(PCI_BUS_SETTLE_TIME_MSEC);
/* Now double check with the firmware to make sure the device is
* ready to be used; if not, wait for recovery. */
- for (i=0; i<10; i++) {
- rc = eeh_slot_availability (pdn);
+ for (i = 0; i < 10; i++) {
+ rc = eeh_slot_availability(pdn);
if (rc < 0)
- printk (KERN_ERR "EEH: failed (%d) to reset slot
%s\n", rc, pdn->node->full_name);
+ printk(KERN_ERR "EEH: failed (%d) to reset slot %s\n",
+ rc, pdn->node->full_name);
if (rc == 0)
return 0;
if (rc < 0)
@@ -564,9 +561,10 @@ rtas_set_slot_reset(struct pci_dn *pdn)
msleep (rc+100);
}
- rc = eeh_slot_availability (pdn);
+ rc = eeh_slot_availability(pdn);
if (rc)
- printk (KERN_ERR "EEH: timeout resetting slot %s\n",
pdn->node->full_name);
+ printk(KERN_ERR "EEH: timeout resetting slot %s\n",
+ pdn->node->full_name);
return rc;
}
@@ -577,7 +575,7 @@ rtas_set_slot_reset(struct pci_dn *pdn)
* Although firmware will set up BARs during boot, it doesn't
* set up device BAR's after a device reset, although it will,
* if requested, set up bridge configuration. Thus, we need to
- * configure the PCI devices ourselves.
+ * configure the PCI devices ourselves.
*/
/**
@@ -586,12 +584,14 @@ rtas_set_slot_reset(struct pci_dn *pdn)
* the expansion ROM base address, the latency timer, and etc.
* from the saved values in the device node.
*/
-static inline void __restore_bars (struct pci_dn *pdn)
+static inline void __restore_bars(struct pci_dn *pdn)
{
int i;
- if (NULL==pdn->phb) return;
- for (i=4; i<10; i++) {
+ if (NULL==pdn->phb)
+ return;
+
+ for (i = 4; i < 10; i++) {
rtas_write_config(pdn, i*4, 4, pdn->config_space[i]);
}
@@ -601,11 +601,11 @@ static inline void __restore_bars (struc
#define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF))
#define SAVED_BYTE(OFF) (((u8 *)(pdn->config_space))[BYTE_SWAP(OFF)])
- rtas_write_config (pdn, PCI_CACHE_LINE_SIZE, 1,
- SAVED_BYTE(PCI_CACHE_LINE_SIZE));
+ rtas_write_config(pdn, PCI_CACHE_LINE_SIZE, 1,
+ SAVED_BYTE(PCI_CACHE_LINE_SIZE));
- rtas_write_config (pdn, PCI_LATENCY_TIMER, 1,
- SAVED_BYTE(PCI_LATENCY_TIMER));
+ rtas_write_config(pdn, PCI_LATENCY_TIMER, 1,
+ SAVED_BYTE(PCI_LATENCY_TIMER));
/* max latency, min grant, interrupt pin and line */
rtas_write_config(pdn, 15*4, 4, pdn->config_space[15]);
@@ -620,15 +620,15 @@ static inline void __restore_bars (struc
void eeh_restore_bars(struct pci_dn *pdn)
{
struct device_node *dn;
- if (!pdn)
+ if (!pdn)
return;
-
+
if ((pdn->eeh_mode & EEH_MODE_SUPPORTED)
&& !IS_BRIDGE(pdn->class_code))- __restore_bars (pdn);
+ __restore_bars(pdn);
dn = pdn->node->child;
while (dn) {
- eeh_restore_bars (PCI_DN(dn));
+ eeh_restore_bars(PCI_DN(dn));
dn = dn->sibling;
}
}
@@ -645,9 +645,9 @@ static void eeh_save_bars(struct pci_dn
{
int i;
- if (!pdn )
+ if (!pdn)
return;
-
+
for (i = 0; i < 16; i++)
rtas_read_config(pdn, i * 4, 4, &pdn->config_space[i]);
}
@@ -663,13 +663,11 @@ rtas_configure_bridge(struct pci_dn *pdn
if (pdn->eeh_pe_config_addr)
config_addr = pdn->eeh_pe_config_addr;
- rc = rtas_call(ibm_configure_bridge,3,1, NULL,
- config_addr,
- BUID_HI(pdn->phb->buid),
- BUID_LO(pdn->phb->buid));
+ rc = rtas_call(ibm_configure_bridge,3,1, NULL, config_addr,
+ BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid));
if (rc) {
- printk (KERN_WARNING "EEH: Unable to configure device bridge
(%d) for %s\n",
- rc, pdn->node->full_name);
+ printk(KERN_WARNING "EEH: Unable to configure device bridge "
+ "(%d) for %s\n", rc, pdn->node->full_name);
}
}
@@ -750,31 +748,35 @@ static void *early_enable_eeh(struct dev
pdn->eeh_mode |= EEH_MODE_SUPPORTED;
pdn->eeh_config_addr = regs[0];
- /* If the newer, better, ibm,get-config-addr-info is
supported,
- * then use that instead. */
+ /* If the newer, better, ibm,get-config-addr-info
+ * is supported, then use that instead. */
pdn->eeh_pe_config_addr = 0;
if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE)
{
unsigned int rets[2];
- ret = rtas_call (ibm_get_config_addr_info, 4,
2, rets,
- pdn->eeh_config_addr,
- info->buid_hi, info->buid_lo,
- 0);
+ ret = rtas_call(ibm_get_config_addr_info, 4,
2,
+ rets, pdn->eeh_config_addr,
+ info->buid_hi, info->buid_lo,
+ 0);
if (ret == 0)
pdn->eeh_pe_config_addr = rets[0];
}
#ifdef DEBUG
- printk(KERN_DEBUG "EEH: %s: eeh enabled, config=%x
pe_config=%x\n",
- dn->full_name, pdn->eeh_config_addr,
pdn->eeh_pe_config_addr);
+ printk(KERN_DEBUG "EEH: %s: eeh enabled, config=%x "
+ "pe_config=%x\n", dn->full_name,
+ pdn->eeh_config_addr,
pdn->eeh_pe_config_addr);
#endif
} else {
/* This device doesn't support EEH, but it may have an
* EEH parent, in which case we mark it as supported.
*/ if (dn->parent && PCI_DN(dn->parent)
- && (PCI_DN(dn->parent)->eeh_mode &
EEH_MODE_SUPPORTED)) {
+ && (PCI_DN(dn->parent)->eeh_mode
+ & EEH_MODE_SUPPORTED)) {
+
/* Parent supports EEH. */
pdn->eeh_mode |= EEH_MODE_SUPPORTED;
- pdn->eeh_config_addr =
PCI_DN(dn->parent)->eeh_config_addr;
+ pdn->eeh_config_addr =
+ PCI_DN(dn->parent)->eeh_config_addr;
return NULL;
}
}
@@ -818,7 +820,7 @@ void __init eeh_init(void)
ibm_read_slot_reset_state = rtas_token("ibm,read-slot-reset-state");
ibm_slot_error_detail = rtas_token("ibm,slot-error-detail");
ibm_get_config_addr_info = rtas_token("ibm,get-config-addr-info");
- ibm_configure_bridge = rtas_token ("ibm,configure-bridge");
+ ibm_configure_bridge = rtas_token("ibm,configure-bridge");
if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE)
return;
@@ -828,8 +830,9 @@ void __init eeh_init(void)
eeh_error_buf_size = 1024;
}
if (eeh_error_buf_size > RTAS_ERROR_LOG_MAX) {
- printk(KERN_WARNING "EEH: rtas-error-log-max is bigger than
allocated "
- "buffer ! (%d vs %d)", eeh_error_buf_size,
RTAS_ERROR_LOG_MAX);
+ printk(KERN_WARNING "EEH: rtas-error-log-max is bigger than "
+ "allocated buffer ! (%d vs %d)", eeh_error_buf_size,
+ RTAS_ERROR_LOG_MAX);
eeh_error_buf_size = RTAS_ERROR_LOG_MAX;
}
@@ -848,7 +851,8 @@ void __init eeh_init(void)
}
if (eeh_subsystem_enabled)
- printk(KERN_INFO "EEH: PCI Enhanced I/O Error Handling
Enabled\n");
+ printk(KERN_INFO "EEH: PCI Enhanced I/O Error Handling "
+ "Enabled\n");
else
printk(KERN_WARNING "EEH: No capable adapters found\n");
}
@@ -925,12 +929,12 @@ static void eeh_add_device_late(struct p
printk(KERN_DEBUG "EEH: adding device %s\n", pci_name(dev));
#endif
- pci_dev_get (dev);
+ pci_dev_get(dev);
dn = pci_device_to_OF_node(dev);
pdn = PCI_DN(dn);
pdn->pcidev = dev;
- pci_addr_cache_insert_device (dev);
+ pci_addr_cache_insert_device(dev);
}
/**
@@ -957,7 +961,7 @@ static void eeh_remove_device(struct pci
dn = pci_device_to_OF_node(dev);
PCI_DN(dn)->pcidev = NULL;
- pci_dev_put (dev);
+ pci_dev_put(dev);
}
void eeh_remove_bus_device(struct pci_dev *dev)
@@ -990,9 +994,9 @@ static int proc_eeh_show(struct seq_file
"eeh_false_positives=%ld\n"
"eeh_ignored_failures=%ld\n"
"eeh_slot_resets=%ld\n",
- no_device, no_dn, no_cfg_addr,
- ignored_check, total_mmio_ffs,
- false_positives, ignored_failures,
+ no_device, no_dn, no_cfg_addr,
+ ignored_check, total_mmio_ffs,
+ false_positives, ignored_failures,
slot_resets);
}
^ permalink raw reply
* [PATCH 0/2] Base pSeries PCIe support
From: Jake Moilanen @ 2006-03-31 22:02 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Paul Mackerras
Here are the two base patches for PCIe on pSeries for 2.6.17.
This is enough to probe, find, configure, and run basic I/O to PCIe
enabled devices.
The patches do not include PCIe hotplug, nor multiple MSI vectors per
adapter.
These patches have had limited testing, as firmware still is working on
a few MSI bugs of their own.
^ permalink raw reply
* [PATCH 1/2] Base pSeries PCIe support
From: Jake Moilanen @ 2006-03-31 22:05 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
In-Reply-To: <20060331160203.f2bf8b53.moilanen@austin.ibm.com>
Added recognition of device_type: "pciex" and made PCIe portdrv
buildable on PPC64.
Signed-off-by: Jake Moilanen <moilanen@austin.ibm.com>
---
Index: 2.6.16/arch/powerpc/Kconfig
===================================================================
--- 2.6.16.orig/arch/powerpc/Kconfig 2006-03-31 15:11:20.000000000 -0600
+++ 2.6.16/arch/powerpc/Kconfig 2006-03-31 15:15:35.000000000 -0600
@@ -808,6 +808,8 @@
endchoice
+source "drivers/pci/pcie/Kconfig"
+
source "drivers/pci/Kconfig"
source "drivers/pcmcia/Kconfig"
Index: 2.6.16/arch/powerpc/kernel/pci_64.c
===================================================================
--- 2.6.16.orig/arch/powerpc/kernel/pci_64.c 2006-03-31 15:11:20.000000000 -0600
+++ 2.6.16/arch/powerpc/kernel/pci_64.c 2006-03-31 15:15:35.000000000 -0600
@@ -395,7 +395,7 @@
dev->current_state = 4; /* unknown power state */
- if (!strcmp(type, "pci")) {
+ if (!strcmp(type, "pci") || !strcmp(type, "pciex")) {
/* a PCI-PCI bridge */
dev->hdr_type = PCI_HEADER_TYPE_BRIDGE;
dev->rom_base_reg = PCI_ROM_ADDRESS1;
Index: 2.6.16/arch/powerpc/kernel/rtas_pci.c
===================================================================
--- 2.6.16.orig/arch/powerpc/kernel/rtas_pci.c 2006-03-31 15:11:20.000000000 -0600
+++ 2.6.16/arch/powerpc/kernel/rtas_pci.c 2006-03-31 15:15:35.000000000 -0600
@@ -315,7 +315,8 @@
for (node = of_get_next_child(root, NULL);
node != NULL;
node = of_get_next_child(root, node)) {
- if (node->type == NULL || strcmp(node->type, "pci") != 0)
+
+ if (node->type == NULL || ((strcmp(node->type, "pci") != 0) && (strcmp(node->type, "pciex") != 0)))
continue;
phb = pcibios_alloc_controller(node);
^ permalink raw reply
* [PATCH 2/2] Base pSeries PCIe support
From: Jake Moilanen @ 2006-03-31 22:13 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
In-Reply-To: <20060331160203.f2bf8b53.moilanen@austin.ibm.com>
This patch hooks our current interrupt subsystem and sets up a single
vector MSI as if it was a LSI. Multiple MSI vectors is coming in the
future.
The NR_IRQS got bumped up to 1024, as vectors can go much higher.
Unfortunately, this number was arbitrarily picked as there is no claim
at what the max number really is by either the firmware team, or the
PAPR+.
Signed-off-by: Jake Moilanen <moilanen@austin.ibm.com>
---
Index: 2.6.16/arch/powerpc/kernel/prom.c
===================================================================
--- 2.6.16.orig/arch/powerpc/kernel/prom.c 2006-03-31 15:11:20.000000000 -0600
+++ 2.6.16/arch/powerpc/kernel/prom.c 2006-03-31 15:37:10.000000000 -0600
@@ -88,6 +88,8 @@
struct device_node *dflt_interrupt_controller;
int num_interrupt_controllers;
+void __init finish_msi_node(struct device_node *dn, unsigned long *mem_start, int measure_only);
+
/*
* Wrapper for allocating memory for various data that needs to be
* attached to device nodes as they are processed at boot or when
@@ -120,6 +122,22 @@
return NULL;
}
+int
+property_present(struct device_node *np, const char *name)
+{
+ struct property *pp;
+
+ read_lock(&devtree_lock);
+ for (pp = np->properties; pp != 0; pp = pp->next)
+ if (strcmp(pp->name, name) == 0) {
+ return 1;
+ }
+ read_unlock(&devtree_lock);
+
+ return 0;
+}
+
+
/*
* Find the interrupt parent of a node.
*/
@@ -341,6 +359,14 @@
return 0;
}
+#ifdef CONFIG_PPC_PSERIES
+ if(property_present(np, "ibm,req#msi")) {
+ printk(KERN_EMERG "Found MSI\n");
+ finish_msi_node(np, mem_start, measure_only);
+ return 0;
+ }
+#endif
+
ints = (unsigned int *) get_property(np, "interrupts", &intlen);
TRACE("ints=%p, intlen=%d\n", ints, intlen);
if (ints == NULL)
@@ -503,6 +529,80 @@
DBG(" <- finish_device_tree\n");
}
+void __init finish_msi_node(struct device_node *dn, unsigned long *mem_start, int measure_only)
+{
+ static int seq_num = 1;
+ int i;
+ int rc;
+ int query_token = rtas_token("ibm,query-interrupt-source-number");
+ int devfn;
+ int busno;
+ u32 *reg;
+ int reglen;
+ int ret[3];
+ unsigned int virq;
+ unsigned int addr;
+ unsigned long buid = -1;
+ unsigned long wait_time;
+
+ reg = (u32 *) get_property(dn, "reg", ®len);
+ if (reg == NULL || reglen < 20)
+ return;
+
+ devfn = (reg[0] >> 8) & 0xff;
+ busno = (reg[0] >> 16) & 0xff;
+
+ buid = get_phb_buid(dn->parent);
+ addr = (busno << 16) | (devfn << 8);
+
+ while (1) {
+ rc = rtas_call(rtas_token("ibm,change-msi"), 6, 3, ret, addr,
+ buid >> 32, buid & 0xffffffff,
+ 1, 1, seq_num);
+
+ if (!rc)
+ break;
+ else if (rc == RTAS_BUSY)
+ udelay(1);
+ else if (rtas_is_extended_busy(rc)) {
+ wait_time = rtas_extended_busy_delay_time(rc);
+ udelay(wait_time * 1000);
+ } else {
+ printk(KERN_WARNING "error[%d]: getting the number of"
+ "MSI interrupts for %s\n", rc, dn->name);
+ return;
+ }
+
+ seq_num = ret[1];
+ }
+
+ dn->n_intrs = ret[0];
+
+ dn->intrs = prom_alloc(dn->n_intrs * sizeof(*(dn->intrs)), mem_start);
+ if (!dn->intrs) {
+ printk(KERN_EMERG "finish_msi_node: can't allocate space\n");
+ return;
+ }
+
+ if (measure_only)
+ return;
+
+ for (i = 0; i < dn->n_intrs; i++) {
+ rc = rtas_call(query_token, 4, 3, ret, addr, buid >> 32, buid & 0xffffffff, i);
+
+ if (!rc) {
+ virq = virt_irq_create_mapping(ret[0]);
+
+ dn->intrs[i].line = irq_offset_up(virq);
+ dn->intrs[i].sense = ret[1];
+ } else {
+ printk(KERN_WARNING "error[%d]: query-interrupt-source-number for %s\n",
+ rc, dn->name);
+ }
+ }
+
+}
+
static inline char *find_flat_dt_string(u32 offset)
{
return ((char *)initial_boot_params) +
Index: 2.6.16/include/asm-powerpc/irq.h
===================================================================
--- 2.6.16.orig/include/asm-powerpc/irq.h 2006-03-31 15:11:12.000000000 -0600
+++ 2.6.16/include/asm-powerpc/irq.h 2006-03-31 15:15:46.000000000 -0600
@@ -47,7 +47,7 @@
/*
* Maximum number of interrupt sources that we can handle.
*/
-#define NR_IRQS 512
+#define NR_IRQS 1024
/* Interrupt numbers are virtual in case they are sparsely
* distributed by the hardware.
Index: 2.6.16/include/asm-powerpc/pci-bridge.h
===================================================================
--- 2.6.16.orig/include/asm-powerpc/pci-bridge.h 2006-03-31 15:11:36.000000000 -0600
+++ 2.6.16/include/asm-powerpc/pci-bridge.h 2006-03-31 15:34:50.000000000 -0600
@@ -141,6 +141,7 @@
void pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus);
extern int pcibios_remove_root_bus(struct pci_controller *phb);
+extern unsigned long __devinit get_phb_buid (struct device_node *phb);
static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
{
^ permalink raw reply
* Re: [PATCH 1/2] Base pSeries PCIe support
From: Jake Moilanen @ 2006-03-31 22:18 UTC (permalink / raw)
To: Dave Hansen; +Cc: linuxppc-dev, paulus
In-Reply-To: <1143843311.9731.111.camel@localhost.localdomain>
On Fri, 31 Mar 2006 14:15:11 -0800
Dave Hansen <haveblue@us.ibm.com> wrote:
> On Fri, 2006-03-31 at 16:05 -0600, Jake Moilanen wrote:
> > --- 2.6.16.orig/arch/powerpc/kernel/rtas_pci.c 2006-03-31 15:11:20.000000000 -0600
> > +++ 2.6.16/arch/powerpc/kernel/rtas_pci.c 2006-03-31 15:15:35.000000000 -0600
> > @@ -315,7 +315,8 @@
> > for (node = of_get_next_child(root, NULL);
> > node != NULL;
> > node = of_get_next_child(root, node)) {
> > - if (node->type == NULL || strcmp(node->type, "pci") != 0)
> > +
> > + if (node->type == NULL || ((strcmp(node->type, "pci") != 0) && (strcmp(node->type, "pciex") != 0)))
> > continue;
>
> That one looks to have gone a wee bit over 80 columns.
I need to stop developing on my widescreen. :)
Signed-off-by: Jake Moilanen <moilanen@austin.ibm.com>
---
Index: 2.6.16/arch/powerpc/Kconfig
===================================================================
--- 2.6.16.orig/arch/powerpc/Kconfig 2006-03-31 16:13:26.000000000 -0600
+++ 2.6.16/arch/powerpc/Kconfig 2006-03-31 16:13:36.000000000 -0600
@@ -808,6 +808,8 @@
endchoice
+source "drivers/pci/pcie/Kconfig"
+
source "drivers/pci/Kconfig"
source "drivers/pcmcia/Kconfig"
Index: 2.6.16/arch/powerpc/kernel/pci_64.c
===================================================================
--- 2.6.16.orig/arch/powerpc/kernel/pci_64.c 2006-03-31 16:13:26.000000000 -0600
+++ 2.6.16/arch/powerpc/kernel/pci_64.c 2006-03-31 16:13:36.000000000 -0600
@@ -395,7 +395,7 @@
dev->current_state = 4; /* unknown power state */
- if (!strcmp(type, "pci")) {
+ if (!strcmp(type, "pci") || !strcmp(type, "pciex")) {
/* a PCI-PCI bridge */
dev->hdr_type = PCI_HEADER_TYPE_BRIDGE;
dev->rom_base_reg = PCI_ROM_ADDRESS1;
Index: 2.6.16/arch/powerpc/kernel/rtas_pci.c
===================================================================
--- 2.6.16.orig/arch/powerpc/kernel/rtas_pci.c 2006-03-31 16:13:26.000000000 -0600
+++ 2.6.16/arch/powerpc/kernel/rtas_pci.c 2006-03-31 16:14:10.000000000 -0600
@@ -315,7 +315,9 @@
for (node = of_get_next_child(root, NULL);
node != NULL;
node = of_get_next_child(root, node)) {
- if (node->type == NULL || strcmp(node->type, "pci") != 0)
+
+ if (node->type == NULL || ((strcmp(node->type, "pci") != 0) &&
+ (strcmp(node->type, "pciex") != 0)))
continue;
phb = pcibios_alloc_controller(node);
^ permalink raw reply
* Re: [PATCH 0/2] Base pSeries PCIe support
From: Arnd Bergmann @ 2006-03-31 22:28 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Paul Mackerras
In-Reply-To: <20060331160203.f2bf8b53.moilanen@austin.ibm.com>
Am Saturday 01 April 2006 00:02 schrieb Jake Moilanen:
> Here are the two base patches for PCIe on pSeries for 2.6.17.
>
> This is enough to probe, find, configure, and run basic I/O to PCIe
> enabled devices.
Does this use the draft PCIe bindings from Sun, or something else?
Is it compatible with the way that Apple represents PCIe devices
as plain PCI?
I'm just curious.
Arnd <><
^ permalink raw reply
* Re: [PATCH 0/2] Base pSeries PCIe support
From: Doug Maxey @ 2006-03-31 22:39 UTC (permalink / raw)
To: Jake Moilanen; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20060331160203.f2bf8b53.moilanen@austin.ibm.com>
On Fri, 31 Mar 2006 16:02:03 CST, Jake Moilanen wrote:
>Here are the two base patches for PCIe on pSeries for 2.6.17.
>
>This is enough to probe, find, configure, and run basic I/O to PCIe
>enabled devices.
>
Where are the bindings for pcie? In the papr?
Have you heard of any effort to publish?
++doug
^ permalink raw reply
* Re: [PATCH 0/2] Base pSeries PCIe support
From: Jake Moilanen @ 2006-03-31 22:35 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: linuxppc-dev, paulus
In-Reply-To: <200604010028.43685.arnd@arndb.de>
On Sat, 1 Apr 2006 00:28:43 +0200
Arnd Bergmann <arnd@arndb.de> wrote:
> Am Saturday 01 April 2006 00:02 schrieb Jake Moilanen:
> > Here are the two base patches for PCIe on pSeries for 2.6.17.
> >
> > This is enough to probe, find, configure, and run basic I/O to PCIe
> > enabled devices.
>
> Does this use the draft PCIe bindings from Sun, or something else?
> Is it compatible with the way that Apple represents PCIe devices
> as plain PCI?
>
> I'm just curious.
You can find some info on it:
http://playground.sun.com/1275/bindings/pci/pci-express.txt
Jake
^ permalink raw reply
* Re: [PATCH 2/2] Base pSeries PCIe support
From: Olof Johansson @ 2006-03-31 22:48 UTC (permalink / raw)
To: Jake Moilanen; +Cc: linuxppc-dev, paulus
In-Reply-To: <20060331161330.3c723103.moilanen@austin.ibm.com>
On Fri, Mar 31, 2006 at 04:13:30PM -0600, Jake Moilanen wrote:
> This patch hooks our current interrupt subsystem and sets up a single
> vector MSI as if it was a LSI. Multiple MSI vectors is coming in the
> future.
>
> The NR_IRQS got bumped up to 1024, as vectors can go much higher.
> Unfortunately, this number was arbitrarily picked as there is no claim
> at what the max number really is by either the firmware team, or the
> PAPR+.
What does this do to the kernel size?
> Signed-off-by: Jake Moilanen <moilanen@austin.ibm.com>
>
> ---
>
> Index: 2.6.16/arch/powerpc/kernel/prom.c
> ===================================================================
> --- 2.6.16.orig/arch/powerpc/kernel/prom.c 2006-03-31 15:11:20.000000000 -0600
> +++ 2.6.16/arch/powerpc/kernel/prom.c 2006-03-31 15:37:10.000000000 -0600
> @@ -88,6 +88,8 @@
> struct device_node *dflt_interrupt_controller;
> int num_interrupt_controllers;
>
> +void __init finish_msi_node(struct device_node *dn, unsigned long *mem_start, int measure_only);
The other one is called "finish_node_interrupts", "finish_node_msi"
would make sense here.
> +
> /*
> * Wrapper for allocating memory for various data that needs to be
> * attached to device nodes as they are processed at boot or when
> @@ -120,6 +122,22 @@
> return NULL;
> }
>
> +int
> +property_present(struct device_node *np, const char *name)
> +{
> + struct property *pp;
> +
> + read_lock(&devtree_lock);
> + for (pp = np->properties; pp != 0; pp = pp->next)
> + if (strcmp(pp->name, name) == 0) {
> + return 1;
> + }
> + read_unlock(&devtree_lock);
> +
> + return 0;
> +}
Please use of_find_property() instead of reimplementing it, i.e. do what
get_property() does now, just don't return the value.
I assume you can't use get_property() because the properties you look
for lack values, right?
> +
> /*
> * Find the interrupt parent of a node.
> */
> @@ -341,6 +359,14 @@
> return 0;
> }
>
> +#ifdef CONFIG_PPC_PSERIES
> + if(property_present(np, "ibm,req#msi")) {
> + printk(KERN_EMERG "Found MSI\n");
KERN_DEBUG, if anything, right?
Also, get rid of the ifdef.
> + finish_msi_node(np, mem_start, measure_only);
> + return 0;
> + }
> +#endif
> +
> ints = (unsigned int *) get_property(np, "interrupts", &intlen);
> TRACE("ints=%p, intlen=%d\n", ints, intlen);
> if (ints == NULL)
> @@ -503,6 +529,80 @@
> DBG(" <- finish_device_tree\n");
> }
>
> +void __init finish_msi_node(struct device_node *dn, unsigned long *mem_start, int measure_only)
I know you said no hotplug support yet, but in preparation, it might
make sense to mark it as __devinit instead.
> +{
> + static int seq_num = 1;
> + int i;
> + int rc;
> + int query_token = rtas_token("ibm,query-interrupt-source-number");
> + int devfn;
> + int busno;
> + u32 *reg;
> + int reglen;
> + int ret[3];
> + unsigned int virq;
> + unsigned int addr;
> + unsigned long buid = -1;
> + unsigned long wait_time;
> +
> + reg = (u32 *) get_property(dn, "reg", ®len);
> + if (reg == NULL || reglen < 20)
> + return;
> +
> + devfn = (reg[0] >> 8) & 0xff;
> + busno = (reg[0] >> 16) & 0xff;
> +
> + buid = get_phb_buid(dn->parent);
> + addr = (busno << 16) | (devfn << 8);
> +
> + while (1) {
> + rc = rtas_call(rtas_token("ibm,change-msi"), 6, 3, ret, addr,
> + buid >> 32, buid & 0xffffffff,
> + 1, 1, seq_num);
> +
> + if (!rc)
> + break;
> + else if (rc == RTAS_BUSY)
> + udelay(1);
> + else if (rtas_is_extended_busy(rc)) {
> + wait_time = rtas_extended_busy_delay_time(rc);
> + udelay(wait_time * 1000);
> + } else {
> + printk(KERN_WARNING "error[%d]: getting the number of"
> + "MSI interrupts for %s\n", rc, dn->name);
> + return;
> + }
This is reimplemented with a few variations in a few places now. They
should be consolidated into a single function that will handle the
delay itself.
> +
> + seq_num = ret[1];
> + }
> +
> + dn->n_intrs = ret[0];
> +
> + dn->intrs = prom_alloc(dn->n_intrs * sizeof(*(dn->intrs)), mem_start);
> + if (!dn->intrs) {
> + printk(KERN_EMERG "finish_msi_node: can't allocate space\n");
> + return;
> + }
> +
> + if (measure_only)
> + return;
You probably want to return from measure_only _before_ you allocate and
populate intrs...
> +
> + for (i = 0; i < dn->n_intrs; i++) {
> + rc = rtas_call(query_token, 4, 3, ret, addr, buid >> 32, buid & 0xffffffff, i);
> +
> + if (!rc) {
> + virq = virt_irq_create_mapping(ret[0]);
> +
> + dn->intrs[i].line = irq_offset_up(virq);
> + dn->intrs[i].sense = ret[1];
> + } else {
> + printk(KERN_WARNING "error[%d]: query-interrupt-source-number for %s\n",
> + rc, dn->name);
> + }
> + }
> +
> +}
> +
> static inline char *find_flat_dt_string(u32 offset)
> {
> return ((char *)initial_boot_params) +
> Index: 2.6.16/include/asm-powerpc/irq.h
> ===================================================================
> --- 2.6.16.orig/include/asm-powerpc/irq.h 2006-03-31 15:11:12.000000000 -0600
> +++ 2.6.16/include/asm-powerpc/irq.h 2006-03-31 15:15:46.000000000 -0600
> @@ -47,7 +47,7 @@
> /*
> * Maximum number of interrupt sources that we can handle.
> */
> -#define NR_IRQS 512
> +#define NR_IRQS 1024
>
> /* Interrupt numbers are virtual in case they are sparsely
> * distributed by the hardware.
> Index: 2.6.16/include/asm-powerpc/pci-bridge.h
> ===================================================================
> --- 2.6.16.orig/include/asm-powerpc/pci-bridge.h 2006-03-31 15:11:36.000000000 -0600
> +++ 2.6.16/include/asm-powerpc/pci-bridge.h 2006-03-31 15:34:50.000000000 -0600
> @@ -141,6 +141,7 @@
> void pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus);
>
> extern int pcibios_remove_root_bus(struct pci_controller *phb);
> +extern unsigned long __devinit get_phb_buid (struct device_node *phb);
I think the get_phb_buid() call from prom.c might break 32-bit, since
rtas_pci.c isn't always built there. An empty declaration here for
#ifndef CONFIG_<x> would take care of it.
>
> static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
> {
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH 2/2] Base pSeries PCIe support
From: Olof Johansson @ 2006-03-31 23:08 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev, paulus
In-Reply-To: <20060331224858.GC952@pb15.lixom.net>
On Fri, Mar 31, 2006 at 04:48:58PM -0600, Olof Johansson wrote:
> > + dn->intrs = prom_alloc(dn->n_intrs * sizeof(*(dn->intrs)), mem_start);
> > + if (!dn->intrs) {
> > + printk(KERN_EMERG "finish_msi_node: can't allocate space\n");
> > + return;
> > + }
> > +
> > + if (measure_only)
> > + return;
>
> You probably want to return from measure_only _before_ you allocate and
> populate intrs...
Nevermind, this is correct as-is.
-Olof
^ permalink raw reply
* Re: Oops: mounting floppy disk on PPC64 (power3)
From: Nathan Lynch @ 2006-03-31 22:50 UTC (permalink / raw)
To: Markus Rothe; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <200603312138.16032.markus@unixforces.net>
Hello.
Markus Rothe wrote:
>
> this is kernel 2.6.16.1 compiled with gcc 4.1.0 (gentoo patches). I never
> tried to mount a floppy on this system before, so I don't know if it Oops'ed
> in previous kernel versions, too.
>
> power3 ~ # uname -a
> Linux power3 2.6.16.1 #1 Fri Mar 31 21:08:43 UTC 2006 ppc64 POWER3 (630+) CHRP
> IBM,7044-170 GNU/Linux
> power3 ~ # modprobe floppy
> power3 ~ # mount /mnt/floppy/
> Oops: Kernel access of bad area, sig: 11 [#1]
> NUMA PSERIES
> Modules linked in: floppy
> NIP: C0000000000201E8 LR: D0000000000C43A4 CTR: C0000000000201D8
> REGS: c0000000003df470 TRAP: 0300 Not tainted (2.6.16.1)
> MSR: A000000000001032 <ME,IR,DR> CR: 48000082 XER: 00000000
> DAR: 0000000000000178, DSISR: 0000000040000000
> TASK = c0000000003fc9b0[0] 'swapper' THREAD: c0000000003dc000
> GPR00: C00000000042FC08 C0000000003DF6F0 C0000000004D3310 0000000000000000
> GPR04: C00000000161D000 0000000000000400 0000000000000002 0000000000000750
> GPR08: 0000000000000064 D0000000000D4AE0 D0000000000D5F20 C0000000000201D8
> GPR12: D0000000000CB280 C0000000003FCF80 0000000000000000 0000000000000000
> GPR16: 0000000000000000 0000000000000000 4000000001400000 C0000000003595E0
> GPR20: C0000000003D1F28 00000000017D1A80 C0000000003D1A80 0000000000000060
> GPR24: 00000000000003F0 A000000000009032 0000000000000044 00000000000000D9
> GPR28: 0000000000000400 0000000000000002 D0000000000DB880 C00000000161D000
> NIP [C0000000000201E8] .dma_map_single+0x10/0x70
> LR [D0000000000C43A4] .setup_rw_floppy+0x2c0/0xaa8 [floppy]
> Call Trace:
> [C0000000003DF6F0] [D0000000000C5790] .start_motor+0x108/0x158 [floppy]
> (unreli)
> [C0000000003DF760] [D0000000000C43A4] .setup_rw_floppy+0x2c0/0xaa8 [floppy]
> [C0000000003DF810] [C000000000044714] .run_timer_softirq+0x174/0x20c
> [C0000000003DF8B0] [C00000000003FC68] .__do_softirq+0x80/0x128
> [C0000000003DF940] [C00000000003FD5C] .do_softirq+0x4c/0x68
> [C0000000003DF9C0] [C00000000001C9E8] .timer_interrupt+0x360/0x388
> [C0000000003DFA90] [C0000000000034B8] decrementer_common+0xb8/0x100
> --- Exception: 901 at .ppc64_runlatch_off+0x0/0x50
> LR = .default_idle+0x48/0x70
> [C0000000003DFD80] [C000000000016764] .default_idle+0x68/0x70 (unreliable)
> [C0000000003DFE00] [C0000000000166E8] .cpu_idle+0x40/0x54
> [C0000000003DFE70] [C0000000000092B0] .rest_init+0x3c/0x54
> [C0000000003DFEF0] [C0000000003B16D4] .start_kernel+0x1f0/0x208
> [C0000000003DFF90] [C000000000008514] .start_here_common+0x88/0x174
> Instruction dump:
> 4e800421 e8410028 48000008 0fe00000 38210070 e8010010 7c0803a6 4e800020
> 7c0802a6 f8010010 f821ff91 e80298d0 <e9230178> 7fa90000 409e000c e92298d8
>
> Am I doing something wrong?
Nope.
I believe this was fixed in Linus' tree as of a couple days ago:
diff-tree b239cbe957ae730caa8af2f169a4d35b8c1bb299 (from
69ed3324983bb937d78a857Author: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Tue Mar 28 14:40:58 2006 +1100
[PATCH] powerpc: make ISA floppies work again
We used to assume that a DMA mapping request with a NULL dev was
for
ISA DMA. This assumption was broken at some point. Now we
explicitly
pass the detected ISA PCI device in the floppy setup.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Maybe you could verify with latest -git, or 2.6.17-rc1 when it's
released?
^ permalink raw reply
* Re: [PATCH 1/2] Base pSeries PCIe support
From: Dave Hansen @ 2006-03-31 22:15 UTC (permalink / raw)
To: Jake Moilanen; +Cc: linuxppc-dev, paulus
In-Reply-To: <20060331160545.db3fa210.moilanen@austin.ibm.com>
On Fri, 2006-03-31 at 16:05 -0600, Jake Moilanen wrote:
> --- 2.6.16.orig/arch/powerpc/kernel/rtas_pci.c 2006-03-31 15:11:20.000000000 -0600
> +++ 2.6.16/arch/powerpc/kernel/rtas_pci.c 2006-03-31 15:15:35.000000000 -0600
> @@ -315,7 +315,8 @@
> for (node = of_get_next_child(root, NULL);
> node != NULL;
> node = of_get_next_child(root, node)) {
> - if (node->type == NULL || strcmp(node->type, "pci") != 0)
> +
> + if (node->type == NULL || ((strcmp(node->type, "pci") != 0) && (strcmp(node->type, "pciex") != 0)))
> continue;
That one looks to have gone a wee bit over 80 columns.
-- Dave
^ permalink raw reply
* [PATCH] powerpc: trivial spelling fixes in fault.c
From: Anton Blanchard @ 2006-04-01 0:33 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
This comment exceeded my bad spelling threshold :)
Signed-off-by: Anton Blanchard <anton@samba.org>
---
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index ec4adcb..ba0bc04 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -177,15 +177,15 @@ int __kprobes do_page_fault(struct pt_re
/* When running in the kernel we expect faults to occur only to
* addresses in user space. All other faults represent errors in the
- * kernel and should generate an OOPS. Unfortunatly, in the case of an
- * erroneous fault occuring in a code path which already holds mmap_sem
+ * kernel and should generate an OOPS. Unfortunately, in the case of an
+ * erroneous fault occurring in a code path which already holds mmap_sem
* we will deadlock attempting to validate the fault against the
* address space. Luckily the kernel only validly references user
* space from well defined areas of code, which are listed in the
* exceptions table.
*
* As the vast majority of faults will be valid we will only perform
- * the source reference check when there is a possibilty of a deadlock.
+ * the source reference check when there is a possibility of a deadlock.
* Attempt to lock the address space, if we cannot we then validate the
* source. If this is invalid we can skip the address space check,
* thus avoiding the deadlock.
^ permalink raw reply related
* Re: G5 fan problems return moving to 2.6.15 with dual processor 2.7GHz machine
From: Brian D. Carlstrom @ 2006-04-01 1:16 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc64-dev
In-Reply-To: <1139526280.5003.40.camel@localhost.localdomain>
I just wanted to follow up to my thread from a while ago to say that
although I never resolved my problem with fan control on 2.6.15, moving
to 2.6.16 has fixed the problem...
-bri
^ permalink raw reply
* Re: [PATCH] powerpc/pseries: whitespace cleanups (try 2)
From: Nathan Fontenot @ 2006-03-31 21:21 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
In-Reply-To: <200603311509.25712.nfont@austin.ibm.com>
This patch is nothing but whitespace cleanup for eeh.c. This removes
spaces between function calls and their parameters, edits lines that are
longer than 80 characters and puts function return variables and function
names on one line.
Signed-off-by: Nathan Fontenot <nfont@austin.ibm.com>
----
Let's try this again with a patch that will apply a little cleaner
Index: kernel/arch/powerpc/platforms/pseries/eeh.c
===================================================================
--- kernel.orig/arch/powerpc/platforms/pseries/eeh.c 2006-03-31 09:02:17.%N
-0600
+++ kernel/arch/powerpc/platforms/pseries/eeh.c 2006-03-31 14:34:43.%N -0600
@@ -111,7 +111,7 @@ static unsigned long slot_resets;
/* --------------------------------------------------------------- */
/* Below lies the EEH event infrastructure */
-void eeh_slot_error_detail (struct pci_dn *pdn, int severity)
+void eeh_slot_error_detail(struct pci_dn *pdn, int severity)
{
int config_addr;
unsigned long flags;
@@ -126,13 +126,10 @@ void eeh_slot_error_detail (struct pci_d
if (pdn->eeh_pe_config_addr)
config_addr = pdn->eeh_pe_config_addr;
- rc = rtas_call(ibm_slot_error_detail,
- 8, 1, NULL, config_addr,
- BUID_HI(pdn->phb->buid),
- BUID_LO(pdn->phb->buid), NULL, 0,
- virt_to_phys(slot_errbuf),
- eeh_error_buf_size,
- severity);
+ rc = rtas_call(ibm_slot_error_detail, 8, 1, NULL, config_addr,
+ BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid),
+ NULL, 0, virt_to_phys(slot_errbuf),
+ eeh_error_buf_size, severity);
if (rc == 0)
log_error(slot_errbuf, ERR_TYPE_RTAS_LOG, 0);
@@ -184,7 +181,7 @@ static inline unsigned long eeh_token_to
return pa | (token & (PAGE_SIZE-1));
}
-/**
+/**
* Return the "partitionable endpoint" (pe) under which this device lies
*/
struct device_node * find_device_pe(struct device_node *dn)
@@ -203,8 +200,7 @@ struct device_node * find_device_pe(stru
* and the slot is frozen, then the driver can deadlock in
* an interrupt context, which is bad.
*/
-
-static void __eeh_mark_slot (struct device_node *dn, int mode_flag)
+static void __eeh_mark_slot(struct device_node *dn, int mode_flag)
{
while (dn) {
if (PCI_DN(dn)) {
@@ -217,13 +213,13 @@ static void __eeh_mark_slot (struct devi
dev->error_state = pci_channel_io_frozen;
if (dn->child)
- __eeh_mark_slot (dn->child, mode_flag);
+ __eeh_mark_slot(dn->child, mode_flag);
}
dn = dn->sibling;
}
}
-void eeh_mark_slot (struct device_node *dn, int mode_flag)
+void eeh_mark_slot(struct device_node *dn, int mode_flag)
{
dn = find_device_pe (dn);
@@ -232,36 +228,36 @@ void eeh_mark_slot (struct device_node *
dn = dn->parent;
PCI_DN(dn)->eeh_mode |= mode_flag;
- __eeh_mark_slot (dn->child, mode_flag);
+ __eeh_mark_slot(dn->child, mode_flag);
}
-static void __eeh_clear_slot (struct device_node *dn, int mode_flag)
+static void __eeh_clear_slot(struct device_node *dn, int mode_flag)
{
while (dn) {
if (PCI_DN(dn)) {
PCI_DN(dn)->eeh_mode &= ~mode_flag;
PCI_DN(dn)->eeh_check_count = 0;
if (dn->child)
- __eeh_clear_slot (dn->child, mode_flag);
+ __eeh_clear_slot(dn->child, mode_flag);
}
dn = dn->sibling;
}
}
-void eeh_clear_slot (struct device_node *dn, int mode_flag)
+void eeh_clear_slot(struct device_node *dn, int mode_flag)
{
unsigned long flags;
spin_lock_irqsave(&confirm_error_lock, flags);
-
+
dn = find_device_pe (dn);
-
+
/* Back up one, since config addrs might be shared */
if (PCI_DN(dn) && PCI_DN(dn)->eeh_pe_config_addr)
dn = dn->parent;
PCI_DN(dn)->eeh_mode &= ~mode_flag;
PCI_DN(dn)->eeh_check_count = 0;
- __eeh_clear_slot (dn->child, mode_flag);
+ __eeh_clear_slot(dn->child, mode_flag);
spin_unlock_irqrestore(&confirm_error_lock, flags);
}
@@ -305,8 +301,8 @@ int eeh_dn_check_failure(struct device_n
pdn->eeh_mode & EEH_MODE_NOCHECK) {
ignored_check++;
#ifdef DEBUG
- printk ("EEH:ignored check (%x) for %s %s\n",
- pdn->eeh_mode, pci_name (dev), dn->full_name);
+ printk("EEH:ignored check (%x) for %s %s\n",
+ pdn->eeh_mode, pci_name(dev), dn->full_name);
#endif
return 0;
}
@@ -327,16 +323,17 @@ int eeh_dn_check_failure(struct device_n
if (pdn->eeh_mode & EEH_MODE_ISOLATED) {
pdn->eeh_check_count ++;
if (pdn->eeh_check_count >= EEH_MAX_FAILS) {
- printk (KERN_ERR "EEH: Device driver ignored %d bad
reads, panicing\n",
- pdn->eeh_check_count);
+ printk(KERN_ERR "EEH: Device driver ignored %d bad "
+ "reads, panicing\n", pdn->eeh_check_count);
dump_stack();
-
+
/* re-read the slot reset state */
if (read_slot_reset_state(pdn, rets) != 0)
rets[0] = -1; /* reset state unknown */
- /* If we are here, then we hit an infinite loop. Stop.
*/
- panic("EEH: MMIO halt (%d) on device:%s\n", rets[0],
pci_name(dev));
+ /* If we're here, then we hit an infinite loop. Stop.
*/+ panic("EEH: MMIO halt (%d) on device:%s\n",
+ rets[0], pci_name(dev));
}
goto dn_unlock;
}
@@ -352,8 +349,8 @@ int eeh_dn_check_failure(struct device_n
/* If the call to firmware failed, punt */
if (ret != 0) {
- printk(KERN_WARNING "EEH: read_slot_reset_state() failed;
rc=%d dn=%s\n",
- ret, dn->full_name);
+ printk(KERN_WARNING "EEH: read_slot_reset_state() failed; "
+ "rc=%d dn=%s\n", ret, dn->full_name);
false_positives++;
rc = 0;
goto dn_unlock;
@@ -361,8 +358,8 @@ int eeh_dn_check_failure(struct device_n
/* If EEH is not supported on this device, punt. */
if (rets[1] != 1) {
- printk(KERN_WARNING "EEH: event on unsupported device, rc=%d
dn=%s\n",
- ret, dn->full_name);
+ printk(KERN_WARNING "EEH: event on unsupported device, rc=%d "
+ "dn=%s\n", ret, dn->full_name);
false_positives++;
rc = 0;
goto dn_unlock;
@@ -384,11 +381,11 @@ int eeh_dn_check_failure(struct device_n
}
slot_resets++;
-
+
/* Avoid repeated reports of this failure, including problems
* with other functions on this device, and functions under
* bridges. */
- eeh_mark_slot (dn, EEH_MODE_ISOLATED);
+ eeh_mark_slot(dn, EEH_MODE_ISOLATED);
spin_unlock_irqrestore(&confirm_error_lock, flags);
state = pci_channel_io_normal;
@@ -396,12 +393,13 @@ int eeh_dn_check_failure(struct device_n
state = pci_channel_io_frozen;
if (rets[0] == 5)
state = pci_channel_io_perm_failure;
- eeh_send_failure_event (dn, dev, state, rets[2]);
+ eeh_send_failure_event(dn, dev, state, rets[2]);
/* Most EEH events are due to device driver bugs. Having
* a stack trace will help the device-driver authors figure
* out what happened. So print that out. */
- if (rets[0] != 5) dump_stack();
+ if (rets[0] != 5)
+ dump_stack();
return 1;
dn_unlock:
@@ -438,7 +436,7 @@ unsigned long eeh_check_failure(const vo
}
dn = pci_device_to_OF_node(dev);
- eeh_dn_check_failure (dn, dev);
+ eeh_dn_check_failure(dn, dev);
pci_dev_put(dev);
return val;
@@ -453,26 +451,29 @@ EXPORT_SYMBOL(eeh_check_failure);
* a number of milliseconds to wait until the PCI slot is
* ready to be used.
*/
-static int
-eeh_slot_availability(struct pci_dn *pdn)
+static int eeh_slot_availability(struct pci_dn *pdn)
{
int rc;
int rets[3];
rc = read_slot_reset_state(pdn, rets);
- if (rc) return rc;
+ if (rc)
+ return rc;
- if (rets[1] == 0) return -1; /* EEH is not supported */
- if (rets[0] == 0) return 0; /* Oll Korrect */
+ if (rets[1] == 0)
+ return -1; /* EEH is not supported */
+ if (rets[0] == 0)
+ return 0; /* Oll Korrect */
if (rets[0] == 5) {
- if (rets[2] == 0) return -1; /* permanently unavailable */
+ if (rets[2] == 0)
+ return -1; /* permanently unavailable */
return rets[2]; /* number of millisecs to wait */
}
if (rets[0] == 1)
return 250;
- printk (KERN_ERR "EEH: Slot unavailable: rc=%d, rets=%d %d %d\n",
+ printk(KERN_ERR "EEH: Slot unavailable: rc=%d, rets=%d %d %d\n",
rc, rets[0], rets[1], rets[2]);
return -1;
}
@@ -486,18 +487,16 @@ eeh_slot_availability(struct pci_dn *pdn
* safe to call in an interrupt context.
*
*/
-
-static void
-rtas_pci_slot_reset(struct pci_dn *pdn, int state)
+static void rtas_pci_slot_reset(struct pci_dn *pdn, int state)
{
int config_addr;
int rc;
- BUG_ON (pdn==NULL);
+ BUG_ON (pdn==NULL);
if (!pdn->phb) {
- printk (KERN_WARNING "EEH: in slot reset, device node %s has
no phb\n",
- pdn->node->full_name);
+ printk(KERN_WARNING "EEH: in slot reset, device node %s "
+ "has no phb\n", pdn->node->full_name);
return;
}
@@ -506,14 +505,13 @@ rtas_pci_slot_reset(struct pci_dn *pdn,
if (pdn->eeh_pe_config_addr)
config_addr = pdn->eeh_pe_config_addr;
- rc = rtas_call(ibm_set_slot_reset,4,1, NULL,
- config_addr,
- BUID_HI(pdn->phb->buid),
- BUID_LO(pdn->phb->buid),
+ rc = rtas_call(ibm_set_slot_reset,4,1, NULL, config_addr,
+ BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid),
state);
if (rc) {
- printk (KERN_WARNING "EEH: Unable to reset the failed slot,
(%d) #RST=%d dn=%s\n",
- rc, state, pdn->node->full_name);
+ printk(KERN_WARNING "EEH: Unable to reset the failed slot, "
+ "(%d) #RST=%d dn=%s\n", rc, state,
+ pdn->node->full_name);
return;
}
}
@@ -523,39 +521,38 @@ rtas_pci_slot_reset(struct pci_dn *pdn,
*
* Return 0 if success, else a non-zero value.
*/
-
-int
-rtas_set_slot_reset(struct pci_dn *pdn)
+int rtas_set_slot_reset(struct pci_dn *pdn)
{
int i, rc;
- rtas_pci_slot_reset (pdn, 1);
+ rtas_pci_slot_reset(pdn, 1);
/* The PCI bus requires that the reset be held high for at least
* a 100 milliseconds. We wait a bit longer 'just in case'. */
#define PCI_BUS_RST_HOLD_TIME_MSEC 250
- msleep (PCI_BUS_RST_HOLD_TIME_MSEC);
-
- /* We might get hit with another EEH freeze as soon as the
+ msleep(PCI_BUS_RST_HOLD_TIME_MSEC);
+
+ /* We might get hit with another EEH freeze as soon as the
* pci slot reset line is dropped. Make sure we don't miss
* these, and clear the flag now. */
- eeh_clear_slot (pdn->node, EEH_MODE_ISOLATED);
+ eeh_clear_slot(pdn->node, EEH_MODE_ISOLATED);
- rtas_pci_slot_reset (pdn, 0);
+ rtas_pci_slot_reset(pdn, 0);
/* After a PCI slot has been reset, the PCI Express spec requires
* a 1.5 second idle time for the bus to stabilize, before starting
* up traffic. */
#define PCI_BUS_SETTLE_TIME_MSEC 1800
- msleep (PCI_BUS_SETTLE_TIME_MSEC);
+ msleep(PCI_BUS_SETTLE_TIME_MSEC);
/* Now double check with the firmware to make sure the device is
* ready to be used; if not, wait for recovery. */
- for (i=0; i<10; i++) {
- rc = eeh_slot_availability (pdn);
+ for (i = 0; i < 10; i++) {
+ rc = eeh_slot_availability(pdn);
if (rc < 0)
- printk (KERN_ERR "EEH: failed (%d) to reset slot
%s\n", rc, pdn->node->full_name);
+ printk(KERN_ERR "EEH: failed (%d) to reset slot %s\n",
+ rc, pdn->node->full_name);
if (rc == 0)
return 0;
if (rc < 0)
@@ -564,9 +561,10 @@ rtas_set_slot_reset(struct pci_dn *pdn)
msleep (rc+100);
}
- rc = eeh_slot_availability (pdn);
+ rc = eeh_slot_availability(pdn);
if (rc)
- printk (KERN_ERR "EEH: timeout resetting slot %s\n",
pdn->node->full_name);
+ printk(KERN_ERR "EEH: timeout resetting slot %s\n",
+ pdn->node->full_name);
return rc;
}
@@ -577,7 +575,7 @@ rtas_set_slot_reset(struct pci_dn *pdn)
* Although firmware will set up BARs during boot, it doesn't
* set up device BAR's after a device reset, although it will,
* if requested, set up bridge configuration. Thus, we need to
- * configure the PCI devices ourselves.
+ * configure the PCI devices ourselves.
*/
/**
@@ -586,12 +584,14 @@ rtas_set_slot_reset(struct pci_dn *pdn)
* the expansion ROM base address, the latency timer, and etc.
* from the saved values in the device node.
*/
-static inline void __restore_bars (struct pci_dn *pdn)
+static inline void __restore_bars(struct pci_dn *pdn)
{
int i;
- if (NULL==pdn->phb) return;
- for (i=4; i<10; i++) {
+ if (NULL==pdn->phb)
+ return;
+
+ for (i = 4; i < 10; i++) {
rtas_write_config(pdn, i*4, 4, pdn->config_space[i]);
}
@@ -601,11 +601,11 @@ static inline void __restore_bars (struc
#define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF))
#define SAVED_BYTE(OFF) (((u8 *)(pdn->config_space))[BYTE_SWAP(OFF)])
- rtas_write_config (pdn, PCI_CACHE_LINE_SIZE, 1,
- SAVED_BYTE(PCI_CACHE_LINE_SIZE));
+ rtas_write_config(pdn, PCI_CACHE_LINE_SIZE, 1,
+ SAVED_BYTE(PCI_CACHE_LINE_SIZE));
- rtas_write_config (pdn, PCI_LATENCY_TIMER, 1,
- SAVED_BYTE(PCI_LATENCY_TIMER));
+ rtas_write_config(pdn, PCI_LATENCY_TIMER, 1,
+ SAVED_BYTE(PCI_LATENCY_TIMER));
/* max latency, min grant, interrupt pin and line */
rtas_write_config(pdn, 15*4, 4, pdn->config_space[15]);
@@ -620,15 +620,15 @@ static inline void __restore_bars (struc
void eeh_restore_bars(struct pci_dn *pdn)
{
struct device_node *dn;
- if (!pdn)
+ if (!pdn)
return;
-
+
if ((pdn->eeh_mode & EEH_MODE_SUPPORTED)
&& !IS_BRIDGE(pdn->class_code))- __restore_bars (pdn);
+ __restore_bars(pdn);
dn = pdn->node->child;
while (dn) {
- eeh_restore_bars (PCI_DN(dn));
+ eeh_restore_bars(PCI_DN(dn));
dn = dn->sibling;
}
}
@@ -645,9 +645,9 @@ static void eeh_save_bars(struct pci_dn
{
int i;
- if (!pdn )
+ if (!pdn)
return;
-
+
for (i = 0; i < 16; i++)
rtas_read_config(pdn, i * 4, 4, &pdn->config_space[i]);
}
@@ -663,13 +663,11 @@ rtas_configure_bridge(struct pci_dn *pdn
if (pdn->eeh_pe_config_addr)
config_addr = pdn->eeh_pe_config_addr;
- rc = rtas_call(ibm_configure_bridge,3,1, NULL,
- config_addr,
- BUID_HI(pdn->phb->buid),
- BUID_LO(pdn->phb->buid));
+ rc = rtas_call(ibm_configure_bridge,3,1, NULL, config_addr,
+ BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid));
if (rc) {
- printk (KERN_WARNING "EEH: Unable to configure device bridge
(%d) for %s\n",
- rc, pdn->node->full_name);
+ printk(KERN_WARNING "EEH: Unable to configure device bridge "
+ "(%d) for %s\n", rc, pdn->node->full_name);
}
}
@@ -750,31 +748,35 @@ static void *early_enable_eeh(struct dev
pdn->eeh_mode |= EEH_MODE_SUPPORTED;
pdn->eeh_config_addr = regs[0];
- /* If the newer, better, ibm,get-config-addr-info is
supported,
- * then use that instead. */
+ /* If the newer, better, ibm,get-config-addr-info
+ * is supported, then use that instead. */
pdn->eeh_pe_config_addr = 0;
if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE)
{
unsigned int rets[2];
- ret = rtas_call (ibm_get_config_addr_info, 4,
2, rets,
- pdn->eeh_config_addr,
- info->buid_hi, info->buid_lo,
- 0);
+ ret = rtas_call(ibm_get_config_addr_info, 4,
2,
+ rets, pdn->eeh_config_addr,
+ info->buid_hi, info->buid_lo,
+ 0);
if (ret == 0)
pdn->eeh_pe_config_addr = rets[0];
}
#ifdef DEBUG
- printk(KERN_DEBUG "EEH: %s: eeh enabled, config=%x
pe_config=%x\n",
- dn->full_name, pdn->eeh_config_addr,
pdn->eeh_pe_config_addr);
+ printk(KERN_DEBUG "EEH: %s: eeh enabled, config=%x "
+ "pe_config=%x\n", dn->full_name,
+ pdn->eeh_config_addr,
pdn->eeh_pe_config_addr);
#endif
} else {
/* This device doesn't support EEH, but it may have an
* EEH parent, in which case we mark it as supported.
*/ if (dn->parent && PCI_DN(dn->parent)
- && (PCI_DN(dn->parent)->eeh_mode &
EEH_MODE_SUPPORTED)) {
+ && (PCI_DN(dn->parent)->eeh_mode
+ & EEH_MODE_SUPPORTED)) {
+
/* Parent supports EEH. */
pdn->eeh_mode |= EEH_MODE_SUPPORTED;
- pdn->eeh_config_addr =
PCI_DN(dn->parent)->eeh_config_addr;
+ pdn->eeh_config_addr =
+ PCI_DN(dn->parent)->eeh_config_addr;
return NULL;
}
}
@@ -818,7 +820,7 @@ void __init eeh_init(void)
ibm_read_slot_reset_state = rtas_token("ibm,read-slot-reset-state");
ibm_slot_error_detail = rtas_token("ibm,slot-error-detail");
ibm_get_config_addr_info = rtas_token("ibm,get-config-addr-info");
- ibm_configure_bridge = rtas_token ("ibm,configure-bridge");
+ ibm_configure_bridge = rtas_token("ibm,configure-bridge");
if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE)
return;
@@ -828,8 +830,9 @@ void __init eeh_init(void)
eeh_error_buf_size = 1024;
}
if (eeh_error_buf_size > RTAS_ERROR_LOG_MAX) {
- printk(KERN_WARNING "EEH: rtas-error-log-max is bigger than
allocated "
- "buffer ! (%d vs %d)", eeh_error_buf_size,
RTAS_ERROR_LOG_MAX);
+ printk(KERN_WARNING "EEH: rtas-error-log-max is bigger than "
+ "allocated buffer ! (%d vs %d)", eeh_error_buf_size,
+ RTAS_ERROR_LOG_MAX);
eeh_error_buf_size = RTAS_ERROR_LOG_MAX;
}
@@ -848,7 +851,8 @@ void __init eeh_init(void)
}
if (eeh_subsystem_enabled)
- printk(KERN_INFO "EEH: PCI Enhanced I/O Error Handling
Enabled\n");
+ printk(KERN_INFO "EEH: PCI Enhanced I/O Error Handling "
+ "Enabled\n");
else
printk(KERN_WARNING "EEH: No capable adapters found\n");
}
@@ -925,12 +929,12 @@ static void eeh_add_device_late(struct p
printk(KERN_DEBUG "EEH: adding device %s\n", pci_name(dev));
#endif
- pci_dev_get (dev);
+ pci_dev_get(dev);
dn = pci_device_to_OF_node(dev);
pdn = PCI_DN(dn);
pdn->pcidev = dev;
- pci_addr_cache_insert_device (dev);
+ pci_addr_cache_insert_device(dev);
}
/**
@@ -957,7 +961,7 @@ static void eeh_remove_device(struct pci
dn = pci_device_to_OF_node(dev);
PCI_DN(dn)->pcidev = NULL;
- pci_dev_put (dev);
+ pci_dev_put(dev);
}
void eeh_remove_bus_device(struct pci_dev *dev)
@@ -990,9 +994,9 @@ static int proc_eeh_show(struct seq_file
"eeh_false_positives=%ld\n"
"eeh_ignored_failures=%ld\n"
"eeh_slot_resets=%ld\n",
- no_device, no_dn, no_cfg_addr,
- ignored_check, total_mmio_ffs,
- false_positives, ignored_failures,
+ no_device, no_dn, no_cfg_addr,
+ ignored_check, total_mmio_ffs,
+ false_positives, ignored_failures,
slot_resets);
}
^ permalink raw reply
* Re: Oops: mounting floppy disk on PPC64 (power3)
From: Markus Rothe @ 2006-04-01 7:43 UTC (permalink / raw)
To: linux-kernel; +Cc: linuxppc-dev
In-Reply-To: <20060331225034.GA25663@localdomain>
[-- Attachment #1: Type: text/plain, Size: 181 bytes --]
On Friday 31 March 2006 22:50, Nathan Lynch wrote:
> Maybe you could verify with latest -git, or 2.6.17-rc1 when it's
> released?
Yes, it is fixed.
Thanks for help!
Markus Rothe
[-- Attachment #2: Type: application/pgp-signature, Size: 191 bytes --]
^ permalink raw reply
* Re: [PATCH 2/2] Base pSeries PCIe support
From: Paul Mackerras @ 2006-04-01 8:36 UTC (permalink / raw)
To: Jake Moilanen; +Cc: linuxppc-dev
In-Reply-To: <20060331161330.3c723103.moilanen@austin.ibm.com>
Jake Moilanen writes:
> The NR_IRQS got bumped up to 1024, as vectors can go much higher.
> Unfortunately, this number was arbitrarily picked as there is no claim
> at what the max number really is by either the firmware team, or the
> PAPR+.
What matters is the number of different vectors, not the actual value
of the vectors, because we remap interrupt numbers that the firmware
gives us to logical Linux irq numbers between 0 and NR_IRQS-1. We had
to do that when the POWER5 systems came out, because the interrupt
numbers there occupy 24 bits.
Paul.
^ permalink raw reply
* Re: [PATCH 2/2] Base pSeries PCIe support
From: Paul Mackerras @ 2006-04-01 8:38 UTC (permalink / raw)
To: Jake Moilanen; +Cc: linuxppc-dev
In-Reply-To: <20060331161330.3c723103.moilanen@austin.ibm.com>
Jake Moilanen writes:
> +property_present(struct device_node *np, const char *name)
> +{
> + struct property *pp;
> +
> + read_lock(&devtree_lock);
> + for (pp = np->properties; pp != 0; pp = pp->next)
> + if (strcmp(pp->name, name) == 0) {
> + return 1;
Ummm, did you mean to return with the devtree_lock held? I suspect
not. In any case, why not just use get_property or of_find_property?
Paul.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox