* Re: [PATCH RT] ehea: make receive irq handler non-threaded (IRQF_NODELAY), Re: [PATCH RT] ehea: make receive irq handler non-threaded (IRQF_NODELAY)
From: Milton Miller @ 2010-05-21 9:18 UTC (permalink / raw)
To: Thomas Gleixner, Jan-Bernd Themann
Cc: Darren Hart, dvhltc, linux-kernel, Milton Miller, Will Schmidt,
Brian King, niv, Doug Maxey, linuxppc-dev
In-Reply-To: <alpine.LFD.2.00.1005201014250.3368@localhost.localdomain>
On Thu, 20 May 2010 at 10:21:36 +0200 (CEST) Thomas Gleixner wrote:
> On Thu, 20 May 2010, Michael Ellerman wrote:
> > On Wed, 2010-05-19 at 16:38 +0200, Thomas Gleixner wrote:
> > > On Wed, 19 May 2010, Darren Hart wrote:
> > >
> > > > On 05/18/2010 06:25 PM, Michael Ellerman wrote:
> > > > > On Tue, 2010-05-18 at 15:22 -0700, Darren Hart wrote:
> >
> > > > > The result of the discussion about two years ago on this was that we
> > > > > needed a custom flow handler for XICS on RT.
> > > >
> > > > I'm still not clear on why the ultimate solution wasn't to have XICS report
> > > > edge triggered as edge triggered. Probably some complexity of the entire power
> > > > stack that I am ignorant of.
> > > >
> > > > > Apart from the issue of loosing interrupts there is also the fact that
> > > > > masking on the XICS requires an RTAS call which takes a global lock.
> > >
> > > Right, I'd love to avoid that but with real level interrupts we'd run
> > > into an interrupt storm. Though another solution would be to issue the
> > > EOI after the threaded handler finished, that'd work as well, but
> > > needs testing.
> >
> > Yeah I think that was the idea for the custom flow handler. We'd reset
> > the processor priority so we can take other interrupts (which the EOI
> > usually does for you), then do the actual EOI after the handler
> > finished.
>
> That only works when the card does not issue new interrupts until the
> EOI happens. If the EOI is only relevant for the interrupt controller,
> then you are going to lose any edge which comes in before the EOI as
> well.
Well, the real MSIs have an extra bit to allow the eoi to dally behind
the mmio on another path and that should cover this race when the irq
is left enabled.
Jan-Bernd HEA has that change, right?
milton
^ permalink raw reply
* [git pull] Please pull powerpc.git next branch
From: Benjamin Herrenschmidt @ 2010-05-21 9:11 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linuxppc-dev list, Andrew Morton, Linux Kernel list
Hi Linus !
Here's the powerpc batch for this merge window.
Most of it is in arch/powerpc, a few powerpc specific drivers are hit
too, including removing one that has been unused (and unselectable in
Kconfig) for a long time (hdpuftrs), probably remains of a long dead
platform.
This time around, there's a lot of bits and pieces left and right, no
huge highlight. Some notable fixes to kexec/kdump that might make this
thing finally somewhat reliable from Mikey and Anton and a big cpumask
conversion from Anton as well.
Cheers,
Ben.
The following changes since commit 7a9b149212f3716c598afe973b6261fd58453b7a:
Linus Torvalds (1):
Merge git://git.kernel.org/.../gregkh/usb-2.6
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git next
Akinobu Mita (1):
powerpc/iseries/pci: Use __ratelimit
Andreas Schwab (1):
powerpc: Fix string library functions
Anton Blanchard (25):
powerpc/numa: Set a smaller value for RECLAIM_DISTANCE to enable zone reclaim
powerpc/pseries: Call ibm,os-term if the ibm,extended-os-term is present
powerpc/mm: Bump SECTION_SIZE_BITS from 16MB to 256MB
powerpc/cpumask: Use cpu_online_mask
powerpc/cpumask: Convert rtasd to new cpumask API
powerpc/cpumask: Convert smp_cpus_done to new cpumask API
powerpc/cpumask: Convert fixup_irqs to new cpumask API
powerpc/cpumask: Convert iseries SMP code to new cpumask API
powerpc/cpumask: Convert pseries SMP code to new cpumask API
powerpc/cpumask: Convert xics driver to new cpumask API
powerpc/cpumask: Refactor /proc/cpuinfo code
powerpc/cpumask: Convert /proc/cpuinfo to new cpumask API
powerpc/cpumask: Dynamically allocate cpu_sibling_map and cpu_core_map cpumasks
powerpc/cpumask: Convert hotplug-cpu code to new cpumask API
powerpc/cpumask: Convert NUMA code to new cpumask API
powerpc/cpumask: Update some comments
powerpc/cpumask: Add DEBUG_PER_CPU_MAPS option
powerpc/eeh: Fix oops when probing in early boot
powerpc/kdump: CPUs assume the context of the oopsing CPU
powerpc/kdump: Use chip->shutdown to disable IRQs
powerpc: Use more accurate limit for first segment memory allocations
powerpc: Remove check of ibm,smt-snooze-delay OF property
powerpc: Use smt_snooze_delay=-1 to always busy loop
powerpc/numa: Set a smaller value for RECLAIM_DISTANCE to enable zone reclaim
powerpc/numa: Use ibm,architecture-vec-5 to detect form 1 affinity
Anton Vorontsov (3):
powerpc/85xx: Add eTSEC 2.0 support for P1020RDB boards
powerpc/85xx: Fix P1020RDB boot hang due USB2
powerpc/83xx: Add MCU LEDs support for MPC837xRDB and MPC8315RDB boards
Benjamin Herrenschmidt (9):
Remove unused HDPU driver
powerpc: Fix ioremap_flags() with book3e pte definition
powerpc/vio: Add modalias support
powerpc/vio: Add power management support
Revert "powerpc/mm: Bump SECTION_SIZE_BITS from 16MB to 256MB"
powerpc: Fix CONFIG_DEBUG_PAGEALLOC on 603/e300
powerpc: Invoke oom-killer from page fault
powerpc/cpumask: Convert mpic driver to new cpumask API
Merge commit 'origin/master' into next
Brian King (1):
powerpc/vio: Switch VIO Bus PM to use generic helpers
Corey Minyard (2):
powerpc: Add a new zImage for maple using a different link address
powerpc/mpsc: Set the port device in the mpsc serial driver
Dave Kleikamp (5):
powerpc/44x: break out cpu init code into stand-alone function
powerpc/47x: Base ppc476 support
powerpc/476: add machine check handler for 47x core
powerpc/476: Add isync after loading mmu and debug spr's
powerpc/47x: defconfig for 476 on the iss 4xx simulator
FUJITA Tomonori (1):
powerpc: Remove unused 'protect4gb' boot parameter
Jason Gunthorpe (1):
powerpc/ppc32: Fixup pmd_page to work when ARCH_PFN_OFFSET is non-zero
Jeff Mahoney (1):
powerpc: Fix handling of strncmp with zero len
Joakim Tjernlund (4):
powerpc/8xx: Optimze TLB Miss handlers
powerpc/8xx: Avoid testing for kernel space in ITLB Miss.
powerpc/8xx: Don't touch ACCESSED when no SWAP.
powerpc/8xx: Use SPRG2 and DAR registers to stash r11 and cr.
Julia Lawall (6):
powerpc/pmac/windfarm: Correct potential double free
powerpc/pseries/dlpar: Eliminate use after free
powerpc/pseries/dlpar: Use kasprintf
powerpc/vio: Add missing unlock in error path
powerpc/pmac: Add missing unlocks in error path
powerpc: Use set_cpus_allowed_ptr
K.Prasad (1):
powerpc: Disable interrupts for data breakpoint exceptions
Kim Phillips (1):
powerpc: remove tls_ssl_stream descriptor type capability in sec3.3 node
Kumar Gala (1):
powerpc/fsl-booke: Move loadcam_entry back to asm code to fix SMP ftrace
Li Yang (1):
powerpc/fsl-booke: Fix InstructionTLBError execute permission check
Mahesh Salgaonkar (1):
powerpc: Add kprobe-based event tracer
Mark Nelson (2):
powerpc/mm: Track backing pages allocated by vmemmap_populate()
powerpc/pseries: Make request_ras_irqs() available to other pseries code
Martyn Welch (1):
powerpc: Correct parport interrupt parsing
Maxim Uvarov (1):
powerpc/crashdump: Do not fail on NULL pointer dereferencing
Michael Ellerman (1):
powerpc/rtasd: Don't start event scan if scan rate is zero
Michael Neuling (7):
powerpc/pseries: Make query_cpu_stopped callable outside hotplug cpu
powerpc/pseries: Only call start-cpu when a CPU is stopped
powerpc/pseries: Add hcall to read 4 ptes at a time in real mode
powerpc/kexec: Speedup kexec hash PTE tear down
powerpc/kexec: Fix race in kexec shutdown
powerpc/kdump: Fix race in kdump shutdown
powerpc: Build-in e1000e for pseries & ppc64_defconfig
Milton Miller (1):
powerpc: Use common cpu_die (fixes SMP+SUSPEND build)
Paul Mackerras (1):
powerpc: Avoid bad relocations in iSeries code
Peter Korsgaard (1):
powerpc: Add interrupt support to mpc8xxx_gpio
Sonny Rao (1):
powerpc/pci: Check devices status property when scanning OF tree
Stefan Roese (1):
powerpc/4xx: Add optional "reset_type" property to control reboot via dts
Timur Tabi (1):
powerpc/8610: add probing for individual DMA channels, not just DMA controllers
Torez Smith (2):
powerpc/booke: Add Stack Marking support to Booke Exception Prolog
powerpc/4xx: Simple platform for the ISS 4xx simulator
Vaidyanathan Srinivasan (1):
powerpc/pseries: Export data from new hcall H_EM_GET_PARMS
Wolfram Sang (4):
powerpc/pmac: Fix dangling pointers
i2c/mpc: Drop NO_IRQ
i2c/cpm: Drop NO_IRQ
i2c/ibm-iic: Drop NO_IRQ
d binderman (3):
powerpc/aoa: gpio-pmf.c: 3 * redundant code
powerpc/pmac/low_i2c.c: three minor problems
powerpc/pmac/windfarm: Don't test pointers before kfree()
Documentation/powerpc/dts-bindings/4xx/reboot.txt | 18 +
.../powerpc/dts-bindings/fsl/8xxx_gpio.txt | 22 +-
arch/powerpc/Kconfig | 1 +
arch/powerpc/Kconfig.debug | 12 +
arch/powerpc/boot/Makefile | 9 +-
arch/powerpc/boot/dts/iss4xx-mpic.dts | 155 +++
arch/powerpc/boot/dts/iss4xx.dts | 116 +++
arch/powerpc/boot/dts/mpc8315erdb.dts | 16 +-
arch/powerpc/boot/dts/mpc8377_rdb.dts | 14 +
arch/powerpc/boot/dts/mpc8378_rdb.dts | 14 +
arch/powerpc/boot/dts/mpc8379_rdb.dts | 14 +
arch/powerpc/boot/dts/p1020rdb.dts | 125 +++
arch/powerpc/boot/treeboot-iss4xx.c | 56 ++
arch/powerpc/boot/wrapper | 9 +-
arch/powerpc/configs/44x/iss476-smp_defconfig | 1026 ++++++++++++++++++++
arch/powerpc/configs/ppc64_defconfig | 2 +-
arch/powerpc/configs/pseries_defconfig | 2 +-
arch/powerpc/include/asm/cache.h | 6 +-
arch/powerpc/include/asm/cputable.h | 5 +
arch/powerpc/include/asm/hvcall.h | 2 +
arch/powerpc/include/asm/kexec.h | 4 +
arch/powerpc/include/asm/mmu-44x.h | 51 +-
arch/powerpc/include/asm/mmu.h | 1 +
arch/powerpc/include/asm/mmzone.h | 2 +-
arch/powerpc/include/asm/mpic.h | 3 -
arch/powerpc/include/asm/paca.h | 1 +
arch/powerpc/include/asm/parport.h | 11 +-
arch/powerpc/include/asm/pgalloc-64.h | 6 +
arch/powerpc/include/asm/pgtable-ppc32.h | 2 +-
arch/powerpc/include/asm/ptrace.h | 64 ++
arch/powerpc/include/asm/reg.h | 4 +
arch/powerpc/include/asm/reg_booke.h | 24 +
arch/powerpc/include/asm/smp.h | 18 +-
arch/powerpc/include/asm/topology.h | 26 +-
arch/powerpc/kernel/asm-offsets.c | 9 +
arch/powerpc/kernel/cputable.c | 29 +
arch/powerpc/kernel/crash.c | 38 +-
arch/powerpc/kernel/entry_32.S | 5 +
arch/powerpc/kernel/exceptions-64s.S | 13 +-
arch/powerpc/kernel/head_44x.S | 828 +++++++++++++----
arch/powerpc/kernel/head_8xx.S | 70 +-
arch/powerpc/kernel/head_booke.h | 4 +
arch/powerpc/kernel/head_fsl_booke.S | 13 +-
arch/powerpc/kernel/iommu.c | 12 -
arch/powerpc/kernel/irq.c | 17 +-
arch/powerpc/kernel/kprobes.c | 3 +
arch/powerpc/kernel/lparcfg.c | 12 +-
arch/powerpc/kernel/machine_kexec_64.c | 48 +-
arch/powerpc/kernel/misc_32.S | 9 +-
arch/powerpc/kernel/misc_64.S | 8 +-
arch/powerpc/kernel/paca.c | 2 +
arch/powerpc/kernel/pci_of_scan.c | 2 +
arch/powerpc/kernel/process.c | 3 +
arch/powerpc/kernel/ptrace.c | 103 ++
arch/powerpc/kernel/rtas.c | 15 +-
arch/powerpc/kernel/rtasd.c | 16 +-
arch/powerpc/kernel/setup-common.c | 86 +-
arch/powerpc/kernel/setup_64.c | 23 +-
arch/powerpc/kernel/smp.c | 73 +-
arch/powerpc/kernel/sysfs.c | 46 +-
arch/powerpc/kernel/traps.c | 40 +
arch/powerpc/kernel/vio.c | 26 +-
arch/powerpc/lib/string.S | 18 +-
arch/powerpc/mm/44x_mmu.c | 144 +++-
arch/powerpc/mm/fault.c | 19 +-
arch/powerpc/mm/fsl_booke_mmu.c | 25 +-
arch/powerpc/mm/init_64.c | 43 +
arch/powerpc/mm/mmu_context_nohash.c | 8 +
arch/powerpc/mm/mmu_decl.h | 17 +-
arch/powerpc/mm/numa.c | 78 ++-
arch/powerpc/mm/pgtable_32.c | 12 +-
arch/powerpc/mm/pgtable_64.c | 8 +
arch/powerpc/mm/tlb_nohash_low.S | 146 +++-
arch/powerpc/platforms/44x/Kconfig | 20 +
arch/powerpc/platforms/44x/Makefile | 1 +
arch/powerpc/platforms/44x/iss4xx.c | 167 ++++
arch/powerpc/platforms/83xx/mpc831x_rdb.c | 1 +
arch/powerpc/platforms/83xx/mpc837x_rdb.c | 1 +
arch/powerpc/platforms/86xx/mpc8610_hpcd.c | 3 +-
arch/powerpc/platforms/Kconfig.cputype | 5 +-
arch/powerpc/platforms/cell/cbe_cpufreq.c | 2 +-
arch/powerpc/platforms/iseries/exception.S | 4 +-
arch/powerpc/platforms/iseries/pci.c | 10 +-
arch/powerpc/platforms/iseries/smp.c | 2 +-
arch/powerpc/platforms/pasemi/cpufreq.c | 2 +-
arch/powerpc/platforms/powermac/cpufreq_64.c | 2 +-
arch/powerpc/platforms/powermac/low_i2c.c | 7 +-
arch/powerpc/platforms/powermac/pmac.h | 2 +
arch/powerpc/platforms/powermac/setup.c | 13 +-
arch/powerpc/platforms/powermac/smp.c | 9 +-
arch/powerpc/platforms/pseries/Makefile | 2 +-
arch/powerpc/platforms/pseries/dlpar.c | 8 +-
arch/powerpc/platforms/pseries/eeh.c | 2 +-
arch/powerpc/platforms/pseries/event_sources.c | 79 ++
arch/powerpc/platforms/pseries/hotplug-cpu.c | 67 +-
arch/powerpc/platforms/pseries/hvCall.S | 38 +
arch/powerpc/platforms/pseries/lpar.c | 35 +-
arch/powerpc/platforms/pseries/plpar_wrappers.h | 26 +
arch/powerpc/platforms/pseries/pseries.h | 7 +
arch/powerpc/platforms/pseries/ras.c | 62 +--
arch/powerpc/platforms/pseries/setup.c | 10 +-
arch/powerpc/platforms/pseries/smp.c | 42 +-
arch/powerpc/platforms/pseries/xics.c | 38 +-
arch/powerpc/sysdev/mpc8xxx_gpio.c | 147 +++
arch/powerpc/sysdev/mpic.c | 72 +-
arch/powerpc/sysdev/ppc4xx_soc.c | 24 +-
drivers/i2c/busses/i2c-cpm.c | 2 +-
drivers/i2c/busses/i2c-ibm_iic.c | 14 +-
drivers/i2c/busses/i2c-mpc.c | 6 +-
drivers/macintosh/macio-adb.c | 1 +
drivers/macintosh/smu.c | 4 +-
drivers/macintosh/therm_adt746x.c | 2 +
drivers/macintosh/windfarm_pm81.c | 6 +-
drivers/macintosh/windfarm_pm91.c | 9 +-
drivers/misc/Makefile | 1 -
drivers/misc/hdpuftrs/Makefile | 1 -
drivers/misc/hdpuftrs/hdpu_cpustate.c | 256 -----
drivers/misc/hdpuftrs/hdpu_nexus.c | 149 ---
drivers/serial/mpsc.c | 1 +
include/linux/hdpu_features.h | 26 -
sound/aoa/core/gpio-pmf.c | 9 +-
121 files changed, 4157 insertions(+), 1152 deletions(-)
create mode 100644 Documentation/powerpc/dts-bindings/4xx/reboot.txt
create mode 100644 arch/powerpc/boot/dts/iss4xx-mpic.dts
create mode 100644 arch/powerpc/boot/dts/iss4xx.dts
create mode 100644 arch/powerpc/boot/treeboot-iss4xx.c
create mode 100644 arch/powerpc/configs/44x/iss476-smp_defconfig
create mode 100644 arch/powerpc/platforms/44x/iss4xx.c
create mode 100644 arch/powerpc/platforms/pseries/event_sources.c
delete mode 100644 drivers/misc/hdpuftrs/Makefile
delete mode 100644 drivers/misc/hdpuftrs/hdpu_cpustate.c
delete mode 100644 drivers/misc/hdpuftrs/hdpu_nexus.c
delete mode 100644 include/linux/hdpu_features.h
^ permalink raw reply
* Re: Problem of PowerPc 82xx when using smc
From: hellohello @ 2010-05-21 3:33 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <20100520170608.GA10712@schlenkerla.am.freescale.net>
PiBObywgaXQgc2hvdWxkbid0IC0tIHJ4X2JkX2Jhc2UgaXMgb2YgdHlwZSAiY2JkX3QgKiIsIHNv
IHRoZSBtdWx0aXBsaWNhdGlvbg0KPiBhbHJlYWR5IGhhcHBlbnMgYXMgcGFydCBvZiBwb2ludGVy
IGFyaXRobWV0aWMuDQotLS1ZZXMsIHlvdSBhcmUgcmlnaHQuIEkgbWFkZSBhIGJhc2ljIG1pc3Rh
a2UuIA0KDQpCdXQgbm93IEkgaGF2ZSBhbm90aGVyIHF1ZXN0aW9uLg0KVGhlIFNNQzEgcGFyYW1z
IGNhbiBiZSByZWxvY2F0ZWQgdG8gYW55IG9mZnNldCBvZiB0aGUgRFBSQU0gb24gYSA2NCBieXRl
IGJvdW5kYXJ5LCBub3QgYXMgdGhlIFNDQzEsIHdoaWNoIG11c3QgYmUgIGF0IDB4ODAwMCBvZmZz
ZXQgb2YgdGhlIERQUkFNLg0KVGhlIFNNQzEgcGFyYW1zIGJhc2UgaXMgc2V0IGF0IDB4ODdGQyBv
ZmZzZXQgb2YgdGhlIERQUkFNLg0KDQpTbyBpZiAgSSB3YW50IFNNQzEgcGFyYW1zIHN0YXJ0IGF0
ICAweDIwMCBpbiBEUFJBTSAgLCBJIHNob3VsZCBzZXQgMHgyMDAgdG8gdGhlIDB4ODdGQyBvZmZz
ZXQgb2YgdGhlIERQUkFNLg0KSSBoYXZlIHNlZSB0aGlzIGNvZGUgaW4gdS1ib290LCBidXQgSSBj
YW4gbm90IGZpbmQgdGhpcyBjb2RlIGluIG5laXRoZXIgY3BtX3VhcnRfY3BtMi5jIG5vciBjcG1f
dWFydF9jb3JlLmMuDQoNClNob3VsZCBJIGFkZCB0aGVzZSBjb2RlIHRvICBjcG1fdWFydF9jb3Jl
LmM/DQoNCi0tZHBfbWVtID0gY3BtX2RwcmFtX2FkZHIoMHg4N2ZjKTsNCi0tb3V0X2JlMTYoZHBf
bWVtLCBTTUMxX0JBU0UpOw0KDQoNCg0KDQoNCg0KDQotLS0tLSBPcmlnaW5hbCBNZXNzYWdlIC0t
LS0tIA0KRnJvbTogIlNjb3R0IFdvb2QiIDxzY290dHdvb2RAZnJlZXNjYWxlLmNvbT4NClRvOiAi
aGVsbG9oZWxsbyIgPGhlbGxvaGVsbG8wMDhAMTYzLmNvbT4NCkNjOiA8bGludXhwcGMtZGV2QGxp
c3RzLm96bGFicy5vcmc+DQpTZW50OiBGcmlkYXksIE1heSAyMSwgMjAxMCAxOjA2IEFNDQpTdWJq
ZWN0OiBSZTogUHJvYmxlbSBvZiBQb3dlclBjIDgyeHggd2hlbiB1c2luZyBzbWMNCg0KDQo+IE9u
IFRodSwgTWF5IDIwLCAyMDEwIGF0IDA0OjU4OjI3UE0gKzA4MDAsIGhlbGxvaGVsbG8gd3JvdGU6
DQo+PiANCj4+IEkgZmluZCBhIHByb2JsZW0gaW4gDQo+PiBkcml2ZXJzL3NlcmlhbC9jcG1fdWFy
dC9jcG1fdWFydF9jcG0yLmM6DQo+PiBpbnQgY3BtX3VhcnRfYWxsb2NidWYoc3RydWN0IHVhcnRf
Y3BtX3BvcnQgKnBpbmZvLCB1bnNpZ25lZCBpbnQgaXNfY29uKQ0KPj4gew0KPj4gLi4uIC4uLg0K
Pj4gcGluZm8tPnR4X2JkX2Jhc2UgPSBwaW5mby0+cnhfYmRfYmFzZSArIHBpbmZvLT5yeF9ucmZp
Zm9zOw0KPj4gLypUaGUgYWJvdmUgbGluZSBzaG91bGQgYmUg77yaKi8NCj4+ICBwaW5mby0+dHhf
YmRfYmFzZSA9IHBpbmZvLT5yeF9iZF9iYXNlICsgc2l6ZW9mKGNiZF90KSAqIHBpbmZvLT5yeF9u
cmZpZm9zOw0KPiANCj4gTm8sIGl0IHNob3VsZG4ndCAtLSByeF9iZF9iYXNlIGlzIG9mIHR5cGUg
ImNiZF90ICoiLCBzbyB0aGUgbXVsdGlwbGljYXRpb24NCj4gYWxyZWFkeSBoYXBwZW5zIGFzIHBh
cnQgb2YgcG9pbnRlciBhcml0aG1ldGljLg0KPiANCj4+IHJldHVybiAwOw0KPj4gfQ0KPj4gDQo+
PiBXaGVyZSB0byBnZXQgdGhlIG5ld2VzdCBjb2RlIGZvciBrZXJuZWw/DQo+IA0KPiBnaXQua2Vy
bmVsLm9yZw0KPiANCj4+IEhvdyB0byBrbm93IHdoZXRoZXIgaXQgaXMgYWxyZWFkeSBwYXRjaGVk
IGJ5IGFueW9uZSBlbHNlPyAgSnVzdCBzZWFyY2ggaW4gIHRoaXMgbWFpbCBsaXN0Pw0KPiANCj4g
QXMgd2VsbCBhcyB0aGUgY3VycmVudCBnaXQgdHJlZS4NCj4gDQo+IC1TY290dA0KPiBfX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXw0KPiBMaW51eHBwYy1kZXYg
bWFpbGluZyBsaXN0DQo+IExpbnV4cHBjLWRldkBsaXN0cy5vemxhYnMub3JnDQo+IGh0dHBzOi8v
bGlzdHMub3psYWJzLm9yZy9saXN0aW5mby9saW51eHBwYy1kZXY=
^ permalink raw reply
* Re: [PATCH RT] ehea: make receive irq handler non-threaded (IRQF_NODELAY)
From: Will Schmidt @ 2010-05-20 21:44 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Darren Hart, Jan-Bernd Themann, dvhltc, linux-kernel, Brian King,
niv, Doug Maxey, linuxppc-dev
In-Reply-To: <alpine.LFD.2.00.1005201644400.3368@localhost.localdomain>
On Thu, 2010-05-20 at 16:45 +0200, Thomas Gleixner wrote:
> On Thu, 20 May 2010, Darren Hart wrote:
>
> > On 05/20/2010 01:14 AM, Thomas Gleixner wrote:
> > > On Thu, 20 May 2010, Jan-Bernd Themann wrote:
> > > > > > Thought more about that. The case at hand (ehea) is nasty:
> > > > > >
> > > > > > The driver does _NOT_ disable the rx interrupt in the card in the rx
> > > > > > interrupt handler - for whatever reason.
> > > > >
> > > > > Yeah I saw that, but I don't know why it's written that way. Perhaps
> > > > > Jan-Bernd or Doug will chime in and enlighten us? :)
> > > >
> > > > From our perspective there is no need to disable interrupts for the
> > > > RX side as the chip does not fire further interrupts until we tell
> > > > the chip to do so for a particular queue. We have multiple receive
> > >
> > > The traces tell a different story though:
> > >
> > > ehea_recv_irq_handler()
> > > napi_reschedule()
> > > eoi()
> > > ehea_poll()
> > > ...
> > > ehea_recv_irq_handler()<---------------- ???
> > > napi_reschedule()
> > > ...
> > > napi_complete()
> > >
> > > Can't tell whether you can see the same behaviour in mainline, but I
> > > don't see a reason why not.
> >
> > I was going to suggest that because these are threaded handlers, perhaps they
> > are rescheduled on a different CPU and then receive the interrupt for the
> > other CPU/queue that Jan was mentioning.
> >
> > But, the handlers are affined if I remember correctly, and we aren't running
> > with multiple receive queues. So, we're back to the same question, why are we
> > seeing another irq. It comes in before napi_complete() and therefor before the
> > ehea_reset*() block of calls which do the equivalent of re-enabling
> > interrupts.
>
> Can you slap a few trace points into that driver with a stock mainline
> kernel and verify that ?
2.6.33.4 (non-rt kernel) with similar trace_printk hooks in place...
Most data lumps look like so:
<idle>-0 [000] 1097.685337: .handle_fasteoi_irq: ENTER 260 4000
<idle>-0 [000] 1097.685339: .handle_fasteoi_irq: pre-action 260 4100
<idle>-0 [000] 1097.685339: .ehea_recv_irq_handler: ENTER c0000000e8980700
<idle>-0 [000] 1097.685340: .ehea_recv_irq_handler: napi_schedule ... c0000000e8980700
<idle>-0 [000] 1097.685341: .ehea_recv_irq_handler: napi_schedule Calling __napi_schedule ... c0000000e8980700
<idle>-0 [000] 1097.685342: .ehea_recv_irq_handler: EXIT c0000000e8980700
<idle>-0 [000] 1097.685343: .handle_fasteoi_irq: post-action 260 4100
<idle>-0 [000] 1097.685344: .handle_fasteoi_irq: EXIT. 260 4000
<idle>-0 [000] 1097.685346: .ehea_poll: ENTER c0000000e8980700
<idle>-0 [000] 1097.685352: .napi_complete: napi_complete: ENTER c0000000e8980700
<idle>-0 [000] 1097.685352: .napi_complete: napi_complete: EXIT c0000000e8980700
<idle>-0 [000] 1097.685355: .ehea_poll: EXIT !cqe rx(1) c0000000e8980700
But I did see one like this, which shows a ehea_recv_irq_handler ENTER
within a ehea_poll ENTER. (which I think is what you were expecting,
or wanted to verify..)
<idle>-0 [000] 1097.616261: .handle_fasteoi_irq: ENTER 260 4000
<idle>-0 [000] 1097.616262: .handle_fasteoi_irq: pre-action 260 4100
* <idle>-0 [000] 1097.616263: .ehea_recv_irq_handler: ENTER c0000000e8980700
<idle>-0 [000] 1097.616264: .ehea_recv_irq_handler: napi_schedule ... c0000000e8980700
<idle>-0 [000] 1097.616265: .ehea_recv_irq_handler: napi_schedule Calling __napi_schedule ... c0000000e8980700
<idle>-0 [000] 1097.616265: .ehea_recv_irq_handler: EXIT c0000000e8980700
<idle>-0 [000] 1097.616266: .handle_fasteoi_irq: post-action 260 4100
<idle>-0 [000] 1097.616268: .handle_fasteoi_irq: EXIT. 260 4000
* <idle>-0 [000] 1097.616270: .ehea_poll: ENTER c0000000e8980700
<idle>-0 [000] 1097.616282: .handle_fasteoi_irq: ENTER 260 4000
<idle>-0 [000] 1097.616283: .handle_fasteoi_irq: pre-action 260 4100
* <idle>-0 [000] 1097.616284: .ehea_recv_irq_handler: ENTER c0000000e8980700
<idle>-0 [000] 1097.616285: .ehea_recv_irq_handler: napi_schedule ... c0000000e8980700
<idle>-0 [000] 1097.616286: .ehea_recv_irq_handler: napi_schedule NOT Calling __napi_schedule... c0000000e8980700
<idle>-0 [000] 1097.616286: .ehea_recv_irq_handler: EXIT c0000000e8980700
<idle>-0 [000] 1097.616287: .handle_fasteoi_irq: post-action 260 4100
<idle>-0 [000] 1097.616289: .handle_fasteoi_irq: EXIT. 260 4000
<idle>-0 [000] 1097.616299: .napi_complete: napi_complete: ENTER c0000000e8980700
<idle>-0 [000] 1097.616300: .napi_complete: napi_complete: EXIT c0000000e8980700
<idle>-0 [000] 1097.616302: .ehea_poll: napi_reschedule COMpleted c0000000e8980700
<idle>-0 [000] 1097.616303: .napi_complete: napi_complete: ENTER c0000000e8980700
<idle>-0 [000] 1097.616304: .napi_complete: napi_complete: EXIT c0000000e8980700
* <idle>-0 [000] 1097.616306: .ehea_poll: EXIT !cqe rx(4) c0000000e8980700
Let me know if you want/need more or a variation, etc..
Thanks,
-Will
^ permalink raw reply
* Re: [lm-sensors] [PATCH] hwmon: (tmp421) Add nfactor support (2nd attempt)
From: Andre Prendel @ 2010-05-20 19:35 UTC (permalink / raw)
To: Jeff Angielski; +Cc: Jean Delvare, linuxppc-dev, lm-sensors
In-Reply-To: <4BF58859.3090702@theptrgroup.com>
On Thu, May 20, 2010 at 03:07:05PM -0400, Jeff Angielski wrote:
> On 05/20/2010 02:50 PM, Andre Prendel wrote:
> > You made a careless mistake, see below. Please fix this and resend the patch
> > again. Then I added my Acked-by and I think Jean will schedule the patch for
> > 2.6.35 (after another review of course :))
>
> You sir, would be correct... *sigh* I tried using the scripts/Lindent on it to
> be sure there were no coding style issues but that messed up even your original
> code.
/scripts/checkpatch.pl is the key ;)
> In any event, here it is again:
Acked-by: Andre Prendel <andre.prendel@gmx.de>
>
> >From 9acd29ff48c64e58a7f5cdb888c86e737c56281c Mon Sep 17 00:00:00 2001
> From: Jeff Angielski <jeff@theptrgroup.com>
> Date: Mon, 10 May 2010 10:26:34 -0400
> Subject: [PATCH] hwmon: (tmp421) Add nfactor support
>
> Add support for reading and writing the n-factor correction
> registers. This is needed to compensate for the characteristics
> of a particular sensor hanging off of the remote channels.
>
> Signed-off-by: Jeff Angielski <jeff@theptrgroup.com>
> ---
> Documentation/hwmon/tmp421 | 19 +++++++++++++++++++
> drivers/hwmon/tmp421.c | 41 +++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 60 insertions(+), 0 deletions(-)
>
> diff --git a/Documentation/hwmon/tmp421 b/Documentation/hwmon/tmp421
> index 0cf07f8..668228a 100644
> --- a/Documentation/hwmon/tmp421
> +++ b/Documentation/hwmon/tmp421
> @@ -17,6 +17,7 @@ Supported chips:
>
> Authors:
> Andre Prendel <andre.prendel@gmx.de>
> + Jeff Angielski <jeff@theptrgroup.com>
>
> Description
> -----------
> @@ -34,3 +35,21 @@ the temperature values via the following sysfs files:
>
> temp[1-4]_input
> temp[2-4]_fault
> +
> +The chips allow the user to adjust the n-factor value that is used
> +when converting the remote channel measurements to temperature. The
> +adjustment has a range of -128 to +127 that yields an effective
> +n-factor range of 0.706542 to 1.747977. The power on reset value
> +for the adjustment is 0 which results in an n-factor of 1.008.
> +
> +The effective n-factor is calculated according to the following
> +equation:
> +
> +n_factor = (1.008 * 300) / (300 - nfactor_adjust)
> +
> +The driver exports the n-factor adjustment value via the following
> +sysfs files:
> +
> +temp[2-4]_n_adjust
> +
> +
> diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c
> index 738c472..dfd62be 100644
> --- a/drivers/hwmon/tmp421.c
> +++ b/drivers/hwmon/tmp421.c
> @@ -49,6 +49,7 @@ enum chips { tmp421, tmp422, tmp423 };
>
> static const u8 TMP421_TEMP_MSB[4] = { 0x00, 0x01, 0x02, 0x03 };
> static const u8 TMP421_TEMP_LSB[4] = { 0x10, 0x11, 0x12, 0x13 };
> +static const u8 TMP421_N_CORRECT[3] = { 0x21, 0x22, 0x23 };
>
> /* Flags */
> #define TMP421_CONFIG_SHUTDOWN 0x40
> @@ -76,6 +77,7 @@ struct tmp421_data {
> int channels;
> u8 config;
> s16 temp[4];
> + s8 n_adjust[3];
> };
>
> static int temp_from_s16(s16 reg)
> @@ -115,6 +117,10 @@ static struct tmp421_data *tmp421_update_device(struct device *dev)
> data->temp[i] |= i2c_smbus_read_byte_data(client,
> TMP421_TEMP_LSB[i]);
> }
> + for (i = 1; i < data->channels; i++) {
> + data->n_adjust[i - 1] = i2c_smbus_read_byte_data(client,
> + TMP421_N_CORRECT[i - 1]);
> + }
> data->last_updated = jiffies;
> data->valid = 1;
> }
> @@ -157,6 +163,32 @@ static ssize_t show_fault(struct device *dev,
> return sprintf(buf, "0\n");
> }
>
> +static ssize_t show_n_adjust(struct device *dev,
> + struct device_attribute *devattr, char *buf)
> +{
> + int index = to_sensor_dev_attr(devattr)->index;
> + struct tmp421_data *data = tmp421_update_device(dev);
> +
> + return sprintf(buf, "%d\n", data->n_adjust[index - 1]);
> +}
> +
> +static ssize_t set_n_adjust(struct device *dev,
> + struct device_attribute *devattr,
> + const char *buf, size_t count)
> +{
> + struct i2c_client *client = to_i2c_client(dev);
> + struct tmp421_data *data = i2c_get_clientdata(client);
> + int index = to_sensor_dev_attr(devattr)->index;
> + int n_adjust = simple_strtol(buf, NULL, 10);
> +
> + mutex_lock(&data->update_lock);
> + i2c_smbus_write_byte_data(client, TMP421_N_CORRECT[index - 1],
> + SENSORS_LIMIT(n_adjust, -128, 127));
> + mutex_unlock(&data->update_lock);
> +
> + return count;
> +}
> +
> static mode_t tmp421_is_visible(struct kobject *kobj, struct attribute *a,
> int n)
> {
> @@ -177,19 +209,28 @@ static mode_t tmp421_is_visible(struct kobject *kobj, struct attribute *a,
> static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_value, NULL, 0);
> static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_value, NULL, 1);
> static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_fault, NULL, 1);
> +static SENSOR_DEVICE_ATTR(temp2_n_adjust, S_IRUSR | S_IWUSR | S_IRGRP,
> + show_n_adjust, set_n_adjust, 1);
> static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_value, NULL, 2);
> static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_fault, NULL, 2);
> +static SENSOR_DEVICE_ATTR(temp3_n_adjust, S_IRUSR | S_IWUSR | S_IRGRP,
> + show_n_adjust, set_n_adjust, 2);
> static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_value, NULL, 3);
> static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_fault, NULL, 3);
> +static SENSOR_DEVICE_ATTR(temp4_n_adjust, S_IRUSR | S_IWUSR | S_IRGRP,
> + show_n_adjust, set_n_adjust, 3);
>
> static struct attribute *tmp421_attr[] = {
> &sensor_dev_attr_temp1_input.dev_attr.attr,
> &sensor_dev_attr_temp2_input.dev_attr.attr,
> &sensor_dev_attr_temp2_fault.dev_attr.attr,
> + &sensor_dev_attr_temp2_n_adjust.dev_attr.attr,
> &sensor_dev_attr_temp3_input.dev_attr.attr,
> &sensor_dev_attr_temp3_fault.dev_attr.attr,
> + &sensor_dev_attr_temp3_n_adjust.dev_attr.attr,
> &sensor_dev_attr_temp4_input.dev_attr.attr,
> &sensor_dev_attr_temp4_fault.dev_attr.attr,
> + &sensor_dev_attr_temp4_n_adjust.dev_attr.attr,
> NULL
> };
>
> --
> 1.7.0.4
>
>
> --
> Jeff Angielski
> The PTR Group
> www.theptrgroup.com
>
> _______________________________________________
> lm-sensors mailing list
> lm-sensors@lm-sensors.org
> http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
^ permalink raw reply
* Re: [lm-sensors] [PATCH] hwmon: (tmp421) Add nfactor support (2nd attempt)
From: Jeff Angielski @ 2010-05-20 19:07 UTC (permalink / raw)
To: Andre Prendel; +Cc: Jean Delvare, linuxppc-dev, lm-sensors
In-Reply-To: <20100520185035.GA2153@andre-laptop>
On 05/20/2010 02:50 PM, Andre Prendel wrote:
> You made a careless mistake, see below. Please fix this and resend the patch
> again. Then I added my Acked-by and I think Jean will schedule the patch for
> 2.6.35 (after another review of course :))
You sir, would be correct... *sigh* I tried using the scripts/Lindent on it to
be sure there were no coding style issues but that messed up even your original
code.
In any event, here it is again:
>From 9acd29ff48c64e58a7f5cdb888c86e737c56281c Mon Sep 17 00:00:00 2001
From: Jeff Angielski <jeff@theptrgroup.com>
Date: Mon, 10 May 2010 10:26:34 -0400
Subject: [PATCH] hwmon: (tmp421) Add nfactor support
Add support for reading and writing the n-factor correction
registers. This is needed to compensate for the characteristics
of a particular sensor hanging off of the remote channels.
Signed-off-by: Jeff Angielski <jeff@theptrgroup.com>
---
Documentation/hwmon/tmp421 | 19 +++++++++++++++++++
drivers/hwmon/tmp421.c | 41 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 60 insertions(+), 0 deletions(-)
diff --git a/Documentation/hwmon/tmp421 b/Documentation/hwmon/tmp421
index 0cf07f8..668228a 100644
--- a/Documentation/hwmon/tmp421
+++ b/Documentation/hwmon/tmp421
@@ -17,6 +17,7 @@ Supported chips:
Authors:
Andre Prendel <andre.prendel@gmx.de>
+ Jeff Angielski <jeff@theptrgroup.com>
Description
-----------
@@ -34,3 +35,21 @@ the temperature values via the following sysfs files:
temp[1-4]_input
temp[2-4]_fault
+
+The chips allow the user to adjust the n-factor value that is used
+when converting the remote channel measurements to temperature. The
+adjustment has a range of -128 to +127 that yields an effective
+n-factor range of 0.706542 to 1.747977. The power on reset value
+for the adjustment is 0 which results in an n-factor of 1.008.
+
+The effective n-factor is calculated according to the following
+equation:
+
+n_factor = (1.008 * 300) / (300 - nfactor_adjust)
+
+The driver exports the n-factor adjustment value via the following
+sysfs files:
+
+temp[2-4]_n_adjust
+
+
diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c
index 738c472..dfd62be 100644
--- a/drivers/hwmon/tmp421.c
+++ b/drivers/hwmon/tmp421.c
@@ -49,6 +49,7 @@ enum chips { tmp421, tmp422, tmp423 };
static const u8 TMP421_TEMP_MSB[4] = { 0x00, 0x01, 0x02, 0x03 };
static const u8 TMP421_TEMP_LSB[4] = { 0x10, 0x11, 0x12, 0x13 };
+static const u8 TMP421_N_CORRECT[3] = { 0x21, 0x22, 0x23 };
/* Flags */
#define TMP421_CONFIG_SHUTDOWN 0x40
@@ -76,6 +77,7 @@ struct tmp421_data {
int channels;
u8 config;
s16 temp[4];
+ s8 n_adjust[3];
};
static int temp_from_s16(s16 reg)
@@ -115,6 +117,10 @@ static struct tmp421_data *tmp421_update_device(struct device *dev)
data->temp[i] |= i2c_smbus_read_byte_data(client,
TMP421_TEMP_LSB[i]);
}
+ for (i = 1; i < data->channels; i++) {
+ data->n_adjust[i - 1] = i2c_smbus_read_byte_data(client,
+ TMP421_N_CORRECT[i - 1]);
+ }
data->last_updated = jiffies;
data->valid = 1;
}
@@ -157,6 +163,32 @@ static ssize_t show_fault(struct device *dev,
return sprintf(buf, "0\n");
}
+static ssize_t show_n_adjust(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ int index = to_sensor_dev_attr(devattr)->index;
+ struct tmp421_data *data = tmp421_update_device(dev);
+
+ return sprintf(buf, "%d\n", data->n_adjust[index - 1]);
+}
+
+static ssize_t set_n_adjust(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct tmp421_data *data = i2c_get_clientdata(client);
+ int index = to_sensor_dev_attr(devattr)->index;
+ int n_adjust = simple_strtol(buf, NULL, 10);
+
+ mutex_lock(&data->update_lock);
+ i2c_smbus_write_byte_data(client, TMP421_N_CORRECT[index - 1],
+ SENSORS_LIMIT(n_adjust, -128, 127));
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
static mode_t tmp421_is_visible(struct kobject *kobj, struct attribute *a,
int n)
{
@@ -177,19 +209,28 @@ static mode_t tmp421_is_visible(struct kobject *kobj, struct attribute *a,
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_value, NULL, 0);
static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_value, NULL, 1);
static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_fault, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp2_n_adjust, S_IRUSR | S_IWUSR | S_IRGRP,
+ show_n_adjust, set_n_adjust, 1);
static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_value, NULL, 2);
static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_fault, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp3_n_adjust, S_IRUSR | S_IWUSR | S_IRGRP,
+ show_n_adjust, set_n_adjust, 2);
static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_value, NULL, 3);
static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_fault, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp4_n_adjust, S_IRUSR | S_IWUSR | S_IRGRP,
+ show_n_adjust, set_n_adjust, 3);
static struct attribute *tmp421_attr[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp2_input.dev_attr.attr,
&sensor_dev_attr_temp2_fault.dev_attr.attr,
+ &sensor_dev_attr_temp2_n_adjust.dev_attr.attr,
&sensor_dev_attr_temp3_input.dev_attr.attr,
&sensor_dev_attr_temp3_fault.dev_attr.attr,
+ &sensor_dev_attr_temp3_n_adjust.dev_attr.attr,
&sensor_dev_attr_temp4_input.dev_attr.attr,
&sensor_dev_attr_temp4_fault.dev_attr.attr,
+ &sensor_dev_attr_temp4_n_adjust.dev_attr.attr,
NULL
};
--
1.7.0.4
--
Jeff Angielski
The PTR Group
www.theptrgroup.com
^ permalink raw reply related
* Re: [lm-sensors] [PATCH] hwmon: (tmp421) Add nfactor support (2nd attempt)
From: Andre Prendel @ 2010-05-20 18:50 UTC (permalink / raw)
To: Jeff Angielski; +Cc: Jean Delvare, linuxppc-dev, lm-sensors
In-Reply-To: <4BF41C20.60502@theptrgroup.com>
On Wed, May 19, 2010 at 01:13:04PM -0400, Jeff Angielski wrote:
> On 05/19/2010 03:26 AM, Andre Prendel wrote:
> > Ok, so there is only one remaining task :) Please update the documentation under
> > Documentation/hwmon/tmp421. Then you will get my Acked-by.
>
> Documentation is updated in this patch along with the source file.
>
> There is a small cosmetic change in this patch. I changed the name of the
> sysfs entry and internal variable name from nfactor to n_adjust. This was
> done to make sure the users know we are modifying the N[adjust] parameter
> in the nfactor corrections register and not the actual nfactor itself. I
> also changed the reference to the register from NFACTOR to N_CORRECT since
> the datasheet uses that name for the register in question.
>
> I think the method of using the nfactor adjustment value is specific to this
> chipset. Consequently, it's not appropriate to go into the general documentation.
>
You made a careless mistake, see below. Please fix this and resend the patch
again. Then I added my Acked-by and I think Jean will schedule the patch for
2.6.35 (after another review of course :))
>
>
>
> >From 61f1c203620b06463695b399bae27a884008f169 Mon Sep 17 00:00:00 2001
> From: Jeff Angielski <jeff@theptrgroup.com>
> Date: Mon, 10 May 2010 10:26:34 -0400
> Subject: [PATCH] hwmon: (tmp421) Add nfactor support
>
> Add support for reading and writing the n-factor correction
> registers. This is needed to compensate for the characteristics
> of a particular sensor hanging off of the remote channels.
>
> Signed-off-by: Jeff Angielski <jeff@theptrgroup.com>
> ---
> Documentation/hwmon/tmp421 | 19 +++++++++++++++++++
> drivers/hwmon/tmp421.c | 41 +++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 60 insertions(+), 0 deletions(-)
>
> diff --git a/Documentation/hwmon/tmp421 b/Documentation/hwmon/tmp421
> index 0cf07f8..668228a 100644
> --- a/Documentation/hwmon/tmp421
> +++ b/Documentation/hwmon/tmp421
> @@ -17,6 +17,7 @@ Supported chips:
>
> Authors:
> Andre Prendel <andre.prendel@gmx.de>
> + Jeff Angielski <jeff@theptrgroup.com>
>
> Description
> -----------
> @@ -34,3 +35,21 @@ the temperature values via the following sysfs files:
>
> temp[1-4]_input
> temp[2-4]_fault
> +
> +The chips allow the user to adjust the n-factor value that is used
> +when converting the remote channel measurements to temperature. The
> +adjustment has a range of -128 to +127 that yields an effective
> +n-factor range of 0.706542 to 1.747977. The power on reset value
> +for the adjustment is 0 which results in an n-factor of 1.008.
> +
> +The effective n-factor is calculated according to the following
> +equation:
> +
> +n_factor = (1.008 * 300) / (300 - nfactor_adjust)
> +
> +The driver exports the n-factor adjustment value via the following
> +sysfs files:
> +
> +temp[2-4]_n_adjust
> +
> +
> diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c
> index 738c472..83edbc8 100644
> --- a/drivers/hwmon/tmp421.c
> +++ b/drivers/hwmon/tmp421.c
> @@ -49,6 +49,7 @@ enum chips { tmp421, tmp422, tmp423 };
>
> static const u8 TMP421_TEMP_MSB[4] = { 0x00, 0x01, 0x02, 0x03 };
> static const u8 TMP421_TEMP_LSB[4] = { 0x10, 0x11, 0x12, 0x13 };
> +static const u8 TMP421_N_CORRECT[3] = { 0x21, 0x22, 0x23 };
>
> /* Flags */
> #define TMP421_CONFIG_SHUTDOWN 0x40
> @@ -76,6 +77,7 @@ struct tmp421_data {
> int channels;
> u8 config;
> s16 temp[4];
> + s8 n_adjust[3];
> };
>
> static int temp_from_s16(s16 reg)
> @@ -115,6 +117,10 @@ static struct tmp421_data *tmp421_update_device(struct device *dev)
> data->temp[i] |= i2c_smbus_read_byte_data(client,
> TMP421_TEMP_LSB[i]);
> }
> + for (i = 1; i < data->channels; i++) {
> + data->n_adjust[i - 1] = i2c_smbus_read_byte_data(client,
> + TMP421_N_CORRECT[i - 1]);
> + }
> data->last_updated = jiffies;
> data->valid = 1;
> }
> @@ -157,6 +163,32 @@ static ssize_t show_fault(struct device *dev,
> return sprintf(buf, "0\n");
> }
>
> +static ssize_t show_n_adjust(struct device *dev,
> + struct device_attribute *devattr, char *buf)
> +{
> + int index = to_sensor_dev_attr(devattr)->index;
> + struct tmp421_data *data = tmp421_update_device(dev);
> +
> + return sprintf(buf, "%d\n", data->n_adjust[index - 1]);
> +}
> +
> +static ssize_t set_n_adjust(struct device *dev,
> + struct device_attribute *devattr,
> + const char *buf, size_t count)
> +{
> + struct i2c_client *client = to_i2c_client(dev);
> + struct tmp421_data *data = i2c_get_clientdata(client);
> + int index = to_sensor_dev_attr(devattr)->index;
> + int n_adjust= simple_strtol(buf, NULL, 10);
Missing space in front of '='.
> +
> + mutex_lock(&data->update_lock);
> + i2c_smbus_write_byte_data(client, TMP421_N_CORRECT[index - 1],
> + SENSORS_LIMIT(n_adjust, -128, 127));
> + mutex_unlock(&data->update_lock);
> +
> + return count;
> +}
> +
> static mode_t tmp421_is_visible(struct kobject *kobj, struct attribute *a,
> int n)
> {
> @@ -177,19 +209,28 @@ static mode_t tmp421_is_visible(struct kobject *kobj, struct attribute *a,
> static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_value, NULL, 0);
> static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_value, NULL, 1);
> static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_fault, NULL, 1);
> +static SENSOR_DEVICE_ATTR(temp2_n_adjust, S_IRUSR | S_IWUSR | S_IRGRP,
> + show_n_adjust, set_n_adjust, 1);
> static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_value, NULL, 2);
> static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_fault, NULL, 2);
> +static SENSOR_DEVICE_ATTR(temp3_n_adjust, S_IRUSR | S_IWUSR | S_IRGRP,
> + show_n_adjust, set_n_adjust, 2);
> static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_value, NULL, 3);
> static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_fault, NULL, 3);
> +static SENSOR_DEVICE_ATTR(temp4_n_adjust, S_IRUSR | S_IWUSR | S_IRGRP,
> + show_n_adjust, set_n_adjust, 3);
>
> static struct attribute *tmp421_attr[] = {
> &sensor_dev_attr_temp1_input.dev_attr.attr,
> &sensor_dev_attr_temp2_input.dev_attr.attr,
> &sensor_dev_attr_temp2_fault.dev_attr.attr,
> + &sensor_dev_attr_temp2_n_adjust.dev_attr.attr,
> &sensor_dev_attr_temp3_input.dev_attr.attr,
> &sensor_dev_attr_temp3_fault.dev_attr.attr,
> + &sensor_dev_attr_temp3_n_adjust.dev_attr.attr,
> &sensor_dev_attr_temp4_input.dev_attr.attr,
> &sensor_dev_attr_temp4_fault.dev_attr.attr,
> + &sensor_dev_attr_temp4_n_adjust.dev_attr.attr,
> NULL
> };
>
Thanks,
Andre
^ permalink raw reply
* Re: Problem of PowerPc 82xx when using smc
From: Scott Wood @ 2010-05-20 17:06 UTC (permalink / raw)
To: hellohello; +Cc: linuxppc-dev
In-Reply-To: <042201caf7fa$9d038a20$a51cbcc0@sfdomain.com>
On Thu, May 20, 2010 at 04:58:27PM +0800, hellohello wrote:
>
> I find a problem in
> drivers/serial/cpm_uart/cpm_uart_cpm2.c:
> int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
> {
> ... ...
> pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos;
> /*The above line should be :*/
> pinfo->tx_bd_base = pinfo->rx_bd_base + sizeof(cbd_t) * pinfo->rx_nrfifos;
No, it shouldn't -- rx_bd_base is of type "cbd_t *", so the multiplication
already happens as part of pointer arithmetic.
> return 0;
> }
>
> Where to get the newest code for kernel?
git.kernel.org
> How to know whether it is already patched by anyone else? Just search in this mail list?
As well as the current git tree.
-Scott
^ permalink raw reply
* Re: [PATCH] powerpc: make the padding for the device tree a configurable option
From: Scott Wood @ 2010-05-20 16:04 UTC (permalink / raw)
To: Timur Tabi, Benjamin Herrenschmidt, linuxppc-dev,
devicetree-discuss
In-Reply-To: <20100520011820.GT25892@yookeroo>
On 05/19/2010 08:18 PM, David Gibson wrote:
> On Wed, May 19, 2010 at 07:03:17PM -0500, Timur Tabi wrote:
>> On Wed, May 19, 2010 at 5:44 PM, Benjamin Herrenschmidt
>>> The padding in the kernel built is intended to
>>> make space for DT changes done by the zImage wrapper.
>>
>> Well, okay. I think it would be nice if we expanded that to handle
>> general usage.
Don't we have dynamic expansion in the zImage wrapper?
>>> Maybe we could add to libfdt a way to provide a realloc() callback to it
>>> when it hits the max size, and uboot can then move things around (or
>>> fail).
>>
>> The problem is that the code which allocates a block for the fdt is
>> completely distinct from the code that manipulates the fdt. We'd need
>> to put in either some kind of funky callback mechanism, or insist that
>> every fdt exist in a block of memory allocated by some specific method
>> (e.g. lmb).
>>
>> I'm stuck between a rock and a hard place, it seems. No one is
>> willing to compromise on any of my ideas. It's hard to convince our
>> BSP developers that they should be pushing more code upstream when I
>> get so much resistance for a such a mundane change.
>
> Couldn't you use the configurable padding, but put the stuff to do it
> into u-boot. i.e. repad the dtb at u-boot build time, rather than
> u-boot runtime.
Currently generating a dtb is not done as part of the u-boot build
process -- and apparently some people are using the Linux makefile
target to do it.
I think the right thing is to do whatever we need to do in u-boot to get
dynamic expansion fully working (it already does it in some
circumstances, just not always, or necessarily safely). Static padding
is too fragile.
-Scott
^ permalink raw reply
* MBX drivers ads5121-rev4-v20090603
From: CTAG / Moisés Domínguez @ 2010-05-20 14:48 UTC (permalink / raw)
To: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 1263 bytes --]
Hi all,
I am trying to use MBX 3D engine driver of my ads5121. AFAIK, drivers were
built against same kernel as mine but I get problems for testing the demos
and for loading the service:
[root@freescale /]# etc/init.d/rc.pvr start
[ 29.526994] dbgdrv: module license 'unspecified' taints kernel.
[ 29.721065] _IORemapWrapper: mapping 1048576 bytes uncached from
0x80000000 to 0xe5280000
I read in previous threads of this list about similar problems:
- MBX on kernel 2.6.31:
ttp://old.nabble.com/MPC5121ADS-PowerVR-MBX-driver-on-2.6.31-kernel--td26613
966.html
- MBX on kernel 2.6.24:
http://lists.ozlabs.org/pipermail/linuxppc-dev/2009-February/067967.html
According those posts, I would need to recompile modules against my kernel,
but, of course, I do not have the sources. Reading ltib doc I read:
Proprietary Packages:
mbx_build13_binaries: This package provides proprietary binary kernel
modules, libraries,
and test code built from the MBX OpenGL ES DDK.
Have anybody tested MBX demos provided with freescale SDK with ltib
v20090603 without having to recompile provided .kos?
Regards,
Moises
Board ads5121
Ltib version 20090603
Linux kernel version 2.6.24.6
[-- Attachment #2: Type: text/html, Size: 5459 bytes --]
^ permalink raw reply
* Re: [PATCH RT] ehea: make receive irq handler non-threaded (IRQF_NODELAY)
From: Will Schmidt @ 2010-05-20 14:53 UTC (permalink / raw)
To: Jan-Bernd Themann
Cc: Darren Hart, dvhltc, linux-kernel, Brian King, niv,
Thomas Gleixner, Doug Maxey, linuxppc-dev
In-Reply-To: <OFCBBE5EB9.FD616EDA-ONC1257729.0030B539-C1257729.0031FB06@de.ibm.com>
On Thu, 2010-05-20 at 11:05 +0200, Jan-Bernd Themann wrote:
> Hi Thomas
>
> > Re: [PATCH RT] ehea: make receive irq handler non-threaded (IRQF_NODELAY)
> >
> > On Thu, 20 May 2010, Jan-Bernd Themann wrote:
> > > > > Thought more about that. The case at hand (ehea) is nasty:
> > > > >
> > > > > The driver does _NOT_ disable the rx interrupt in the card in the
> rx
> > > > > interrupt handler - for whatever reason.
> > > >
> > > > Yeah I saw that, but I don't know why it's written that way. Perhaps
> > > > Jan-Bernd or Doug will chime in and enlighten us? :)
> > >
> > > From our perspective there is no need to disable interrupts for the
> > > RX side as the chip does not fire further interrupts until we tell
> > > the chip to do so for a particular queue. We have multiple receive
> >
> > The traces tell a different story though:
> >
> > ehea_recv_irq_handler()
> > napi_reschedule()
> > eoi()
> > ehea_poll()
> > ...
> > ehea_recv_irq_handler() <---------------- ???
> > napi_reschedule()
> > ...
> > napi_complete()
> >
> > Can't tell whether you can see the same behaviour in mainline, but I
> > don't see a reason why not.
>
> Is this the same interrupt we are seeing here, or do we see a second other
> interrupt popping up on the same CPU? As I said, with multiple receive
> queues
> (if enabled) you can have multiple interrupts in parallel.
Same interrupt number (260). Per the trace data, the first
ehea_recv_irq_handler (at 117.904525) was on cpu 0, the second (at
117.904689) was on cpu 1.
<...>-2180 [000] 117.904525: .ehea_recv_irq_handler: ENTER 0 c0000000e8bd08b0
<...>-2180 [000] 117.904527: .ehea_recv_irq_handler: napi_reschedule COMpleted c0000000e8bd08b0
<...>-2180 [000] 117.904528: .ehea_recv_irq_handler: EXIT reschedule(1) 1 c0000000e8bd08b0
<...>-2180 [000] 117.904529: .xics_unmask_irq: xics: unmask virq 260 772
<...>-2180 [000] 117.904547: .xics_unmask_irq: xics: unmask virq pre-xive 260 772 0 status:0 ff
<...>-2180 [000] 117.904586: .xics_unmask_irq: xics: unmask virq post-xive 260 772 0 D:11416 status:0 5
<...>-2180 [000] 117.904602: .handle_fasteoi_irq: 260 8004000
<...>-2180 [000] 117.904603: .xics_mask_irq: xics: mask virq 260 772
<...>-2180 [000] 117.904634: .xics_mask_real_irq: xics: before: mask_real 772 status:0 5
<...>-2180 [000] 117.904668: .xics_mask_real_irq: xics: after: mask_real 772 status:0 ff
<...>-2180 [000] 117.904669: .handle_fasteoi_irq: pre-action: 260 8004100
<...>-2180 [000] 117.904671: .handle_fasteoi_irq: post-action: 260 8004100
<...>-2180 [000] 117.904672: .handle_fasteoi_irq: exit. 260 8004000
<...>-7 [000] 117.904681: .ehea_poll: ENTER 1 c0000000e8bd08b0 poll_counter:0 force:0
<...>-7 [000] 117.904683: .ehea_proc_rwqes: ehea_check_cqe 0
<...>-2180 [001] 117.904689: .ehea_recv_irq_handler: ENTER 1 c0000000e8bd08b0
<...>-7 [000] 117.904690: .ehea_proc_rwqes: ehea_check_cqe 0
<...>-2180 [001] 117.904691: .ehea_recv_irq_handler: napi_reschedule inCOMplete c0000000e8bd08b0
<...>-2180 [001] 117.904692: .ehea_recv_irq_handler: EXIT reschedule(0) 1 c0000000e8bd08b0
<...>-2180 [001] 117.904694: .xics_unmask_irq: xics: unmask virq 260 772
<...>-7 [000] 117.904702: .ehea_refill_rq2: ehea_refill_rq2
<...>-7 [000] 117.904703: .ehea_refill_rq_def: ehea_refill_rq_def
<...>-7 [000] 117.904704: .ehea_refill_rq3: ehea_refill_rq3
<...>-7 [000] 117.904705: .ehea_refill_rq_def: ehea_refill_rq_def
<...>-7 [000] 117.904706: .napi_complete: napi_complete: ENTER state: 1 c0000000e8bd08b0
<...>-7 [000] 117.904707: .napi_complete: napi_complete: EXIT state: 0 c0000000e8bd08b0
<...>-7 [000] 117.904710: .ehea_poll: EXIT !cqe rx(2). 0 c0000000e8bd08b0
<...>-2180 [001] 117.904719: .xics_unmask_irq: xics: unmask virq pre-xive 260 772 0 status:0 ff
<...>-2180 [001] 117.904761: .xics_unmask_irq: xics: unmask virq post-xive 260 772 0 D:12705 status:0 5
> Pleaes check if multiple queues are enabled. The following module parameter
> is used for that:
>
> MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 0
> ");
No module parameters were used, should be plain old defaults.
>
> you should also see the number of used HEA interrupts in /proc/interrupts
>
256: 1 0 0 0 0 0 0 0 XICS Level ehea_neq
259: 0 0 0 0 0 0 0 0 XICS Level eth0-aff
260: 361965 0 0 0 0 0 0 0 XICS Level eth0-queue0
>
> >
> > > queues with an own interrupt each so that the interrupts can arrive
> > > on multiple CPUs in parallel. Interrupts are enabled again when we
> > > leave the NAPI Poll function for the corresponding receive queue.
> >
> > I can't see a piece of code which does that, but that's probably just
> > lack of detailed hardware knowledge on my side.
>
> If you mean the "re-enable" piece of code, it is not very obvious, you are
> right.
> Interrupts are only generated if a particular register for our completion
> queues
> is written. We do this in the following line:
>
> ehea_reset_cq_ep(pr->recv_cq);
> ehea_reset_cq_ep(pr->send_cq);
> ehea_reset_cq_n1(pr->recv_cq);
> ehea_reset_cq_n1(pr->send_cq);
>
> So this is in a way an indirect way to ask for interrupts when new
> completions were
> written to memory. We don't really disable/enable interrupts on the HEA
> chip itself.
>
> I think there are some mechanisms build in the HEA chip that should prevent
> that
> interrupts don't get lost. But that is something that is / was completely
> hidden from
> us, so my skill is very limited there.
>
> If more details are needed here we should involve the PHYP guys + eHEA HW
> guys if not
> already done. Did anyone already talk to them?
>
> Regards,
> Jan-Bernd
>
^ permalink raw reply
* Re: [PATCH RT] ehea: make receive irq handler non-threaded (IRQF_NODELAY)
From: Thomas Gleixner @ 2010-05-20 14:45 UTC (permalink / raw)
To: Darren Hart
Cc: Jan-Bernd Themann, dvhltc, linux-kernel, Will Schmidt, Brian King,
niv, Doug Maxey, linuxppc-dev
In-Reply-To: <4BF5499F.8050203@us.ibm.com>
On Thu, 20 May 2010, Darren Hart wrote:
> On 05/20/2010 01:14 AM, Thomas Gleixner wrote:
> > On Thu, 20 May 2010, Jan-Bernd Themann wrote:
> > > > > Thought more about that. The case at hand (ehea) is nasty:
> > > > >
> > > > > The driver does _NOT_ disable the rx interrupt in the card in the rx
> > > > > interrupt handler - for whatever reason.
> > > >
> > > > Yeah I saw that, but I don't know why it's written that way. Perhaps
> > > > Jan-Bernd or Doug will chime in and enlighten us? :)
> > >
> > > From our perspective there is no need to disable interrupts for the
> > > RX side as the chip does not fire further interrupts until we tell
> > > the chip to do so for a particular queue. We have multiple receive
> >
> > The traces tell a different story though:
> >
> > ehea_recv_irq_handler()
> > napi_reschedule()
> > eoi()
> > ehea_poll()
> > ...
> > ehea_recv_irq_handler()<---------------- ???
> > napi_reschedule()
> > ...
> > napi_complete()
> >
> > Can't tell whether you can see the same behaviour in mainline, but I
> > don't see a reason why not.
>
> I was going to suggest that because these are threaded handlers, perhaps they
> are rescheduled on a different CPU and then receive the interrupt for the
> other CPU/queue that Jan was mentioning.
>
> But, the handlers are affined if I remember correctly, and we aren't running
> with multiple receive queues. So, we're back to the same question, why are we
> seeing another irq. It comes in before napi_complete() and therefor before the
> ehea_reset*() block of calls which do the equivalent of re-enabling
> interrupts.
Can you slap a few trace points into that driver with a stock mainline
kernel and verify that ?
Thanks,
tglx
^ permalink raw reply
* Re: [PATCH RT] ehea: make receive irq handler non-threaded (IRQF_NODELAY)
From: Darren Hart @ 2010-05-20 14:39 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Jan-Bernd Themann, dvhltc, linux-kernel, Will Schmidt, Brian King,
niv, Doug Maxey, linuxppc-dev
In-Reply-To: <alpine.LFD.2.00.1005200950410.3368@localhost.localdomain>
On 05/20/2010 01:14 AM, Thomas Gleixner wrote:
> On Thu, 20 May 2010, Jan-Bernd Themann wrote:
>>>> Thought more about that. The case at hand (ehea) is nasty:
>>>>
>>>> The driver does _NOT_ disable the rx interrupt in the card in the rx
>>>> interrupt handler - for whatever reason.
>>>
>>> Yeah I saw that, but I don't know why it's written that way. Perhaps
>>> Jan-Bernd or Doug will chime in and enlighten us? :)
>>
>> From our perspective there is no need to disable interrupts for the
>> RX side as the chip does not fire further interrupts until we tell
>> the chip to do so for a particular queue. We have multiple receive
>
> The traces tell a different story though:
>
> ehea_recv_irq_handler()
> napi_reschedule()
> eoi()
> ehea_poll()
> ...
> ehea_recv_irq_handler()<---------------- ???
> napi_reschedule()
> ...
> napi_complete()
>
> Can't tell whether you can see the same behaviour in mainline, but I
> don't see a reason why not.
I was going to suggest that because these are threaded handlers, perhaps
they are rescheduled on a different CPU and then receive the interrupt
for the other CPU/queue that Jan was mentioning.
But, the handlers are affined if I remember correctly, and we aren't
running with multiple receive queues. So, we're back to the same
question, why are we seeing another irq. It comes in before
napi_complete() and therefor before the ehea_reset*() block of calls
which do the equivalent of re-enabling interrupts.
--
Darren
>
>> queues with an own interrupt each so that the interrupts can arrive
>> on multiple CPUs in parallel. Interrupts are enabled again when we
>> leave the NAPI Poll function for the corresponding receive queue.
>
> I can't see a piece of code which does that, but that's probably just
> lack of detailed hardware knowledge on my side.
>
> Thanks,
>
> tglx
--
Darren Hart
IBM Linux Technology Center
Real-Time Linux Team
^ permalink raw reply
* Re: [PATCH RT] ehea: make receive irq handler non-threaded (IRQF_NODELAY)
From: Nivedita Singhvi @ 2010-05-20 14:26 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Darren Hart, Jan-Bernd Themann, dvhltc, linux-kernel,
Will Schmidt, Brian King, niv, Doug Maxey, linuxppc-dev
In-Reply-To: <alpine.LFD.2.00.1005201112000.3368@localhost.localdomain>
Thomas Gleixner wrote:
>> Pleaes check if multiple queues are enabled. The following module parameter
>> is used for that:
>>
>> MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 0
>> ");
>>
>> you should also see the number of used HEA interrupts in /proc/interrupts
>
> I leave that for Will and Darren, they have the hardware :)
16: 477477 ... XICS Level IPI
17: 129 ... XICS Level hvc_console
18: 0 ... XICS Level RAS_EPOW
33: 139232 ... XICS Level mlx4_core
256: 3 ... XICS Level ehea_neq
259: 0 ... XICS Level eth0-aff
260: 2082153 ... XICS Level eth0-queue0
289: 119166 ... XICS Level ipr
305: 0 ... XICS Level ohci_hcd:usb2
306: 0 ... XICS Level ohci_hcd:usb3
307: 2389839 ... XICS Level ehci_hcd:usb1
Nope, multiple rx queues not enabled.
thanks,
Nivedita
^ permalink raw reply
* Re: [PATCH] device-tree: Drop properties with "/" in their name
From: Michael Ellerman @ 2010-05-20 13:51 UTC (permalink / raw)
To: linuxppc-dev; +Cc: lists, microblaze-uclinux, monstr
In-Reply-To: <0958c243b32f5f77028a794a9ce0d55f9a12121e.1274272289.git.michael@ellerman.id.au>
[-- Attachment #1: Type: text/plain, Size: 709 bytes --]
On Wed, 2010-05-19 at 22:32 +1000, Michael Ellerman wrote:
> Some bogus firmwares include properties with "/" in their name. This
> causes problems when creating the /proc/device-tree file system,
> because the slash is taken to indicate a directory.
>
> We don't care about those properties, and we don't want to encourage
> them, so just throw them away when creating /proc/device-tree.
>
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
> ---
>
> Hi Christian, if you could test this new patch that'd be great, thanks!
And thanks to Christian for testing it:
https://bugzilla.kernel.org/show_bug.cgi?id=15589
Tested-by: Christian Kujau <lists@nerdbynature.de>
cheers
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* Re: [Patch 2/2] PPC64-HWBKPT: Implement hw-breakpoints for PPC64
From: Paul Mackerras @ 2010-05-20 13:10 UTC (permalink / raw)
To: K.Prasad
Cc: Michael Neuling, Benjamin Herrenschmidt, shaggy,
Frederic Weisbecker, David Gibson, linuxppc-dev@ozlabs.org,
Alan Stern, Roland McGrath
In-Reply-To: <20100520040603.GA7448@in.ibm.com>
On Thu, May 20, 2010 at 09:36:03AM +0530, K.Prasad wrote:
> > Right. However, the thread is running the signal handler without the
> > DABR being set, which is unfortunate.
> >
>
> In order to keep the breakpoint active during signal handling, a
> PowerPC specific signal handling code, say do_signal_pending() in
> arch/powerpc/kernel/signal.c, must be tapped to check for/restore
> the breakpoint for the process (if it exists).
What I would suggest is something slightly different: anything that
causes the thread to change where it's executing -- signal delivery,
modification of NIP with ptrace -- should cancel the single-step and
reinstall the breakpoint in the DABR. In other words we just forget
that we hit the breakpoint, and rely on hitting it again if we ever
get back to that instruction. I think that is by far the most
reliable approach.
That means that the hw-breakpoint code needs to export a function
called, say, thread_change_pc(), which is called whenever we're
changing a thread's userspace PC (NIP) value. If the hw-breakpoint
code has put that thread into single-step mode, we cancel the
single-step and if the thread is current, set DABR.
> I'm afraid if this is more complexity than we want to handle in the
> first patchset. I agree that this will create a 'blind-spot' of code
> which cannot not be monitored using breakpoints and may limit debugging
> efforts (specially for memory corruption); however suspecting that signal
> handlers (especially those that don't return to original instruction)
> would be rare, I feel that this could be a 'feature' that can be brought
> later-in. What do you think?
I think the thread_change_pc() approach is quite a bit simpler, and I
think it's better to get this right at the outset rather than have it
cause bugs later on, when we've all forgotten all the curly
details. :)
> > Imagine this scenario: we get the DABR match, set MSR_SE and return to
> > the task. In the meantime another higher-priority task has become
> > runnable and our need_resched flag is set, so we call schedule() on
> > the way back out to usermode. The other task runs and then blocks and
> > our task gets scheduled again. As part of the context switch,
> > arch_install_hw_breakpoint() will get called and will set DABR. So
> > we'll return to usermode with both DABR and MSE_SE set.
> >
>
> I didn't foresee such a possibility. I think this can be handled by
> putting a check in arch_install_hw_breakpoint() as shown below:
>
> int arch_install_hw_breakpoint(struct perf_event *bp)
> {
> struct arch_hw_breakpoint *info = counter_arch_bp(bp);
> struct perf_event **slot = &__get_cpu_var(bp_per_reg);
>
> *slot = bp;
> if (!current->thread.last_hit_ubp)
> set_dabr(info->address | info->type | DABR_TRANSLATION);
> return 0;
> }
Yes, basically, but don't we need to handle per-cpu breakpoints as
well? That is, we only want the extra check if this breakpoint is a
per-task breakpoint. Or am I not seeing enough context here?
Also, I have just posted extensions to emulate_single_step() to handle
loads and stores. I think this should be enough to handle DABR
interrupts that occur in kernel mode, so we should never need to
actually single-step in that case -- if emulate_step fails we should
just print a warning, uninstall the breakpoint, and continue. That
way we don't have to worry about all the interrupts and other
eventualities that could occur while single-stepping in the kernel.
For DABR interrupts that occur in user mode, I think the approach of
single-stepping together with calls to thread_change_pc() in the
signal delivery and ptrace code should handle all the cases, at least
for per-task breakpoints. Per-cpu breakpoints that get hit in user
mode will be a bit trickier, but I assume we can restrict per-cpu
breakpoints to kernel addresses for now. If you want help adding the
thread_change_pc() calls to signal delivery and ptrace, let me know.
Paul.
^ permalink raw reply
* [RFC PATCH] powerpc: Emulate most load and store instructions in emulate_step()
From: Paul Mackerras @ 2010-05-20 12:49 UTC (permalink / raw)
To: linuxppc-dev; +Cc: K.Prasad
This extends the emulate_step() function to handle most of the load
and store instructions implemented on current 64-bit server processors.
The aim is to handle all the load and store instructions used in the
kernel, so this handles the Altivec/VMX lvx and stvx and the VSX
lxv2dx and stxv2dx instructions (implemented in POWER7).
The new code can emulate user mode instructions, and checks the
effective address for a load or store if the saved state is for
user mode. It doesn't handle little-endian mode at present.
For floating-point, Altivec/VMX and VSX instructions, it checks
that the saved MSR has the enable bit for the relevant facility
set, and if so, assumes that the FP/VMX/VSX registers contain
valid state, and does loads or stores directly to/from the
FP/VMX/VSX registers, using assembly helpers in ldstfp.S.
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
arch/powerpc/lib/Makefile | 4 +-
arch/powerpc/lib/ldstfp.S | 207 +++++++++++++
arch/powerpc/lib/sstep.c | 753 +++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 937 insertions(+), 27 deletions(-)
create mode 100644 arch/powerpc/lib/ldstfp.S
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 3040dac..7581dbf 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -18,8 +18,8 @@ obj-$(CONFIG_HAS_IOMEM) += devres.o
obj-$(CONFIG_PPC64) += copypage_64.o copyuser_64.o \
memcpy_64.o usercopy_64.o mem_64.o string.o
-obj-$(CONFIG_XMON) += sstep.o
-obj-$(CONFIG_KPROBES) += sstep.o
+obj-$(CONFIG_XMON) += sstep.o ldstfp.o
+obj-$(CONFIG_KPROBES) += sstep.o ldstfp.o
ifeq ($(CONFIG_PPC64),y)
obj-$(CONFIG_SMP) += locks.o
diff --git a/arch/powerpc/lib/ldstfp.S b/arch/powerpc/lib/ldstfp.S
new file mode 100644
index 0000000..a462767
--- /dev/null
+++ b/arch/powerpc/lib/ldstfp.S
@@ -0,0 +1,207 @@
+/*
+ * Floating-point, VMX/Altivec and VSX loads and stores
+ * for use in instruction emulation.
+ *
+ * Copyright 2010 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/processor.h>
+#include <asm/ppc_asm.h>
+#include <asm/reg.h>
+#include <asm/asm-offsets.h>
+#include <linux/errno.h>
+
+ .macro inst32 op
+ reg = 0
+ .rept 32
+20: \op reg,0,r4
+ b 3f
+ .section __ex_table,"a"
+ PPC_LONG 20b,99f
+ .previous
+ reg = reg + 1
+ .endr
+ .endm
+
+/* Load FP reg N from float at *p. N is in r3, p in r4. */
+_GLOBAL(do_lfs)
+ mflr r0
+ mfmsr r6
+ ori r7,r6,MSR_FP
+ rlwinm r3,r3,3,0xf8
+ bcl 20,31,2f
+1: inst32 lfsx
+2: mflr r5
+ mtlr r0
+ add r8,r3,r5
+ mtctr r8
+ li r3,0
+ mtmsrd r7
+ isync
+ bctr
+99: li r3,-EFAULT
+3: mtmsrd r6
+ blr
+
+/* Load FP reg N from double at *p. N is in r3, p in r4. */
+_GLOBAL(do_lfd)
+ mflr r0
+ mfmsr r6
+ ori r7,r6,MSR_FP
+ rlwinm r3,r3,3,0xf8
+ bcl 20,31,2f
+1: inst32 lfdx
+2: mflr r5
+ mtlr r0
+ add r8,r3,r5
+ mtctr r8
+ li r3,0
+ mtmsrd r7
+ isync
+ bctr
+99: li r3,-EFAULT
+3: mtmsrd r6
+ blr
+
+
+/* Store FP reg N to float at *p. N is in r3, p in r4. */
+_GLOBAL(do_stfs)
+ mflr r0
+ mfmsr r6
+ ori r7,r6,MSR_FP
+ rlwinm r3,r3,3,0xf8
+ bcl 20,31,2f
+1: inst32 stfsx
+2: mflr r5
+ mtlr r0
+ add r8,r3,r5
+ mtctr r8
+ li r3,0
+ mtmsrd r7
+ isync
+ bctr
+99: li r3,-EFAULT
+3: mtmsrd r6
+ blr
+
+/* Store FP reg N to double at *p. N is in r3, p in r4. */
+_GLOBAL(do_stfd)
+ mflr r0
+ mfmsr r6
+ ori r7,r6,MSR_FP
+ rlwinm r3,r3,3,0xf8
+ bcl 20,31,2f
+1: inst32 stfdx
+2: mflr r5
+ mtlr r0
+ add r8,r3,r5
+ mtctr r8
+ li r3,0
+ mtmsrd r7
+ isync
+ bctr
+99: li r3,-EFAULT
+3: mtmsrd r6
+ blr
+
+#ifdef CONFIG_ALTIVEC
+/* Load vector reg N from *p. N is in r3, p in r4. */
+_GLOBAL(do_lvx)
+ mflr r0
+ mfmsr r6
+ oris r7,r6,MSR_VEC@h
+ rlwinm r3,r3,3,0xf8
+ bcl 20,31,2f
+1: inst32 lvx
+2: mflr r5
+ mtlr r0
+ add r8,r3,r5
+ mtctr r8
+ li r3,0
+ mtmsrd r7
+ isync
+ bctr
+3: mtmsrd r6
+ blr
+
+/* Store vector reg N to *p. N is in r3, p in r4. */
+_GLOBAL(do_stvx)
+ mflr r0
+ mfmsr r6
+ oris r7,r6,MSR_VEC@h
+ rlwinm r3,r3,3,0xf8
+ bcl 20,31,2f
+1: inst32 stvx
+2: mflr r5
+ mtlr r0
+ add r8,r3,r5
+ mtctr r8
+ li r3,0
+ mtmsrd r7
+ isync
+ bctr
+99: li r3,-EFAULT
+3: mtmsrd r6
+ blr
+#endif /* CONFIG_ALTIVEC */
+
+#ifdef CONFIG_VSX
+
+ .macro inst64 opcode
+ reg = 0
+ .rept 64
+20: .long \opcode + ((reg & 0x1f) << 21) + ((reg >> 5) & 1) + (4 << 11)
+ b 3f
+ .section __ex_table,"a"
+ PPC_LONG 20b,99f
+ .previous
+ reg = reg + 1
+ .endr
+ .endm
+
+/* Load VSX reg N from vector doubleword *p. N is in r3, p in r4. */
+_GLOBAL(do_lxvd2x)
+ mflr r0
+ mfmsr r6
+ oris r7,r6,MSR_VSX@h
+ rlwinm r3,r3,3,0xf8
+ bcl 20,31,2f
+1: inst64 PPC_INST_LXVD2X
+2: mflr r5
+ mtlr r0
+ add r8,r3,r5
+ mtctr r8
+ li r3,0
+ mtmsrd r7
+ isync
+ bctr
+99: li r3,-EFAULT
+3: mtmsrd r6
+ blr
+
+/* Store VSX reg N to vector doubleword *p. N is in r3, p in r4. */
+_GLOBAL(do_stxvd2x)
+ mflr r0
+ mfmsr r6
+ oris r7,r6,MSR_VSX@h
+ rlwinm r3,r3,3,0xf8
+ bcl 20,31,2f
+1: inst64 PPC_INST_STXVD2X
+2: mflr r5
+ mtlr r0
+ add r8,r3,r5
+ mtctr r8
+ li r3,0
+ mtmsrd r7
+ isync
+ bctr
+99: li r3,-EFAULT
+3: mtmsrd r6
+ blr
+
+#endif /* CONFIG_VSX */
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 13b7d54..6313313 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -13,6 +13,8 @@
#include <linux/ptrace.h>
#include <asm/sstep.h>
#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/cputable.h>
extern char system_call_common[];
@@ -24,6 +26,18 @@ extern char system_call_common[];
#endif
/*
+ * Functions in ldstfp.S
+ */
+extern int do_lfs(int rn, unsigned long ea);
+extern int do_lfd(int rn, unsigned long ea);
+extern int do_stfs(int rn, unsigned long ea);
+extern int do_stfd(int rn, unsigned long ea);
+extern int do_lvx(int rn, unsigned long ea);
+extern int do_stvx(int rn, unsigned long ea);
+extern int do_lxvd2x(int rn, unsigned long ea);
+extern int do_stxvd2x(int rn, unsigned long ea);
+
+/*
* Determine whether a conditional branch instruction would branch.
*/
static int __kprobes branch_taken(unsigned int instr, struct pt_regs *regs)
@@ -47,15 +61,356 @@ static int __kprobes branch_taken(unsigned int instr, struct pt_regs *regs)
}
/*
- * Emulate instructions that cause a transfer of control.
+ * Calculate effective address for a D-form instruction
+ */
+static inline unsigned long dform_ea(unsigned int instr, struct pt_regs *regs)
+{
+ int ra;
+ unsigned long ea;
+
+ ra = (instr >> 16) & 0x1f;
+ ea = (signed short) instr; /* sign-extend */
+ if (ra) {
+ ea += regs->gpr[ra];
+ if (instr & 0x04000000) /* update forms */
+ regs->gpr[ra] = ea;
+ }
+#ifdef __powerpc64__
+ if (!(regs->msr & MSR_SF))
+ ea &= 0xffffffffUL;
+#endif
+ return ea;
+}
+
+/*
+ * Calculate effective address for a DS-form instruction
+ */
+static inline unsigned long dsform_ea(unsigned int instr, struct pt_regs *regs)
+{
+ int ra;
+ unsigned long ea;
+
+ ra = (instr >> 16) & 0x1f;
+ ea = (signed short) (instr & ~3); /* sign-extend */
+ if (ra) {
+ ea += regs->gpr[ra];
+ if ((instr & 3) == 1) /* update forms */
+ regs->gpr[ra] = ea;
+ }
+#ifdef __powerpc64__
+ if (!(regs->msr & MSR_SF))
+ ea &= 0xffffffffUL;
+#endif
+ return ea;
+}
+
+/*
+ * Calculate effective address for an X-form instruction
+ */
+static inline unsigned long xform_ea(unsigned int instr, struct pt_regs *regs)
+{
+ int ra, rb;
+ unsigned long ea;
+
+ ra = (instr >> 16) & 0x1f;
+ rb = (instr >> 11) & 0x1f;
+ ea = regs->gpr[rb];
+ if (ra) {
+ ea += regs->gpr[ra];
+ if (instr & 0x40) /* update forms */
+ regs->gpr[ra] = ea;
+ }
+#ifdef __powerpc64__
+ if (!(regs->msr & MSR_SF))
+ ea &= 0xffffffffUL;
+#endif
+ return ea;
+}
+
+/*
+ * Return the largest power of 2, not greater than sizeof(unsigned long),
+ * such that x is a multiple of it.
+ */
+static inline unsigned long max_align(unsigned long x)
+{
+ x |= sizeof(unsigned long);
+ return x & -x; /* isolates rightmost bit */
+}
+
+
+static inline unsigned long byterev_2(unsigned long x)
+{
+ return ((x >> 8) & 0xff) | ((x & 0xff) << 8);
+}
+
+static inline unsigned long byterev_4(unsigned long x)
+{
+ return ((x >> 24) & 0xff) | ((x >> 8) & 0xff00) |
+ ((x & 0xff00) << 8) | ((x & 0xff) << 24);
+}
+
+#ifdef __powerpc64__
+static inline unsigned long byterev_8(unsigned long x)
+{
+ return (byterev_4(x) << 32) | byterev_4(x >> 32);
+}
+#endif
+
+static inline int read_mem_aligned(unsigned long *dest, unsigned long ea,
+ int nb)
+{
+ int err = 0;
+ unsigned long x = 0;
+
+ switch (nb) {
+ case 1:
+ err = __get_user(x, (unsigned char __user *) ea);
+ break;
+ case 2:
+ err = __get_user(x, (unsigned short __user *) ea);
+ break;
+ case 4:
+ err = __get_user(x, (unsigned int __user *) ea);
+ break;
+#ifdef __powerpc64__
+ case 8:
+ err = __get_user(x, (unsigned long __user *) ea);
+ break;
+#endif
+ }
+ if (!err)
+ *dest = x;
+ return err;
+}
+
+static int __kprobes read_mem_unaligned(unsigned long *dest, unsigned long ea,
+ int nb, struct pt_regs *regs)
+{
+ int err;
+ unsigned long x, b, c;
+
+ /* unaligned, do this in pieces */
+ x = 0;
+ for (; nb > 0; nb -= c) {
+ c = max_align(ea);
+ if (c > nb)
+ c = max_align(nb);
+ err = read_mem_aligned(&b, ea, c);
+ if (err)
+ return err;
+ x = (x << (8 * c)) + b;
+ ea += c;
+ }
+ *dest = x;
+ return 0;
+}
+
+/*
+ * Read memory at address ea for nb bytes, return 0 for success
+ * or -EFAULT if an error occurred.
+ */
+static inline int read_mem(unsigned long *dest, unsigned long ea, int nb,
+ struct pt_regs *regs)
+{
+ if (user_mode(regs) && !access_ok(VERIFY_READ, ea, nb))
+ return -EFAULT;
+ if ((ea & (nb - 1)) == 0)
+ return read_mem_aligned(dest, ea, nb);
+ return read_mem_unaligned(dest, ea, nb, regs);
+}
+
+static inline int write_mem_aligned(unsigned long val, unsigned long ea,
+ int nb)
+{
+ int err = 0;
+
+ switch (nb) {
+ case 1:
+ err = __put_user(val, (unsigned char __user *) ea);
+ break;
+ case 2:
+ err = __put_user(val, (unsigned short __user *) ea);
+ break;
+ case 4:
+ err = __put_user(val, (unsigned int __user *) ea);
+ break;
+#ifdef __powerpc64__
+ case 8:
+ err = __put_user(val, (unsigned long __user *) ea);
+ break;
+#endif
+ }
+ return err;
+}
+
+static int __kprobes write_mem_unaligned(unsigned long val, unsigned long ea,
+ int nb, struct pt_regs *regs)
+{
+ int err;
+ unsigned long c;
+
+ /* unaligned or little-endian, do this in pieces */
+ for (; nb > 0; nb -= c) {
+ c = max_align(ea);
+ if (c > nb)
+ c = max_align(nb);
+ err = write_mem_aligned(val >> (nb - c) * 8, ea, c);
+ if (err)
+ return err;
+ ++ea;
+ }
+ return 0;
+}
+
+/*
+ * Write memory at address ea for nb bytes, return 0 for success
+ * or -EFAULT if an error occurred.
+ */
+static inline int write_mem(unsigned long val, unsigned long ea, int nb,
+ struct pt_regs *regs)
+{
+ if (user_mode(regs) && !access_ok(VERIFY_WRITE, ea, nb))
+ return -EFAULT;
+ if ((ea & (nb - 1)) == 0)
+ return write_mem_aligned(val, ea, nb);
+ return write_mem_unaligned(val, ea, nb, regs);
+}
+
+/*
+ * Check the address and alignment, and call func to do the actual
+ * load or store.
+ */
+static int __kprobes do_fp_load(int rn, int (*func)(int, unsigned long),
+ unsigned long ea, int nb,
+ struct pt_regs *regs)
+{
+ int err;
+ unsigned long val[sizeof(double) / sizeof(long)];
+ unsigned long ptr;
+
+ if (user_mode(regs) && !access_ok(VERIFY_READ, ea, nb))
+ return -EFAULT;
+ if ((ea & 3) == 0)
+ return (*func)(rn, ea);
+ ptr = (unsigned long) &val[0];
+ if (sizeof(unsigned long) == 8 || nb == 4) {
+ err = read_mem_unaligned(&val[0], ea, nb, regs);
+ ptr += sizeof(unsigned long) - nb;
+ } else {
+ /* reading a double on 32-bit */
+ err = read_mem_unaligned(&val[0], ea, 4, regs);
+ if (!err)
+ err = read_mem_unaligned(&val[1], ea + 4, 4, regs);
+ }
+ if (err)
+ return err;
+ return (*func)(rn, ptr);
+}
+
+static int __kprobes do_fp_store(int rn, int (*func)(int, unsigned long),
+ unsigned long ea, int nb,
+ struct pt_regs *regs)
+{
+ int err;
+ unsigned long val[sizeof(double) / sizeof(long)];
+ unsigned long ptr;
+
+ if (user_mode(regs) && !access_ok(VERIFY_WRITE, ea, nb))
+ return -EFAULT;
+ if ((ea & 3) == 0)
+ return (*func)(rn, ea);
+ ptr = (unsigned long) &val[0];
+ if (sizeof(unsigned long) == 8 || nb == 4) {
+ ptr += sizeof(unsigned long) - nb;
+ err = (*func)(rn, ptr);
+ if (err)
+ return err;
+ err = write_mem_unaligned(val[0], ea, nb, regs);
+ } else {
+ /* writing a double on 32-bit */
+ err = (*func)(rn, ptr);
+ if (err)
+ return err;
+ err = write_mem_unaligned(val[0], ea, 4, regs);
+ if (!err)
+ err = write_mem_unaligned(val[1], ea + 4, 4, regs);
+ }
+ return err;
+}
+
+#ifdef CONFIG_ALTIVEC
+/* For Altivec/VMX, no need to worry about alignment */
+static inline int do_vec_load(int rn, int (*func)(int, unsigned long),
+ unsigned long ea, struct pt_regs *regs)
+{
+ if (user_mode(regs) && !access_ok(VERIFY_READ, ea & ~0xfUL, 16))
+ return -EFAULT;
+ return (*func)(rn, ea);
+}
+
+static inline int do_vec_store(int rn, int (*func)(int, unsigned long),
+ unsigned long ea, struct pt_regs *regs)
+{
+ if (user_mode(regs) && !access_ok(VERIFY_WRITE, ea & ~0xfUL, 16))
+ return -EFAULT;
+ return (*func)(rn, ea);
+}
+#endif /* CONFIG_ALTIVEC */
+
+#ifdef CONFIG_VSX
+static int __kprobes do_vsx_load(int rn, int (*func)(int, unsigned long),
+ unsigned long ea, struct pt_regs *regs)
+{
+ int err;
+ unsigned long val[2];
+
+ if (user_mode(regs) && !access_ok(VERIFY_READ, ea, 16))
+ return -EFAULT;
+ if ((ea & 3) == 0)
+ return (*func)(rn, ea);
+ err = read_mem_unaligned(&val[0], ea, 8, regs);
+ if (!err)
+ err = read_mem_unaligned(&val[1], ea + 8, 8, regs);
+ if (!err)
+ err = (*func)(rn, (unsigned long) &val[0]);
+ return err;
+}
+
+static int __kprobes do_vsx_store(int rn, int (*func)(int, unsigned long),
+ unsigned long ea, struct pt_regs *regs)
+{
+ int err;
+ unsigned long val[2];
+
+ if (user_mode(regs) && !access_ok(VERIFY_WRITE, ea, 16))
+ return -EFAULT;
+ if ((ea & 3) == 0)
+ return (*func)(rn, ea);
+ err = (*func)(rn, (unsigned long) &val[0]);
+ if (err)
+ return err;
+ err = write_mem_unaligned(val[0], ea, 8, regs);
+ if (!err)
+ err = write_mem_unaligned(val[1], ea + 8, 8, regs);
+ return err;
+}
+#endif /* CONFIG_VSX */
+
+/*
+ * Emulate instructions that cause a transfer of control,
+ * loads and stores, and a few other instructions.
* Returns 1 if the step was emulated, 0 if not,
* or -1 if the instruction is one that should not be stepped,
* such as an rfid, or a mtmsrd that would clear MSR_RI.
*/
int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
{
- unsigned int opcode, rs, rb, rd, spr;
+ unsigned int opcode, rs, ra, rb, rd, spr;
unsigned long int imm;
+ unsigned long int val;
+ unsigned long int ea;
+ int err;
+ mm_segment_t oldfs;
opcode = instr >> 26;
switch (opcode) {
@@ -78,7 +433,13 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
* entry code works. If that is changed, this will
* need to be changed also.
*/
+ if (regs->gpr[0] == 0x1ebe &&
+ cpu_has_feature(CPU_FTR_REAL_LE)) {
+ regs->msr ^= MSR_LE;
+ goto instr_done;
+ }
regs->gpr[9] = regs->gpr[13];
+ regs->gpr[10] = MSR_KERNEL;
regs->gpr[11] = regs->nip + 4;
regs->gpr[12] = regs->msr & MSR_MASK;
regs->gpr[13] = (unsigned long) get_paca();
@@ -119,27 +480,35 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
case 0x24: /* rfid, scary */
return -1;
}
- case 31:
- rd = (instr >> 21) & 0x1f;
+ }
+
+ /* Following cases refer to regs->gpr[], so we need all regs */
+ if (!FULL_REGS(regs))
+ return 0;
+
+ rd = (instr >> 21) & 0x1f;
+ if (opcode == 31) {
switch (instr & 0x7fe) {
case 0xa6: /* mfmsr */
+ if (regs->msr & MSR_PR)
+ break;
regs->gpr[rd] = regs->msr & MSR_MASK;
- regs->nip += 4;
- if ((regs->msr & MSR_SF) == 0)
- regs->nip &= 0xffffffffUL;
- return 1;
+ goto instr_done;
case 0x124: /* mtmsr */
+ if (regs->msr & MSR_PR)
+ break;
imm = regs->gpr[rd];
if ((imm & MSR_RI) == 0)
/* can't step mtmsr that would clear MSR_RI */
return -1;
regs->msr = imm;
- regs->nip += 4;
- return 1;
+ goto instr_done;
#ifdef CONFIG_PPC64
case 0x164: /* mtmsrd */
/* only MSR_EE and MSR_RI get changed if bit 15 set */
/* mtmsrd doesn't change MSR_HV and MSR_ME */
+ if (regs->msr & MSR_PR)
+ break;
imm = (instr & 0x10000)? 0x8002: 0xefffffffffffefffUL;
imm = (regs->msr & MSR_MASK & ~imm)
| (regs->gpr[rd] & imm);
@@ -147,28 +516,25 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
/* can't step mtmsrd that would clear MSR_RI */
return -1;
regs->msr = imm;
- regs->nip += 4;
- if ((imm & MSR_SF) == 0)
- regs->nip &= 0xffffffffUL;
- return 1;
+ goto instr_done;
#endif
case 0x26: /* mfcr */
regs->gpr[rd] = regs->ccr;
regs->gpr[rd] &= 0xffffffffUL;
- goto mtspr_out;
+ goto instr_done;
case 0x2a6: /* mfspr */
spr = (instr >> 11) & 0x3ff;
switch (spr) {
case 0x20: /* mfxer */
regs->gpr[rd] = regs->xer;
regs->gpr[rd] &= 0xffffffffUL;
- goto mtspr_out;
+ goto instr_done;
case 0x100: /* mflr */
regs->gpr[rd] = regs->link;
- goto mtspr_out;
+ goto instr_done;
case 0x120: /* mfctr */
regs->gpr[rd] = regs->ctr;
- goto mtspr_out;
+ goto instr_done;
}
break;
case 0x378: /* orx */
@@ -179,7 +545,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
if (rs == rb) { /* mr */
rd = (instr >> 16) & 0x1f;
regs->gpr[rd] = regs->gpr[rs];
- goto mtspr_out;
+ goto instr_done;
}
break;
case 0x3a6: /* mtspr */
@@ -187,17 +553,354 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
switch (spr) {
case 0x20: /* mtxer */
regs->xer = (regs->gpr[rd] & 0xffffffffUL);
- goto mtspr_out;
+ goto instr_done;
case 0x100: /* mtlr */
regs->link = regs->gpr[rd];
- goto mtspr_out;
+ goto instr_done;
case 0x120: /* mtctr */
regs->ctr = regs->gpr[rd];
-mtspr_out:
- regs->nip += 4;
- return 1;
+ goto instr_done;
}
+ break;
}
}
- return 0;
+
+ /*
+ * Following cases are for loads and stores, so bail out
+ * if we're in little-endian mode.
+ */
+ if (regs->msr & MSR_LE)
+ return 0;
+
+ /*
+ * Make sure access_ok() checks against TASK_SIZE
+ */
+ oldfs = get_fs();
+ set_fs(USER_DS);
+
+ switch (opcode) {
+ case 31:
+ switch (instr & 0x7fe) {
+#ifdef __powerpc64__
+ case 0x2a: /* ldx */
+ case 0x6a: /* ldux */
+ err = read_mem(®s->gpr[rd], xform_ea(instr, regs),
+ 8, regs);
+ goto ldst_done;
+#endif
+
+ case 0x2e: /* lwzx */
+ case 0x6e: /* lwzux */
+ err = read_mem(®s->gpr[rd], xform_ea(instr, regs),
+ 4, regs);
+ goto ldst_done;
+
+ case 0xae: /* lbzx */
+ case 0xee: /* lbzux */
+ err = read_mem(®s->gpr[rd], xform_ea(instr, regs),
+ 1, regs);
+ goto ldst_done;
+
+#ifdef CONFIG_ALTIVEC
+ case 0xce: /* lvx */
+ case 0x2ce: /* lvxl */
+ if (!(regs->msr & MSR_VEC))
+ break;
+ ea = xform_ea(instr, regs);
+ err = do_vec_load(rd, do_lvx, ea, regs);
+ goto ldst_done;
+
+ case 0x1ce: /* stvx */
+ case 0x3ce: /* stvxl */
+ if (!(regs->msr & MSR_VEC))
+ break;
+ ea = xform_ea(instr, regs);
+ err = do_vec_store(rd, do_stvx, ea, regs);
+ goto ldst_done;
+#endif /* CONFIG_ALTIVEC */
+
+#ifdef __powerpc64__
+ case 0x12a: /* stdx */
+ case 0x16a: /* stdux */
+ val = regs->gpr[rd];
+ err = write_mem(val, xform_ea(instr, regs), 8, regs);
+ goto ldst_done;
+#endif
+
+ case 0x12e: /* stwx */
+ case 0x16e: /* stwux */
+ val = regs->gpr[rd];
+ err = write_mem(val, xform_ea(instr, regs), 4, regs);
+ goto ldst_done;
+
+ case 0x1ae: /* stbx */
+ case 0x1ee: /* stbux */
+ val = regs->gpr[rd];
+ err = write_mem(val, xform_ea(instr, regs), 1, regs);
+ goto ldst_done;
+
+ case 0x22e: /* lhzx */
+ case 0x26e: /* lhzux */
+ err = read_mem(®s->gpr[rd], xform_ea(instr, regs),
+ 2, regs);
+ goto ldst_done;
+
+#ifdef __powerpc64__
+ case 0x2aa: /* lwax */
+ case 0x2ea: /* lwaux */
+ err = read_mem(®s->gpr[rd], xform_ea(instr, regs),
+ 8, regs);
+ if (!err)
+ regs->gpr[rd] = (signed int) regs->gpr[rd];
+ goto ldst_done;
+#endif
+
+ case 0x2ae: /* lhax */
+ case 0x2ee: /* lhaux */
+ err = read_mem(®s->gpr[rd], xform_ea(instr, regs),
+ 2, regs);
+ if (!err)
+ regs->gpr[rd] = (signed short) regs->gpr[rd];
+ goto ldst_done;
+
+ case 0x32e: /* sthx */
+ case 0x36e: /* sthux */
+ val = regs->gpr[rd];
+ err = write_mem(val, xform_ea(instr, regs), 2, regs);
+ goto ldst_done;
+
+#ifdef __powerpc64__
+ case 0x428: /* ldbrx */
+ err = read_mem(&val, xform_ea(instr, regs), 8, regs);
+ if (!err)
+ regs->gpr[rd] = byterev_8(val);
+ goto ldst_done;
+
+#endif
+
+ case 0x42c: /* lwbrx */
+ err = read_mem(&val, xform_ea(instr, regs), 4, regs);
+ if (!err)
+ regs->gpr[rd] = byterev_4(val);
+ goto ldst_done;
+
+ case 0x42e: /* lfsx */
+ case 0x46e: /* lfsux */
+ if (!(regs->msr & MSR_FP))
+ break;
+ ea = xform_ea(instr, regs);
+ err = do_fp_load(rd, do_lfs, ea, 4, regs);
+ goto ldst_done;
+
+ case 0x4ae: /* lfdx */
+ case 0x4ee: /* lfdux */
+ if (!(regs->msr & MSR_FP))
+ break;
+ ea = xform_ea(instr, regs);
+ err = do_fp_load(rd, do_lfd, ea, 8, regs);
+ goto ldst_done;
+
+ case 0x52e: /* stfsx */
+ case 0x56e: /* stfsux */
+ if (!(regs->msr & MSR_FP))
+ break;
+ ea = xform_ea(instr, regs);
+ err = do_fp_store(rd, do_stfs, ea, 4, regs);
+ goto ldst_done;
+
+ case 0x5ae: /* stfdx */
+ case 0x5ee: /* stfdux */
+ if (!(regs->msr & MSR_FP))
+ break;
+ ea = xform_ea(instr, regs);
+ err = do_fp_store(rd, do_stfd, ea, 8, regs);
+ goto ldst_done;
+
+#ifdef __powerpc64__
+ case 0x528: /* stdbrx */
+ val = byterev_8(regs->gpr[rd]);
+ err = write_mem(val, xform_ea(instr, regs), 8, regs);
+ goto ldst_done;
+
+#endif
+ case 0x52c: /* stwbrx */
+ val = byterev_4(regs->gpr[rd]);
+ err = write_mem(val, xform_ea(instr, regs), 4, regs);
+ goto ldst_done;
+
+ case 0x62c: /* lhbrx */
+ err = read_mem(&val, xform_ea(instr, regs), 2, regs);
+ if (!err)
+ regs->gpr[rd] = byterev_2(val);
+ goto ldst_done;
+
+ case 0x72c: /* sthbrx */
+ val = byterev_2(regs->gpr[rd]);
+ err = write_mem(val, xform_ea(instr, regs), 2, regs);
+ goto ldst_done;
+
+#ifdef CONFIG_VSX
+ case 0x698: /* lxvd2x */
+ case 0x6d8: /* lxvd2ux */
+ if (!(regs->msr & MSR_VSX))
+ break;
+ rd |= (instr & 1) << 5;
+ ea = xform_ea(instr, regs);
+ err = do_vsx_load(rd, do_lxvd2x, ea, regs);
+ goto ldst_done;
+
+ case 0x798: /* stxvd2x */
+ case 0x7d8: /* stxvd2ux */
+ if (!(regs->msr & MSR_VSX))
+ break;
+ rd |= (instr & 1) << 5;
+ ea = xform_ea(instr, regs);
+ err = do_vsx_store(rd, do_stxvd2x, ea, regs);
+ goto ldst_done;
+
+#endif /* CONFIG_VSX */
+ }
+ break;
+
+ case 32: /* lwz */
+ case 33: /* lwzu */
+ err = read_mem(®s->gpr[rd], dform_ea(instr, regs), 4, regs);
+ goto ldst_done;
+
+ case 34: /* lbz */
+ case 35: /* lbzu */
+ err = read_mem(®s->gpr[rd], dform_ea(instr, regs), 1, regs);
+ goto ldst_done;
+
+ case 36: /* stw */
+ case 37: /* stwu */
+ val = regs->gpr[rd];
+ err = write_mem(val, dform_ea(instr, regs), 4, regs);
+ goto ldst_done;
+
+ case 38: /* stb */
+ case 39: /* stbu */
+ val = regs->gpr[rd];
+ err = write_mem(val, dform_ea(instr, regs), 1, regs);
+ goto ldst_done;
+
+ case 40: /* lhz */
+ case 41: /* lhzu */
+ err = read_mem(®s->gpr[rd], dform_ea(instr, regs), 2, regs);
+ goto ldst_done;
+
+ case 42: /* lha */
+ case 43: /* lhau */
+ err = read_mem(®s->gpr[rd], dform_ea(instr, regs), 2, regs);
+ if (!err)
+ regs->gpr[rd] = (signed short) regs->gpr[rd];
+ goto ldst_done;
+
+ case 44: /* sth */
+ case 45: /* sthu */
+ err = write_mem(val, dform_ea(instr, regs), 2, regs);
+ goto ldst_done;
+
+ case 46: /* lmw */
+ ra = (instr >> 16) & 0x1f;
+ if (ra >= rd)
+ break; /* invalid form, ra in range to load */
+ ea = dform_ea(instr, regs);
+ do {
+ err = read_mem(®s->gpr[rd], ea, 4, regs);
+ if (err)
+ return 0;
+ ea += 4;
+ } while (++rd < 32);
+ goto instr_done;
+
+ case 47: /* stmw */
+ ea = dform_ea(instr, regs);
+ do {
+ err = write_mem(regs->gpr[rd], ea, 4, regs);
+ if (err)
+ return 0;
+ ea += 4;
+ } while (++rd < 32);
+ goto instr_done;
+
+ case 48: /* lfs */
+ case 49: /* lfsu */
+ if (!(regs->msr & MSR_FP))
+ break;
+ ea = dform_ea(instr, regs);
+ err = do_fp_load(rd, do_lfs, ea, 4, regs);
+ goto ldst_done;
+
+ case 50: /* lfd */
+ case 51: /* lfdu */
+ if (!(regs->msr & MSR_FP))
+ break;
+ ea = dform_ea(instr, regs);
+ err = do_fp_load(rd, do_lfd, ea, 8, regs);
+ goto ldst_done;
+
+ case 52: /* stfs */
+ case 53: /* stfsu */
+ if (!(regs->msr & MSR_FP))
+ break;
+ ea = dform_ea(instr, regs);
+ err = do_fp_store(rd, do_stfs, ea, 4, regs);
+ goto ldst_done;
+
+ case 54: /* stfd */
+ case 55: /* stfdu */
+ if (!(regs->msr & MSR_FP))
+ break;
+ ea = dform_ea(instr, regs);
+ err = do_fp_store(rd, do_stfd, ea, 8, regs);
+ goto ldst_done;
+
+#ifdef __powerpc64__
+ case 58: /* ld[u], lwa */
+ switch (instr & 3) {
+ case 0: /* ld */
+ err = read_mem(®s->gpr[rd], dsform_ea(instr, regs),
+ 8, regs);
+ goto ldst_done;
+ case 1: /* ldu */
+ err = read_mem(®s->gpr[rd], dsform_ea(instr, regs),
+ 8, regs);
+ goto ldst_done;
+ case 2: /* lwa */
+ err = read_mem(®s->gpr[rd], dsform_ea(instr, regs),
+ 4, regs);
+ if (!err)
+ regs->gpr[rd] = (signed int) regs->gpr[rd];
+ goto ldst_done;
+ }
+ break;
+
+ case 62: /* std[u] */
+ val = regs->gpr[rd];
+ switch (instr & 3) {
+ case 0: /* ld */
+ err = write_mem(val, dsform_ea(instr, regs), 8, regs);
+ goto ldst_done;
+ case 1: /* ldu */
+ err = write_mem(val, dsform_ea(instr, regs), 8, regs);
+ goto ldst_done;
+ }
+ break;
+#endif /* __powerpc64__ */
+
+ }
+ err = -EINVAL;
+
+ldst_done:
+ set_fs(oldfs);
+ if (err)
+ return 0; /* invoke DSI if -EFAULT? */
+instr_done:
+ regs->nip += 4;
+#ifdef __powerpc64__
+ if ((regs->msr & MSR_SF) == 0)
+ regs->nip &= 0xffffffffUL;
+#endif
+ return 1;
}
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH] powerpc: make the padding for the device tree a configurable option
From: Timur Tabi @ 2010-05-20 11:40 UTC (permalink / raw)
To: Timur Tabi, Benjamin Herrenschmidt, linuxppc-dev,
devicetree-discuss
In-Reply-To: <20100520061739.GE25892@yookeroo>
On Thu, May 20, 2010 at 1:17 AM, David Gibson
<david@gibson.dropbear.id.au> wrote:
> Um.. what? =A0As far as I can tell that thread is about runtime
> expanding the space given to the dtb. =A0I'm talking about altering the
> padding on the file before giving it to u-boot in the first place.
Sorry, I guess I don't understand. How do I alter the padding before
giving it to U-Boot?
--=20
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply
* [PATCHv2] [RFC] Xilinx Virtex 4 FX Soft FPU support
From: Sergey Temerkhanov @ 2010-05-20 10:01 UTC (permalink / raw)
To: linuxppc-dev, Grant Likely
[-- Attachment #1: Type: text/plain, Size: 532 bytes --]
This patch enables support for Xilinx Virtex 4 FX singe-float FPU.
Changelog v1->v2:
-Added MSR_AP bit definition
-Renamed CONFIG_XILINX_FPU to CONFIG_XILINX_SOFTFPU, moved it to
'Platform support' and made it Virtex4-FX-only.
-Changed SAVE_FPR/REST_FPR definition style.
Caveats:
- Hard-float binaries which rely on in-kernel math emulation will give
wrong results since they expect 64-bit double-precision instead of 32-bit
single-precision numbers which Xilinx V4-FX Soft FPU produces.
Regards, Sergey Temerkhanov
[-- Attachment #2: fp.patch --]
[-- Type: text/x-patch, Size: 5582 bytes --]
Signed-off-by: Sergey Temerkhanov<temerkhanov@cifronik.ru>
diff -r b59861a64e13 arch/powerpc/include/asm/ppc_asm.h
--- a/arch/powerpc/include/asm/ppc_asm.h Thu May 20 13:24:53 2010 +0400
+++ b/arch/powerpc/include/asm/ppc_asm.h Thu May 20 13:55:10 2010 +0400
@@ -85,13 +85,21 @@
#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base)
#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base)
-#define SAVE_FPR(n, base) stfd n,THREAD_FPR0+8*TS_FPRWIDTH*(n)(base)
+
+#ifdef CONFIG_XILINX_SOFTFPU
+#define SAVE_FPR(n, base) stfs n,THREAD_FPR0+8*TS_FPRWIDTH*(n)(base)
+#define REST_FPR(n, base) lfs n,THREAD_FPR0+8*TS_FPRWIDTH*(n)(base)
+#else
+#define SAVE_FPR(n, base) stfd n,THREAD_FPR0+8*TS_FPRWIDTH*(n)(base)
+#define REST_FPR(n, base) lfd n,THREAD_FPR0+8*TS_FPRWIDTH*(n)(base)
+#endif
+
#define SAVE_2FPRS(n, base) SAVE_FPR(n, base); SAVE_FPR(n+1, base)
#define SAVE_4FPRS(n, base) SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, base)
#define SAVE_8FPRS(n, base) SAVE_4FPRS(n, base); SAVE_4FPRS(n+4, base)
#define SAVE_16FPRS(n, base) SAVE_8FPRS(n, base); SAVE_8FPRS(n+8, base)
#define SAVE_32FPRS(n, base) SAVE_16FPRS(n, base); SAVE_16FPRS(n+16, base)
-#define REST_FPR(n, base) lfd n,THREAD_FPR0+8*TS_FPRWIDTH*(n)(base)
+
#define REST_2FPRS(n, base) REST_FPR(n, base); REST_FPR(n+1, base)
#define REST_4FPRS(n, base) REST_2FPRS(n, base); REST_2FPRS(n+2, base)
#define REST_8FPRS(n, base) REST_4FPRS(n, base); REST_4FPRS(n+4, base)
diff -r b59861a64e13 arch/powerpc/include/asm/reg.h
--- a/arch/powerpc/include/asm/reg.h Thu May 20 13:24:53 2010 +0400
+++ b/arch/powerpc/include/asm/reg.h Thu May 20 13:55:10 2010 +0400
@@ -30,6 +30,7 @@
#define MSR_ISF_LG 61 /* Interrupt 64b mode valid on 630 */
#define MSR_HV_LG 60 /* Hypervisor state */
#define MSR_VEC_LG 25 /* Enable AltiVec */
+#define MSR_AP_LG 25 /* Enable APU */
#define MSR_VSX_LG 23 /* Enable VSX */
#define MSR_POW_LG 18 /* Enable Power Management */
#define MSR_WE_LG 18 /* Wait State Enable */
@@ -71,6 +72,7 @@
#define MSR_HV 0
#endif
+#define MSR_AP __MASK(MSR_AP_LG) /* Enable APU */
#define MSR_VEC __MASK(MSR_VEC_LG) /* Enable AltiVec */
#define MSR_VSX __MASK(MSR_VSX_LG) /* Enable VSX */
#define MSR_POW __MASK(MSR_POW_LG) /* Enable Power Management */
diff -r b59861a64e13 arch/powerpc/kernel/fpu.S
--- a/arch/powerpc/kernel/fpu.S Thu May 20 13:24:53 2010 +0400
+++ b/arch/powerpc/kernel/fpu.S Thu May 20 13:55:10 2010 +0400
@@ -57,6 +57,9 @@
_GLOBAL(load_up_fpu)
mfmsr r5
ori r5,r5,MSR_FP
+#ifdef CONFIG_XILINX_SOFTFPU
+ oris r5,r5,MSR_AP@h
+#endif
#ifdef CONFIG_VSX
BEGIN_FTR_SECTION
oris r5,r5,MSR_VSX@h
@@ -85,6 +88,9 @@
toreal(r5)
PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
li r10,MSR_FP|MSR_FE0|MSR_FE1
+#ifdef CONFIG_XILINX_SOFTFPU
+ oris r10,r10,MSR_AP@h
+#endif
andc r4,r4,r10 /* disable FP for previous task */
PPC_STL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1:
@@ -94,6 +100,9 @@
mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */
lwz r4,THREAD_FPEXC_MODE(r5)
ori r9,r9,MSR_FP /* enable FP for current */
+#ifdef CONFIG_XILINX_SOFTFPU
+ oris r9,r9,MSR_AP@h
+#endif
or r9,r9,r4
#else
ld r4,PACACURRENT(r13)
@@ -124,6 +133,9 @@
_GLOBAL(giveup_fpu)
mfmsr r5
ori r5,r5,MSR_FP
+#ifdef CONFIG_XILINX_SOFTFPU
+ oris r5,r5,MSR_AP@h
+#endif
#ifdef CONFIG_VSX
BEGIN_FTR_SECTION
oris r5,r5,MSR_VSX@h
@@ -145,6 +157,9 @@
beq 1f
PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
li r3,MSR_FP|MSR_FE0|MSR_FE1
+#ifdef CONFIG_XILINX_SOFTFPU
+ oris r3,r3,MSR_AP@h
+#endif
#ifdef CONFIG_VSX
BEGIN_FTR_SECTION
oris r3,r3,MSR_VSX@h
diff -r b59861a64e13 arch/powerpc/kernel/head_40x.S
--- a/arch/powerpc/kernel/head_40x.S Thu May 20 13:24:53 2010 +0400
+++ b/arch/powerpc/kernel/head_40x.S Thu May 20 13:55:10 2010 +0400
@@ -420,7 +420,19 @@
addi r3,r1,STACK_FRAME_OVERHEAD
EXC_XFER_STD(0x700, program_check_exception)
+/* 0x0800 - FPU unavailable Exception */
+#ifdef CONFIG_PPC_FPU
+ START_EXCEPTION(0x0800, FloatingPointUnavailable)
+ NORMAL_EXCEPTION_PROLOG
+ beq 1f; \
+ bl load_up_fpu; /* if from user, just load it up */ \
+ b fast_exception_return; \
+1: addi r3,r1,STACK_FRAME_OVERHEAD; \
+ EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception)
+#else
EXCEPTION(0x0800, Trap_08, unknown_exception, EXC_XFER_EE)
+#endif
+
EXCEPTION(0x0900, Trap_09, unknown_exception, EXC_XFER_EE)
EXCEPTION(0x0A00, Trap_0A, unknown_exception, EXC_XFER_EE)
EXCEPTION(0x0B00, Trap_0B, unknown_exception, EXC_XFER_EE)
@@ -432,7 +444,7 @@
EXCEPTION(0x0D00, Trap_0D, unknown_exception, EXC_XFER_EE)
EXCEPTION(0x0E00, Trap_0E, unknown_exception, EXC_XFER_EE)
- EXCEPTION(0x0F00, Trap_0F, unknown_exception, EXC_XFER_EE)
+ EXCEPTION(0x0F20, Trap_0F, unknown_exception, EXC_XFER_EE)
/* 0x1000 - Programmable Interval Timer (PIT) Exception */
START_EXCEPTION(0x1000, Decrementer)
@@ -821,8 +833,10 @@
* The PowerPC 4xx family of processors do not have an FPU, so this just
* returns.
*/
+#ifndef CONFIG_PPC_FPU
_ENTRY(giveup_fpu)
blr
+#endif
/* This is where the main kernel code starts.
*/
diff -r b59861a64e13 arch/powerpc/platforms/Kconfig
--- a/arch/powerpc/platforms/Kconfig Thu May 20 13:24:53 2010 +0400
+++ b/arch/powerpc/platforms/Kconfig Thu May 20 13:55:10 2010 +0400
@@ -333,4 +333,9 @@
bool "Xilinx PCI host bridge support"
depends on PCI && XILINX_VIRTEX
+config XILINX_SOFTFPU
+ bool "Xilinx Soft FPU"
+ select PPC_FPU
+ depends on XILINX_VIRTEX_4_FX && !PPC40x_SIMPLE && !405GP && !405GPR
+
endmenu
^ permalink raw reply
* Re: [PATCH] [RFC] Xilinx Virtex 4 FX Soft FPU support
From: Sergey Temerkhanov @ 2010-05-20 9:44 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-dev
In-Reply-To: <AANLkTil1Gbg7tED2MgheQjFpZIJMjS-qqmQ7Gu2Vbh5f@mail.gmail.com>
On Wednesday 19 May 2010 20:52:01 Grant Likely wrote:
> Hi Sergey. Comments below.
>
> > diff -r 9d9ac97e095d .config
> > --- a/.config Thu Feb 25 21:23:42 2010 +0300
> > +++ b/.config Thu Feb 25 21:49:02 2010 +0300
>
> .config changes should not appear in your patch file.
>
> > diff -r 9d9ac97e095d arch/powerpc/include/asm/ppc_asm.h
> > --- a/arch/powerpc/include/asm/ppc_asm.h Thu Feb 25 21:23:42 2010 +0300
> > +++ b/arch/powerpc/include/asm/ppc_asm.h Thu Feb 25 21:49:02 2010 +0300
> > @@ -85,13 +85,23 @@
> > #define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base)
> > #define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base)
> >
> > -#define SAVE_FPR(n, base) stfd n,THREAD_FPR0+8*TS_FPRWIDTH*(n)
(base)
> > +
> > +#ifdef CONFIG_XILINX_FPU
> > +#define stfr stfs
> > +#define lfr lfs
> > +#else
> > +#define stfr stfd
> > +#define lfr lfd
> > +#endif
>
> the stfr/lfr redirect is a little weird. Why not simply:
> > +
> > +#ifdef CONFIG_XILINX_FPU
> > +#define SAVE_FPR(n, base) stfs n,THREAD_FPR0+8*TS_FPRWIDTH*(n)(base)
> > +#define REST_FPR(n, base) lfs n,THREAD_FPR0+8*TS_FPRWIDTH*(n)(base)
> > +#else
> > +#define SAVE_FPR(n, base) stfd n,THREAD_FPR0+8*TS_FPRWIDTH*(n)(base)
> > +#define REST_FPR(n, base) lfd n,THREAD_FPR0+8*TS_FPRWIDTH*(n)(base)
> > +#endif
>
> A comment here describing that only single precision works with the
> XILINX 405 FPU wouldn't go amiss either.
>
Agreed.
> > diff -r 9d9ac97e095d arch/powerpc/kernel/fpu.S
> > --- a/arch/powerpc/kernel/fpu.S Thu Feb 25 21:23:42 2010 +0300
> > +++ b/arch/powerpc/kernel/fpu.S Thu Feb 25 21:49:02 2010 +0300
> > @@ -57,6 +57,9 @@
> > _GLOBAL(load_up_fpu)
> > mfmsr r5
> > ori r5,r5,MSR_FP
> > +#ifdef CONFIG_XILINX_FPU
> > + oris r5,r5,MSR_VEC@h
> > +#endif
>
> So AltiVec is being enabled here, but double precision is not
> supported?
That bit means 'APU enabled' for PowerPC 405 core. I've simply used existing
#define. As Xilinx uses APU facilities for their FPU this bit must be set too.
> What instructions are supported?
Only single precision is supported for Virtex-4 FPU. Double presicion opcodes
work as single precision there.
>
> Also, please stick with the same whitespace convention used in the
> lines above (tab indent instead of a space). Again, a comment would
> not go amiss.
>
> > #ifdef CONFIG_VSX
> > BEGIN_FTR_SECTION
> > oris r5,r5,MSR_VSX@h
> > @@ -85,6 +88,9 @@
> > toreal(r5)
> > PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
> > li r10,MSR_FP|MSR_FE0|MSR_FE1
> > +#ifdef CONFIG_XILINX_FPU
> > + oris r10,r10,MSR_VEC@h
> > +#endif
> > andc r4,r4,r10 /* disable FP for previous task */
> > PPC_STL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
> > 1:
> > @@ -94,6 +100,9 @@
> > mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */
> > lwz r4,THREAD_FPEXC_MODE(r5)
> > ori r9,r9,MSR_FP /* enable FP for current */
> > +#ifdef CONFIG_XILINX_FPU
> > + oris r9,r9,MSR_VEC@h
> > +#endif
> > or r9,r9,r4
> > #else
> > ld r4,PACACURRENT(r13)
> > @@ -124,6 +133,9 @@
> > _GLOBAL(giveup_fpu)
> > mfmsr r5
> > ori r5,r5,MSR_FP
> > +#ifdef CONFIG_XILINX_FPU
> > + oris r5,r5,MSR_VEC@h
> > +#endif
> > #ifdef CONFIG_VSX
> > BEGIN_FTR_SECTION
> > oris r5,r5,MSR_VSX@h
> > @@ -145,6 +157,9 @@
> > beq 1f
> > PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
> > li r3,MSR_FP|MSR_FE0|MSR_FE1
> > +#ifdef CONFIG_XILINX_FPU
> > + oris r3,r3,MSR_VEC@h
> > +#endif
> > #ifdef CONFIG_VSX
> > BEGIN_FTR_SECTION
> > oris r3,r3,MSR_VSX@h
> > diff -r 9d9ac97e095d arch/powerpc/kernel/head_40x.S
> > --- a/arch/powerpc/kernel/head_40x.S Thu Feb 25 21:23:42 2010 +0300
> > +++ b/arch/powerpc/kernel/head_40x.S Thu Feb 25 21:49:02 2010 +0300
> > @@ -420,7 +420,19 @@
> > addi r3,r1,STACK_FRAME_OVERHEAD
> > EXC_XFER_STD(0x700, program_check_exception)
> >
> > +/* 0x0800 - FPU unavailable Exception */
> > +#ifdef CONFIG_PPC_FPU
> > + START_EXCEPTION(0x0800, FloatingPointUnavailable)
> > + NORMAL_EXCEPTION_PROLOG
> > + beq 1f; \
> > + bl load_up_fpu; /* if from user, just load it up */ \
> > + b fast_exception_return; \
> > +1: addi r3,r1,STACK_FRAME_OVERHEAD; \
> > + EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception)
> > +#else
> > EXCEPTION(0x0800, Trap_08, unknown_exception, EXC_XFER_EE)
> > +#endif
> > +
> > EXCEPTION(0x0900, Trap_09, unknown_exception, EXC_XFER_EE)
> > EXCEPTION(0x0A00, Trap_0A, unknown_exception, EXC_XFER_EE)
> > EXCEPTION(0x0B00, Trap_0B, unknown_exception, EXC_XFER_EE)
> > @@ -432,7 +444,7 @@
> >
> > EXCEPTION(0x0D00, Trap_0D, unknown_exception, EXC_XFER_EE)
> > EXCEPTION(0x0E00, Trap_0E, unknown_exception, EXC_XFER_EE)
> > - EXCEPTION(0x0F00, Trap_0F, unknown_exception, EXC_XFER_EE)
> > + EXCEPTION(0x0F20, Trap_0F, unknown_exception, EXC_XFER_EE)
>
> Why?
Xilinx UG011 and IBM PowerPC 405 User guides define no 0xF00 exception but
0xF20 (APU unavailable). For 403 core there seems to be no APU support.
>
> > /* 0x1000 - Programmable Interval Timer (PIT) Exception */
> > START_EXCEPTION(0x1000, Decrementer)
> > @@ -821,8 +833,10 @@
> > * The PowerPC 4xx family of processors do not have an FPU, so this just
> > * returns.
> > */
> > +#ifndef CONFIG_PPC_FPU
> > _ENTRY(giveup_fpu)
> > blr
> > +#endif
> >
> > /* This is where the main kernel code starts.
> > */
> > diff -r 9d9ac97e095d arch/powerpc/platforms/Kconfig.cputype
> > --- a/arch/powerpc/platforms/Kconfig.cputype Thu Feb 25 21:23:42 2010
> > +0300 +++ b/arch/powerpc/platforms/Kconfig.cputype Thu Feb 25 21:49:02
> > 2010 +0300 @@ -290,4 +290,9 @@
> > config CHECK_CACHE_COHERENCY
> > bool
> >
> > +config XILINX_FPU
> > + bool "Xilinx softFPU"
> > + select PPC_FPU
> > + depends on 40x
> > +
>
> Should be more specific. Use something like XILINX_VIRTEX4_405_FPU
> (as opposed to Virtex II pro, or the 440 on the Virtex 5.
>
> Also, this looks to be very multiplatform unfriendly, so you'll need
> to make sure other 405 board support is not selectable when the Xilinx
> FPU is enabled.
Agreed, it must depend on Virtex-4FX only.
>
> Cheers,
> g.
>
^ permalink raw reply
* [PATCH] PPC: Fix zero length strncmp() on powerpc
From: David Howells @ 2010-05-20 9:42 UTC (permalink / raw)
To: srostedt; +Cc: linuxppc-dev
When strncmp() on powerpc is given a length of zero, it detects this and
returns early to make the comparison loop simpler. When it does this, however,
it fails to set a return value, and thus returns the address of the first
string as the number of the character match. It should return 0 instead in
this case.
This can be tested by compiling and attempting to load the following module:
#include <linux/init.h>
#include <linux/module.h>
char string1[1], string2[1];
size_t count_global = 0;
static int __init strncmp_init(void)
{
string1[0] = string2[0] = 0;
if (strncmp(string1, string2, count_global)) {
printk("Strncmp Bug!\n");
return -EIO;
}
return -ENOANO;
}
module_init(strncmp_init);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Probe strncmp() bug");
It should return error "No anode" on success and "I/O error" on failure. The
module will not be retained.
Signed-off-by: David Howells <dhowells@redhat.com>
---
arch/powerpc/lib/string.S | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/lib/string.S b/arch/powerpc/lib/string.S
index 64e2e49..46fe390 100644
--- a/arch/powerpc/lib/string.S
+++ b/arch/powerpc/lib/string.S
@@ -71,7 +71,7 @@ _GLOBAL(strcmp)
_GLOBAL(strncmp)
PPC_LCMPI r5,0
- beqlr
+ beq- 2f
mtctr r5
addi r5,r3,-1
addi r4,r4,-1
@@ -82,6 +82,8 @@ _GLOBAL(strncmp)
beqlr 1
bdnzt eq,1b
blr
+2: li r3,0
+ blr
_GLOBAL(strlen)
addi r4,r3,-1
^ permalink raw reply related
* Re: [PATCH RT] ehea: make receive irq handler non-threaded (IRQF_NODELAY)
From: Thomas Gleixner @ 2010-05-20 9:19 UTC (permalink / raw)
To: Jan-Bernd Themann
Cc: Darren Hart, dvhltc, linux-kernel, Will Schmidt, Brian King, niv,
Doug Maxey, linuxppc-dev
In-Reply-To: <OFCBBE5EB9.FD616EDA-ONC1257729.0030B539-C1257729.0031FB06@de.ibm.com>
Jan-Bernd,
On Thu, 20 May 2010, Jan-Bernd Themann wrote:
>
> Hi Thomas
>
> > Re: [PATCH RT] ehea: make receive irq handler non-threaded (IRQF_NODELAY)
> >
> > On Thu, 20 May 2010, Jan-Bernd Themann wrote:
> > > > > Thought more about that. The case at hand (ehea) is nasty:
> > > > >
> > > > > The driver does _NOT_ disable the rx interrupt in the card in the
> rx
> > > > > interrupt handler - for whatever reason.
> > > >
> > > > Yeah I saw that, but I don't know why it's written that way. Perhaps
> > > > Jan-Bernd or Doug will chime in and enlighten us? :)
> > >
> > > From our perspective there is no need to disable interrupts for the
> > > RX side as the chip does not fire further interrupts until we tell
> > > the chip to do so for a particular queue. We have multiple receive
> >
> > The traces tell a different story though:
> >
> > ehea_recv_irq_handler()
> > napi_reschedule()
> > eoi()
> > ehea_poll()
> > ...
> > ehea_recv_irq_handler() <---------------- ???
> > napi_reschedule()
> > ...
> > napi_complete()
> >
> > Can't tell whether you can see the same behaviour in mainline, but I
> > don't see a reason why not.
>
> Is this the same interrupt we are seeing here, or do we see a second other
> interrupt popping up on the same CPU? As I said, with multiple receive
> queues
> (if enabled) you can have multiple interrupts in parallel.
According to the traces it's the very same interrupt number.
> Pleaes check if multiple queues are enabled. The following module parameter
> is used for that:
>
> MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 0
> ");
>
> you should also see the number of used HEA interrupts in /proc/interrupts
I leave that for Will and Darren, they have the hardware :)
> >
> > > queues with an own interrupt each so that the interrupts can arrive
> > > on multiple CPUs in parallel. Interrupts are enabled again when we
> > > leave the NAPI Poll function for the corresponding receive queue.
> >
> > I can't see a piece of code which does that, but that's probably just
> > lack of detailed hardware knowledge on my side.
>
> If you mean the "re-enable" piece of code, it is not very obvious,
> you are right. Interrupts are only generated if a particular
> register for our completion queues is written. We do this in the
> following line:
>
> ehea_reset_cq_ep(pr->recv_cq);
> ehea_reset_cq_ep(pr->send_cq);
> ehea_reset_cq_n1(pr->recv_cq);
> ehea_reset_cq_n1(pr->send_cq);
>
> So this is in a way an indirect way to ask for interrupts when new
> completions were written to memory. We don't really disable/enable
> interrupts on the HEA chip itself.
Ah, ok. That's after the napi_complete which looks correct.
> I think there are some mechanisms build in the HEA chip that should
> prevent that interrupts don't get lost. But that is something that
> is / was completely hidden from us, so my skill is very limited
> there.
>
> If more details are needed here we should involve the PHYP guys +
> eHEA HW guys if not already done. Did anyone already talk to them?
Will or Darren might have, but lets gather more information first
before we rack their nerves :)
Thanks,
tglx
^ permalink raw reply
* Problem of PowerPc 82xx when using smc
From: hellohello @ 2010-05-20 8:58 UTC (permalink / raw)
To: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 549 bytes --]
I find a problem in
drivers/serial/cpm_uart/cpm_uart_cpm2.c:
int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
{
... ...
pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos;
/*The above line should be :*/
pinfo->tx_bd_base = pinfo->rx_bd_base + sizeof(cbd_t) * pinfo->rx_nrfifos;
return 0;
}
Where to get the newest code for kernel?
How to know whether it is already patched by anyone else? Just search in this mail list?
My Linux Kernel is 2.6.25, platform is mpc82XX.
Thanks for any help.
[-- Attachment #2: Type: text/html, Size: 1275 bytes --]
^ permalink raw reply
* Re: [PATCH RT] ehea: make receive irq handler non-threaded (IRQF_NODELAY)
From: Jan-Bernd Themann @ 2010-05-20 9:05 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Darren Hart, dvhltc, linux-kernel, Will Schmidt, Brian King, niv,
Doug Maxey, linuxppc-dev
In-Reply-To: <alpine.LFD.2.00.1005200950410.3368@localhost.localdomain>
Hi Thomas
> Re: [PATCH RT] ehea: make receive irq handler non-threaded (IRQF_NODELAY)
>
> On Thu, 20 May 2010, Jan-Bernd Themann wrote:
> > > > Thought more about that. The case at hand (ehea) is nasty:
> > > >
> > > > The driver does _NOT_ disable the rx interrupt in the card in the
rx
> > > > interrupt handler - for whatever reason.
> > >
> > > Yeah I saw that, but I don't know why it's written that way. Perhaps
> > > Jan-Bernd or Doug will chime in and enlighten us? :)
> >
> > From our perspective there is no need to disable interrupts for the
> > RX side as the chip does not fire further interrupts until we tell
> > the chip to do so for a particular queue. We have multiple receive
>
> The traces tell a different story though:
>
> ehea_recv_irq_handler()
> napi_reschedule()
> eoi()
> ehea_poll()
> ...
> ehea_recv_irq_handler() <---------------- ???
> napi_reschedule()
> ...
> napi_complete()
>
> Can't tell whether you can see the same behaviour in mainline, but I
> don't see a reason why not.
Is this the same interrupt we are seeing here, or do we see a second other
interrupt popping up on the same CPU? As I said, with multiple receive
queues
(if enabled) you can have multiple interrupts in parallel.
Pleaes check if multiple queues are enabled. The following module parameter
is used for that:
MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 0
");
you should also see the number of used HEA interrupts in /proc/interrupts
>
> > queues with an own interrupt each so that the interrupts can arrive
> > on multiple CPUs in parallel. Interrupts are enabled again when we
> > leave the NAPI Poll function for the corresponding receive queue.
>
> I can't see a piece of code which does that, but that's probably just
> lack of detailed hardware knowledge on my side.
If you mean the "re-enable" piece of code, it is not very obvious, you are
right.
Interrupts are only generated if a particular register for our completion
queues
is written. We do this in the following line:
ehea_reset_cq_ep(pr->recv_cq);
ehea_reset_cq_ep(pr->send_cq);
ehea_reset_cq_n1(pr->recv_cq);
ehea_reset_cq_n1(pr->send_cq);
So this is in a way an indirect way to ask for interrupts when new
completions were
written to memory. We don't really disable/enable interrupts on the HEA
chip itself.
I think there are some mechanisms build in the HEA chip that should prevent
that
interrupts don't get lost. But that is something that is / was completely
hidden from
us, so my skill is very limited there.
If more details are needed here we should involve the PHYP guys + eHEA HW
guys if not
already done. Did anyone already talk to them?
Regards,
Jan-Bernd
^ permalink raw reply
* Re: [PATCH RT] ehea: make receive irq handler non-threaded (IRQF_NODELAY)
From: Thomas Gleixner @ 2010-05-20 8:21 UTC (permalink / raw)
To: Michael Ellerman
Cc: Darren Hart, Jan-Bernd Themann, dvhltc, linux-kernel,
Milton Miller, Will Schmidt, Brian King, niv, Doug Maxey,
linuxppc-dev
In-Reply-To: <1274319125.22892.38.camel@concordia>
On Thu, 20 May 2010, Michael Ellerman wrote:
> On Wed, 2010-05-19 at 16:38 +0200, Thomas Gleixner wrote:
> > On Wed, 19 May 2010, Darren Hart wrote:
> >
> > > On 05/18/2010 06:25 PM, Michael Ellerman wrote:
> > > > On Tue, 2010-05-18 at 15:22 -0700, Darren Hart wrote:
>
> > > > The result of the discussion about two years ago on this was that we
> > > > needed a custom flow handler for XICS on RT.
> > >
> > > I'm still not clear on why the ultimate solution wasn't to have XICS report
> > > edge triggered as edge triggered. Probably some complexity of the entire power
> > > stack that I am ignorant of.
> > >
> > > > Apart from the issue of loosing interrupts there is also the fact that
> > > > masking on the XICS requires an RTAS call which takes a global lock.
> >
> > Right, I'd love to avoid that but with real level interrupts we'd run
> > into an interrupt storm. Though another solution would be to issue the
> > EOI after the threaded handler finished, that'd work as well, but
> > needs testing.
>
> Yeah I think that was the idea for the custom flow handler. We'd reset
> the processor priority so we can take other interrupts (which the EOI
> usually does for you), then do the actual EOI after the handler
> finished.
That only works when the card does not issue new interrupts until the
EOI happens. If the EOI is only relevant for the interrupt controller,
then you are going to lose any edge which comes in before the EOI as
well.
Thanks,
tglx
^ 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